diff --git a/superset-frontend/packages/generator-superset/generators/app/index.js b/superset-frontend/packages/generator-superset/generators/app/index.js index 1bf2f21b46717..88754cc6a1f90 100644 --- a/superset-frontend/packages/generator-superset/generators/app/index.js +++ b/superset-frontend/packages/generator-superset/generators/app/index.js @@ -27,36 +27,13 @@ module.exports = class extends Generator { async prompting() { // Have Yeoman greet the user. this.log( - yosay(`Welcome to the rad ${chalk.red('generator-superset')} generator!`), + yosay(`Welcome to the ${chalk.red('generator-superset')} generator!`), ); this.option('skipInstall'); - - this.answers = await this.prompt([ - { - type: 'list', - name: 'subgenerator', - message: 'What do you want to do?', - choices: [ - { - name: 'Create superset-ui core package', - value: 'package', - }, - { - name: 'Create superset-ui chart plugin package', - value: 'plugin-chart', - }, - ], - }, - ]); } configuring() { - // Redirect the default 'app' generator - // to 'package' subgenerator - // until there are multiple subgenerators - // then this can be changed into a menu to select - // subgenerator. - this.composeWith(require.resolve(`../${this.answers.subgenerator}`)); + this.composeWith(require.resolve(`../plugin-chart`)); } }; diff --git a/superset-frontend/packages/generator-superset/generators/package/index.js b/superset-frontend/packages/generator-superset/generators/package/index.js deleted file mode 100644 index 314d41d0508a7..0000000000000 --- a/superset-frontend/packages/generator-superset/generators/package/index.js +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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. - */ - -/* eslint-disable sort-keys */ - -const Generator = require('yeoman-generator'); -const _ = require('lodash'); - -module.exports = class extends Generator { - async prompting() { - this.option('skipInstall'); - - this.answers = await this.prompt([ - { - type: 'input', - name: 'name', - message: 'Package name:', - default: _.kebabCase(this.appname.replace('superset ui', '').trim()), // Default to current folder name - }, - { - type: 'list', - name: 'language', - message: 'Choose language', - default: 'typescript', - choices: [ - { - name: 'typescript', - value: 'typescript', - short: 't', - }, - { - name: 'javascript', - value: 'javascript', - short: 'j', - }, - ], - }, - ]); - } - - writing() { - this.fs.copyTpl( - this.templatePath('_package.json'), - this.destinationPath('package.json'), - this.answers, - ); - this.fs.copyTpl( - this.templatePath('README.md'), - this.destinationPath('README.md'), - this.answers, - ); - const ext = this.answers.language === 'typescript' ? 'ts' : 'js'; - this.fs.copy( - this.templatePath('src/index.txt'), - this.destinationPath(`src/index.${ext}`), - ); - this.fs.copy( - this.templatePath('test/index.txt'), - this.destinationPath(`test/index.test.${ext}`), - ); - } -}; diff --git a/superset-frontend/packages/generator-superset/generators/package/templates/README.md b/superset-frontend/packages/generator-superset/generators/package/templates/README.md deleted file mode 100644 index 6d27caa51cdac..0000000000000 --- a/superset-frontend/packages/generator-superset/generators/package/templates/README.md +++ /dev/null @@ -1,46 +0,0 @@ - - -## @superset-ui/<%= name %> - -[![Version](https://img.shields.io/npm/v/@superset-ui/<%= name -%>.svg?style=flat)](https://img.shields.io/npm/v/@superset-ui/<%= name %>.svg?style=flat) -[![David (path)](https://img.shields.io/david/apache-superset/superset-ui.svg?path=packages%2Fsuperset-ui-<%= -name -%>&style=flat-square)](https://david-dm.org/apache-superset/superset-ui?path=packages/superset-ui-<%= -name %>) - -Description - -#### Example usage - -```js -import { xxx } from '@superset-ui/<%= name %>'; -``` - -#### API - -`fn(args)` - -- Do something - -### Development - -`@data-ui/build-config` is used to manage the build configuration for this package including babel -builds, jest testing, eslint, and prettier. diff --git a/superset-frontend/packages/generator-superset/generators/package/templates/_package.json b/superset-frontend/packages/generator-superset/generators/package/templates/_package.json deleted file mode 100644 index 5948f303d4009..0000000000000 --- a/superset-frontend/packages/generator-superset/generators/package/templates/_package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "@superset-ui/<%= name %>", - "version": "0.0.0", - "description": "Superset UI <%= name %>", - "sideEffects": false, - "main": "lib/index.js", - "module": "esm/index.js", - "files": ["esm", "lib"], - "repository": { - "type": "git", - "url": "git+https://github.com/apache-superset/superset-ui.git" - }, - "keywords": ["superset"], - "author": "Superset", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/apache-superset/superset-ui/issues" - }, - "homepage": "https://github.com/apache-superset/superset-ui#readme", - "publishConfig": { - "access": "public" - } -} diff --git a/superset-frontend/packages/generator-superset/generators/package/templates/src/index.txt b/superset-frontend/packages/generator-superset/generators/package/templates/src/index.txt deleted file mode 100644 index f3d181a859498..0000000000000 --- a/superset-frontend/packages/generator-superset/generators/package/templates/src/index.txt +++ /dev/null @@ -1,2 +0,0 @@ -const x = 1; -export default x; diff --git a/superset-frontend/packages/generator-superset/generators/package/templates/test/index.txt b/superset-frontend/packages/generator-superset/generators/package/templates/test/index.txt deleted file mode 100644 index 457263a03f069..0000000000000 --- a/superset-frontend/packages/generator-superset/generators/package/templates/test/index.txt +++ /dev/null @@ -1,5 +0,0 @@ -describe('My Test', () => { - it('tests something', () => { - expect(1).toEqual(1); - }); -}); diff --git a/superset-frontend/packages/generator-superset/generators/plugin-chart/index.js b/superset-frontend/packages/generator-superset/generators/plugin-chart/index.js index 58f94a84829a5..df76e0c99ee57 100644 --- a/superset-frontend/packages/generator-superset/generators/plugin-chart/index.js +++ b/superset-frontend/packages/generator-superset/generators/plugin-chart/index.js @@ -32,7 +32,9 @@ module.exports = class extends Generator { name: 'packageName', message: 'Package name:', // Default to current folder name - default: _.kebabCase(this.appname.replace('plugin chart', '').trim()), + default: _.kebabCase( + this.appname.replace('superset plugin chart', '').trim(), + ), }, { type: 'input', @@ -40,24 +42,9 @@ module.exports = class extends Generator { message: 'Description:', // Default to current folder name default: _.upperFirst( - _.startCase(this.appname.replace('plugin chart', '').trim()), + _.startCase(this.appname.replace('superset plugin chart', '').trim()), ), }, - { - type: 'list', - name: 'componentType', - message: 'What type of React component would you like?', - choices: [ - { - name: 'Class component', - value: 'class', - }, - { - name: 'Function component (with hooks)', - value: 'function', - }, - ], - }, { type: 'list', name: 'chartType', @@ -73,12 +60,6 @@ module.exports = class extends Generator { }, ], }, - { - type: 'confirm', - name: 'addBadges', - message: "Add superset-ui badges to your plugin's README.md", - default: true, - }, ]); } @@ -96,9 +77,11 @@ module.exports = class extends Generator { }; [ + ['babel.config.erb', 'babel.config.js'], + ['jest.config.erb', 'jest.config.js'], ['package.erb', 'package.json'], - ['tsconfig.json', 'tsconfig.json'], ['README.erb', 'README.md'], + ['tsconfig.json', 'tsconfig.json'], ['src/index.erb', 'src/index.ts'], ['src/plugin/buildQuery.erb', 'src/plugin/buildQuery.ts'], ['src/plugin/controlPanel.erb', 'src/plugin/controlPanel.ts'], @@ -107,6 +90,10 @@ module.exports = class extends Generator { ['src/types.erb', 'src/types.ts'], ['src/MyChart.erb', `src/${packageLabel}.tsx`], ['test/index.erb', 'test/index.test.ts'], + [ + 'test/__mocks__/mockExportString.js', + 'test/__mocks__/mockExportString.js', + ], ['test/plugin/buildQuery.test.erb', 'test/plugin/buildQuery.test.ts'], [ 'test/plugin/transformProps.test.erb', diff --git a/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/README.erb b/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/README.erb index a94fe629c57f3..2a117bbcf2f30 100644 --- a/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/README.erb +++ b/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/README.erb @@ -1,6 +1,4 @@ -## @superset-ui/plugin-chart-<%= packageName %> - -<%if (addBadges) { %>[![Version](https://img.shields.io/npm/v/@superset-ui/plugin-chart-<%= packageName %>.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/plugin-chart-<%= packageName %>)<% } %> +## superset-plugin-chart-<%= packageName %> This plugin provides <%= description %> for Superset. diff --git a/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/babel.config.erb b/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/babel.config.erb new file mode 100644 index 0000000000000..78476f30aa2f0 --- /dev/null +++ b/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/babel.config.erb @@ -0,0 +1,20 @@ +const { getConfig } = require('@airbnb/config-babel'); + +const config = getConfig({ + library: true, + react: true, + next: true, + esm: process.env.BABEL_OUTPUT === 'esm', + node: process.env.NODE_ENV === 'test', + typescript: true, + env: { + targets: { esmodules: true }, + }, +}); + +config.plugins = [ + ['babel-plugin-transform-dev', { evaluate: false }], + ['babel-plugin-typescript-to-proptypes', { loose: true }], + ['@babel/plugin-proposal-class-properties', { loose: true }], +]; +module.exports = config; diff --git a/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/jest.config.erb b/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/jest.config.erb new file mode 100644 index 0000000000000..c7b58cc23fb0e --- /dev/null +++ b/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/jest.config.erb @@ -0,0 +1,6 @@ +module.exports = { + moduleFileExtensions: ['mock.js', 'ts', 'tsx', 'js', 'jsx', 'json', 'node'], + moduleNameMapper: { + '\\.(gif|ttf|eot|png|jpg)$': '/test/__mocks__/mockExportString.js', + }, +}; diff --git a/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/package.erb b/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/package.erb index 3061f92b8774e..389a64825ae13 100644 --- a/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/package.erb +++ b/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/package.erb @@ -1,6 +1,6 @@ { - "name": "@superset-ui/plugin-chart-<%= packageName %>", - "version": "0.0.0", + "name": "superset-plugin-chart-<%= packageName %>", + "version": "0.1.0", "description": "Superset Chart - <%= description %>", "sideEffects": false, "main": "lib/index.js", @@ -9,31 +9,38 @@ "esm", "lib" ], - "repository": { - "type": "git", - "url": "git+https://github.com/apache-superset/superset-ui.git" + "scripts": { + "build": "npm run build-cjs && npm run build-esm && npm run ts-types", + "build-cjs": "babel src --extensions \".ts,.tsx,.js,.jsx\" --copy-files --out-dir lib", + "build-clean": "npm run clean && npm run build", + "build-esm": "BABEL_OUTPUT=esm babel src --extensions \".ts,.tsx,.js,.jsx\" --copy-files --out-dir esm", + "clean": "rm -rf {lib,esm,tsconfig.tsbuildinfo}", + "dev": "webpack --mode=development --color --watch", + "ts-types": "tsc --build", + "test": "jest" }, - "keywords": [ - "superset" - ], "author": "Superset", "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/apache-superset/superset-ui/issues" - }, - "homepage": "https://github.com/apache-superset/superset-ui#readme", "publishConfig": { "access": "public" }, "dependencies": { - "@superset-ui/core": "^0.17.40", - "@superset-ui/chart-controls": "^0.17.41" + "@superset-ui/core": "^0.18.25", + "@superset-ui/chart-controls": "^0.18.25" }, "peerDependencies": { "react": "^16.13.1" }, "devDependencies": { - "@types/jest": "^26.0.0", - "jest": "^26.0.1" + "@airbnb/config-babel": "^2.0.1", + "@babel/cli": "^7.16.0", + "@types/jest": "^26.0.4", + "babel-loader": "^8.2.2", + "clean-webpack-plugin": "^4.0.0", + "jest": "^26.6.3", + "thread-loader": "^3.0.4", + "ts-loader": "^9.2.5", + "typescript": "^4.1.2", + "url-loader": "^4.1.1" } } diff --git a/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/src/MyChart.erb b/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/src/MyChart.erb index a7a6b1500b431..cb9e6204d7ee1 100644 --- a/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/src/MyChart.erb +++ b/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/src/MyChart.erb @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import React, { <%if (componentType == 'class') { %>PureComponent<% } %><%if (componentType == 'function') { %>useEffect<% } %>, createRef } from 'react'; +import React, { useEffect, createRef } from 'react'; import { styled } from '@superset-ui/core'; import { <%= packageLabel %>Props, <%= packageLabel %>StylesProps } from './types'; @@ -50,39 +50,7 @@ const Styles = styled.div<<%= packageLabel %>StylesProps>` * * FormData (your controls!) provided as props by transformProps.ts */ -<%if (componentType == 'class') { %>export default class <%= packageLabel %> extends PureComponent<<%= packageLabel %>Props> { - // Often, you just want to get a hold of the DOM and go nuts. - // Here, you can do that with createRef, and componentDidMount. - - rootElem = createRef(); - - componentDidMount() { - const root = this.rootElem.current as HTMLElement; - console.log('Plugin element', root); - } - - render() { - // height and width are the height and width of the DOM element as it exists in the dashboard. - // There is also a `data` prop, which is, of course, your DATA 🎉 - console.log('Approach 1 props', this.props); - const { data, height, width } = this.props; - - console.log('Plugin props', this.props); - - return ( - -

{this.props.headerText}

-
{JSON.stringify(data, null, 2)}
-
- ); - } -}<% } %><%if (componentType == 'function') { %>export default function <%= packageLabel %>(props: <%= packageLabel %>Props) { +export default function <%= packageLabel %>(props: <%= packageLabel %>Props) { // height and width are the height and width of the DOM element as it exists in the dashboard. // There is also a `data` prop, which is, of course, your DATA 🎉 const { data, height, width } = props; @@ -110,4 +78,4 @@ const Styles = styled.div<<%= packageLabel %>StylesProps>`
${JSON.stringify(data, null, 2)}
); -}<% } %> +} diff --git a/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/test/__mocks__/mockExportString.js b/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/test/__mocks__/mockExportString.js new file mode 100644 index 0000000000000..5b7f1d6da9640 --- /dev/null +++ b/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/test/__mocks__/mockExportString.js @@ -0,0 +1,19 @@ +/** + * 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. + */ +module.exports = 'test-file-stub'; diff --git a/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/test/plugin/buildQuery.test.erb b/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/test/plugin/buildQuery.test.erb index 65411e094efff..4ff3d425c3f40 100644 --- a/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/test/plugin/buildQuery.test.erb +++ b/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/test/plugin/buildQuery.test.erb @@ -29,6 +29,6 @@ describe('<%= packageLabel %> buildQuery', () => { it('should build groupby with series in form data', () => { const queryContext = buildQuery(formData); const [query] = queryContext.queries; - expect(query.groupby).toEqual(['foo']); + expect(query.columns).toEqual(['foo']); }); }); diff --git a/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/tsconfig.json b/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/tsconfig.json index b6bfaa2d98446..5cb0a18b6c941 100644 --- a/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/tsconfig.json +++ b/superset-frontend/packages/generator-superset/generators/plugin-chart/templates/tsconfig.json @@ -1,25 +1,44 @@ { "compilerOptions": { + "allowSyntheticDefaultImports": true, + "declaration": true, "declarationDir": "lib", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "isolatedModules": false, + "jsx": "react", + "lib": [ + "dom", + "esnext" + ], + "module": "esnext", + "moduleResolution": "node", + "noEmitOnError": true, + "noImplicitReturns": true, + "noUnusedLocals": true, "outDir": "lib", - "rootDir": "src" + "pretty": true, + "removeComments": false, + "strict": true, + "target": "es2015", + "useDefineForClassFields": false, + "composite": true, + "declarationMap": true, + "rootDir": "src", + "skipLibCheck": true, + "emitDeclarationOnly": true, + "resolveJsonModule": true, + "types": ["jest"], + "typeRoots": [ + "./node_modules/@types" + ] }, "exclude": [ "lib", "test" ], - "extends": "../../tsconfig.json", "include": [ "src/**/*", - "types/**/*", - "../../types/**/*" - ], - "references": [ - { - "path": "../../packages/superset-ui-chart-controls" - }, - { - "path": "../../packages/superset-ui-core" - } + "types/**/*" ] } diff --git a/superset-frontend/packages/generator-superset/test/package.test.js b/superset-frontend/packages/generator-superset/test/package.test.js deleted file mode 100644 index d98412414dd8e..0000000000000 --- a/superset-frontend/packages/generator-superset/test/package.test.js +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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. - */ - -const path = require('path'); -const assert = require('yeoman-assert'); -const helpers = require('yeoman-test'); -const fs = require('fs-extra'); -const packageModule = require('../generators/package'); - -test('generator-superset:package:creates typescript files', () => - helpers - .run(packageModule) - .inTmpDir(function (dir) { - // `dir` is the path to the new temporary directory - fs.copySync(path.join(__dirname, '../generators/package'), dir); - }) - .withPrompts({ name: 'my-package', language: 'typescript' }) - .withOptions({ skipInstall: true }) - .then(function () { - assert.file([ - 'package.json', - 'README.md', - 'src/index.ts', - 'test/index.test.ts', - ]); - })); - -test('generator-superset:package:creates javascript files', () => - helpers - .run(packageModule) - .inTmpDir(function (dir) { - // `dir` is the path to the new temporary directory - fs.copySync(path.join(__dirname, '../generators/package'), dir); - }) - .withPrompts({ name: 'my-package', language: 'javascript' }) - .withOptions({ skipInstall: true }) - .then(function () { - assert.file([ - 'package.json', - 'README.md', - 'src/index.js', - 'test/index.test.js', - ]); - })); diff --git a/superset-frontend/packages/generator-superset/test/plugin-chart.test.js b/superset-frontend/packages/generator-superset/test/plugin-chart.test.js index c6c04108561e1..d5f5f35f89703 100644 --- a/superset-frontend/packages/generator-superset/test/plugin-chart.test.js +++ b/superset-frontend/packages/generator-superset/test/plugin-chart.test.js @@ -40,6 +40,8 @@ test('generator-superset:plugin-chart:creates files', () => .withOptions({ skipInstall: true }) .then(function () { assert.file([ + 'babel.config.js', + 'jest.config.js', 'package.json', 'README.md', 'src/plugin/buildQuery.ts', @@ -49,6 +51,7 @@ test('generator-superset:plugin-chart:creates files', () => 'src/ColdMap.tsx', 'src/index.ts', 'test/index.test.ts', + 'test/__mocks__/mockExportString.js', 'test/plugin/buildQuery.test.ts', 'test/plugin/transformProps.test.ts', 'types/external.d.ts', diff --git a/superset-frontend/webpack.config.js b/superset-frontend/webpack.config.js index 1d68969d8b4c3..98538dc9bd96d 100644 --- a/superset-frontend/webpack.config.js +++ b/superset-frontend/webpack.config.js @@ -283,7 +283,9 @@ const config = { }, resolve: { modules: [APP_DIR, 'node_modules', ROOT_DIR], - alias: {}, + alias: { + react: path.resolve('./node_modules/react'), + }, extensions: ['.ts', '.tsx', '.js', '.jsx', '.yml'], fallback: { fs: false, @@ -422,7 +424,16 @@ const config = { // find all the symlinked plugins and use their source code for imports Object.entries(packageConfig.dependencies).forEach(([pkg, version]) => { const srcPath = `./node_modules/${pkg}/src`; - if (/^@superset-ui/.test(pkg) && fs.existsSync(srcPath)) { + if (/^superset-plugin-/.test(pkg) && fs.existsSync(srcPath)) { + console.log( + `[Superset External Plugin] Use symlink source for ${pkg} @ ${version}`, + ); + // TODO: remove alias once React has been upgraaded to v. 17 + config.resolve.alias[pkg] = path.resolve( + APP_DIR, + `node_modules/${pkg}/src`, + ); + } else if (/^@superset-ui/.test(pkg) && fs.existsSync(srcPath)) { console.log(`[Superset Plugin] Use symlink source for ${pkg} @ ${version}`); // only allow exact match so imports like `@superset-ui/plugin-name/lib` // and `@superset-ui/plugin-name/esm` can still work.