feat(build): uplift Lerna + replace insecure shortid with nanoid + uplift Yeoman-related packages + ESM-ize generator-superset (#29419)

Signed-off-by: hainenber <dotronghai96@gmail.com>
This commit is contained in:
Đỗ Trọng Hải 2024-07-17 06:35:37 +07:00 committed by GitHub
parent 028e9c9294
commit c30ca534a3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
35 changed files with 12553 additions and 16800 deletions

View File

@ -76,7 +76,7 @@ jobs:
- name: generator-superset unit tests - name: generator-superset unit tests
if: steps.check.outputs.frontend if: steps.check.outputs.frontend
working-directory: ./superset-frontend/packages/generator-superset working-directory: ./superset-frontend/packages/generator-superset
run: npx jest run: npm run test
- name: Upload code coverage - name: Upload code coverage
uses: codecov/codecov-action@v4 uses: codecov/codecov-action@v4
with: with:

View File

@ -25,3 +25,5 @@ CHANGELOG/
*.geojson *.geojson
*-topo.json *-topo.json
storybook-static/ storybook-static/
/.nx/workspace-data

View File

@ -21,7 +21,7 @@
// *********************************************** // ***********************************************
import rison from 'rison'; import rison from 'rison';
import shortid from 'shortid'; import { nanoid } from 'nanoid';
import { interceptChart } from 'cypress/utils'; import { interceptChart } from 'cypress/utils';
import { HEALTH_POP_FORM_DATA_DEFAULTS } from './visualizations/shared.helper'; import { HEALTH_POP_FORM_DATA_DEFAULTS } from './visualizations/shared.helper';
@ -71,7 +71,7 @@ describe('Test explore links', () => {
metrics: ['sum__SP_POP_TOTL'], metrics: ['sum__SP_POP_TOTL'],
groupby: ['country_name'], groupby: ['country_name'],
}; };
const newChartName = `Test chart [${shortid.generate()}]`; const newChartName = `Test chart [${nanoid()}]`;
cy.visitChartByParams(formData); cy.visitChartByParams(formData);
cy.verifySliceSuccess({ waitAlias: '@tableChartData' }); cy.verifySliceSuccess({ waitAlias: '@tableChartData' });
@ -109,8 +109,8 @@ describe('Test explore links', () => {
it('Test chart save as and add to new dashboard', () => { it('Test chart save as and add to new dashboard', () => {
const chartName = 'Growth Rate'; const chartName = 'Growth Rate';
const newChartName = `${chartName} [${shortid.generate()}]`; const newChartName = `${chartName} [${nanoid()}]`;
const dashboardTitle = `Test dashboard [${shortid.generate()}]`; const dashboardTitle = `Test dashboard [${nanoid()}]`;
cy.visitChartByName(chartName); cy.visitChartByName(chartName);
cy.verifySliceSuccess({ waitAlias: '@chartData' }); cy.verifySliceSuccess({ waitAlias: '@chartData' });

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
import * as shortid from 'shortid'; import { nanoid } from 'nanoid';
import { selectResultsTab, assertSQLLabResultsAreEqual } from './sqllab.helper'; import { selectResultsTab, assertSQLLabResultsAreEqual } from './sqllab.helper';
function parseClockStr(node: JQuery) { function parseClockStr(node: JQuery) {
@ -86,7 +86,7 @@ describe('SqlLab query panel', () => {
const query = const query =
'SELECT ds, gender, name, num FROM main.birth_names ORDER BY name LIMIT 3'; 'SELECT ds, gender, name, num FROM main.birth_names ORDER BY name LIMIT 3';
const savedQueryTitle = `CYPRESS TEST QUERY ${shortid.generate()}`; const savedQueryTitle = `CYPRESS TEST QUERY ${nanoid()}`;
// we will assert that the results of the query we save, and the saved query are the same // we will assert that the results of the query we save, and the saved query are the same
let initialResultsTable: HTMLElement | null = null; let initialResultsTable: HTMLElement | null = null;

View File

@ -15,10 +15,10 @@
"brace": "^0.11.1", "brace": "^0.11.1",
"cy-verify-downloads": "^0.1.6", "cy-verify-downloads": "^0.1.6",
"cypress-fail-on-console-error": "^4.0.3", "cypress-fail-on-console-error": "^4.0.3",
"nanoid": "^5.0.7",
"querystringify": "^2.2.0", "querystringify": "^2.2.0",
"react-dom": "^16.13.0", "react-dom": "^16.13.0",
"rison": "^0.1.1", "rison": "^0.1.1"
"shortid": "^2.2.15"
}, },
"devDependencies": { "devDependencies": {
"@types/querystringify": "^2.0.0", "@types/querystringify": "^2.0.0",
@ -8019,9 +8019,22 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
}, },
"node_modules/nanoid": { "node_modules/nanoid": {
"version": "2.1.11", "version": "5.0.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz",
"integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==" "integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"bin": {
"nanoid": "bin/nanoid.js"
},
"engines": {
"node": "^18 || >=20"
}
}, },
"node_modules/natural-compare": { "node_modules/natural-compare": {
"version": "1.4.0", "version": "1.4.0",
@ -9258,14 +9271,6 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/shortid": {
"version": "2.2.16",
"resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.16.tgz",
"integrity": "sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g==",
"dependencies": {
"nanoid": "^2.1.0"
}
},
"node_modules/side-channel": { "node_modules/side-channel": {
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
@ -16471,9 +16476,9 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
}, },
"nanoid": { "nanoid": {
"version": "2.1.11", "version": "5.0.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz",
"integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==" "integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ=="
}, },
"natural-compare": { "natural-compare": {
"version": "1.4.0", "version": "1.4.0",
@ -17404,14 +17409,6 @@
"resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz",
"integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==" "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA=="
}, },
"shortid": {
"version": "2.2.16",
"resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.16.tgz",
"integrity": "sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g==",
"requires": {
"nanoid": "^2.1.0"
}
},
"side-channel": { "side-channel": {
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",

View File

@ -25,7 +25,7 @@
"querystringify": "^2.2.0", "querystringify": "^2.2.0",
"react-dom": "^16.13.0", "react-dom": "^16.13.0",
"rison": "^0.1.1", "rison": "^0.1.1",
"shortid": "^2.2.15" "nanoid": "^5.0.7"
}, },
"devDependencies": { "devDependencies": {
"@types/querystringify": "^2.0.0", "@types/querystringify": "^2.0.0",

View File

@ -56,7 +56,7 @@ module.exports = {
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'], moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'],
snapshotSerializers: ['@emotion/jest/enzyme-serializer'], snapshotSerializers: ['@emotion/jest/enzyme-serializer'],
transformIgnorePatterns: [ transformIgnorePatterns: [
'node_modules/(?!d3-(interpolate|color)|remark-gfm|markdown-table|micromark-*.|decode-named-character-reference|character-entities|mdast-util-*.|unist-util-*.|ccount|escape-string-regexp)', 'node_modules/(?!d3-(interpolate|color)|remark-gfm|markdown-table|micromark-*.|decode-named-character-reference|character-entities|mdast-util-*.|unist-util-*.|ccount|escape-string-regexp|nanoid)',
], ],
globals: { globals: {
__DEV__: true, __DEV__: true,

View File

@ -1,8 +1,6 @@
{ {
"lerna": "3.2.1",
"npmClient": "npm", "npmClient": "npm",
"packages": ["packages/*", "plugins/*", "src/setup/*"], "packages": ["packages/*", "plugins/*", "src/setup/*"],
"useWorkspaces": true,
"version": "0.18.25", "version": "0.18.25",
"ignoreChanges": [ "ignoreChanges": [
"**/*.md", "**/*.md",
@ -19,5 +17,6 @@
"message": "chore(superset-ui): publish %s", "message": "chore(superset-ui): publish %s",
"exact": true "exact": true
} }
} },
"$schema": "node_modules/lerna/schemas/lerna-schema.json"
} }

File diff suppressed because it is too large Load Diff

View File

@ -83,7 +83,8 @@
"@emotion/cache": "^11.4.0", "@emotion/cache": "^11.4.0",
"@emotion/react": "^11.4.1", "@emotion/react": "^11.4.1",
"@emotion/styled": "^11.3.0", "@emotion/styled": "^11.3.0",
"@fontsource/inter": "^4.0.0", "@fontsource/fira-code": "^5.0.18",
"@fontsource/inter": "^5.0.18",
"@reduxjs/toolkit": "^1.9.3", "@reduxjs/toolkit": "^1.9.3",
"@scarf/scarf": "^1.3.0", "@scarf/scarf": "^1.3.0",
"@superset-ui/chart-controls": "file:./packages/superset-ui-chart-controls", "@superset-ui/chart-controls": "file:./packages/superset-ui-chart-controls",
@ -135,7 +136,6 @@
"dom-to-pdf": "^0.3.1", "dom-to-pdf": "^0.3.1",
"emotion-rgba": "0.0.12", "emotion-rgba": "0.0.12",
"fast-glob": "^3.2.7", "fast-glob": "^3.2.7",
"fontsource-fira-code": "^4.0.0",
"fs-extra": "^10.0.0", "fs-extra": "^10.0.0",
"fuse.js": "^7.0.0", "fuse.js": "^7.0.0",
"geolib": "^2.0.24", "geolib": "^2.0.24",
@ -199,7 +199,7 @@
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"rison": "^0.1.1", "rison": "^0.1.1",
"scroll-into-view-if-needed": "^3.1.0", "scroll-into-view-if-needed": "^3.1.0",
"shortid": "^2.2.16", "nanoid": "^5.0.7",
"tinycolor2": "^1.4.2", "tinycolor2": "^1.4.2",
"urijs": "^1.19.8", "urijs": "^1.19.8",
"use-event-callback": "^0.1.0", "use-event-callback": "^0.1.0",
@ -322,7 +322,7 @@
"jest-html-reporter": "^3.10.2", "jest-html-reporter": "^3.10.2",
"jest-websocket-mock": "^2.5.0", "jest-websocket-mock": "^2.5.0",
"jsdom": "^24.0.0", "jsdom": "^24.0.0",
"lerna": "^6.6.2", "lerna": "^8.1.5",
"less": "^4.2.0", "less": "^4.2.0",
"less-loader": "^10.2.0", "less-loader": "^10.2.0",
"mini-css-extract-plugin": "^2.7.6", "mini-css-extract-plugin": "^2.7.6",

View File

@ -0,0 +1,25 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
{
"settings": {
"import/resolver": {
"typescript": {}
}
}
}

View File

@ -17,13 +17,13 @@
* under the License. * under the License.
*/ */
/* eslint-disable sort-keys */ import chalk from 'chalk';
import { dirname, resolve } from 'path';
import { fileURLToPath } from 'url';
import yosay from 'yosay';
import Generator from 'yeoman-generator';
const Generator = require('yeoman-generator'); export default class extends Generator {
const chalk = require('chalk');
const yosay = require('yosay');
module.exports = class extends Generator {
async prompting() { async prompting() {
// Have Yeoman greet the user. // Have Yeoman greet the user.
this.log( this.log(
@ -33,7 +33,10 @@ module.exports = class extends Generator {
this.option('skipInstall'); this.option('skipInstall');
} }
configuring() { async configuring() {
this.composeWith(require.resolve(`../plugin-chart`)); const generatorDirname = dirname(fileURLToPath(import.meta.url));
await this.composeWith(
resolve(generatorDirname, `../plugin-chart/index.js`),
);
} }
}; }

View File

@ -19,17 +19,10 @@
/* eslint-disable sort-keys */ /* eslint-disable sort-keys */
const Generator = require('yeoman-generator'); import Generator from 'yeoman-generator';
// eslint-disable-next-line lodash/import-scope import { kebabCase, camelCase, startCase, upperFirst } from 'lodash-es';
const kebabCase = require('lodash/kebabCase');
// eslint-disable-next-line lodash/import-scope
const startCase = require('lodash/startCase');
// eslint-disable-next-line lodash/import-scope
const camelCase = require('lodash/camelCase');
// eslint-disable-next-line lodash/import-scope
const upperFirst = require('lodash/upperFirst');
module.exports = class extends Generator { export default class extends Generator {
async prompting() { async prompting() {
this.option('skipInstall'); this.option('skipInstall');
@ -121,4 +114,4 @@ module.exports = class extends Generator {
this.fs.copy(this.templatePath(file), this.destinationPath(file)); this.fs.copy(this.templatePath(file), this.destinationPath(file));
}); });
} }
}; }

View File

@ -17,8 +17,9 @@
* under the License. * under the License.
*/ */
module.exports = { export default {
displayName: 'generator-superset', displayName: 'generator-superset',
testRegex: 'test\\/.*\\.test\\.[jt]sx?$', testRegex: 'test\\/.*\\.test\\.[jt]sx?$',
testEnvironment: 'node', testEnvironment: 'node',
transform: {},
}; };

View File

@ -19,23 +19,29 @@
}, },
"license": "Apache-2.0", "license": "Apache-2.0",
"author": "Superset", "author": "Superset",
"type": "module",
"main": "generators/index.js", "main": "generators/index.js",
"files": [ "files": [
"generators" "generators"
], ],
"scripts": {
"test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest"
},
"dependencies": { "dependencies": {
"chalk": "^4.0.0", "chalk": "^5.3.0",
"lodash": "^4.17.21", "lodash-es": "^4.17.21",
"yeoman-generator": "^5.7.0", "yeoman-generator": "^7.3.2",
"yosay": "^2.0.2" "yosay": "^3.0.0"
}, },
"devDependencies": { "devDependencies": {
"cross-env": "^5.2.1",
"fs-extra": "^11.2.0", "fs-extra": "^11.2.0",
"yeoman-assert": "^3.1.1", "yeoman-test": "^8.3.0",
"yeoman-test": "^6.2.0" "jest": "^29.7.0"
}, },
"engines": { "engines": {
"npm": ">= 4.0.0" "npm": ">= 4.0.0",
"node": ">= 18.0.0"
}, },
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"

View File

@ -17,22 +17,18 @@
* under the License. * under the License.
*/ */
const assert = require('yeoman-assert'); import helpers, { result } from 'yeoman-test';
const helpers = require('yeoman-test'); import appModule from '../generators/app';
const appModule = require('../generators/app');
test('generator-superset:app:creates files', () => test('generator-superset:app:creates files', async () => {
helpers await helpers.run(appModule).withPrompts({
.run(appModule) subgenerator: 'package',
.withPrompts({ name: 'my-package',
subgenerator: 'package', });
name: 'my-package', result.assertFile([
}) 'package.json',
.then(function () { 'README.md',
assert.file([ 'src/index.ts',
'package.json', 'test/index.test.ts',
'README.md', ]);
'src/index.ts', });
'test/index.test.ts',
]);
}));

View File

@ -17,19 +17,22 @@
* under the License. * under the License.
*/ */
/* eslint-env node */ import { dirname, join } from 'path';
const path = require('path'); import helpers, { result } from 'yeoman-test';
const assert = require('yeoman-assert'); import { copySync } from 'fs-extra/esm';
const helpers = require('yeoman-test'); import { fileURLToPath } from 'url';
const fs = require('fs-extra'); import pluginChartModule from '../generators/plugin-chart';
const pluginChartModule = require('../generators/plugin-chart');
test('generator-superset:plugin-chart:creates files', () => test('generator-superset:plugin-chart:creates files', async () => {
helpers await helpers
.run(pluginChartModule) .run(pluginChartModule)
.inTmpDir(function (dir) { .onTargetDirectory(dir => {
// `dir` is the path to the new temporary directory // `dir` is the path to the new temporary directory
fs.copySync(path.join(__dirname, '../generators/plugin-chart'), dir); const generatorDirname = dirname(fileURLToPath(import.meta.url));
copySync(
join(generatorDirname, '../generators/plugin-chart/templates'),
join(dir, 'unknown/templates'),
);
}) })
.withPrompts({ .withPrompts({
packageName: 'cold-map', packageName: 'cold-map',
@ -37,25 +40,25 @@ test('generator-superset:plugin-chart:creates files', () =>
componentType: 'function', componentType: 'function',
chartType: 'regular', chartType: 'regular',
}) })
.withOptions({ skipInstall: true }) .withOptions({ skipInstall: true });
.then(function () {
assert.file([ result.assertFile([
'.gitignore', '.gitignore',
'babel.config.js', 'babel.config.js',
'jest.config.js', 'jest.config.js',
'package.json', 'package.json',
'README.md', 'README.md',
'src/plugin/buildQuery.ts', 'src/plugin/buildQuery.ts',
'src/plugin/controlPanel.ts', 'src/plugin/controlPanel.ts',
'src/plugin/index.ts', 'src/plugin/index.ts',
'src/plugin/transformProps.ts', 'src/plugin/transformProps.ts',
'src/ColdMap.tsx', 'src/ColdMap.tsx',
'src/index.ts', 'src/index.ts',
'test/index.test.ts', 'test/index.test.ts',
'test/__mocks__/mockExportString.js', 'test/__mocks__/mockExportString.js',
'test/plugin/buildQuery.test.ts', 'test/plugin/buildQuery.test.ts',
'test/plugin/transformProps.test.ts', 'test/plugin/transformProps.test.ts',
'types/external.d.ts', 'types/external.d.ts',
'src/images/thumbnail.png', 'src/images/thumbnail.png',
]); ]);
})); });

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
import shortid from 'shortid'; import { nanoid } from 'nanoid';
import rison from 'rison'; import rison from 'rison';
import { import {
FeatureFlag, FeatureFlag,
@ -239,7 +239,7 @@ export function clearInactiveQueries(interval) {
export function startQuery(query) { export function startQuery(query) {
Object.assign(query, { Object.assign(query, {
id: query.id ? query.id : shortid.generate(), id: query.id ? query.id : nanoid(11),
progress: 0, progress: 0,
startDttm: now(), startDttm: now(),
state: query.runAsync ? 'pending' : 'running', state: query.runAsync ? 'pending' : 'running',
@ -404,7 +404,7 @@ export function runQueryFromSqlEditor(
export function reRunQuery(query) { export function reRunQuery(query) {
// run Query with a new id // run Query with a new id
return function (dispatch) { return function (dispatch) {
dispatch(runQuery({ ...query, id: shortid.generate() })); dispatch(runQuery({ ...query, id: nanoid(11) }));
}; };
} }
@ -534,7 +534,7 @@ export function syncQueryEditor(queryEditor) {
export function addQueryEditor(queryEditor) { export function addQueryEditor(queryEditor) {
const newQueryEditor = { const newQueryEditor = {
...queryEditor, ...queryEditor,
id: shortid.generate().toString(), id: nanoid(11),
loaded: true, loaded: true,
inLocalStorage: true, inLocalStorage: true,
}; };
@ -942,7 +942,7 @@ export function addTable(queryEditor, tableName, catalogName, schemaName) {
mergeTable( mergeTable(
{ {
...table, ...table,
id: shortid.generate(), id: nanoid(11),
expanded: true, expanded: true,
}, },
null, null,
@ -962,7 +962,7 @@ export function runTablePreviewQuery(newTable) {
if (database && !database.disable_data_preview) { if (database && !database.disable_data_preview) {
const dataPreviewQuery = { const dataPreviewQuery = {
id: shortid.generate(), id: nanoid(11),
dbId, dbId,
catalog, catalog,
schema, schema,
@ -1039,7 +1039,7 @@ export function changeDataPreviewId(oldQueryId, newQuery) {
export function reFetchQueryResults(query) { export function reFetchQueryResults(query) {
return function (dispatch) { return function (dispatch) {
const newQuery = { const newQuery = {
id: shortid.generate(), id: nanoid(),
dbId: query.dbId, dbId: query.dbId,
sql: query.sql, sql: query.sql,
tableName: query.tableName, tableName: query.tableName,

View File

@ -20,7 +20,6 @@ import sinon from 'sinon';
import fetchMock from 'fetch-mock'; import fetchMock from 'fetch-mock';
import configureMockStore from 'redux-mock-store'; import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk'; import thunk from 'redux-thunk';
import shortid from 'shortid';
import { waitFor } from '@testing-library/react'; import { waitFor } from '@testing-library/react';
import * as uiCore from '@superset-ui/core'; import * as uiCore from '@superset-ui/core';
import * as actions from 'src/SqlLab/actions/sqlLab'; import * as actions from 'src/SqlLab/actions/sqlLab';
@ -35,6 +34,14 @@ import {
const middlewares = [thunk]; const middlewares = [thunk];
const mockStore = configureMockStore(middlewares); const mockStore = configureMockStore(middlewares);
jest.mock('nanoid', () => ({
nanoid: () => 'abcd',
}));
afterAll(() => {
jest.resetAllMocks();
});
describe('getUpToDateQuery', () => { describe('getUpToDateQuery', () => {
test('should return the up to date query editor state', () => { test('should return the up to date query editor state', () => {
const outOfUpdatedQueryEditor = { const outOfUpdatedQueryEditor = {
@ -347,14 +354,6 @@ describe('async actions', () => {
}); });
describe('reRunQuery', () => { describe('reRunQuery', () => {
let stub;
beforeEach(() => {
stub = sinon.stub(shortid, 'generate').returns('abcd');
});
afterEach(() => {
stub.restore();
});
it('creates new query with a new id', () => { it('creates new query with a new id', () => {
const id = 'id'; const id = 'id';
const state = { const state = {
@ -412,14 +411,6 @@ describe('async actions', () => {
}); });
describe('cloneQueryToNewTab', () => { describe('cloneQueryToNewTab', () => {
let stub;
beforeEach(() => {
stub = sinon.stub(shortid, 'generate').returns('abcd');
});
afterEach(() => {
stub.restore();
});
it('creates new query editor', () => { it('creates new query editor', () => {
expect.assertions(1); expect.assertions(1);
@ -462,14 +453,6 @@ describe('async actions', () => {
}); });
describe('addQueryEditor', () => { describe('addQueryEditor', () => {
let stub;
beforeEach(() => {
stub = sinon.stub(shortid, 'generate').returns('abcd');
});
afterEach(() => {
stub.restore();
});
it('creates new query editor', () => { it('creates new query editor', () => {
expect.assertions(1); expect.assertions(1);
@ -577,14 +560,6 @@ describe('async actions', () => {
afterEach(fetchMock.resetHistory); afterEach(fetchMock.resetHistory);
describe('addQueryEditor', () => { describe('addQueryEditor', () => {
let stub;
beforeEach(() => {
stub = sinon.stub(shortid, 'generate').returns('abcd');
});
afterEach(() => {
stub.restore();
});
it('creates the tab state in the local storage', () => { it('creates the tab state in the local storage', () => {
expect.assertions(2); expect.assertions(2);

View File

@ -31,7 +31,7 @@ import { pick } from 'lodash';
import ButtonGroup from 'src/components/ButtonGroup'; import ButtonGroup from 'src/components/ButtonGroup';
import Alert from 'src/components/Alert'; import Alert from 'src/components/Alert';
import Button from 'src/components/Button'; import Button from 'src/components/Button';
import shortid from 'shortid'; import { nanoid } from 'nanoid';
import { import {
QueryState, QueryState,
styled, styled,
@ -250,7 +250,7 @@ const ResultSet = ({
const popSelectStar = (tempSchema: string | null, tempTable: string) => { const popSelectStar = (tempSchema: string | null, tempTable: string) => {
const qe = { const qe = {
id: shortid.generate(), id: nanoid(11),
name: tempTable, name: tempTable,
autorun: false, autorun: false,
dbId: query.dbId, dbId: query.dbId,

View File

@ -18,7 +18,7 @@
*/ */
import { createRef, useMemo } from 'react'; import { createRef, useMemo } from 'react';
import { shallowEqual, useDispatch, useSelector } from 'react-redux'; import { shallowEqual, useDispatch, useSelector } from 'react-redux';
import shortid from 'shortid'; import { nanoid } from 'nanoid';
import Tabs from 'src/components/Tabs'; import Tabs from 'src/components/Tabs';
import { styled, t } from '@superset-ui/core'; import { styled, t } from '@superset-ui/core';
@ -139,7 +139,7 @@ const SouthPane = ({
activeKey={activeSouthPaneTab} activeKey={activeSouthPaneTab}
className="SouthPaneTabs" className="SouthPaneTabs"
onChange={switchTab} onChange={switchTab}
id={shortid.generate()} id={nanoid(11)}
fullWidth={false} fullWidth={false}
animated={false} animated={false}
> >

View File

@ -28,6 +28,6 @@
@import '~@fontsource/inter/600.css'; @import '~@fontsource/inter/600.css';
/******************************* Fira Code ********************************/ /******************************* Fira Code ********************************/
@import '~fontsource-fira-code/400.css'; @import '~@fontsource/fira-code/400.css';
@import '~fontsource-fira-code/500.css'; @import '~@fontsource/fira-code/500.css';
@import '~fontsource-fira-code/600.css'; @import '~@fontsource/fira-code/600.css';

View File

@ -23,7 +23,7 @@ import {
PureComponent, PureComponent,
} from 'react'; } from 'react';
import shortid from 'shortid'; import { nanoid } from 'nanoid';
import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls'; import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls';
import { t, styled } from '@superset-ui/core'; import { t, styled } from '@superset-ui/core';
@ -86,7 +86,7 @@ function createCollectionArray(collection: object) {
function createKeyedCollection(arr: Array<object>) { function createKeyedCollection(arr: Array<object>) {
const collectionArray = arr.map((o: any) => ({ const collectionArray = arr.map((o: any) => ({
...o, ...o,
id: o.id || shortid.generate(), id: o.id || nanoid(),
})); }));
const collection = {}; const collection = {};
@ -209,7 +209,7 @@ export default class CRUDCollection extends PureComponent<
if (this.props.itemGenerator) { if (this.props.itemGenerator) {
let newItem = this.props.itemGenerator(); let newItem = this.props.itemGenerator();
if (!newItem.id) { if (!newItem.id) {
newItem = { ...newItem, id: shortid.generate() }; newItem = { ...newItem, id: nanoid() };
} }
this.changeCollection(this.state.collection, newItem); this.changeCollection(this.state.collection, newItem);
} }

View File

@ -23,7 +23,7 @@ import { Radio } from 'src/components/Radio';
import Card from 'src/components/Card'; import Card from 'src/components/Card';
import Alert from 'src/components/Alert'; import Alert from 'src/components/Alert';
import Badge from 'src/components/Badge'; import Badge from 'src/components/Badge';
import shortid from 'shortid'; import { nanoid } from 'nanoid';
import { import {
css, css,
isFeatureEnabled, isFeatureEnabled,
@ -718,7 +718,7 @@ class DatasourceEditor extends PureComponent {
if (!currentCol) { if (!currentCol) {
// new column // new column
finalColumns.push({ finalColumns.push({
id: shortid.generate(), id: nanoid(),
column_name: col.column_name, column_name: col.column_name,
type: col.type, type: col.type,
groupby: true, groupby: true,

View File

@ -16,13 +16,13 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
import shortid from 'shortid'; import { nanoid } from 'nanoid';
import { ToastType, ToastMeta } from './types'; import { ToastType, ToastMeta } from './types';
type ToastOptions = Partial<Omit<ToastMeta, 'id' | 'toastType' | 'text'>>; type ToastOptions = Partial<Omit<ToastMeta, 'id' | 'toastType' | 'text'>>;
export function getToastUuid(type: ToastType) { export function getToastUuid(type: ToastType) {
return `${type}-${shortid.generate()}`; return `${type}-${nanoid()}`;
} }
export const ADD_TOAST = 'ADD_TOAST'; export const ADD_TOAST = 'ADD_TOAST';

View File

@ -17,7 +17,7 @@
* under the License. * under the License.
*/ */
import { FormInstance } from 'src/components'; import { FormInstance } from 'src/components';
import shortid from 'shortid'; import { nanoid } from 'nanoid';
import { getInitialDataMask } from 'src/dataMask/reducer'; import { getInitialDataMask } from 'src/dataMask/reducer';
import { import {
Filter, Filter,
@ -197,7 +197,7 @@ export const generateFilterId = (type: NativeFilterType) => {
type === NativeFilterType.NativeFilter type === NativeFilterType.NativeFilter
? NATIVE_FILTER_PREFIX ? NATIVE_FILTER_PREFIX
: NATIVE_FILTER_DIVIDER_PREFIX; : NATIVE_FILTER_DIVIDER_PREFIX;
return `${prefix}${shortid.generate()}`; return `${prefix}${nanoid()}`;
}; };
export const getFilterIds = (config: FilterConfiguration) => export const getFilterIds = (config: FilterConfiguration) =>

View File

@ -42,7 +42,7 @@ import {
} from 'src/dashboard/components/nativeFilters/FilterBar/keyValue'; } from 'src/dashboard/components/nativeFilters/FilterBar/keyValue';
import DashboardContainer from 'src/dashboard/containers/Dashboard'; import DashboardContainer from 'src/dashboard/containers/Dashboard';
import shortid from 'shortid'; import { nanoid } from 'nanoid';
import { RootState } from '../types'; import { RootState } from '../types';
import { import {
chartContextMenuStyles, chartContextMenuStyles,
@ -76,7 +76,7 @@ export const DashboardPage: FC<PageProps> = ({ idOrSlug }: PageProps) => {
const theme = useTheme(); const theme = useTheme();
const dispatch = useDispatch(); const dispatch = useDispatch();
const history = useHistory(); const history = useHistory();
const dashboardPageId = useMemo(() => shortid.generate(), []); const dashboardPageId = useMemo(() => nanoid(), []);
const hasDashboardInfoInitiated = useSelector<RootState, Boolean>( const hasDashboardInfoInitiated = useSelector<RootState, Boolean>(
({ dashboardInfo }) => ({ dashboardInfo }) =>
dashboardInfo && Object.keys(dashboardInfo).length > 0, dashboardInfo && Object.keys(dashboardInfo).length > 0,

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
import shortid from 'shortid'; import { nanoid } from 'nanoid';
import { t } from '@superset-ui/core'; import { t } from '@superset-ui/core';
import { import {
@ -65,7 +65,7 @@ const typeToDefaultMetaData = {
}; };
function uuid(type) { function uuid(type) {
return `${type}-${shortid.generate()}`; return `${type}-${nanoid()}`;
} }
export default function entityFactory(type, meta, parents = []) { export default function entityFactory(type, meta, parents = []) {

View File

@ -19,7 +19,7 @@
import { Component } from 'react'; import { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { List } from 'src/components'; import { List } from 'src/components';
import shortid from 'shortid'; import { nanoid } from 'nanoid';
import { t, withTheme } from '@superset-ui/core'; import { t, withTheme } from '@superset-ui/core';
import { import {
SortableContainer, SortableContainer,
@ -57,7 +57,7 @@ const defaultProps = {
description: null, description: null,
onChange: () => {}, onChange: () => {},
placeholder: t('Empty collection'), placeholder: t('Empty collection'),
itemGenerator: () => ({ key: shortid.generate() }), itemGenerator: () => ({ key: nanoid(11) }),
keyAccessor: o => o.key, keyAccessor: o => o.key,
value: [], value: [],
addTooltip: t('Add an item'), addTooltip: t('Add an item'),

View File

@ -17,7 +17,7 @@
* under the License. * under the License.
*/ */
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import shortid from 'shortid'; import { nanoid } from 'nanoid';
import { BroadcastChannel } from 'broadcast-channel'; import { BroadcastChannel } from 'broadcast-channel';
interface TabIdChannelMessage { interface TabIdChannelMessage {
@ -43,7 +43,7 @@ export function useTabId() {
useEffect(() => { useEffect(() => {
if (!isStorageAvailable()) { if (!isStorageAvailable()) {
if (!tabId) { if (!tabId) {
setTabId(shortid.generate()); setTabId(nanoid());
} }
return; return;
} }

View File

@ -18,7 +18,7 @@
*/ */
/* eslint-disable camelcase */ /* eslint-disable camelcase */
/* eslint prefer-const: 2 */ /* eslint prefer-const: 2 */
import shortid from 'shortid'; import { nanoid } from 'nanoid';
import { SupersetClient } from '@superset-ui/core'; import { SupersetClient } from '@superset-ui/core';
import { safeStringify } from '../utils/safeStringify'; import { safeStringify } from '../utils/safeStringify';
@ -117,7 +117,7 @@ const loggerMiddleware = store => next => action => {
trigger_event: lastEventId, trigger_event: lastEventId,
}; };
} else { } else {
lastEventId = shortid.generate(); lastEventId = nanoid();
eventData = { eventData = {
...eventData, ...eventData,
event_type: 'user', event_type: 'user',

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
import shortid from 'shortid'; import { nanoid } from 'nanoid';
import { compose } from 'redux'; import { compose } from 'redux';
import persistState, { StorageAdapter } from 'redux-localstorage'; import persistState, { StorageAdapter } from 'redux-localstorage';
import { import {
@ -38,7 +38,7 @@ export function addToObject(
const copiedObject = { ...obj }; const copiedObject = { ...obj };
if (!copiedObject.id) { if (!copiedObject.id) {
copiedObject.id = shortid.generate(); copiedObject.id = nanoid();
} }
newObject[copiedObject.id] = copiedObject; newObject[copiedObject.id] = copiedObject;
return { ...state, [arrKey]: newObject }; return { ...state, [arrKey]: newObject };
@ -108,7 +108,7 @@ export function addToArr(
) { ) {
const newObj = { ...obj }; const newObj = { ...obj };
if (!newObj.id) { if (!newObj.id) {
newObj.id = shortid.generate(); newObj.id = nanoid();
} }
const newState = {}; const newState = {};
if (prepend) { if (prepend) {
@ -129,7 +129,7 @@ export function extendArr(
newArr.forEach(el => { newArr.forEach(el => {
if (!el.id) { if (!el.id) {
/* eslint-disable no-param-reassign */ /* eslint-disable no-param-reassign */
el.id = shortid.generate(); el.id = nanoid();
} }
}); });
const newState = {}; const newState = {};

View File

@ -18,7 +18,7 @@
*/ */
import parseCookie from 'src/utils/parseCookie'; import parseCookie from 'src/utils/parseCookie';
import rison from 'rison'; import rison from 'rison';
import shortid from 'shortid'; import { nanoid } from 'nanoid';
export default function handleResourceExport( export default function handleResourceExport(
resource: string, resource: string,
@ -26,7 +26,7 @@ export default function handleResourceExport(
done: () => void, done: () => void,
interval = 200, interval = 200,
): void { ): void {
const token = shortid.generate(); const token = nanoid();
const url = `/api/v1/${resource}/export/?q=${rison.encode( const url = `/api/v1/${resource}/export/?q=${rison.encode(
ids, ids,
)}&token=${token}`; )}&token=${token}`;

View File

@ -16,14 +16,14 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
import shortid from 'shortid'; import { nanoid } from 'nanoid';
export function addToObject(state, arrKey, obj) { export function addToObject(state, arrKey, obj) {
const newObject = { ...state[arrKey] }; const newObject = { ...state[arrKey] };
const copiedObject = { ...obj }; const copiedObject = { ...obj };
if (!copiedObject.id) { if (!copiedObject.id) {
copiedObject.id = shortid.generate(); copiedObject.id = nanoid();
} }
newObject[copiedObject.id] = copiedObject; newObject[copiedObject.id] = copiedObject;
return { ...state, [arrKey]: newObject }; return { ...state, [arrKey]: newObject };
@ -63,7 +63,7 @@ export function removeFromArr(state, arrKey, obj, idKey = 'id') {
export function addToArr(state, arrKey, obj) { export function addToArr(state, arrKey, obj) {
const newObj = { ...obj }; const newObj = { ...obj };
if (!newObj.id) { if (!newObj.id) {
newObj.id = shortid.generate(); newObj.id = nanoid();
} }
const newState = {}; const newState = {};
newState[arrKey] = [...state[arrKey], newObj]; newState[arrKey] = [...state[arrKey], newObj];

View File

@ -47,7 +47,7 @@ import {
DatasourcesActionPayload, DatasourcesActionPayload,
DatasourcesAction, DatasourcesAction,
} from 'src/dashboard/actions/datasources'; } from 'src/dashboard/actions/datasources';
import shortid from 'shortid'; import { nanoid } from 'nanoid';
import { import {
BootstrapUser, BootstrapUser,
UndefinedUser, UndefinedUser,
@ -126,7 +126,7 @@ const reducers = {
messageToasts: messageToastReducer, messageToasts: messageToastReducer,
common: noopReducer(bootstrapData.common), common: noopReducer(bootstrapData.common),
user: userReducer, user: userReducer,
impressionId: noopReducer(shortid.generate()), impressionId: noopReducer(nanoid()),
charts, charts,
datasources: CombinedDatasourceReducers, datasources: CombinedDatasourceReducers,
dashboardInfo, dashboardInfo,