From 02eee1f9b384581b5468de19d9150efb9ca0e48f Mon Sep 17 00:00:00 2001 From: Frederick Engelhardt Date: Tue, 23 Jun 2020 11:45:51 -0700 Subject: [PATCH 1/8] wip: working prompt library with commander to fire off prompt and create to handle output json --- packages/particle-cli/bin/particle-cli.ts | 9 +- packages/particle-cli/lib/create.ts | 4 +- .../particle-cli/lib/generatePromptOptions.ts | 121 ++++++++++++++++++ packages/particle-cli/package.json | 6 +- 4 files changed, 133 insertions(+), 7 deletions(-) create mode 100644 packages/particle-cli/lib/generatePromptOptions.ts diff --git a/packages/particle-cli/bin/particle-cli.ts b/packages/particle-cli/bin/particle-cli.ts index de5e9e7020..c6ef74aab3 100755 --- a/packages/particle-cli/bin/particle-cli.ts +++ b/packages/particle-cli/bin/particle-cli.ts @@ -1,9 +1,10 @@ #!/usr/bin/env node -const program = require('commander') -// const pkg = require('../package'); // can't do since this is not copied over into dist unless its an import +import program from 'commander' + import pkg from '../package.json' -const create = require('../lib/create') +import { generatePromptOptions } from './../lib/generatePromptOptions' +import create from '../lib/create' /** * Initialize Commander program with version. @@ -16,7 +17,7 @@ program .description('Scaffold your project from a set of prompts.') .action(function () { // @TODO Implement Create Function. - create() + generatePromptOptions().then(create) }) // allow commander to parse `process.argv` diff --git a/packages/particle-cli/lib/create.ts b/packages/particle-cli/lib/create.ts index 805cb848db..1108bc649a 100644 --- a/packages/particle-cli/lib/create.ts +++ b/packages/particle-cli/lib/create.ts @@ -24,8 +24,8 @@ * */ -const create = () => { - console.log('Create Particle Project') +const create = (data: any) => { + console.log('Create Particle Project with the data:', data) return true } diff --git a/packages/particle-cli/lib/generatePromptOptions.ts b/packages/particle-cli/lib/generatePromptOptions.ts new file mode 100644 index 0000000000..b111abd7e9 --- /dev/null +++ b/packages/particle-cli/lib/generatePromptOptions.ts @@ -0,0 +1,121 @@ +import inquirer from 'inquirer' + +const prompt = inquirer.createPromptModule() + +const genericValidate = ({ min, max }: { min: number; max?: number }) => ( + answer: Record[] +) => { + // if (max && answer.length > max){ + + // } + if (answer.length < min || (!max ? false : answer.length > max)) { + return `You must choose a minimum of ${min} option(s)${ + max ? ` and a maximum of ${max} option(s)` : '' + }` + } + return true +} + +/** + * Returns a promise with a json schema + * The JSON schema will be used for the create method to generate files based off of the options selected in the prompt + * Two ways to do this, first way is to have all options selectable, second way is to have all separated options as seperate steps. + */ +const configurationPrompt = () => + prompt([ + { + type: 'checkbox', + message: 'Choose a configuration', + name: 'config', + choices: ['default', 'custom'], + validate: genericValidate({ min: 1, max: 1 }), + }, + ]) + +export const generatePromptOptions = async () => { + const results = await configurationPrompt() + if (new Set(results.config).has('custom')) { + return prompt([ + { + type: 'checkbox', + message: 'choose a design system', + name: 'designSystem', + choices: [ + new inquirer.Separator('-- Design System choose(1 or both)--'), + { + name: 'Storybook', + checked: true, + }, + { + name: 'Pattern Lab', + }, + ], + validate: genericValidate({ min: 1 }), + }, + { + type: 'checkbox', + message: 'Choose a CSS library', + name: 'cssLibrary', + choices: [ + { name: 'Tailwind', checked: true }, + 'Sass', + { name: 'bootstrap', disabled: true }, + ], + }, + { + type: 'checkbox', + message: '[optional] choose a static typing library', + name: 'staticTestingLibrary', + choices: ['typescript'], + }, + { + type: 'checkbox', + message: 'Do you want ESModule support for typescript?', + name: 'Typescript options', + when: (answer) => { + // Checks to see if we enabled typescript previously then asks the prompt + if (new Set(answer.staticTestingLibrary).has('typescript')) { + return true + } + return false + }, + choices: [ + new inquirer.Separator( + '-- choose(1 or both): Using both will allow for the best of both worlds but you will have to support bundling ESM for modern browsers and CJS for all other browsers --' + ), // TODO perhaps we add this part into the message + 'typescript ESM (for modern browsers only)', + { + name: 'typescript CJS (all browsers but slower on modern browsers)', + checked: true, + }, + ], + }, + { + type: 'checkbox', + message: 'What frontened framework are you using?', + name: 'frontendFramework', + choices: [ + { name: 'ReactJS', checked: true }, + 'Twig', + 'Polymer', + 'none', + ], + }, + { + type: 'checkbox', + name: 'Are you using SVGs?', + choices: [{ checked: true, name: 'yes' }, 'no'], + validate: genericValidate({ min: 1, max: 1 }), + }, + { + type: 'checkbox', + message: 'What testing libraries do you want to use?', + name: 'testingLibraries', + choices: ['Jest', 'Cypress', 'Loki (Storybook only VRT)'], + validate: genericValidate({ min: 1 }), + }, + ]) + } + + return Promise.resolve(results) +} diff --git a/packages/particle-cli/package.json b/packages/particle-cli/package.json index 23eac4d5af..be24849502 100644 --- a/packages/particle-cli/package.json +++ b/packages/particle-cli/package.json @@ -31,6 +31,10 @@ }, "dependencies": { "commander": "^5.1.0", - "esm": "^3.2.25" + "esm": "^3.2.25", + "inquirer": "^7.2.0" + }, + "devDependencies": { + "@types/inquirer": "^6.5.0" } } From 81cfdc760923f100210e94d3f04d2d60f09c0871 Mon Sep 17 00:00:00 2001 From: Frederick Engelhardt Date: Wed, 24 Jun 2020 12:40:57 -0700 Subject: [PATCH 2/8] * refactor typescript approach: all typescript packages will contain a tsconfig that extends the base config * rename module.export files back to .js extensions and remove allowJS from typescript config * base file no longer compiles to dist and base file will no longer allow for JS to be compile alongside TS files * particle-cli: fix testing type error and add repo name option --- .gitignore | 5 +- package.json | 6 +- packages/eslint-config/{index.ts => index.js} | 2 +- .../generators/app/{index.ts => index.js} | 0 packages/particle-cli/bin/particle-cli.ts | 4 +- .../particle-cli/lib/generatePromptOptions.ts | 121 ------------- packages/particle-cli/package.json | 8 +- packages/particle-cli/{lib => src}/create.ts | 0 .../particle-cli/src/generatePromptOptions.ts | 162 ++++++++++++++++++ packages/particle-cli/src/types.ts | 21 +++ .../{__tests__ => test}/create.test.ts | 4 +- packages/particle-cli/tsconfig.json | 7 + packages/stylelint-config/index.js | 24 +++ src/scripts/build.ts | 9 +- tsconfig.json | 9 +- 15 files changed, 239 insertions(+), 143 deletions(-) rename packages/eslint-config/{index.ts => index.js} (99%) rename packages/generator-particle-drupal/generators/app/{index.ts => index.js} (100%) delete mode 100644 packages/particle-cli/lib/generatePromptOptions.ts rename packages/particle-cli/{lib => src}/create.ts (100%) create mode 100644 packages/particle-cli/src/generatePromptOptions.ts create mode 100644 packages/particle-cli/src/types.ts rename packages/particle-cli/{__tests__ => test}/create.test.ts (66%) create mode 100644 packages/particle-cli/tsconfig.json create mode 100644 packages/stylelint-config/index.js diff --git a/.gitignore b/.gitignore index f1fc82cf1e..dab821aeb7 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ node_modules # Errors npm-debug.log php_errors.log +lerna-debug.log -# Typescript -dist \ No newline at end of file +# Typescript outdir +packages/*/lib \ No newline at end of file diff --git a/package.json b/package.json index 49f0b0b05d..2a7e86741c 100644 --- a/package.json +++ b/package.json @@ -27,16 +27,18 @@ "pretty-check": "prettier --check packages/**/*.js", "test": "jest", "test:watch": "jest --watch", - "build": "tsc -p tsconfig.json && npm run postbuild", + "build": "lerna run --parallel --scope='@phase2/*' tsc && npm run postbuild", + "build:watch": "lerna run --parallel --scope='@phase2/*' tsc:watch", "postbuild": "ts-node ./src/scripts/build.ts", - "build:watch": "tsc -p tsconfig.json --watch", "update:check": "npx ncu && npx lerna exec --concurrency 1 --no-bail -- npx ncu", "update:start": "npm-upgrade && lerna exec --concurrency 1 -- npm-upgrade; npm run lerna:install" }, "devDependencies": { "@babel/core": "^7.10.2", "@babel/preset-env": "^7.10.2", + "@lerna/link": "^3.21.0", "@types/jest": "^26.0.0", + "@types/node": "^14.0.14", "babel-plugin-transform-remove-console": "^6.9.4", "eslint": "^7.2.0", "jest": "^26.0.1", diff --git a/packages/eslint-config/index.ts b/packages/eslint-config/index.js similarity index 99% rename from packages/eslint-config/index.ts rename to packages/eslint-config/index.js index d796f0cdb1..ebbd5da659 100644 --- a/packages/eslint-config/index.ts +++ b/packages/eslint-config/index.js @@ -34,4 +34,4 @@ module.exports = { rules: { 'import/no-extraneous-dependencies': ['error', { devDependencies: true }], }, -}; +} diff --git a/packages/generator-particle-drupal/generators/app/index.ts b/packages/generator-particle-drupal/generators/app/index.js similarity index 100% rename from packages/generator-particle-drupal/generators/app/index.ts rename to packages/generator-particle-drupal/generators/app/index.js diff --git a/packages/particle-cli/bin/particle-cli.ts b/packages/particle-cli/bin/particle-cli.ts index c6ef74aab3..6dcb466002 100755 --- a/packages/particle-cli/bin/particle-cli.ts +++ b/packages/particle-cli/bin/particle-cli.ts @@ -3,8 +3,8 @@ import program from 'commander' import pkg from '../package.json' -import { generatePromptOptions } from './../lib/generatePromptOptions' -import create from '../lib/create' +import { generatePromptOptions } from '../src/generatePromptOptions' +import create from '../src/create' /** * Initialize Commander program with version. diff --git a/packages/particle-cli/lib/generatePromptOptions.ts b/packages/particle-cli/lib/generatePromptOptions.ts deleted file mode 100644 index b111abd7e9..0000000000 --- a/packages/particle-cli/lib/generatePromptOptions.ts +++ /dev/null @@ -1,121 +0,0 @@ -import inquirer from 'inquirer' - -const prompt = inquirer.createPromptModule() - -const genericValidate = ({ min, max }: { min: number; max?: number }) => ( - answer: Record[] -) => { - // if (max && answer.length > max){ - - // } - if (answer.length < min || (!max ? false : answer.length > max)) { - return `You must choose a minimum of ${min} option(s)${ - max ? ` and a maximum of ${max} option(s)` : '' - }` - } - return true -} - -/** - * Returns a promise with a json schema - * The JSON schema will be used for the create method to generate files based off of the options selected in the prompt - * Two ways to do this, first way is to have all options selectable, second way is to have all separated options as seperate steps. - */ -const configurationPrompt = () => - prompt([ - { - type: 'checkbox', - message: 'Choose a configuration', - name: 'config', - choices: ['default', 'custom'], - validate: genericValidate({ min: 1, max: 1 }), - }, - ]) - -export const generatePromptOptions = async () => { - const results = await configurationPrompt() - if (new Set(results.config).has('custom')) { - return prompt([ - { - type: 'checkbox', - message: 'choose a design system', - name: 'designSystem', - choices: [ - new inquirer.Separator('-- Design System choose(1 or both)--'), - { - name: 'Storybook', - checked: true, - }, - { - name: 'Pattern Lab', - }, - ], - validate: genericValidate({ min: 1 }), - }, - { - type: 'checkbox', - message: 'Choose a CSS library', - name: 'cssLibrary', - choices: [ - { name: 'Tailwind', checked: true }, - 'Sass', - { name: 'bootstrap', disabled: true }, - ], - }, - { - type: 'checkbox', - message: '[optional] choose a static typing library', - name: 'staticTestingLibrary', - choices: ['typescript'], - }, - { - type: 'checkbox', - message: 'Do you want ESModule support for typescript?', - name: 'Typescript options', - when: (answer) => { - // Checks to see if we enabled typescript previously then asks the prompt - if (new Set(answer.staticTestingLibrary).has('typescript')) { - return true - } - return false - }, - choices: [ - new inquirer.Separator( - '-- choose(1 or both): Using both will allow for the best of both worlds but you will have to support bundling ESM for modern browsers and CJS for all other browsers --' - ), // TODO perhaps we add this part into the message - 'typescript ESM (for modern browsers only)', - { - name: 'typescript CJS (all browsers but slower on modern browsers)', - checked: true, - }, - ], - }, - { - type: 'checkbox', - message: 'What frontened framework are you using?', - name: 'frontendFramework', - choices: [ - { name: 'ReactJS', checked: true }, - 'Twig', - 'Polymer', - 'none', - ], - }, - { - type: 'checkbox', - name: 'Are you using SVGs?', - choices: [{ checked: true, name: 'yes' }, 'no'], - validate: genericValidate({ min: 1, max: 1 }), - }, - { - type: 'checkbox', - message: 'What testing libraries do you want to use?', - name: 'testingLibraries', - choices: ['Jest', 'Cypress', 'Loki (Storybook only VRT)'], - validate: genericValidate({ min: 1 }), - }, - ]) - } - - return Promise.resolve(results) -} diff --git a/packages/particle-cli/package.json b/packages/particle-cli/package.json index be24849502..f922483e42 100644 --- a/packages/particle-cli/package.json +++ b/packages/particle-cli/package.json @@ -13,8 +13,8 @@ "init" ], "bin": { - "@phase2/particle-cli": "bin/particle-cli.js", - "particle-cli": "bin/particle-cli.js" + "@phase2/particle-cli": "lib/bin/particle-cli.js", + "particle-cli": "lib/bin/particle-cli.js" }, "homepage": "https://github.com/phase2/particle#readme", "repository": { @@ -27,7 +27,9 @@ }, "license": "GPL-2.0", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1", + "tsc": "tsc", + "tsc:watch": "tsc --watch" }, "dependencies": { "commander": "^5.1.0", diff --git a/packages/particle-cli/lib/create.ts b/packages/particle-cli/src/create.ts similarity index 100% rename from packages/particle-cli/lib/create.ts rename to packages/particle-cli/src/create.ts diff --git a/packages/particle-cli/src/generatePromptOptions.ts b/packages/particle-cli/src/generatePromptOptions.ts new file mode 100644 index 0000000000..593b595656 --- /dev/null +++ b/packages/particle-cli/src/generatePromptOptions.ts @@ -0,0 +1,162 @@ +import { + DesignSystemPatternLibraryOptions, + StaticTestingLibraryOptions, +} from './types' +import inquirer from 'inquirer' + +const prompt = inquirer.createPromptModule() + +const genericValidate = ({ min, max }: { min: number; max?: number }) => ( + answer: Record[] +) => { + if (answer.length < min || (!max ? false : answer.length > max)) { + return `You must choose a minimum of ${min} option(s)${ + max ? ` and a maximum of ${max} option(s)` : '' + }` + } + return true +} + +const configurationPrompt = () => + prompt([ + { + type: 'input', + message: 'choose a repo name', + name: 'repoName', + validate: (name: string) => { + if (!name || name.length < 4) { + return 'Please enter a repo name of more than 4 characters length' + } + return true + }, + }, + { + type: 'input', + message: 'choose a design system name', + name: 'designSystemName', + default: 'default', + validate: (name: string) => { + if (!name || name.length < 4) { + return 'Please enter a repo name of more than 4 characters length' + } + return true + }, + }, + { + type: 'checkbox', + message: 'Choose a configuration', + name: 'config', + choices: [ + { + name: + 'modern react (storybook, tailwind, react, typescript, jest | cypress, svgs)', + value: 'modern-react', + }, + { name: 'drupal only (Pattern Lab, Tailwind, Svgs)', value: 'drupal' }, + { name: 'custom', value: 'custom' }, + ], + validate: genericValidate({ min: 1, max: 1 }), + }, + ]) + +const customPromptOptions = () => { + return prompt([ + { + type: 'checkbox', + message: 'choose a Component/Pattern Library or a Design System', + name: 'designSystem', + choices: [ + new inquirer.Separator('-- Design System choose(1 or both)--'), + { + name: 'Storybook', + value: DesignSystemPatternLibraryOptions.STORYBOOK, + checked: true, + }, + { + name: 'Pattern Lab', + value: DesignSystemPatternLibraryOptions.PATTERN_LAB, + }, + ], + validate: genericValidate({ min: 1 }), + }, + { + type: 'checkbox', + message: 'Choose a CSS library', + name: 'cssLibrary', + choices: [ + { name: 'Tailwind', checked: true }, + 'Sass', + { name: 'bootstrap', disabled: true }, + ], + }, + { + type: 'checkbox', + message: '[optional] choose a static typing library', + name: 'staticTestingLibrary', + choices: [StaticTestingLibraryOptions.TYPESCRIPT], + }, + { + type: 'checkbox', + message: + 'Do you want ESModule support for typescript? \n -- choose(1 or both): Using both will allow for the best of both worlds but you will have to support bundling ESM for modern browsers and CJS for all other browsers --', + name: 'Typescript options', + when: (answer) => { + // Checks to see if we enabled typescript previously then asks the prompt + if ( + new Set(answer.staticTestingLibrary).has( + StaticTestingLibraryOptions.TYPESCRIPT + ) + ) { + return true + } + return false + }, + choices: [ + new inquirer.Separator( + '-- choose(1 or both): Using both will allow for the best of both worlds but you will have to support bundling ESM for modern browsers and CJS for all other browsers --' + ), // TODO perhaps we add this part into the message + { + name: 'typescript CJS (all browsers but slower on modern browsers)', + value: 'cjs', + checked: true, + }, + { name: 'typescript ESM (for modern browsers only)', value: 'esm' }, + ], + }, + { + type: 'checkbox', + message: 'What frontened framework are you using?', + name: 'frontendFramework', + choices: [{ name: 'ReactJS', checked: true }, 'Twig', 'Polymer', 'none'], + }, + { + type: 'checkbox', + name: 'Are you using SVGs?', + choices: [ + { checked: true, name: 'yes', value: true }, + { name: 'no', value: false }, + ], + validate: genericValidate({ min: 1, max: 1 }), + }, + { + type: 'checkbox', + message: 'What testing libraries do you want to use?', + name: 'testingLibraries', + choices: ['Jest', 'Cypress', 'Loki (Storybook only VRT)'], + validate: genericValidate({ min: 1 }), + }, + ]) +} + +/** + * Returns a promise with a json schema + * The JSON schema will be used for the create method to generate files based off of the options selected in the prompt + */ +export const generatePromptOptions = async () => { + const results = await configurationPrompt() + if (new Set(results.config).has('custom')) { + return customPromptOptions() + } + + return Promise.resolve(results) +} diff --git a/packages/particle-cli/src/types.ts b/packages/particle-cli/src/types.ts new file mode 100644 index 0000000000..b646ec4b0b --- /dev/null +++ b/packages/particle-cli/src/types.ts @@ -0,0 +1,21 @@ +export enum CSSLibraryOptions { + TAILWIND = 'tailwind', + BOOTSTRAP = 'bootstrap', +} + +export enum DesignSystemPatternLibraryOptions { + STORYBOOK = 'storybook', + PATTERN_LAB = 'pattern_lab', +} + +export enum ConfigurationOptions { + CUSTOM = 'custom', + MODERN_REACT = 'modern_react', + DRUPAL_ONLY = 'drupal', +} + +export enum StaticTestingLibraryOptions { + TYPESCRIPT = 'typescript', +} + +// export enum diff --git a/packages/particle-cli/__tests__/create.test.ts b/packages/particle-cli/test/create.test.ts similarity index 66% rename from packages/particle-cli/__tests__/create.test.ts rename to packages/particle-cli/test/create.test.ts index d2560fd68a..46f0daccf1 100644 --- a/packages/particle-cli/__tests__/create.test.ts +++ b/packages/particle-cli/test/create.test.ts @@ -1,10 +1,10 @@ -import create from '../lib/create' +import create from '../src/create' import repoPackage from '../package.json' const { name } = repoPackage describe(`${name}/create`, () => { it('show log', () => { - expect(create()).toBeTruthy() + expect(create({})).toBeTruthy() }) }) diff --git a/packages/particle-cli/tsconfig.json b/packages/particle-cli/tsconfig.json new file mode 100644 index 0000000000..32387ae18d --- /dev/null +++ b/packages/particle-cli/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./lib" + }, + "include": ["./src", "./bin"] +} diff --git a/packages/stylelint-config/index.js b/packages/stylelint-config/index.js new file mode 100644 index 0000000000..cef8306aa4 --- /dev/null +++ b/packages/stylelint-config/index.js @@ -0,0 +1,24 @@ +module.exports = { + extends: [ + 'stylelint-config-prettier' + ], + plugins: [ + 'stylelint-scss', + ], + rules: { + 'indentation': 2, + 'declaration-colon-space-after': 'always', + 'declaration-no-important': true, + 'max-nesting-depth': 3, + 'selector-max-specificity': '0,3,3', + 'selector-max-id': 0, + 'scss/at-extend-no-missing-placeholder': true, + 'scss/selector-no-redundant-nesting-selector': true, + 'at-rule-no-vendor-prefix': true, + 'media-feature-name-no-vendor-prefix': true, + 'property-no-vendor-prefix': true, + 'selector-no-vendor-prefix': true, + 'value-no-vendor-prefix': true + }, +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/src/scripts/build.ts b/src/scripts/build.ts index 6388c6c33a..34293d1517 100644 --- a/src/scripts/build.ts +++ b/src/scripts/build.ts @@ -1,8 +1,8 @@ import fs from 'fs' import { exec } from 'child_process' -const distFolder = './dist' // add your scripts to folder named scripts -const packagesFolder = './packages' +const libFolder = '/lib' // add your scripts to folder named scripts +const packagesFolder = '/packages' const files = fs.readdirSync(distFolder) // reading files from folders enum CopyFiles { @@ -13,17 +13,16 @@ enum CopyFiles { /** * iterates through all dist packages and references the dist folder to the packages folder and grabs files unrelated to JS or TS that are required for publishing the package * */ - files.forEach((packageName: string) => { const path = `${packagesFolder}/${packageName}` const b = fs.readdirSync(path).forEach((item: string) => { if (item === CopyFiles.README || item === CopyFiles.PACKAGE) { exec( - `cp ${path}/${item} ${distFolder}/${packageName}/${item}`, + `cp ${path}/${item} ${path}/${libFolder}/${item}`, { shell: '/bin/bash' }, (err: any, stdout: any, stderr: any) => { console.log( - `successfully wrote ${path}/${item} to dist`, + `successfully wrote ${path}/${item} to lib`, stdout, stderr ) diff --git a/tsconfig.json b/tsconfig.json index 3e82e01e4a..e92f6fbd09 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,16 +2,15 @@ "compilerOptions": { "module": "commonjs", "esModuleInterop": true, - "target": "ES2020", + "target": "ES2019", "moduleResolution": "node", "sourceMap": true, - "outDir": "dist", - "allowJs": true, "resolveJsonModule": true, "forceConsistentCasingInFileNames": true, "declaration": true, - "noImplicitAny": true + "noImplicitAny": true, + "removeComments": true, + "noLib": false }, - "include": ["packages/**/*"], "exclude": ["node_modules", "**/__tests__/*"] } From 50c8b56e0ec83a484d9f1d4ca9c57be7f891b805 Mon Sep 17 00:00:00 2001 From: Frederick Engelhardt Date: Mon, 29 Jun 2020 11:47:27 -0700 Subject: [PATCH 3/8] WIP clean up types and add conditional queries to inquierer --- .../particle-cli/src/generatePromptOptions.ts | 78 +++++++++++++++---- packages/particle-cli/src/types.ts | 27 ++++++- 2 files changed, 87 insertions(+), 18 deletions(-) diff --git a/packages/particle-cli/src/generatePromptOptions.ts b/packages/particle-cli/src/generatePromptOptions.ts index 593b595656..093e457438 100644 --- a/packages/particle-cli/src/generatePromptOptions.ts +++ b/packages/particle-cli/src/generatePromptOptions.ts @@ -1,12 +1,15 @@ import { + CustomAnswers, + ConfigurationAnswers, DesignSystemPatternLibraryOptions, + FrontendFrameworkOptions, StaticTestingLibraryOptions, } from './types' import inquirer from 'inquirer' const prompt = inquirer.createPromptModule() -const genericValidate = ({ min, max }: { min: number; max?: number }) => ( +const minMaxOptionsValidate = ({ min, max }: { min: number; max?: number }) => ( answer: Record[] ) => { if (answer.length < min || (!max ? false : answer.length > max)) { @@ -17,15 +20,18 @@ const genericValidate = ({ min, max }: { min: number; max?: number }) => ( return true } -const configurationPrompt = () => +const configurationPrompt = (): Promise => prompt([ { type: 'input', - message: 'choose a repo name', - name: 'repoName', + message: 'choose a project name using kebab case, example: "my-project"', + name: 'projectName', validate: (name: string) => { if (!name || name.length < 4) { - return 'Please enter a repo name of more than 4 characters length' + return 'Please enter a project name of more than 4 characters length' + } + if (name.indexOf(' ') > 0) { + return 'Please enter a project name with no spaces' } return true }, @@ -55,11 +61,11 @@ const configurationPrompt = () => { name: 'drupal only (Pattern Lab, Tailwind, Svgs)', value: 'drupal' }, { name: 'custom', value: 'custom' }, ], - validate: genericValidate({ min: 1, max: 1 }), + validate: minMaxOptionsValidate({ min: 1, max: 1 }), }, ]) -const customPromptOptions = () => { +const customPromptOptions = (): Promise => { return prompt([ { type: 'checkbox', @@ -77,7 +83,51 @@ const customPromptOptions = () => { value: DesignSystemPatternLibraryOptions.PATTERN_LAB, }, ], - validate: genericValidate({ min: 1 }), + validate: minMaxOptionsValidate({ min: 1 }), + }, + { + type: 'checkbox', + message: 'What frontend framework are you using with Storybook?', + name: 'frontendFramework', + choices: [ + { + name: 'React', + checked: true, + value: FrontendFrameworkOptions.REACT, + }, + { + name: 'Webcomponents', + value: FrontendFrameworkOptions.WEBCOMPONENTS, + }, + ], + // PR up for docs on inquirer to annotate second param answers https://github.com/SBoudrias/Inquirer.js/pull/936 + filter: (value: FrontendFrameworkOptions[], answers: CustomAnswers) => { + if ( + answers.designSystem.includes( + DesignSystemPatternLibraryOptions.PATTERN_LAB + ) + ) { + return [FrontendFrameworkOptions.TWIG, ...value] + } + return value + // throw new Error(answers.designSystem) + // input will { answers, values } as we are modifying the return value in the choices section + }, + when: (answers: CustomAnswers) => { + // Checks to see if we enabled typescript previously then asks the prompt + if ( + new Set(answers.designSystem).has( + DesignSystemPatternLibraryOptions.STORYBOOK + ) + ) { + return true + } + + // Mutates answers object adds twig to selected choice (does not prompt user) + answers.frontendFramework = [FrontendFrameworkOptions.TWIG] + + return false + }, }, { type: 'checkbox', @@ -100,7 +150,7 @@ const customPromptOptions = () => { message: 'Do you want ESModule support for typescript? \n -- choose(1 or both): Using both will allow for the best of both worlds but you will have to support bundling ESM for modern browsers and CJS for all other browsers --', name: 'Typescript options', - when: (answer) => { + when: (answer: CustomAnswers) => { // Checks to see if we enabled typescript previously then asks the prompt if ( new Set(answer.staticTestingLibrary).has( @@ -123,12 +173,6 @@ const customPromptOptions = () => { { name: 'typescript ESM (for modern browsers only)', value: 'esm' }, ], }, - { - type: 'checkbox', - message: 'What frontened framework are you using?', - name: 'frontendFramework', - choices: [{ name: 'ReactJS', checked: true }, 'Twig', 'Polymer', 'none'], - }, { type: 'checkbox', name: 'Are you using SVGs?', @@ -136,14 +180,14 @@ const customPromptOptions = () => { { checked: true, name: 'yes', value: true }, { name: 'no', value: false }, ], - validate: genericValidate({ min: 1, max: 1 }), + validate: minMaxOptionsValidate({ min: 1, max: 1 }), }, { type: 'checkbox', message: 'What testing libraries do you want to use?', name: 'testingLibraries', choices: ['Jest', 'Cypress', 'Loki (Storybook only VRT)'], - validate: genericValidate({ min: 1 }), + validate: minMaxOptionsValidate({ min: 1 }), }, ]) } diff --git a/packages/particle-cli/src/types.ts b/packages/particle-cli/src/types.ts index b646ec4b0b..60c99fc1e2 100644 --- a/packages/particle-cli/src/types.ts +++ b/packages/particle-cli/src/types.ts @@ -18,4 +18,29 @@ export enum StaticTestingLibraryOptions { TYPESCRIPT = 'typescript', } -// export enum +export enum FrontendFrameworkOptions { + TWIG = 'twig', + REACT = 'react', + WEBCOMPONENTS = 'webcomponents', +} + +export enum ConfigOptions { + MODERN_REACT = 'modern_react', + DRUPAL = 'drupal', + CUSTOM = 'custom', +} + +interface Naming { + projectName: string + designSystemName: string +} + +export interface ConfigurationAnswers extends Naming { + config: ConfigOptions +} + +export interface CustomAnswers { + designSystem: DesignSystemPatternLibraryOptions[] + frontendFramework: FrontendFrameworkOptions[] + staticTestingLibrary: StaticTestingLibraryOptions[] +} From 5e7b3537036f8bc8f664f283941a7ff5756b432c Mon Sep 17 00:00:00 2001 From: Frederick Engelhardt Date: Mon, 29 Jun 2020 11:58:20 -0700 Subject: [PATCH 4/8] remove duplicate type ConfigurationOptions and use ConfigOptions in check for custom --- packages/particle-cli/src/generatePromptOptions.ts | 3 ++- packages/particle-cli/src/types.ts | 6 ------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/particle-cli/src/generatePromptOptions.ts b/packages/particle-cli/src/generatePromptOptions.ts index 093e457438..c79b1309f2 100644 --- a/packages/particle-cli/src/generatePromptOptions.ts +++ b/packages/particle-cli/src/generatePromptOptions.ts @@ -1,5 +1,6 @@ import { CustomAnswers, + ConfigOptions, ConfigurationAnswers, DesignSystemPatternLibraryOptions, FrontendFrameworkOptions, @@ -198,7 +199,7 @@ const customPromptOptions = (): Promise => { */ export const generatePromptOptions = async () => { const results = await configurationPrompt() - if (new Set(results.config).has('custom')) { + if (new Set(results.config).has(ConfigOptions.CUSTOM)) { return customPromptOptions() } diff --git a/packages/particle-cli/src/types.ts b/packages/particle-cli/src/types.ts index 60c99fc1e2..595006d1c9 100644 --- a/packages/particle-cli/src/types.ts +++ b/packages/particle-cli/src/types.ts @@ -8,12 +8,6 @@ export enum DesignSystemPatternLibraryOptions { PATTERN_LAB = 'pattern_lab', } -export enum ConfigurationOptions { - CUSTOM = 'custom', - MODERN_REACT = 'modern_react', - DRUPAL_ONLY = 'drupal', -} - export enum StaticTestingLibraryOptions { TYPESCRIPT = 'typescript', } From 30840d491b89511b5d5e2a6bcb20c8c016148397 Mon Sep 17 00:00:00 2001 From: Frederick Engelhardt Date: Mon, 29 Jun 2020 12:06:45 -0700 Subject: [PATCH 5/8] remove babel from project as it is unnecessary alongside typescript --- babel.config.js | 20 -------------------- package.json | 8 +------- 2 files changed, 1 insertion(+), 27 deletions(-) delete mode 100644 babel.config.js diff --git a/babel.config.js b/babel.config.js deleted file mode 100644 index 1bbde700a7..0000000000 --- a/babel.config.js +++ /dev/null @@ -1,20 +0,0 @@ -module.exports = { - presets: [ - [ - '@babel/preset-env', - { - useBuiltIns: 'entry', - target: { node: 12 }, - }, - ], - '@babel/preset-typescript', - ], - env: { - test: { - presets: [['@babel/preset-env']], - }, - production: { - plugins: ['transform-remove-console'], - }, - }, -} diff --git a/package.json b/package.json index 2a7e86741c..e9424aec85 100644 --- a/package.json +++ b/package.json @@ -34,12 +34,9 @@ "update:start": "npm-upgrade && lerna exec --concurrency 1 -- npm-upgrade; npm run lerna:install" }, "devDependencies": { - "@babel/core": "^7.10.2", - "@babel/preset-env": "^7.10.2", "@lerna/link": "^3.21.0", "@types/jest": "^26.0.0", "@types/node": "^14.0.14", - "babel-plugin-transform-remove-console": "^6.9.4", "eslint": "^7.2.0", "jest": "^26.0.1", "jest-watch-typeahead": "^0.6.0", @@ -50,8 +47,5 @@ "ts-jest": "^26.1.0", "ts-node": "^8.10.2", "typescript": "^3.9.5" - }, - "files": [ - "dist/**/*" - ] + } } From 3fb67e602ce7aecb70ed49161742ef2a34c5ffa4 Mon Sep 17 00:00:00 2001 From: Frederick Engelhardt Date: Mon, 29 Jun 2020 12:26:01 -0700 Subject: [PATCH 6/8] add Particle to keywords --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index e9424aec85..a6ec141a02 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ }, "private": true, "keywords:": [ + "Particle", "Storybook", "Pattern Lab", "Drupal" From 40dd3c086c09d4d05ee7446ed7b7b40c0b4d7c22 Mon Sep 17 00:00:00 2001 From: Frederick Engelhardt Date: Wed, 1 Jul 2020 12:32:46 -0700 Subject: [PATCH 7/8] add more types and swap single options to booleans --- .../particle-cli/src/generatePromptOptions.ts | 68 ++++++++----------- packages/particle-cli/src/types.ts | 18 +++-- 2 files changed, 42 insertions(+), 44 deletions(-) diff --git a/packages/particle-cli/src/generatePromptOptions.ts b/packages/particle-cli/src/generatePromptOptions.ts index c79b1309f2..c0095300df 100644 --- a/packages/particle-cli/src/generatePromptOptions.ts +++ b/packages/particle-cli/src/generatePromptOptions.ts @@ -2,9 +2,10 @@ import { CustomAnswers, ConfigOptions, ConfigurationAnswers, + CSSLibraryOptions, DesignSystemPatternLibraryOptions, FrontendFrameworkOptions, - StaticTestingLibraryOptions, + TestingLibraryOptions, } from './types' import inquirer from 'inquirer' @@ -50,7 +51,7 @@ const configurationPrompt = (): Promise => }, }, { - type: 'checkbox', + type: 'list', message: 'Choose a configuration', name: 'config', choices: [ @@ -62,7 +63,6 @@ const configurationPrompt = (): Promise => { name: 'drupal only (Pattern Lab, Tailwind, Svgs)', value: 'drupal' }, { name: 'custom', value: 'custom' }, ], - validate: minMaxOptionsValidate({ min: 1, max: 1 }), }, ]) @@ -131,63 +131,53 @@ const customPromptOptions = (): Promise => { }, }, { - type: 'checkbox', + type: 'list', message: 'Choose a CSS library', name: 'cssLibrary', choices: [ - { name: 'Tailwind', checked: true }, - 'Sass', - { name: 'bootstrap', disabled: true }, + { name: 'Tailwind', checked: true, value: CSSLibraryOptions.TAILWIND }, + { name: 'Sass', value: CSSLibraryOptions.SASS }, + { + name: 'Bootstrap', + disabled: true, + value: CSSLibraryOptions.BOOTSTRAP, + }, ], }, { - type: 'checkbox', - message: '[optional] choose a static typing library', - name: 'staticTestingLibrary', - choices: [StaticTestingLibraryOptions.TYPESCRIPT], + type: 'confirm', + message: 'Do you want to use typescript?', + name: 'hasTypescript', }, { - type: 'checkbox', - message: - 'Do you want ESModule support for typescript? \n -- choose(1 or both): Using both will allow for the best of both worlds but you will have to support bundling ESM for modern browsers and CJS for all other browsers --', - name: 'Typescript options', + type: 'confirm', + message: 'Do you want ESModule support for typescript?', + name: 'typescriptEsm', when: (answer: CustomAnswers) => { // Checks to see if we enabled typescript previously then asks the prompt - if ( - new Set(answer.staticTestingLibrary).has( - StaticTestingLibraryOptions.TYPESCRIPT - ) - ) { + if (answer.hasTypescript) { return true } return false }, - choices: [ - new inquirer.Separator( - '-- choose(1 or both): Using both will allow for the best of both worlds but you will have to support bundling ESM for modern browsers and CJS for all other browsers --' - ), // TODO perhaps we add this part into the message - { - name: 'typescript CJS (all browsers but slower on modern browsers)', - value: 'cjs', - checked: true, - }, - { name: 'typescript ESM (for modern browsers only)', value: 'esm' }, - ], }, { - type: 'checkbox', + type: 'confirm', name: 'Are you using SVGs?', - choices: [ - { checked: true, name: 'yes', value: true }, - { name: 'no', value: false }, - ], - validate: minMaxOptionsValidate({ min: 1, max: 1 }), }, { type: 'checkbox', message: 'What testing libraries do you want to use?', name: 'testingLibraries', - choices: ['Jest', 'Cypress', 'Loki (Storybook only VRT)'], + choices: [ + { name: 'Jest', value: TestingLibraryOptions.JEST }, + { name: 'Cypress', value: TestingLibraryOptions.CYPRESS }, + { name: 'Selenium', value: TestingLibraryOptions.SELENIUM }, + { + name: 'Loki (Storybook only VRT)', + value: TestingLibraryOptions.LOKI, + }, + ], validate: minMaxOptionsValidate({ min: 1 }), }, ]) @@ -199,7 +189,7 @@ const customPromptOptions = (): Promise => { */ export const generatePromptOptions = async () => { const results = await configurationPrompt() - if (new Set(results.config).has(ConfigOptions.CUSTOM)) { + if (results.config === ConfigOptions.CUSTOM) { return customPromptOptions() } diff --git a/packages/particle-cli/src/types.ts b/packages/particle-cli/src/types.ts index 595006d1c9..eb0a599344 100644 --- a/packages/particle-cli/src/types.ts +++ b/packages/particle-cli/src/types.ts @@ -1,5 +1,6 @@ export enum CSSLibraryOptions { TAILWIND = 'tailwind', + SASS = 'sass', BOOTSTRAP = 'bootstrap', } @@ -8,10 +9,6 @@ export enum DesignSystemPatternLibraryOptions { PATTERN_LAB = 'pattern_lab', } -export enum StaticTestingLibraryOptions { - TYPESCRIPT = 'typescript', -} - export enum FrontendFrameworkOptions { TWIG = 'twig', REACT = 'react', @@ -29,12 +26,23 @@ interface Naming { designSystemName: string } +export enum TestingLibraryOptions { + JEST = 'jest', + CYPRESS = 'cypress', + LOKI = 'loki', + SELENIUM = 'selenium', +} + export interface ConfigurationAnswers extends Naming { config: ConfigOptions } export interface CustomAnswers { + cssLibrary: CSSLibraryOptions designSystem: DesignSystemPatternLibraryOptions[] frontendFramework: FrontendFrameworkOptions[] - staticTestingLibrary: StaticTestingLibraryOptions[] + hasSVG: boolean + hasTypescript: boolean + testingLibraries: TestingLibraryOptions[] + typescriptEsm?: boolean } From d84da93775d5b01e7d501d51293c9fa52bacc3cc Mon Sep 17 00:00:00 2001 From: Frederick Engelhardt Date: Wed, 1 Jul 2020 12:43:35 -0700 Subject: [PATCH 8/8] update readme for devs regarding new workflow with individual packages compiling to typescript within lib. --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1ed9bb6037..98778e0dfd 100644 --- a/README.md +++ b/README.md @@ -19,13 +19,14 @@ TBD 1. Clone the repo 1. Run `npm install`, This will install all dev dependencies and run the postinstall script `lerna:install` which runs `lerna bootstrap --nohoist` and installs all package dependencies. 1. If you update subdependencies, simply run `npm install` or `npm run lerna:install` to re-install lerna package dependencies. This is especially helpful when you are pulling in new code (with sub dependency additionas) from another branch. -1. `npm run build:watch` build the project in the dist folder +1. `npm run build:watch` build the project in the `packages//lib` folder, packages that do not contain a .tsconfig and do not have a `tsc` and `tsc:build` script will be ignored lerna executes packages that contain only these scripts. +1. For all packages, simply execute the target file such as `node packages/particle-cli/lib/bin/particle-cli.js init` to run things, typescript must be compiled for typescript packages to execute 1. `npm run test:watch` to start jest in watch mode (recommended) ### Installing A Dependency 1. Run `npm run build`, build will fire off the `tsc` build script and also copy the package.json and README.md files from the `packages/*` directories directly into the dist folder. Alternatively have the compiler in watch mode `npm run build:watch` and run `npm run postbuild` to copy the files in. -1. Cd into `dist/` and run `npm link`, this will link the **bin** alias as an alias in your terminal. Example the bin is named `@phase2/particle-cli` therefore running `npx @phase2/particle-cli -v` will invoke the binary file `particle-cli`. +1. Cd into `package/` and run `npm link`, this will link the **lib/bin** or `main/index.js` alias as an alias in your terminal. Example the bin is named (or aliased) `@phase2/particle-cli` therefore running `npx @phase2/particle-cli -v` will invoke the binary file `particle-cli`. #### Example @@ -41,7 +42,7 @@ particle-cli -V; // works ### Clean the repo -To remove package-lock.json from all levels of the repo simply run this command. PS is used to prevent grep from exiting as this throws an error with `lerna exec` even with the `--no-bail` flag. +To remove package-lock.json from all levels of the repo simply run this command. `ps` is used to prevent grep from exiting as this throws an error with `lerna exec` even with the `--no-bail` flag. ```bash ps -ef | (grep -q -s -R ^$1 package-lock.json && rm -rf package-lock.json) | { grep -v grep || true; }; lerna exec -- ps -ef | (grep -q -s -R ^$1 package-lock.json && rm -rf package-lock.json) | { grep -v grep || true; }