diff --git a/docs/getting-started.md b/docs/getting-started.md index 50bf4445ef1ac..f53ddc533cc6f 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -19,7 +19,12 @@ If you have questions about anything related to Next.js, you're always welcome t ## Automatic Setup -We recommend creating a new Next.js app using `create-next-app`, which sets up everything automatically for you. To create a project, run: +We recommend creating a new Next.js app using `create-next-app`, which sets up +everything automatically for you. + +### Interactive + +You can create a new project interactively by running: ```bash npx create-next-app@latest @@ -29,14 +34,63 @@ yarn create next-app pnpm create next-app ``` -If you want to start with a TypeScript project you can use the `--typescript` flag: +You will be asked for the name of your project, and then whether you want to +create a TypeScript project: + +``` +✔ Would you like to use TypeScript with this project? … No / Yes +``` + +Select **Yes** to install the necessary types/dependencies and create a new TS project. + +### Non-interactive + +You can also pass command line arguments to set up a new project +non-interactively. See `create-next-app --help`: + +``` +create-next-app [options] + +Options: + -V, --version output the version number + --ts, --typescript + + Initialize as a TypeScript project. (default) + + --js, --javascript + + Initialize as a JavaScript project. + + --use-npm + + Explicitly tell the CLI to bootstrap the app using npm + + --use-pnpm + + Explicitly tell the CLI to bootstrap the app using pnpm + + -e, --example [name]|[github-url] + + An example to bootstrap the app with. You can use an example name + from the official Next.js repo or a GitHub URL. The URL can use + any branch and/or subdirectory + + --example-path + + In a rare case, your GitHub URL might contain a branch name with + a slash (e.g. bug/fix-1) and the path to the example (e.g. foo/bar). + In this case, you must specify the path to the example separately: + --example-path foo/bar +``` + +#### Examples ```bash -npx create-next-app@latest --typescript +npx create-next-app@latest --ts my-project # or -yarn create next-app --typescript +yarn create next-app --js my-project # or -pnpm create next-app --typescript +pnpm create next-app --javascript my-project ``` After the installation is complete: diff --git a/packages/create-next-app/index.ts b/packages/create-next-app/index.ts index 13fffa432cb95..7245f6efcf665 100644 --- a/packages/create-next-app/index.ts +++ b/packages/create-next-app/index.ts @@ -23,7 +23,14 @@ const program = new Commander.Command(packageJson.name) '--ts, --typescript', ` - Initialize as a TypeScript project. + Initialize as a TypeScript project. (default) +` + ) + .option( + '--js, --javascript', + ` + + Initialize as a JavaScript project. ` ) .option( @@ -136,13 +143,52 @@ async function run(): Promise { } const example = typeof program.example === 'string' && program.example.trim() + + /** + * If the user does not provide the necessary flags, prompt them for whether + * to use TS or JS. + * + * @todo Allow appDir to support TS or JS, currently TS-only and disables all + * --ts, --js features. + */ + if (!program.experimentalApp && !program.typescript && !program.javascript) { + const styledTypeScript = chalk.hex('#007acc')('TypeScript') + const { typescript } = await prompts( + { + type: 'toggle', + name: 'typescript', + message: `Would you like to use ${styledTypeScript} with this project?`, + initial: true, + active: 'Yes', + inactive: 'No', + }, + { + /** + * User inputs Ctrl+C or Ctrl+D to exit the prompt. We should close the + * process and not write to the file system. + */ + onCancel: () => { + console.error('Exiting.') + process.exit(1) + }, + } + ) + + if (typescript) { + program.typescript = true + } else { + program.javascript = false + program.javascript = true + } + } + try { await createApp({ appPath: resolvedProjectPath, packageManager, example: example && example !== 'default' ? example : undefined, examplePath: program.examplePath, - typescript: program.typescript, + typescript: !program.javascript || program.typescript, experimentalApp: program.experimentalApp, }) } catch (reason) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 96527f165dbdd..853ad67849d21 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -404,22 +404,26 @@ importers: '@next/eslint-plugin-next': 13.0.1-canary.0 '@rushstack/eslint-patch': ^1.1.3 '@typescript-eslint/parser': ^5.21.0 + eslint: ^7.23.0 || ^8.0.0 eslint-import-resolver-node: ^0.3.6 eslint-import-resolver-typescript: ^2.7.1 eslint-plugin-import: ^2.26.0 eslint-plugin-jsx-a11y: ^6.5.1 eslint-plugin-react: ^7.31.7 eslint-plugin-react-hooks: ^4.5.0 + typescript: '>=3.3.1' dependencies: '@next/eslint-plugin-next': link:../eslint-plugin-next '@rushstack/eslint-patch': 1.1.3 '@typescript-eslint/parser': 5.21.0_td6yqss6ra3qoebludh4ctrhym + eslint: 7.32.0 eslint-import-resolver-node: 0.3.6 eslint-import-resolver-typescript: 2.7.1_hpmu7kn6tcn2vnxpfzvv33bxmy eslint-plugin-import: 2.26.0_asoxhzjlkaozogjqriaz4fv5ly eslint-plugin-jsx-a11y: 6.5.1_eslint@7.32.0 eslint-plugin-react: 7.31.8_eslint@7.32.0 eslint-plugin-react-hooks: 4.5.0_eslint@7.32.0 + typescript: 4.8.2 packages/eslint-plugin-next: specifiers: @@ -553,6 +557,7 @@ importers: domain-browser: 4.19.0 edge-runtime: 2.0.0 events: 3.3.0 + fibers: '>= 3.1.0' find-cache-dir: 3.3.1 find-up: 4.1.0 fresh: 0.5.2 @@ -580,6 +585,7 @@ importers: neo-async: 2.6.1 node-fetch: 2.6.7 node-html-parser: 5.3.3 + node-sass: ^6.0.0 || ^7.0.0 ora: 4.0.4 os-browserify: 0.3.0 p-limit: 3.1.0 @@ -600,9 +606,12 @@ importers: punycode: 2.1.1 querystring-es3: 0.2.1 raw-body: 2.4.1 + react: ^18.0.0-0 + react-dom: ^18.0.0-0 react-is: 18.2.0 react-refresh: 0.12.0 regenerator-runtime: 0.13.4 + sass: ^1.3.0 sass-loader: 12.4.0 schema-utils2: npm:schema-utils@2.7.1 schema-utils3: npm:schema-utils@3.0.0 @@ -614,8 +623,8 @@ importers: stacktrace-parser: 0.1.10 stream-browserify: 3.0.0 stream-http: 3.1.1 - string_decoder: 1.3.0 string-hash: 1.1.3 + string_decoder: 1.3.0 strip-ansi: 6.0.0 styled-jsx: 5.1.0 tar: 6.1.11 @@ -641,7 +650,12 @@ importers: '@next/env': link:../next-env '@swc/helpers': 0.4.11 caniuse-lite: 1.0.30001406 + fibers: 5.0.3 + node-sass: 7.0.3 postcss: 8.4.14 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + sass: 1.54.0 styled-jsx: 5.1.0_uuaxwgga6hqycsez5ok7v2wg4i use-sync-external-store: 1.2.0_react@18.2.0 devDependencies: @@ -800,7 +814,7 @@ importers: react-is: 18.2.0 react-refresh: 0.12.0 regenerator-runtime: 0.13.4 - sass-loader: 12.4.0_webpack@5.74.0 + sass-loader: 12.4.0_y7k4qxzyfvxio3t476zhrzlwf4 schema-utils2: /schema-utils/2.7.1 schema-utils3: /schema-utils/3.0.0 semver: 7.3.2 @@ -811,8 +825,8 @@ importers: stacktrace-parser: 0.1.10 stream-browserify: 3.0.0 stream-http: 3.1.1 - string_decoder: 1.3.0 string-hash: 1.1.3 + string_decoder: 1.3.0 strip-ansi: 6.0.0 tar: 6.1.11 taskr: 1.1.0 @@ -875,10 +889,18 @@ importers: rimraf: 3.0.2 packages/next-mdx: - specifiers: {} + specifiers: + '@mdx-js/loader': '>=0.15.0' + '@mdx-js/react': '*' + dependencies: + '@mdx-js/loader': 0.18.0_bulxuubf6ggdxnp6z2exkrzdzy + '@mdx-js/react': 2.1.5_react@16.14.0 packages/next-plugin-storybook: - specifiers: {} + specifiers: + next: '*' + dependencies: + next: link:../next packages/next-polyfill-module: specifiers: @@ -913,10 +935,13 @@ importers: css.escape: 1.5.1 data-uri-to-buffer: 3.0.1 platform: 1.3.6 + react: ^17.0.2 + react-dom: ^17.0.2 shell-quote: 1.7.3 source-map: 0.8.0-beta.0 stacktrace-parser: 0.1.10 strip-ansi: 6.0.1 + webpack: ^4 || ^5 dependencies: '@babel/code-frame': 7.12.11 '@types/babel__code-frame': 7.0.2 @@ -925,10 +950,13 @@ importers: css.escape: 1.5.1 data-uri-to-buffer: 3.0.1 platform: 1.3.6 + react: 17.0.2 + react-dom: 17.0.2_react@17.0.2 shell-quote: 1.7.3 source-map: 0.8.0-beta.0 stacktrace-parser: 0.1.10 strip-ansi: 6.0.1 + webpack: 5.74.0 packages/react-refresh-utils: specifiers: @@ -2294,7 +2322,6 @@ packages: dependencies: '@babel/core': 7.18.0 '@babel/helper-plugin-utils': 7.19.0 - dev: true /@babel/plugin-syntax-logical-assignment-operators/7.10.4_@babel+core@7.18.0: resolution: @@ -4461,7 +4488,6 @@ packages: { integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==, } - dev: true /@grpc/grpc-js/0.8.1: resolution: @@ -4930,7 +4956,6 @@ packages: dependencies: '@jridgewell/gen-mapping': 0.3.1 '@jridgewell/trace-mapping': 0.3.13 - dev: true /@jridgewell/sourcemap-codec/1.4.11: resolution: @@ -5838,6 +5863,20 @@ packages: - supports-color dev: true + /@mdx-js/loader/0.18.0_bulxuubf6ggdxnp6z2exkrzdzy: + resolution: + { + integrity: sha512-eRgtB14JwyIiZZPXjrpYhSHHQ5+GtZ5cbG744EV2DZVKjxxg4OT/EtKc4JoxWHRK2HVU6W7cf8IXjQpqDviRuQ==, + } + dependencies: + '@mdx-js/mdx': 0.18.2_@babel+core@7.18.0 + '@mdx-js/tag': 0.18.0_react@16.14.0 + loader-utils: 1.4.0 + transitivePeerDependencies: + - '@babel/core' + - react + dev: false + /@mdx-js/loader/0.18.0_uuaxwgga6hqycsez5ok7v2wg4i: resolution: { @@ -5859,7 +5898,7 @@ packages: } dependencies: '@babel/plugin-proposal-object-rest-spread': 7.18.0_@babel+core@7.18.0 - '@babel/plugin-syntax-jsx': 7.14.5_@babel+core@7.18.0 + '@babel/plugin-syntax-jsx': 7.18.6_@babel+core@7.18.0 change-case: 3.1.0 detab: 2.0.4 mdast-util-to-hast: 4.0.0 @@ -5871,7 +5910,30 @@ packages: unist-util-visit: 1.4.1 transitivePeerDependencies: - '@babel/core' - dev: true + + /@mdx-js/react/2.1.5_react@16.14.0: + resolution: + { + integrity: sha512-3Az1I6SAWA9R38rYjz5rXBrGKeZhq96CSSyQtqY+maPj8stBsoUH5pNcmIixuGkufYsh8F5+ka2CVPo2fycWZw==, + } + peerDependencies: + react: '>=16' + dependencies: + '@types/mdx': 2.0.3 + '@types/react': 16.9.17 + react: 16.14.0 + dev: false + + /@mdx-js/tag/0.18.0_react@16.14.0: + resolution: + { + integrity: sha512-3g1NOnbw+sJZohNOEN9NlaYYDdzq1y34S7PDimSn3zLV8etCu7pTCMFbnFHMSe6mMmm4yJ1gfbS3QiE7t+WMGA==, + } + peerDependencies: + react: ^0.14.x || ^15.x || ^16.x + dependencies: + react: 16.14.0 + dev: false /@mdx-js/tag/0.18.0_react@18.2.0: resolution: @@ -5961,7 +6023,6 @@ packages: dependencies: '@gar/promisify': 1.1.3 semver: 7.3.7 - dev: true /@npmcli/git/2.0.4: resolution: @@ -6002,7 +6063,6 @@ packages: engines: { node: '>=10' } dependencies: mkdirp: 1.0.4 - dev: true /@npmcli/node-gyp/1.0.2: resolution: @@ -7106,7 +7166,6 @@ packages: integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==, } engines: { node: '>= 6' } - dev: true /@types/amphtml-validator/1.0.0: resolution: @@ -7324,7 +7383,6 @@ packages: dependencies: '@types/eslint': 7.28.0 '@types/estree': 0.0.51 - dev: true /@types/eslint/7.28.0: resolution: @@ -7334,7 +7392,6 @@ packages: dependencies: '@types/estree': 0.0.51 '@types/json-schema': 7.0.9 - dev: true /@types/estree/0.0.39: resolution: @@ -7348,7 +7405,6 @@ packages: { integrity: sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==, } - dev: true /@types/events/3.0.0: resolution: @@ -7533,7 +7589,6 @@ packages: { integrity: sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==, } - dev: true /@types/json5/0.0.29: resolution: @@ -7606,6 +7661,13 @@ packages: } dev: true + /@types/mdx/2.0.3: + resolution: + { + integrity: sha512-IgHxcT3RC8LzFLhKwP3gbMPeaK7BM9eBH46OdapPA7yvuIUJ8H6zHZV53J8hGZcTSnt95jANt+rTBNUUc22ACQ==, + } + dev: false + /@types/micromatch/4.0.2: resolution: { @@ -7689,7 +7751,6 @@ packages: { integrity: sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==, } - dev: true /@types/normalize-package-data/2.4.0: resolution: @@ -7747,7 +7808,6 @@ packages: { integrity: sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==, } - dev: true /@types/q/1.5.2: resolution: @@ -7798,7 +7858,6 @@ packages: dependencies: '@types/prop-types': 15.7.3 csstype: 2.6.8 - dev: true /@types/relay-runtime/13.0.0: resolution: @@ -7960,7 +8019,6 @@ packages: { integrity: sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==, } - dev: true /@types/uuid/8.3.1: resolution: @@ -7984,7 +8042,6 @@ packages: deprecated: This is a stub types definition. vfile-message provides its own type definitions, so you do not need this installed. dependencies: vfile-message: 3.0.2 - dev: true /@types/vfile/3.0.2: resolution: @@ -7995,7 +8052,6 @@ packages: '@types/node': 17.0.21 '@types/unist': 2.0.3 '@types/vfile-message': 2.0.0 - dev: true /@types/webpack-sources/0.1.5: resolution: @@ -8352,28 +8408,24 @@ packages: dependencies: '@webassemblyjs/helper-numbers': 1.11.1 '@webassemblyjs/helper-wasm-bytecode': 1.11.1 - dev: true /@webassemblyjs/floating-point-hex-parser/1.11.1: resolution: { integrity: sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==, } - dev: true /@webassemblyjs/helper-api-error/1.11.1: resolution: { integrity: sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==, } - dev: true /@webassemblyjs/helper-buffer/1.11.1: resolution: { integrity: sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==, } - dev: true /@webassemblyjs/helper-numbers/1.11.1: resolution: @@ -8384,14 +8436,12 @@ packages: '@webassemblyjs/floating-point-hex-parser': 1.11.1 '@webassemblyjs/helper-api-error': 1.11.1 '@xtuc/long': 4.2.2 - dev: true /@webassemblyjs/helper-wasm-bytecode/1.11.1: resolution: { integrity: sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==, } - dev: true /@webassemblyjs/helper-wasm-section/1.11.1: resolution: @@ -8403,7 +8453,6 @@ packages: '@webassemblyjs/helper-buffer': 1.11.1 '@webassemblyjs/helper-wasm-bytecode': 1.11.1 '@webassemblyjs/wasm-gen': 1.11.1 - dev: true /@webassemblyjs/ieee754/1.11.1: resolution: @@ -8412,7 +8461,6 @@ packages: } dependencies: '@xtuc/ieee754': 1.2.0 - dev: true /@webassemblyjs/leb128/1.11.1: resolution: @@ -8421,14 +8469,12 @@ packages: } dependencies: '@xtuc/long': 4.2.2 - dev: true /@webassemblyjs/utf8/1.11.1: resolution: { integrity: sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==, } - dev: true /@webassemblyjs/wasm-edit/1.11.1: resolution: @@ -8444,7 +8490,6 @@ packages: '@webassemblyjs/wasm-opt': 1.11.1 '@webassemblyjs/wasm-parser': 1.11.1 '@webassemblyjs/wast-printer': 1.11.1 - dev: true /@webassemblyjs/wasm-gen/1.11.1: resolution: @@ -8457,7 +8502,6 @@ packages: '@webassemblyjs/ieee754': 1.11.1 '@webassemblyjs/leb128': 1.11.1 '@webassemblyjs/utf8': 1.11.1 - dev: true /@webassemblyjs/wasm-opt/1.11.1: resolution: @@ -8469,7 +8513,6 @@ packages: '@webassemblyjs/helper-buffer': 1.11.1 '@webassemblyjs/wasm-gen': 1.11.1 '@webassemblyjs/wasm-parser': 1.11.1 - dev: true /@webassemblyjs/wasm-parser/1.11.1: resolution: @@ -8483,7 +8526,6 @@ packages: '@webassemblyjs/ieee754': 1.11.1 '@webassemblyjs/leb128': 1.11.1 '@webassemblyjs/utf8': 1.11.1 - dev: true /@webassemblyjs/wast-printer/1.11.1: resolution: @@ -8493,21 +8535,18 @@ packages: dependencies: '@webassemblyjs/ast': 1.11.1 '@xtuc/long': 4.2.2 - dev: true /@xtuc/ieee754/1.2.0: resolution: { integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==, } - dev: true /@xtuc/long/4.2.2: resolution: { integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==, } - dev: true /@zeit/dns-cached-resolve/2.1.2: resolution: @@ -8557,7 +8596,6 @@ packages: { integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==, } - dev: true /abort-controller/3.0.0: resolution: @@ -8599,7 +8637,6 @@ packages: acorn: ^8 dependencies: acorn: 8.8.0 - dev: true /acorn-jsx/5.3.1_acorn@7.4.1: resolution: @@ -8713,7 +8750,6 @@ packages: debug: 4.3.4 transitivePeerDependencies: - supports-color - dev: true /agentkeepalive/3.4.1: resolution: @@ -8737,7 +8773,6 @@ packages: humanize-ms: 1.2.1 transitivePeerDependencies: - supports-color - dev: true /aggregate-error/3.0.1: resolution: @@ -8758,7 +8793,6 @@ packages: ajv: ^6.9.1 dependencies: ajv: 6.12.6 - dev: true /ajv/6.12.6: resolution: @@ -8883,7 +8917,6 @@ packages: integrity: sha512-wFUFA5bg5dviipbQQ32yOQhl6gcJaJXiHE7dvR8VYPG97+J/GNC5FKGepKdEDUFeXRzDxPF1X/Btc8L+v7oqIQ==, } engines: { node: '>=4' } - dev: true /ansi-regex/4.1.0: resolution: @@ -8979,7 +9012,6 @@ packages: dependencies: normalize-path: 3.0.0 picomatch: 2.2.3 - dev: true /append-field/1.0.0: resolution: @@ -9000,7 +9032,6 @@ packages: { integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==, } - dev: true /are-we-there-yet/1.1.5: resolution: @@ -9012,6 +9043,26 @@ packages: readable-stream: 2.3.7 dev: true + /are-we-there-yet/2.0.0: + resolution: + { + integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==, + } + engines: { node: '>=10' } + dependencies: + delegates: 1.0.0 + readable-stream: 3.6.0 + + /are-we-there-yet/3.0.1: + resolution: + { + integrity: sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==, + } + engines: { node: ^12.13.0 || ^14.15.0 || >=16.0.0 } + dependencies: + delegates: 1.0.0 + readable-stream: 3.6.0 + /arg/4.1.0: resolution: { @@ -9313,7 +9364,6 @@ packages: } dependencies: safer-buffer: 2.1.2 - dev: true /assert-plus/1.0.0: resolution: @@ -9321,7 +9371,6 @@ packages: integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==, } engines: { node: '>=0.8' } - dev: true /assert/2.0.0: resolution: @@ -9373,6 +9422,12 @@ packages: } dev: true + /async-foreach/0.1.3: + resolution: + { + integrity: sha512-VUeSMD8nEGBWaZK4lizI1sf3yEC7pnAQ/mrI7pC2fBz2s/tq5jWWEngTwaf0Gruu/OoXRGLGg1XFqpYBiGTYJA==, + } + /async-retry/1.2.1: resolution: { @@ -9433,7 +9488,6 @@ packages: { integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==, } - dev: true /asyncro/3.0.0: resolution: @@ -9528,14 +9582,12 @@ packages: { integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==, } - dev: true /aws4/1.9.0: resolution: { integrity: sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A==, } - dev: true /axe-core/4.3.5: resolution: @@ -9836,7 +9888,6 @@ packages: { integrity: sha512-S8vuDB4w6YpRhICUDET3guPlQpaJl7od94tpZ0Fvnyp+MKW/HyDTcRDck+29C9g+d/qQHnddRH3+94kZdrW0Ww==, } - dev: true /balanced-match/1.0.0: resolution: @@ -9874,7 +9925,6 @@ packages: } dependencies: tweetnacl: 0.14.5 - dev: true /before-after-hook/1.4.0: resolution: @@ -9895,7 +9945,6 @@ packages: { integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==, } - dev: true /big.js/6.1.1: resolution: @@ -9919,7 +9968,6 @@ packages: integrity: sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==, } engines: { node: '>=8' } - dev: true /bindings/1.5.0: resolution: @@ -10388,7 +10436,6 @@ packages: unique-filename: 1.1.1 transitivePeerDependencies: - bluebird - dev: true /cache-base/1.0.1: resolution: @@ -10510,7 +10557,6 @@ packages: dependencies: no-case: 2.3.2 upper-case: 1.1.3 - dev: true /camel-case/4.1.2: resolution: @@ -10630,7 +10676,6 @@ packages: { integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==, } - dev: true /ccount/1.1.0: resolution: @@ -10763,7 +10808,6 @@ packages: title-case: 2.1.1 upper-case: 1.1.3 upper-case-first: 1.1.2 - dev: true /change-case/4.1.2: resolution: @@ -10805,21 +10849,18 @@ packages: { integrity: sha512-YAxUpPoPwxYFsslbdKkhrGnXAtXoHNgYjlBM3WMXkWGTl5RsY3QmOyhwAgL8Nxm9l5LBThXGawxKPn68y6/fww==, } - dev: true /character-entities/1.2.3: resolution: { integrity: sha512-yB4oYSAa9yLcGyTbB4ItFwHw43QHdH129IJ5R+WvxOkWlyFnR5FAaBNnUq4mcxsTVZGh28bHoeTHMKXH1wZf3w==, } - dev: true /character-reference-invalid/1.1.3: resolution: { integrity: sha512-VOq6PRzQBam/8Jm6XBGk2fNEnHXAdGd6go0rtd4weAGECBamHDwwCQSOT12TACIYUZegUXnV6xBXqUssijtxIg==, } - dev: true /chardet/0.4.2: resolution: @@ -10937,7 +10978,6 @@ packages: readdirp: 3.5.0 optionalDependencies: fsevents: 2.1.3 - dev: true /chownr/1.1.3: resolution: @@ -10952,7 +10992,6 @@ packages: integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==, } engines: { node: '>=10' } - dev: true /chrome-trace-event/1.0.2: resolution: @@ -10962,7 +11001,6 @@ packages: engines: { node: '>=6.0' } dependencies: tslib: 1.11.1 - dev: true /ci-info/2.0.0: resolution: @@ -11140,7 +11178,6 @@ packages: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 7.0.0 - dev: true /clone-deep/4.0.1: resolution: @@ -11245,7 +11282,6 @@ packages: { integrity: sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==, } - dev: true /collect-v8-coverage/1.0.1: resolution: @@ -11304,6 +11340,13 @@ packages: simple-swizzle: 0.2.2 dev: true + /color-support/1.1.3: + resolution: + { + integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==, + } + hasBin: true + /color/3.1.3: resolution: { @@ -11354,7 +11397,6 @@ packages: engines: { node: '>= 0.8' } dependencies: delayed-stream: 1.0.0 - dev: true /comma-separated-tokens/1.0.8: resolution: @@ -11374,7 +11416,6 @@ packages: { integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==, } - dev: true /commander/5.1.0: resolution: @@ -11568,7 +11609,6 @@ packages: { integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==, } - dev: true /constant-case/2.0.0: resolution: @@ -11578,7 +11618,6 @@ packages: dependencies: snake-case: 2.1.0 upper-case: 1.1.3 - dev: true /constant-case/3.0.4: resolution: @@ -11706,8 +11745,8 @@ packages: engines: { node: '>=10' } hasBin: true dependencies: - is-text-path: 1.0.1 JSONStream: 1.3.5 + is-text-path: 1.0.1 lodash: 4.17.21 meow: 8.1.2 split2: 2.2.0 @@ -11828,7 +11867,6 @@ packages: { integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==, } - dev: true /cors/2.8.5: resolution: @@ -12512,7 +12550,6 @@ packages: { integrity: sha512-msVS9qTuMT5zwAGCVm4mxfrZ18BNc6Csd0oJAtiFMZ1FAx1CCvy2+5MDmYoix63LM/6NDbNtodCiGYGmFgO0dA==, } - dev: true /csstype/3.0.10: resolution: @@ -12581,7 +12618,6 @@ packages: engines: { node: '>=0.10' } dependencies: assert-plus: 1.0.0 - dev: true /data-uri-to-buffer/3.0.1: resolution: @@ -12974,14 +13010,12 @@ packages: integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==, } engines: { node: '>=0.4.0' } - dev: true /delegates/1.0.0: resolution: { integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==, } - dev: true /depd/1.1.2: resolution: @@ -12989,7 +13023,6 @@ packages: integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==, } engines: { node: '>= 0.6' } - dev: true /deprecation/2.3.1: resolution: @@ -13022,7 +13055,6 @@ packages: } dependencies: repeat-string: 1.6.1 - dev: true /detect-file/1.0.0: resolution: @@ -13055,7 +13087,6 @@ packages: } engines: { node: '>=0.10' } hasBin: true - dev: true /detect-newline/3.1.0: resolution: @@ -13384,7 +13415,6 @@ packages: } dependencies: no-case: 2.3.2 - dev: true /dot-case/3.0.4: resolution: @@ -13476,7 +13506,6 @@ packages: dependencies: jsbn: 0.1.1 safer-buffer: 2.1.2 - dev: true /ecdsa-sig-formatter/1.0.11: resolution: @@ -13583,7 +13612,6 @@ packages: integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==, } engines: { node: '>= 4' } - dev: true /empty-npm-package/1.0.0: resolution: @@ -13604,7 +13632,6 @@ packages: } dependencies: iconv-lite: 0.6.2 - dev: true /end-of-stream/1.4.4: resolution: @@ -13623,7 +13650,6 @@ packages: dependencies: graceful-fs: 4.2.10 tapable: 2.2.0 - dev: true /enquirer/2.3.6: resolution: @@ -13653,7 +13679,6 @@ packages: integrity: sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==, } engines: { node: '>=6' } - dev: true /envinfo/7.7.4: resolution: @@ -13676,7 +13701,6 @@ packages: { integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==, } - dev: true /error-ex/1.3.2: resolution: @@ -13750,7 +13774,6 @@ packages: { integrity: sha512-qU2eN/XHsrl3E4y7mK1wdWnyy5c8gXtCbfP6Xcsemm7fPUR1PIV1JhZfP7ojcN0Fzp69CfrS3u76h2tusvfKiQ==, } - dev: true /es-shim-unscopables/1.0.0: resolution: @@ -14473,7 +14496,6 @@ packages: integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==, } engines: { node: '>=0.8.x' } - dev: true /evp_bytestokey/1.0.3: resolution: @@ -14738,7 +14760,6 @@ packages: { integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==, } - dev: true /external-editor/2.2.0: resolution: @@ -14814,7 +14835,6 @@ packages: integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==, } engines: { '0': node >=0.6.0 } - dev: true /extsprintf/1.4.0: resolution: @@ -14822,7 +14842,6 @@ packages: integrity: sha512-6NW8DZ8pWBc5NbGYUiqqccj9dXnuSzilZYqprdKJBZsQodGH9IyUoFOGxIWVDcBzHMb8ET24aqx9p66tZEWZkA==, } engines: { '0': node >=0.6.0 } - dev: true /faker/5.5.3: resolution: @@ -14963,6 +14982,16 @@ packages: pend: 1.2.0 dev: true + /fibers/5.0.3: + resolution: + { + integrity: sha512-/qYTSoZydQkM21qZpGLDLuCq8c+B8KhuCQ1kLPvnRNhxhVbvrpmH9l2+Lblf5neDuEsY4bfT7LeO553TXQDvJw==, + } + engines: { node: '>=10.0.0' } + requiresBuild: true + dependencies: + detect-libc: 1.0.3 + /figgy-pudding/3.5.1: resolution: { @@ -15352,7 +15381,6 @@ packages: { integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==, } - dev: true /form-data/2.3.3: resolution: @@ -15364,7 +15392,6 @@ packages: asynckit: 0.4.0 combined-stream: 1.0.8 mime-types: 2.1.30 - dev: true /form-data/2.5.1: resolution: @@ -15513,7 +15540,6 @@ packages: engines: { node: '>= 8' } dependencies: minipass: 3.1.3 - dev: true /fs.realpath/1.0.0: resolution: @@ -15547,7 +15573,6 @@ packages: os: [darwin] deprecated: '"Please update to latest v2.3 or v2.2"' requiresBuild: true - dev: true optional: true /fsevents/2.3.2: @@ -15607,6 +15632,48 @@ packages: wide-align: 1.1.3 dev: true + /gauge/3.0.2: + resolution: + { + integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==, + } + engines: { node: '>=10' } + dependencies: + aproba: 2.0.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + object-assign: 4.1.1 + signal-exit: 3.0.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.3 + + /gauge/4.0.4: + resolution: + { + integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==, + } + engines: { node: ^12.13.0 || ^14.15.0 || >=16.0.0 } + dependencies: + aproba: 2.0.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + signal-exit: 3.0.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.5 + + /gaze/1.1.3: + resolution: + { + integrity: sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==, + } + engines: { node: '>= 4.0.0' } + dependencies: + globule: 1.3.4 + /generic-names/2.0.1: resolution: { @@ -15629,7 +15696,6 @@ packages: integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==, } engines: { node: 6.* || 8.* || >= 10.* } - dev: true /get-intrinsic/1.1.1: resolution: @@ -15694,7 +15760,6 @@ packages: integrity: sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==, } engines: { node: '>=0.10.0' } - dev: true /get-stream/3.0.0: resolution: @@ -15756,7 +15821,6 @@ packages: } dependencies: assert-plus: 1.0.0 - dev: true /gh-got/6.0.0: resolution: @@ -15961,7 +16025,10 @@ packages: is-glob: 4.0.3 /glob-to-regexp/0.3.0: - resolution: { integrity: sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= } + resolution: + { + integrity: sha512-Iozmtbqv0noj0uDDqoL0zNq0VBEfK2YFoMAZoxJe4cwphvLR+JskfF30QhXHOR4m3KrE6NLRYw+U9MRXvifyig==, + } dev: true /glob-to-regexp/0.4.1: @@ -15969,7 +16036,6 @@ packages: { integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==, } - dev: true /glob/7.1.6: resolution: @@ -16164,6 +16230,17 @@ packages: } dev: true + /globule/1.3.4: + resolution: + { + integrity: sha512-OPTIfhMBh7JbBYDpa5b+Q5ptmMWKwcNcFSR/0c6t8V4f3ZAVBEsKNY37QdVqmLRYSMhOUGYrY0QhSoEpzGr/Eg==, + } + engines: { node: '>= 0.10' } + dependencies: + glob: 7.1.7 + lodash: 4.17.21 + minimatch: 3.0.4 + /got/10.7.0: resolution: { @@ -16320,7 +16397,6 @@ packages: integrity: sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==, } engines: { node: '>=4' } - dev: true /har-validator/5.1.3: resolution: @@ -16332,7 +16408,6 @@ packages: dependencies: ajv: 6.12.6 har-schema: 2.0.0 - dev: true /hard-rejection/2.1.0: resolution: @@ -16437,7 +16512,6 @@ packages: { integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==, } - dev: true /has-value/0.3.1: resolution: @@ -16646,7 +16720,6 @@ packages: dependencies: no-case: 2.3.2 upper-case: 1.1.3 - dev: true /header-case/2.0.4: resolution: @@ -16706,7 +16779,6 @@ packages: engines: { node: '>=10' } dependencies: lru-cache: 6.0.0 - dev: true /hsl-regex/1.0.0: resolution: @@ -16827,7 +16899,6 @@ packages: { integrity: sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==, } - dev: true /http-errors/1.7.2: resolution: @@ -16886,7 +16957,6 @@ packages: debug: 4.3.4 transitivePeerDependencies: - supports-color - dev: true /http-proxy/1.18.1: resolution: @@ -16912,7 +16982,6 @@ packages: assert-plus: 1.0.0 jsprim: 1.4.1 sshpk: 1.16.1 - dev: true /http-status/1.5.3: resolution: @@ -16950,7 +17019,6 @@ packages: debug: 4.3.4 transitivePeerDependencies: - supports-color - dev: true /human-signals/1.1.1: resolution: @@ -16974,7 +17042,6 @@ packages: } dependencies: ms: 2.1.3 - dev: true /husky/8.0.0: resolution: @@ -17002,7 +17069,6 @@ packages: engines: { node: '>=0.10.0' } dependencies: safer-buffer: 2.1.2 - dev: true /icss-replace-symbols/1.1.0: resolution: @@ -17107,7 +17173,6 @@ packages: { integrity: sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==, } - dev: true /import-cwd/3.0.0: resolution: @@ -17214,7 +17279,6 @@ packages: { integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==, } - dev: true /inflight/1.0.6: resolution: @@ -17376,7 +17440,6 @@ packages: { integrity: sha512-rBtCAQAJm8A110nbwn6YdveUnuZH3WrC36IwkRXxDnq53JvXA2NVQvB7IHyKomxK1MJ4VDNw3UtFDdXQ+AvLYA==, } - dev: true /ipaddr.js/1.9.0: resolution: @@ -17430,7 +17493,6 @@ packages: { integrity: sha512-eEMa6MKpHFzw38eKm56iNNi6GJ7lf6aLLio7Kr23sJPAECscgRtZvOBYybejWDQ2bM949Y++61PY+udzj5QMLA==, } - dev: true /is-alphanumerical/1.0.3: resolution: @@ -17440,7 +17502,6 @@ packages: dependencies: is-alphabetical: 1.0.3 is-decimal: 1.0.3 - dev: true /is-animated/2.0.2: resolution: @@ -17491,7 +17552,6 @@ packages: engines: { node: '>=8' } dependencies: binary-extensions: 2.1.0 - dev: true /is-boolean-object/1.1.0: resolution: @@ -17515,7 +17575,6 @@ packages: integrity: sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==, } engines: { node: '>=4' } - dev: true /is-callable/1.2.4: resolution: @@ -17598,7 +17657,6 @@ packages: { integrity: sha512-bvLSwoDg2q6Gf+E2LEPiklHZxxiSi3XAh4Mav65mKqTfCO1HM3uBs24TjEH8iJX3bbDdLXKJXBTmGzuTUuAEjQ==, } - dev: true /is-descriptor/0.1.6: resolution: @@ -17717,7 +17775,6 @@ packages: integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==, } engines: { node: '>=4' } - dev: true /is-fullwidth-code-point/3.0.0: resolution: @@ -17786,7 +17843,6 @@ packages: { integrity: sha512-zxQ9//Q3D/34poZf8fiy3m3XVpbQc7ren15iKqrTtLPwkPD/t3Scy9Imp63FujULGxuK0ZlCwoo5xNpktFgbOA==, } - dev: true /is-installed-globally/0.3.2: resolution: @@ -17820,7 +17876,6 @@ packages: { integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==, } - dev: true /is-lower-case/1.1.3: resolution: @@ -17829,7 +17884,6 @@ packages: } dependencies: lower-case: 1.1.4 - dev: true /is-module/1.0.0: resolution: @@ -18138,7 +18192,6 @@ packages: { integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==, } - dev: true /is-unc-path/1.0.0: resolution: @@ -18173,7 +18226,6 @@ packages: } dependencies: upper-case: 1.1.3 - dev: true /is-utf8/0.2.1: resolution: { integrity: sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= } @@ -18199,7 +18251,6 @@ packages: { integrity: sha512-SNPgMLz9JzPccD3nPctcj8sZlX9DAMJSKH8bP7Z6bohCwuNgX8xbWr1eTAYXX9Vpi/aSn8Y1akL9WgM3t43YNQ==, } - dev: true /is-windows/0.2.0: resolution: @@ -18221,7 +18272,6 @@ packages: { integrity: sha512-0wfcrFgOOOBdgRNT9H33xe6Zi6yhX/uoc4U8NBZGeQQB0ctU1dnlNTyL9JM2646bHDTpsDm1Brb3VPoCIMrd/A==, } - dev: true /is-wsl/1.1.0: resolution: @@ -18315,7 +18365,6 @@ packages: { integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==, } - dev: true /istanbul-lib-coverage/3.2.0: resolution: @@ -19271,7 +19320,6 @@ packages: '@types/node': 17.0.21 merge-stream: 2.0.0 supports-color: 8.1.1 - dev: true /jest-worker/27.5.1: resolution: @@ -19322,7 +19370,6 @@ packages: { integrity: sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==, } - dev: true /js-tokens/4.0.0: resolution: @@ -19345,7 +19392,6 @@ packages: { integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==, } - dev: true /jscodeshift/0.13.1_@babel+preset-env@7.18.0: resolution: @@ -19471,7 +19517,6 @@ packages: { integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==, } - dev: true /json-schema-traverse/0.4.1: resolution: @@ -19494,7 +19539,6 @@ packages: /json-schema/0.2.3: resolution: { integrity: sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= } - dev: true /json-stable-stringify-without-jsonify/1.0.1: resolution: @@ -19507,7 +19551,6 @@ packages: { integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==, } - dev: true /json-to-ast/2.1.0: resolution: @@ -19627,7 +19670,6 @@ packages: extsprintf: 1.3.0 json-schema: 0.2.3 verror: 1.10.0 - dev: true /jsx-ast-utils/3.2.1: resolution: @@ -20139,7 +20181,6 @@ packages: integrity: sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==, } engines: { node: '>=6.11.5' } - dev: true /loader-utils/1.4.0: resolution: @@ -20151,7 +20192,6 @@ packages: big.js: 5.2.2 emojis-list: 3.0.0 json5: 1.0.1 - dev: true /loader-utils/2.0.0: resolution: @@ -20499,14 +20539,12 @@ packages: } dependencies: lower-case: 1.1.4 - dev: true /lower-case/1.1.4: resolution: { integrity: sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==, } - dev: true /lower-case/2.0.2: resolution: @@ -20631,6 +20669,33 @@ packages: - supports-color dev: true + /make-fetch-happen/9.1.0: + resolution: + { + integrity: sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==, + } + engines: { node: '>= 10' } + dependencies: + agentkeepalive: 4.1.4 + cacache: 15.3.0 + http-cache-semantics: 4.1.0 + http-proxy-agent: 4.0.1 + https-proxy-agent: 5.0.0 + is-lambda: 1.0.1 + lru-cache: 6.0.0 + minipass: 3.1.3 + minipass-collect: 1.0.2 + minipass-fetch: 1.3.3 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + negotiator: 0.6.2 + promise-retry: 2.0.1 + socks-proxy-agent: 6.1.1 + ssri: 8.0.1 + transitivePeerDependencies: + - bluebird + - supports-color + /make-iterator/1.0.1: resolution: { @@ -20697,7 +20762,6 @@ packages: { integrity: sha512-XUi5HJhhV5R74k8/0H2oCbCiYf/u4cO/rX8tnGkRvrqhsr5BRNU6Mg0yt/8UIx1iIS8220BNJsDb7XnILhLepw==, } - dev: true /math-random/1.0.4: resolution: @@ -20744,7 +20808,6 @@ packages: } dependencies: unist-util-remove: 1.0.3 - dev: true /mdast-util-definitions/1.2.5: resolution: @@ -20753,7 +20816,6 @@ packages: } dependencies: unist-util-visit: 1.4.1 - dev: true /mdast-util-mdx-expression/0.1.1: resolution: @@ -20814,7 +20876,6 @@ packages: unist-util-position: 3.0.4 unist-util-visit: 1.4.1 xtend: 4.0.2 - dev: true /mdast-util-to-markdown/0.6.5: resolution: @@ -20861,7 +20922,6 @@ packages: { integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==, } - dev: true /media-typer/0.3.0: resolution: { integrity: sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= } @@ -20954,6 +21014,26 @@ packages: yargs-parser: 20.2.4 dev: true + /meow/9.0.0: + resolution: + { + integrity: sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==, + } + engines: { node: '>=10' } + dependencies: + '@types/minimist': 1.2.0 + camelcase-keys: 6.2.2 + decamelize: 1.2.0 + decamelize-keys: 1.1.0 + hard-rejection: 2.1.0 + minimist-options: 4.1.0 + normalize-package-data: 3.0.0 + read-pkg-up: 7.0.1 + redent: 3.0.0 + trim-newlines: 3.0.0 + type-fest: 0.18.1 + yargs-parser: 20.2.4 + /merge-descriptors/1.0.1: resolution: { @@ -21021,15 +21101,16 @@ packages: rollup-plugin-bundle-size: 1.0.3 rollup-plugin-postcss: 4.0.0_postcss@8.4.5 rollup-plugin-terser: 7.0.2_rollup@2.35.1 - rollup-plugin-typescript2: 0.29.0_qdoq77m3lkibs3ktoonmxnobxy + rollup-plugin-typescript2: 0.29.0_44ydqmng6h4ke4g2ndcb3briji rollup-plugin-visualizer: 5.6.0_rollup@2.35.1 sade: 1.7.4 terser: 5.10.0 tiny-glob: 0.2.8 tslib: 2.4.0 - typescript: 4.6.3 + typescript: 4.8.2 transitivePeerDependencies: - '@types/babel__core' + - acorn - supports-color dev: true @@ -21194,7 +21275,6 @@ packages: integrity: sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==, } engines: { node: '>= 0.6' } - dev: true /mime-types/2.1.30: resolution: @@ -21204,7 +21284,6 @@ packages: engines: { node: '>= 0.6' } dependencies: mime-db: 1.47.0 - dev: true /mime/1.6.0: resolution: @@ -21301,7 +21380,6 @@ packages: } dependencies: brace-expansion: 1.1.11 - dev: true /minimatch/3.1.2: resolution: @@ -21346,7 +21424,6 @@ packages: engines: { node: '>= 8' } dependencies: minipass: 3.1.3 - dev: true /minipass-fetch/1.3.3: resolution: @@ -21360,7 +21437,6 @@ packages: minizlib: 2.1.2 optionalDependencies: encoding: 0.1.13 - dev: true /minipass-flush/1.0.5: resolution: @@ -21370,7 +21446,6 @@ packages: engines: { node: '>= 8' } dependencies: minipass: 3.1.3 - dev: true /minipass-json-stream/1.0.1: resolution: @@ -21390,7 +21465,6 @@ packages: engines: { node: '>=8' } dependencies: minipass: 3.1.3 - dev: true /minipass-sized/1.0.3: resolution: @@ -21400,7 +21474,6 @@ packages: engines: { node: '>=8' } dependencies: minipass: 3.1.3 - dev: true /minipass/2.9.0: resolution: @@ -21420,7 +21493,6 @@ packages: engines: { node: '>=8' } dependencies: yallist: 4.0.0 - dev: true /minizlib/1.3.3: resolution: @@ -21440,7 +21512,6 @@ packages: dependencies: minipass: 3.1.3 yallist: 4.0.0 - dev: true /mixin-deep/1.3.2: resolution: @@ -21487,7 +21558,6 @@ packages: } engines: { node: '>=10' } hasBin: true - dev: true /modify-values/1.0.1: resolution: @@ -21616,7 +21686,6 @@ packages: { integrity: sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==, } - dev: true /nanoid/3.1.30: resolution: @@ -21686,7 +21755,6 @@ packages: integrity: sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==, } engines: { node: '>= 0.6' } - dev: true /neo-async/2.6.1: resolution: @@ -21762,7 +21830,6 @@ packages: } dependencies: lower-case: 1.1.4 - dev: true /no-case/3.0.4: resolution: @@ -21880,6 +21947,28 @@ packages: which: 2.0.2 dev: true + /node-gyp/8.4.1: + resolution: + { + integrity: sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==, + } + engines: { node: '>= 10.12.0' } + hasBin: true + dependencies: + env-paths: 2.2.0 + glob: 7.2.0 + graceful-fs: 4.2.10 + make-fetch-happen: 9.1.0 + nopt: 5.0.0 + npmlog: 6.0.2 + rimraf: 3.0.2 + semver: 7.3.7 + tar: 6.1.11 + which: 2.0.2 + transitivePeerDependencies: + - bluebird + - supports-color + /node-html-parser/5.3.3: resolution: { @@ -21939,6 +22028,34 @@ packages: integrity: sha512-maHFz6OLqYxz+VQyCAtA3PTX4UP/53pa05fyDNc9CwjvJ0yEh6+xBwKsgCxMNhS8taUKBFYxfuiaD9U/55iFaw==, } + /node-sass/7.0.3: + resolution: + { + integrity: sha512-8MIlsY/4dXUkJDYht9pIWBhMil3uHmE8b/AdJPjmFn1nBx9X9BASzfzmsCy0uCCb8eqI3SYYzVPDswWqSx7gjw==, + } + engines: { node: '>=12' } + hasBin: true + requiresBuild: true + dependencies: + async-foreach: 0.1.3 + chalk: 4.1.2 + cross-spawn: 7.0.3 + gaze: 1.1.3 + get-stdin: 4.0.1 + glob: 7.2.0 + lodash: 4.17.21 + meow: 9.0.0 + nan: 2.15.0 + node-gyp: 8.4.1 + npmlog: 5.0.1 + request: 2.88.2 + sass-graph: 4.0.1 + stdout-stream: 1.4.1 + true-case-path: 1.0.3 + transitivePeerDependencies: + - bluebird + - supports-color + /node-version/1.1.3: resolution: { @@ -21975,7 +22092,6 @@ packages: hasBin: true dependencies: abbrev: 1.1.1 - dev: true /normalize-html-whitespace/1.0.0: resolution: @@ -22007,7 +22123,6 @@ packages: resolve: 1.22.0 semver: 7.3.7 validate-npm-package-license: 3.0.4 - dev: true /normalize-path/2.1.1: resolution: @@ -22025,7 +22140,6 @@ packages: integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==, } engines: { node: '>=0.10.0' } - dev: true /normalize-range/0.1.2: resolution: { integrity: sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= } @@ -22211,6 +22325,29 @@ packages: set-blocking: 2.0.0 dev: true + /npmlog/5.0.1: + resolution: + { + integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==, + } + dependencies: + are-we-there-yet: 2.0.0 + console-control-strings: 1.1.0 + gauge: 3.0.2 + set-blocking: 2.0.0 + + /npmlog/6.0.2: + resolution: + { + integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==, + } + engines: { node: ^12.13.0 || ^14.15.0 || >=16.0.0 } + dependencies: + are-we-there-yet: 3.0.1 + console-control-strings: 1.1.0 + gauge: 4.0.4 + set-blocking: 2.0.0 + /nprogress/0.2.0: resolution: { integrity: sha1-y480xTIT2JVyP8urkH6UIq28r7E= } dev: true @@ -22266,7 +22403,6 @@ packages: { integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==, } - dev: true /object-assign/4.1.1: resolution: @@ -22737,7 +22873,6 @@ packages: engines: { node: '>=10' } dependencies: yocto-queue: 0.1.0 - dev: true /p-locate/2.0.0: resolution: @@ -22957,7 +23092,6 @@ packages: } dependencies: no-case: 2.3.2 - dev: true /param-case/3.0.4: resolution: @@ -23016,7 +23150,6 @@ packages: is-alphanumerical: 1.0.3 is-decimal: 1.0.3 is-hexadecimal: 1.0.3 - dev: true /parse-entities/2.0.0: resolution: @@ -23183,7 +23316,6 @@ packages: dependencies: camel-case: 3.0.0 upper-case-first: 1.1.2 - dev: true /pascal-case/3.1.2: resolution: @@ -23217,7 +23349,6 @@ packages: } dependencies: no-case: 2.3.2 - dev: true /path-case/3.0.4: resolution: @@ -23382,7 +23513,6 @@ packages: { integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==, } - dev: true /picocolors/1.0.0: resolution: @@ -24896,7 +25026,6 @@ packages: { integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==, } - dev: true /process/0.11.10: resolution: { integrity: sha1-czIwDoQBYb2j5podHZGn1LwW8YI= } @@ -24920,7 +25049,6 @@ packages: peerDependenciesMeta: bluebird: optional: true - dev: true /promise-polyfill/6.1.0: resolution: @@ -24956,7 +25084,6 @@ packages: dependencies: err-code: 2.0.3 retry: 0.12.0 - dev: true /promise.series/0.2.0: resolution: @@ -25102,7 +25229,6 @@ packages: { integrity: sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==, } - dev: true /public-encrypt/4.0.3: resolution: @@ -25195,7 +25321,6 @@ packages: integrity: sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==, } engines: { node: '>=0.6' } - dev: true /qs/6.7.0: resolution: @@ -25293,7 +25418,6 @@ packages: } dependencies: safe-buffer: 5.2.0 - dev: true /randomfill/1.0.4: resolution: @@ -25352,6 +25476,20 @@ packages: strip-json-comments: 2.0.1 dev: true + /react-dom/17.0.2_react@17.0.2: + resolution: + { + integrity: sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==, + } + peerDependencies: + react: 17.0.2 + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react: 17.0.2 + scheduler: 0.20.2 + dev: false + /react-dom/17.0.2_react@18.2.0: resolution: { @@ -25377,7 +25515,6 @@ packages: loose-envify: 1.4.0 react: 18.2.0 scheduler: 0.23.0 - dev: true /react-dom/18.3.0-next-28a574ea8-20221027_react@18.2.0: resolution: @@ -25479,6 +25616,18 @@ packages: react-lifecycles-compat: 3.0.4 dev: true + /react/16.14.0: + resolution: + { + integrity: sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==, + } + engines: { node: '>=0.10.0' } + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + prop-types: 15.8.1 + dev: false + /react/17.0.2: resolution: { @@ -25488,7 +25637,6 @@ packages: dependencies: loose-envify: 1.4.0 object-assign: 4.1.1 - dev: true /react/18.2.0: resolution: @@ -25608,7 +25756,10 @@ packages: type-fest: 0.8.1 /read-pkg/1.1.0: - resolution: { integrity: sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= } + resolution: + { + integrity: sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==, + } engines: { node: '>=0.10.0' } dependencies: load-json-file: 1.1.0 @@ -25704,7 +25855,6 @@ packages: safe-buffer: 5.1.2 string_decoder: 1.1.1 util-deprecate: 1.0.2 - dev: true /readable-stream/3.6.0: resolution: @@ -25716,7 +25866,6 @@ packages: inherits: 2.0.4 string_decoder: 1.3.0 util-deprecate: 1.0.2 - dev: true /readdir-scoped-modules/1.1.0: resolution: @@ -25752,7 +25901,6 @@ packages: engines: { node: '>=8.10.0' } dependencies: picomatch: 2.2.3 - dev: true /recast/0.20.5: resolution: @@ -26153,7 +26301,6 @@ packages: unist-util-remove-position: 1.1.4 vfile-location: 2.0.6 xtend: 4.0.2 - dev: true /remark-parse/8.0.3: resolution: @@ -26195,7 +26342,6 @@ packages: } dependencies: mdast-squeeze-paragraphs: 3.0.5 - dev: true /remote-origin-url/0.5.3: resolution: @@ -26252,7 +26398,6 @@ packages: integrity: sha512-vuNYXC7gG7IeVNBC1xUllqCcZKRbJoSPOBhnTEcAIiKCsbuef6zO3F0Rve3isPMMoNoQRWjQwbAgAjHUHniyEA==, } engines: { node: '>= 0.10' } - dev: true /request-promise-core/1.1.2_request@2.88.2: resolution: @@ -26295,7 +26440,6 @@ packages: tough-cookie: 2.5.0 tunnel-agent: 0.6.0 uuid: 3.3.3 - dev: true /require-directory/2.1.1: resolution: @@ -26303,7 +26447,6 @@ packages: integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==, } engines: { node: '>=0.10.0' } - dev: true /require-from-string/1.2.1: resolution: { integrity: sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg= } @@ -26545,7 +26688,6 @@ packages: /retry/0.12.0: resolution: { integrity: sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= } engines: { node: '>= 4' } - dev: true /reusify/1.0.4: resolution: @@ -26672,7 +26814,7 @@ packages: terser: 5.14.1 dev: true - /rollup-plugin-typescript2/0.29.0_qdoq77m3lkibs3ktoonmxnobxy: + /rollup-plugin-typescript2/0.29.0_44ydqmng6h4ke4g2ndcb3briji: resolution: { integrity: sha512-YytahBSZCIjn/elFugEGQR5qTsVhxhUwGZIsA9TmrSsC88qroGo65O5HZP/TTArH2dm0vUmYWhKchhwi2wL9bw==, @@ -26687,7 +26829,7 @@ packages: resolve: 1.17.0 rollup: 2.35.1 tslib: 2.0.1 - typescript: 4.6.3 + typescript: 4.8.2 dev: true /rollup-plugin-visualizer/5.6.0_rollup@2.35.1: @@ -26798,7 +26940,6 @@ packages: { integrity: sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==, } - dev: true /safe-identifier/0.4.2: resolution: @@ -26822,7 +26963,20 @@ packages: integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==, } - /sass-loader/12.4.0_webpack@5.74.0: + /sass-graph/4.0.1: + resolution: + { + integrity: sha512-5YCfmGBmxoIRYHnKK2AKzrAkCoQ8ozO+iumT8K4tXJXRVCPf+7s1/9KxTSW3Rbvf+7Y7b4FR3mWyLnQr3PHocA==, + } + engines: { node: '>=12' } + hasBin: true + dependencies: + glob: 7.2.0 + lodash: 4.17.21 + scss-tokenizer: 0.4.3 + yargs: 17.5.1 + + /sass-loader/12.4.0_y7k4qxzyfvxio3t476zhrzlwf4: resolution: { integrity: sha512-7xN+8khDIzym1oL9XyS6zP6Ges+Bo2B2xbPrjdMHEYyV3AQYhd/wXeru++3ODHF0zMjYmVadblSKrPrjEkL8mg==, @@ -26841,8 +26995,11 @@ packages: sass: optional: true dependencies: + fibers: 5.0.3 klona: 2.0.4 neo-async: 2.6.2 + node-sass: 7.0.3 + sass: 1.54.0 webpack: 5.74.0 dev: true @@ -26857,7 +27014,6 @@ packages: chokidar: 3.4.3 immutable: 4.1.0 source-map-js: 1.0.2 - dev: true /sax/1.2.4: resolution: @@ -26884,7 +27040,6 @@ packages: dependencies: loose-envify: 1.4.0 object-assign: 4.1.1 - dev: true /scheduler/0.23.0: resolution: @@ -26893,7 +27048,6 @@ packages: } dependencies: loose-envify: 1.4.0 - dev: true /scheduler/0.24.0-next-28a574ea8-20221027: resolution: @@ -26938,7 +27092,15 @@ packages: '@types/json-schema': 7.0.9 ajv: 6.12.6 ajv-keywords: 3.5.2_ajv@6.12.6 - dev: true + + /scss-tokenizer/0.4.3: + resolution: + { + integrity: sha512-raKLgf1LI5QMQnG+RxHz6oK0sL3x3I4FN2UDLqgLOGO8hodECNnNh5BXn7fAyBxrA8zVzdQizQ6XjNJQ+uBwMw==, + } + dependencies: + js-base64: 2.5.1 + source-map: 0.7.3 /seedrandom/3.0.5: resolution: @@ -27057,7 +27219,6 @@ packages: dependencies: no-case: 2.3.2 upper-case-first: 1.1.2 - dev: true /sentence-case/3.0.4: resolution: @@ -27086,7 +27247,6 @@ packages: } dependencies: randombytes: 2.1.0 - dev: true /serve-static/1.14.1: resolution: @@ -27108,7 +27268,6 @@ packages: { integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==, } - dev: true /set-immediate-shim/1.0.1: resolution: { integrity: sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E= } @@ -27337,7 +27496,6 @@ packages: integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==, } engines: { node: '>= 6.0.0', npm: '>= 3.0.0' } - dev: true /snake-case/2.1.0: resolution: @@ -27346,7 +27504,6 @@ packages: } dependencies: no-case: 2.3.2 - dev: true /snake-case/3.0.4: resolution: @@ -27424,7 +27581,6 @@ packages: socks: 2.6.2 transitivePeerDependencies: - supports-color - dev: true /socks/2.6.2: resolution: @@ -27435,7 +27591,6 @@ packages: dependencies: ip: 1.1.5 smart-buffer: 4.2.0 - dev: true /sort-keys/2.0.0: resolution: { integrity: sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg= } @@ -27539,7 +27694,6 @@ packages: integrity: sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==, } engines: { node: '>= 8' } - dev: true /source-map/0.8.0-beta.0: resolution: @@ -27683,7 +27837,6 @@ packages: jsbn: 0.1.1 safer-buffer: 2.1.2 tweetnacl: 0.14.5 - dev: true /ssri/8.0.1: resolution: @@ -27693,7 +27846,6 @@ packages: engines: { node: '>= 8' } dependencies: minipass: 3.1.3 - dev: true /stable/0.1.8: resolution: @@ -27726,7 +27878,6 @@ packages: { integrity: sha512-8LpelPGR0qQM4PnfLiplOQNJcIN1/r2Gy0xKB2zKnIW2YzPMt2sR4I/+gtPjhN7Svh9kw+zqEg2SFwpBO9iNiw==, } - dev: true /static-extend/0.1.2: resolution: @@ -27744,6 +27895,14 @@ packages: engines: { node: '>= 0.6' } dev: true + /stdout-stream/1.4.1: + resolution: + { + integrity: sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==, + } + dependencies: + readable-stream: 2.3.7 + /stream-browserify/3.0.0: resolution: { @@ -27842,7 +28001,6 @@ packages: dependencies: is-fullwidth-code-point: 2.0.0 strip-ansi: 4.0.0 - dev: true /string-width/3.1.0: resolution: @@ -27943,7 +28101,6 @@ packages: } dependencies: safe-buffer: 5.1.2 - dev: true /string_decoder/1.3.0: resolution: @@ -27952,7 +28109,6 @@ packages: } dependencies: safe-buffer: 5.2.0 - dev: true /stringify-entities/3.1.0: resolution: @@ -27995,7 +28151,6 @@ packages: engines: { node: '>=4' } dependencies: ansi-regex: 3.0.0 - dev: true /strip-ansi/5.2.0: resolution: @@ -28274,7 +28429,6 @@ packages: engines: { node: '>=10' } dependencies: has-flag: 4.0.0 - dev: true /supports-hyperlinks/2.1.0: resolution: @@ -28333,7 +28487,6 @@ packages: dependencies: lower-case: 1.1.4 upper-case: 1.1.3 - dev: true /swr/2.0.0-rc.0_react@18.2.0: resolution: @@ -28424,7 +28577,6 @@ packages: integrity: sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw==, } engines: { node: '>=6' } - dev: true /tar/4.4.10: resolution: @@ -28471,7 +28623,6 @@ packages: minizlib: 2.1.2 mkdirp: 1.0.4 yallist: 4.0.0 - dev: true /taskr/1.1.0: resolution: { integrity: sha1-TynQrOJvTerppHjqv5qgQy6IRDg= } @@ -28597,7 +28748,6 @@ packages: source-map: 0.6.1 terser: 5.14.1 webpack: 5.74.0 - dev: true /terser/5.10.0: resolution: @@ -28606,6 +28756,8 @@ packages: } engines: { node: '>=10' } hasBin: true + peerDependencies: + acorn: ^8.5.0 peerDependenciesMeta: acorn: optional: true @@ -28628,7 +28780,6 @@ packages: acorn: 8.8.0 commander: 2.20.3 source-map-support: 0.5.20 - dev: true /terser/5.5.1: resolution: @@ -28787,7 +28938,6 @@ packages: dependencies: no-case: 2.3.2 upper-case: 1.1.3 - dev: true /title-case/3.0.3: resolution: @@ -28891,7 +29041,6 @@ packages: { integrity: sha512-9K8KYegr9hrdm8yPpu5iZjJp5t6RPAp4gFDU5hD9zR8hwqgF4fsoSitMtkRKQG2qkP5j/uG3wajbgV09rjmIqg==, } - dev: true /to-vfile/6.1.0: resolution: @@ -28927,7 +29076,6 @@ packages: dependencies: psl: 1.8.0 punycode: 2.1.1 - dev: true /tough-cookie/4.0.0: resolution: @@ -28978,7 +29126,6 @@ packages: { integrity: sha512-E0ZosSWYK2mkSu+KEtQ9/KqarVjA9HztOSX+9FDdNacRAq29RRV6ZQNgob3iuW8Htar9vAfEa6yyt5qBAHZDBA==, } - dev: true /trim-newlines/1.0.0: resolution: @@ -29005,21 +29152,26 @@ packages: { integrity: sha512-MUjYItdrqqj2zpcHFTkMa9WAv4JHTI6gnRQGPFLrt5L9a6tRMiDnIqYl8JBvu2d2Tc3lWJKQwlGCp0K8AvCM+Q==, } - dev: true /trim/0.0.1: resolution: { integrity: sha512-YzQV+TZg4AxpKxaTHK3c3D+kRDCGVEE7LemdlQZoQXn0iennk10RsIoY6ikzAqJTc9Xjl9C1/waHom/J86ziAQ==, } - dev: true /trough/1.0.4: resolution: { integrity: sha512-tdzBRDGWcI1OpPVmChbdSKhvSVurznZ8X36AYURAcl+0o2ldlCY2XPzyXNNxwJwwyIU+rIglTCG4kxtNKBQH7Q==, } - dev: true + + /true-case-path/1.0.3: + resolution: + { + integrity: sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==, + } + dependencies: + glob: 7.2.0 /tsconfig-paths/3.14.1: resolution: @@ -29099,7 +29251,6 @@ packages: } dependencies: safe-buffer: 5.2.0 - dev: true /turbo-darwin-64/1.5.3: resolution: @@ -29188,7 +29339,6 @@ packages: { integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==, } - dev: true /type-check/0.3.2: resolution: @@ -29238,7 +29388,6 @@ packages: integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==, } engines: { node: '>=10' } - dev: true /type-fest/0.20.2: resolution: @@ -29317,15 +29466,6 @@ packages: } dev: true - /typescript/4.6.3: - resolution: - { - integrity: sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==, - } - engines: { node: '>=4.2.0' } - hasBin: true - dev: true - /typescript/4.8.2: resolution: { @@ -29406,7 +29546,6 @@ packages: dependencies: inherits: 2.0.4 xtend: 4.0.2 - dev: true /unicode-canonical-property-names-ecmascript/1.0.4: resolution: @@ -29557,7 +29696,6 @@ packages: trough: 1.0.4 vfile: 3.0.1 x-is-string: 0.1.0 - dev: true /unified/9.2.1: resolution: @@ -29608,7 +29746,6 @@ packages: } dependencies: unique-slug: 2.0.2 - dev: true /unique-slug/2.0.2: resolution: @@ -29617,7 +29754,6 @@ packages: } dependencies: imurmurhash: 0.1.4 - dev: true /unique-string/1.0.0: resolution: @@ -29646,14 +29782,12 @@ packages: } dependencies: object-assign: 4.1.1 - dev: true /unist-util-generated/1.1.6: resolution: { integrity: sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg==, } - dev: true /unist-util-inspect/5.0.1: resolution: @@ -29669,7 +29803,6 @@ packages: { integrity: sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==, } - dev: true /unist-util-is/4.1.0: resolution: @@ -29692,7 +29825,6 @@ packages: { integrity: sha512-tWvIbV8goayTjobxDIr4zVTyG+Q7ragMSMeKC3xnPl9xzIc0+she8mxXLM3JVNDDsfARPbCd3XdzkyLdo7fF3g==, } - dev: true /unist-util-remove-position/1.1.4: resolution: @@ -29701,7 +29833,6 @@ packages: } dependencies: unist-util-visit: 1.4.1 - dev: true /unist-util-remove-position/2.0.1: resolution: @@ -29728,14 +29859,12 @@ packages: } dependencies: unist-util-is: 3.0.0 - dev: true /unist-util-stringify-position/1.1.2: resolution: { integrity: sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==, } - dev: true /unist-util-stringify-position/2.0.3: resolution: @@ -29753,7 +29882,6 @@ packages: } dependencies: '@types/unist': 2.0.3 - dev: true /unist-util-visit-children/1.1.4: resolution: @@ -29769,7 +29897,6 @@ packages: } dependencies: unist-util-is: 3.0.0 - dev: true /unist-util-visit-parents/3.1.1: resolution: @@ -29788,7 +29915,6 @@ packages: } dependencies: unist-util-visit-parents: 2.1.2 - dev: true /unist-util-visit/2.0.3: resolution: @@ -29926,7 +30052,6 @@ packages: } dependencies: upper-case: 1.1.3 - dev: true /upper-case-first/2.0.2: resolution: @@ -29942,7 +30067,6 @@ packages: { integrity: sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==, } - dev: true /upper-case/2.0.2: resolution: @@ -30024,7 +30148,6 @@ packages: { integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==, } - dev: true /util-promisify/2.1.0: resolution: { integrity: sha1-PCI2R2xNMsX/PEcAKt18E7moKlM= } @@ -30071,7 +30194,6 @@ packages: } deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. hasBin: true - dev: true /uuid/8.3.2: resolution: @@ -30145,7 +30267,6 @@ packages: assert-plus: 1.0.0 core-util-is: 1.0.2 extsprintf: 1.4.0 - dev: true /vfile-find-up/5.0.1: resolution: @@ -30161,7 +30282,6 @@ packages: { integrity: sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA==, } - dev: true /vfile-location/3.2.0: resolution: @@ -30177,7 +30297,6 @@ packages: } dependencies: unist-util-stringify-position: 1.1.2 - dev: true /vfile-message/2.0.4: resolution: @@ -30197,7 +30316,6 @@ packages: dependencies: '@types/unist': 2.0.3 unist-util-stringify-position: 3.0.0 - dev: true /vfile-reporter/6.0.2: resolution: @@ -30237,7 +30355,6 @@ packages: replace-ext: 1.0.0 unist-util-stringify-position: 1.1.2 vfile-message: 1.1.1 - dev: true /vfile/4.2.1: resolution: @@ -30306,7 +30423,6 @@ packages: dependencies: glob-to-regexp: 0.4.1 graceful-fs: 4.2.10 - dev: true /wcwidth/1.0.1: resolution: @@ -30417,7 +30533,6 @@ packages: integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==, } engines: { node: '>=10.13.0' } - dev: true /webpack-stats-plugin/1.1.0: resolution: @@ -30467,7 +30582,6 @@ packages: - '@swc/core' - esbuild - uglify-js - dev: true /webpack/5.74.0_@swc+core@1.2.203: resolution: @@ -30496,7 +30610,7 @@ packages: eslint-scope: 5.1.1 events: 3.3.0 glob-to-regexp: 0.4.1 - graceful-fs: 4.2.9 + graceful-fs: 4.2.10 json-parse-even-better-errors: 2.3.1 loader-runner: 4.2.0 mime-types: 2.1.30 @@ -30650,7 +30764,14 @@ packages: } dependencies: string-width: 2.1.1 - dev: true + + /wide-align/1.1.5: + resolution: + { + integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==, + } + dependencies: + string-width: 4.2.3 /widest-line/3.1.0: resolution: @@ -30841,7 +30962,6 @@ packages: { integrity: sha512-GojqklwG8gpzOVEVki5KudKNoq7MbbjYZCbyWzEz7tyPA7eleiE0+ePwOWQQRb5fm86rD3S8Tc0tSFf3AOv50w==, } - dev: true /xdg-basedir/3.0.0: resolution: @@ -30894,7 +31014,6 @@ packages: integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==, } engines: { node: '>=0.4' } - dev: true /y18n/4.0.0: resolution: @@ -30909,7 +31028,6 @@ packages: integrity: sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==, } engines: { node: '>=10' } - dev: true /yallist/2.1.2: resolution: @@ -30964,7 +31082,6 @@ packages: integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==, } engines: { node: '>=10' } - dev: true /yargs-parser/21.0.1: resolution: @@ -30972,7 +31089,6 @@ packages: integrity: sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==, } engines: { node: '>=12' } - dev: true /yargs/14.2.2: resolution: @@ -31023,7 +31139,6 @@ packages: string-width: 4.2.3 y18n: 5.0.5 yargs-parser: 21.0.1 - dev: true /yauzl/2.10.0: resolution: @@ -31050,7 +31165,6 @@ packages: integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==, } engines: { node: '>=10' } - dev: true /zwitch/1.0.5: resolution: diff --git a/test/integration/create-next-app/index.test.ts b/test/integration/create-next-app/index.test.ts index 3b56e3864aa7f..1982f008777b5 100644 --- a/test/integration/create-next-app/index.test.ts +++ b/test/integration/create-next-app/index.test.ts @@ -1,36 +1,42 @@ /* eslint-env jest */ +/** + * @fileoverview + * + * This file contains integration tests for `create-next-app`. It currently + * aliases all calls to `--js`. + * + * TypeScript project creation via `create-next-app --ts` is tested in + * `./templates.test.ts`, though additional tests can be added here using the + * `shouldBeTypescriptProject` helper. + */ + import execa from 'execa' import fs from 'fs-extra' -import os from 'os' import path from 'path' -const cli = require.resolve('create-next-app/dist/index.js') +import { useTempDir } from '../../lib/use-temp-dir' +import { + projectFilesShouldExist, + projectFilesShouldNotExist, + shouldBeJavascriptProject, +} from './lib/utils' +const cli = require.resolve('create-next-app/dist/index.js') const exampleRepo = 'https://github.com/vercel/next.js/tree/canary' const examplePath = 'examples/basic-css' const run = (args: string[], options: execa.Options) => execa('node', [cli].concat(args), options) -async function usingTempDir(fn: (...args: any[]) => any, options?: any) { - const folder = path.join(os.tmpdir(), Math.random().toString(36).substring(2)) - await fs.mkdirp(folder, options) - try { - await fn(folder) - } finally { - await fs.remove(folder) - } -} - describe('create next app', () => { it('non-empty directory', async () => { - await usingTempDir(async (cwd) => { + await useTempDir(async (cwd) => { const projectName = 'non-empty-directory' await fs.mkdirp(path.join(cwd, projectName)) const pkg = path.join(cwd, projectName, 'package.json') fs.writeFileSync(pkg, '{ "foo": "bar" }') - const res = await run([projectName], { cwd, reject: false }) + const res = await run([projectName, '--js'], { cwd, reject: false }) expect(res.exitCode).toBe(1) expect(res.stdout).toMatch(/contains files that could conflict/) }) @@ -40,158 +46,106 @@ describe('create next app', () => { // stdin is piped instead of inherited on windows if (process.platform !== 'win32') { it('empty directory', async () => { - await usingTempDir(async (cwd) => { + await useTempDir(async (cwd) => { const projectName = 'empty-directory' - const res = await run([projectName], { cwd }) + const res = await run([projectName, '--js'], { cwd }) expect(res.exitCode).toBe(0) - expect( - fs.existsSync(path.join(cwd, projectName, 'package.json')) - ).toBeTruthy() - expect( - fs.existsSync(path.join(cwd, projectName, 'pages/index.js')) - ).toBeTruthy() - expect( - fs.existsSync(path.join(cwd, projectName, '.eslintrc.json')) - ).toBeTruthy() - expect( - fs.existsSync(path.join(cwd, projectName, 'node_modules/next')) - ).toBe(true) + shouldBeJavascriptProject({ cwd, projectName }) }) }) } it('invalid example name', async () => { - await usingTempDir(async (cwd) => { + await useTempDir(async (cwd) => { const projectName = 'invalid-example-name' - const res = await run([projectName, '--example', 'not a real example'], { - cwd, - reject: false, - }) + const res = await run( + [projectName, '--js', '--example', 'not a real example'], + { + cwd, + reject: false, + } + ) expect(res.exitCode).toBe(1) - expect(res.stderr).toMatch(/Could not locate an example named/i) - expect( - fs.existsSync(path.join(cwd, projectName, 'package.json')) - ).toBeFalsy() + projectFilesShouldNotExist({ + cwd, + projectName, + files: ['package.json'], + }) }) }) it('valid example', async () => { - await usingTempDir(async (cwd) => { + await useTempDir(async (cwd) => { const projectName = 'valid-example' - const res = await run([projectName, '--example', 'basic-css'], { cwd }) - expect(res.exitCode).toBe(0) - - expect( - fs.existsSync(path.join(cwd, projectName, 'package.json')) - ).toBeTruthy() - expect( - fs.existsSync(path.join(cwd, projectName, 'pages/index.tsx')) - ).toBeTruthy() - // check we copied default `.gitignore` - expect( - fs.existsSync(path.join(cwd, projectName, '.gitignore')) - ).toBeTruthy() - expect( - fs.existsSync(path.join(cwd, projectName, 'node_modules/next')) - ).toBe(true) - }) - }) - - it('valid example without package.json', async () => { - await usingTempDir(async (cwd) => { - const projectName = 'valid-example-without-package-json' - const res = await run([projectName, '--example', 'with-docker-compose'], { + const res = await run([projectName, '--js', '--example', 'basic-css'], { cwd, }) expect(res.exitCode).toBe(0) - - expect( - fs.existsSync(path.join(cwd, projectName, '.dockerignore')) - ).toBeTruthy() - // check we copied default `.gitignore` - expect( - fs.existsSync(path.join(cwd, projectName, '.gitignore')) - ).toBeTruthy() + projectFilesShouldExist({ + cwd, + projectName, + files: [ + 'package.json', + 'pages/index.tsx', + '.gitignore', + 'node_modules/next', + ], + }) }) }) - it('should support typescript flag', async () => { - await usingTempDir(async (cwd) => { - const projectName = 'typescript' - const res = await run([projectName, '--typescript'], { cwd }) - expect(res.exitCode).toBe(0) - - const files = [ - 'package.json', - 'pages/index.tsx', - 'pages/_app.tsx', - 'pages/api/hello.ts', - 'tsconfig.json', - 'next-env.d.ts', - '.eslintrc.json', - 'node_modules/next', - // check we copied default `.gitignore` - '.gitignore', - ] - - files.forEach((file) => - expect(fs.existsSync(path.join(cwd, projectName, file))).toBeTruthy() + it('valid example without package.json', async () => { + await useTempDir(async (cwd) => { + const projectName = 'valid-example-without-package-json' + const res = await run( + [projectName, '--js', '--example', 'with-docker-compose'], + { + cwd, + } ) - const pkgJSONPath = path.join(cwd, projectName, 'package.json') - - // Assert for dependencies specific to the typescript template - const pkgJSON = require(pkgJSONPath) - expect(Object.keys(pkgJSON.dependencies)).toEqual([ - 'next', - 'react', - 'react-dom', - ]) - expect(Object.keys(pkgJSON.devDependencies)).toEqual([ - '@types/node', - '@types/react', - '@types/react-dom', - 'eslint', - 'eslint-config-next', - 'typescript', - ]) + expect(res.exitCode).toBe(0) + projectFilesShouldExist({ + cwd, + projectName, + files: ['.dockerignore', '.gitignore'], + }) }) }) it('should allow example with GitHub URL', async () => { - await usingTempDir(async (cwd) => { + await useTempDir(async (cwd) => { const projectName = 'github-app' const res = await run( - [projectName, '--example', `${exampleRepo}/${examplePath}`], + [projectName, '--js', '--example', `${exampleRepo}/${examplePath}`], { cwd, } ) expect(res.exitCode).toBe(0) - expect( - fs.existsSync(path.join(cwd, projectName, 'package.json')) - ).toBeTruthy() - expect( - fs.existsSync(path.join(cwd, projectName, 'pages/index.tsx')) - ).toBeTruthy() - expect( - fs.existsSync(path.join(cwd, projectName, '.gitignore')) - ).toBeTruthy() - expect( - fs.existsSync(path.join(cwd, projectName, 'node_modules/next')) - ).toBe(true) + projectFilesShouldExist({ + cwd, + projectName, + files: [ + 'package.json', + 'pages/index.tsx', + '.gitignore', + 'node_modules/next', + ], + }) }) }) it('should allow example with GitHub URL with trailing slash', async () => { - await usingTempDir(async (cwd) => { + await useTempDir(async (cwd) => { const projectName = 'github-app' const res = await run( [ projectName, + '--js', '--example', 'https://github.com/vercel/nextjs-portfolio-starter/', ], @@ -201,53 +155,57 @@ describe('create next app', () => { ) expect(res.exitCode).toBe(0) - expect( - fs.existsSync(path.join(cwd, projectName, 'package.json')) - ).toBeTruthy() - expect( - fs.existsSync(path.join(cwd, projectName, 'pages/index.mdx')) - ).toBeTruthy() - expect( - fs.existsSync(path.join(cwd, projectName, '.gitignore')) - ).toBeTruthy() - expect( - fs.existsSync(path.join(cwd, projectName, 'node_modules/next')) - ).toBe(true) + projectFilesShouldExist({ + cwd, + projectName, + files: [ + 'package.json', + 'pages/index.mdx', + '.gitignore', + 'node_modules/next', + ], + }) }) }) it('should allow example with GitHub URL and example-path', async () => { - await usingTempDir(async (cwd) => { + await useTempDir(async (cwd) => { const projectName = 'github-example-path' const res = await run( - [projectName, '--example', exampleRepo, '--example-path', examplePath], + [ + projectName, + '--js', + '--example', + exampleRepo, + '--example-path', + examplePath, + ], { cwd, } ) expect(res.exitCode).toBe(0) - expect( - fs.existsSync(path.join(cwd, projectName, 'package.json')) - ).toBeTruthy() - expect( - fs.existsSync(path.join(cwd, projectName, 'pages/index.tsx')) - ).toBeTruthy() - expect( - fs.existsSync(path.join(cwd, projectName, '.gitignore')) - ).toBeTruthy() - expect( - fs.existsSync(path.join(cwd, projectName, 'node_modules/next')) - ).toBe(true) + projectFilesShouldExist({ + cwd, + projectName, + files: [ + 'package.json', + 'pages/index.tsx', + '.gitignore', + 'node_modules/react', + ], + }) }) }) it('should use --example-path over the file path in the GitHub URL', async () => { - await usingTempDir(async (cwd) => { + await useTempDir(async (cwd) => { const projectName = 'github-example-path-2' const res = await run( [ projectName, + '--js', '--example', `${exampleRepo}/${examplePath}`, '--example-path', @@ -259,18 +217,16 @@ describe('create next app', () => { ) expect(res.exitCode).toBe(0) - expect( - fs.existsSync(path.join(cwd, projectName, 'package.json')) - ).toBeTruthy() - expect( - fs.existsSync(path.join(cwd, projectName, 'pages/index.tsx')) - ).toBeTruthy() - expect( - fs.existsSync(path.join(cwd, projectName, '.gitignore')) - ).toBeTruthy() - expect( - fs.existsSync(path.join(cwd, projectName, 'node_modules/next')) - ).toBe(true) + projectFilesShouldExist({ + cwd, + projectName, + files: [ + 'package.json', + 'pages/index.tsx', + '.gitignore', + 'node_modules/react', + ], + }) }) }) @@ -278,72 +234,58 @@ describe('create next app', () => { // stdin is piped instead of inherited on windows if (process.platform !== 'win32') { it('should fall back to default template', async () => { - await usingTempDir(async (cwd) => { + await useTempDir(async (cwd) => { const projectName = 'fail-example' const res = await run( - [projectName, '--example', '__internal-testing-retry'], + [projectName, '--js', '--example', '__internal-testing-retry'], { cwd, input: '\n', } ) - expect(res.exitCode).toBe(0) - const files = [ - 'package.json', - 'pages/index.js', - '.gitignore', - '.eslintrc.json', - ] - files.forEach((file) => - expect(fs.existsSync(path.join(cwd, projectName, file))).toBeTruthy() - ) + expect(res.exitCode).toBe(0) + shouldBeJavascriptProject({ cwd, projectName }) }) }) } it('should allow an example named default', async () => { - await usingTempDir(async (cwd) => { + await useTempDir(async (cwd) => { const projectName = 'default-example' - const res = await run([projectName, '--example', 'default'], { cwd }) - expect(res.exitCode).toBe(0) + const res = await run([projectName, '--js', '--example', 'default'], { + cwd, + }) - expect( - fs.existsSync(path.join(cwd, projectName, 'package.json')) - ).toBeTruthy() - expect( - fs.existsSync(path.join(cwd, projectName, 'pages/index.js')) - ).toBeTruthy() - // check we copied default `.gitignore` - expect( - fs.existsSync(path.join(cwd, projectName, '.gitignore')) - ).toBeTruthy() - expect( - fs.existsSync(path.join(cwd, projectName, 'node_modules/next')) - ).toBe(true) + expect(res.exitCode).toBe(0) + shouldBeJavascriptProject({ cwd, projectName }) }) }) it('should exit if example flag is empty', async () => { - await usingTempDir(async (cwd) => { + await useTempDir(async (cwd) => { const projectName = 'no-example-provided' - const res = await run([projectName, '--example'], { cwd, reject: false }) + const res = await run([projectName, '--js', '--example'], { + cwd, + reject: false, + }) + expect(res.exitCode).toBe(1) }) }) it('should exit if the folder is not writable', async () => { - await usingTempDir(async (cwd) => { + await useTempDir(async (cwd) => { const projectName = 'not-writable' - const res = await run([projectName], { cwd, reject: false }) + const res = await run([projectName, '--js'], { cwd, reject: false }) if (process.platform === 'win32') { expect(res.exitCode).toBe(0) - expect( - fs.existsSync(path.join(cwd, projectName, 'package.json')) - ).toBeTruthy() + const files = ['package.json'] + projectFilesShouldExist({ cwd, projectName, files }) return } + expect(res.exitCode).toBe(1) expect(res.stderr).toMatch( /you do not have write permissions for this folder/ @@ -352,7 +294,7 @@ describe('create next app', () => { }) it('should create a project in the current directory', async () => { - await usingTempDir(async (cwd) => { + await useTempDir(async (cwd) => { const env = { ...process.env } const tmpBin = path.join(__dirname, 'bin') const tmpYarn = path.join(tmpBin, 'yarn') @@ -369,7 +311,7 @@ describe('create next app', () => { delete env.npm_config_user_agent } - const res = await run(['.'], { + const res = await run(['.', '--js'], { cwd, env, extendEnv: false, @@ -378,103 +320,77 @@ describe('create next app', () => { await fs.remove(tmpBin) expect(res.exitCode).toBe(0) - - const files = [ - 'package.json', - 'pages/index.js', - '.gitignore', - 'node_modules/next', - '.eslintrc.json', - ] - files.forEach((file) => - expect(fs.existsSync(path.join(cwd, file))).toBeTruthy() - ) + shouldBeJavascriptProject({ cwd, projectName: '.' }) }) }) it('should ask the user for a name for the project if none supplied', async () => { - await usingTempDir(async (cwd) => { + await useTempDir(async (cwd) => { const projectName = 'test-project' - const res = await run([], { cwd, input: `${projectName}\n` }) - expect(res.exitCode).toBe(0) + const res = await run(['--js'], { cwd, input: `${projectName}\n` }) - const files = [ - 'package.json', - 'pages/index.js', - '.gitignore', - 'node_modules/next', - '.eslintrc.json', - ] - files.forEach((file) => - expect(fs.existsSync(path.join(cwd, projectName, file))).toBeTruthy() - ) + expect(res.exitCode).toBe(0) + shouldBeJavascriptProject({ cwd, projectName }) }) }) it('should use npm as the package manager on supplying --use-npm', async () => { - await usingTempDir(async (cwd) => { + await useTempDir(async (cwd) => { const projectName = 'use-npm' - const res = await run([projectName, '--use-npm'], { cwd }) - expect(res.exitCode).toBe(0) + const res = await run([projectName, '--js', '--use-npm'], { cwd }) - const files = [ - 'package.json', - 'pages/index.js', - '.gitignore', - '.eslintrc.json', - 'package-lock.json', - 'node_modules/next', - ] - files.forEach((file) => - expect(fs.existsSync(path.join(cwd, projectName, file))).toBeTruthy() - ) + expect(res.exitCode).toBe(0) + shouldBeJavascriptProject({ cwd, projectName }) }) }) it('should use npm as the package manager on supplying --use-npm with example', async () => { - await usingTempDir(async (cwd) => { + await useTempDir(async (cwd) => { const projectName = 'use-npm' const res = await run( [ projectName, + '--js', '--use-npm', '--example', `${exampleRepo}/${examplePath}`, ], { cwd } ) - expect(res.exitCode).toBe(0) - const files = [ - 'package.json', - 'pages/index.tsx', - '.gitignore', - 'package-lock.json', - 'node_modules/next', - ] - files.forEach((file) => - expect(fs.existsSync(path.join(cwd, projectName, file))).toBeTruthy() - ) + expect(res.exitCode).toBe(0) + projectFilesShouldExist({ + cwd, + projectName, + files: [ + 'package.json', + 'pages/index.tsx', + '.gitignore', + 'package-lock.json', + 'node_modules/next', + ], + }) }) }) it('should use pnpm as the package manager on supplying --use-pnpm', async () => { - await usingTempDir(async (cwd) => { + await useTempDir(async (cwd) => { const projectName = 'use-pnpm' - const res = await run([projectName, '--use-pnpm'], { cwd }) - expect(res.exitCode).toBe(0) + const res = await run([projectName, '--js', '--use-pnpm'], { cwd }) - const files = [ - 'package.json', - 'pages/index.js', - '.gitignore', - '.eslintrc.json', - 'pnpm-lock.yaml', - 'node_modules/next', - ] - files.forEach((file) => - expect(fs.existsSync(path.join(cwd, projectName, file))).toBeTruthy() - ) + expect(res.exitCode).toBe(0) + projectFilesShouldExist({ + cwd, + projectName, + files: [ + 'package.json', + 'pages/index.js', + '.gitignore', + '.eslintrc.json', + 'pnpm-lock.yaml', + 'node_modules/next', + ], + }) }) }) @@ -486,40 +402,41 @@ describe('create next app', () => { await execa('npm', ['i', '-g', 'pnpm']) } - await usingTempDir(async (cwd) => { + await useTempDir(async (cwd) => { const projectName = 'use-pnpm' const res = await run( [ projectName, + '--js', '--use-pnpm', '--example', `${exampleRepo}/${examplePath}`, ], { cwd } ) - expect(res.exitCode).toBe(0) - const files = [ - 'package.json', - 'pages/index.tsx', - '.gitignore', - 'pnpm-lock.yaml', - 'node_modules/next', - ] - files.forEach((file) => - expect(fs.existsSync(path.join(cwd, projectName, file))).toBeTruthy() - ) + expect(res.exitCode).toBe(0) + projectFilesShouldExist({ + cwd, + projectName, + files: [ + 'package.json', + 'pages/index.tsx', + '.gitignore', + 'pnpm-lock.yaml', + 'node_modules/next', + ], + }) }) }) it('should infer npm as the package manager', async () => { - await usingTempDir(async (cwd) => { + await useTempDir(async (cwd) => { const projectName = 'infer-package-manager-npm' - const res = await run([projectName], { + const res = await run([projectName, '--js'], { cwd, env: { ...process.env, npm_config_user_agent: 'npm' }, }) - expect(res.exitCode).toBe(0) const files = [ 'package.json', @@ -529,20 +446,19 @@ describe('create next app', () => { 'package-lock.json', 'node_modules/next', ] - files.forEach((file) => - expect(fs.existsSync(path.join(cwd, projectName, file))).toBeTruthy() - ) + + expect(res.exitCode).toBe(0) + projectFilesShouldExist({ cwd, projectName, files }) }) }) it('should infer npm as the package manager with example', async () => { - await usingTempDir(async (cwd) => { + await useTempDir(async (cwd) => { const projectName = 'infer-package-manager-npm' const res = await run( - [projectName, '--example', `${exampleRepo}/${examplePath}`], + [projectName, '--js', '--example', `${exampleRepo}/${examplePath}`], { cwd, env: { ...process.env, npm_config_user_agent: 'npm' } } ) - expect(res.exitCode).toBe(0) const files = [ 'package.json', @@ -551,9 +467,9 @@ describe('create next app', () => { 'package-lock.json', 'node_modules/next', ] - files.forEach((file) => - expect(fs.existsSync(path.join(cwd, projectName, file))).toBeTruthy() - ) + + expect(res.exitCode).toBe(0) + projectFilesShouldExist({ cwd, projectName, files }) }) }) @@ -565,13 +481,12 @@ describe('create next app', () => { await execa('npm', ['i', '-g', 'yarn']) } - await usingTempDir(async (cwd) => { + await useTempDir(async (cwd) => { const projectName = 'infer-package-manager-yarn' - const res = await run([projectName], { + const res = await run([projectName, '--js'], { cwd, env: { ...process.env, npm_config_user_agent: 'yarn' }, }) - expect(res.exitCode).toBe(0) const files = [ 'package.json', @@ -581,9 +496,9 @@ describe('create next app', () => { 'yarn.lock', 'node_modules/next', ] - files.forEach((file) => - expect(fs.existsSync(path.join(cwd, projectName, file))).toBeTruthy() - ) + + expect(res.exitCode).toBe(0) + projectFilesShouldExist({ cwd, projectName, files }) }) }) @@ -595,13 +510,12 @@ describe('create next app', () => { await execa('npm', ['i', '-g', 'yarn']) } - await usingTempDir(async (cwd) => { + await useTempDir(async (cwd) => { const projectName = 'infer-package-manager-npm' const res = await run( - [projectName, '--example', `${exampleRepo}/${examplePath}`], + [projectName, '--js', '--example', `${exampleRepo}/${examplePath}`], { cwd, env: { ...process.env, npm_config_user_agent: 'yarn' } } ) - expect(res.exitCode).toBe(0) const files = [ 'package.json', @@ -610,9 +524,9 @@ describe('create next app', () => { 'yarn.lock', 'node_modules/next', ] - files.forEach((file) => - expect(fs.existsSync(path.join(cwd, projectName, file))).toBeTruthy() - ) + + expect(res.exitCode).toBe(0) + projectFilesShouldExist({ cwd, projectName, files }) }) }) @@ -624,13 +538,12 @@ describe('create next app', () => { await execa('npm', ['i', '-g', 'pnpm']) } - await usingTempDir(async (cwd) => { + await useTempDir(async (cwd) => { const projectName = 'infer-package-manager' - const res = await run([projectName], { + const res = await run([projectName, '--js'], { cwd, env: { ...process.env, npm_config_user_agent: 'pnpm' }, }) - expect(res.exitCode).toBe(0) const files = [ 'package.json', @@ -640,9 +553,9 @@ describe('create next app', () => { 'pnpm-lock.yaml', 'node_modules/next', ] - files.forEach((file) => - expect(fs.existsSync(path.join(cwd, projectName, file))).toBeTruthy() - ) + + expect(res.exitCode).toBe(0) + projectFilesShouldExist({ cwd, projectName, files }) }) }) }) @@ -655,13 +568,12 @@ it('should infer pnpm as the package manager with example', async () => { await execa('npm', ['i', '-g', 'pnpm']) } - await usingTempDir(async (cwd) => { + await useTempDir(async (cwd) => { const projectName = 'infer-package-manager-npm' const res = await run( - [projectName, '--example', `${exampleRepo}/${examplePath}`], + [projectName, '--js', '--example', `${exampleRepo}/${examplePath}`], { cwd, env: { ...process.env, npm_config_user_agent: 'pnpm' } } ) - expect(res.exitCode).toBe(0) const files = [ 'package.json', @@ -670,8 +582,8 @@ it('should infer pnpm as the package manager with example', async () => { 'pnpm-lock.yaml', 'node_modules/next', ] - files.forEach((file) => - expect(fs.existsSync(path.join(cwd, projectName, file))).toBeTruthy() - ) + + expect(res.exitCode).toBe(0) + projectFilesShouldExist({ cwd, projectName, files }) }) }) diff --git a/test/integration/create-next-app/lib/projectFiles.ts b/test/integration/create-next-app/lib/projectFiles.ts new file mode 100644 index 0000000000000..9aca2462c188b --- /dev/null +++ b/test/integration/create-next-app/lib/projectFiles.ts @@ -0,0 +1,47 @@ +/** + * Required files for a given project template. + */ +export const projectFiles = { + /** + * Files common to all Next.js templates. + */ + global: ['package.json', '.eslintrc.json', 'node_modules/next', '.gitignore'], + /** + * Files specific to Next.js JS-only templates. + */ + js: ['pages/index.js', 'pages/_app.js', 'pages/api/hello.js'], + /** + * Files specific to Next.js TypeScript-only templates. + */ + ts: [ + 'pages/index.tsx', + 'pages/_app.tsx', + 'pages/api/hello.ts', + 'tsconfig.json', + 'next-env.d.ts', + ], + app: [ + 'app/page.tsx', + 'app/layout.tsx', + 'pages/api/hello.ts', + 'tsconfig.json', + 'next-env.d.ts', + ], +} + +export const projectDeps = { + js: ['next', 'react', 'react-dom'], + ts: ['next', 'react', 'react-dom'], +} + +export const projectDevDeps = { + js: ['eslint', 'eslint-config-next'], + ts: [ + '@types/node', + '@types/react', + '@types/react-dom', + 'eslint', + 'eslint-config-next', + 'typescript', + ], +} diff --git a/test/integration/create-next-app/lib/utils.ts b/test/integration/create-next-app/lib/utils.ts new file mode 100644 index 0000000000000..6933ab57cec3b --- /dev/null +++ b/test/integration/create-next-app/lib/utils.ts @@ -0,0 +1,175 @@ +/** + * @fileoverview + * + * This file contains utilities for `create-next-app` testing. + */ + +import { ChildProcess, spawn, SpawnOptions } from 'child_process' +import { existsSync } from 'fs' +import { resolve } from 'path' +import { projectFiles, projectDeps, projectDevDeps } from './projectFiles' + +interface ProjectOptions { + cwd: string + projectName: string +} + +interface ProjectFiles extends ProjectOptions { + files: string[] +} + +interface ProjectDeps extends ProjectOptions { + type: 'dependencies' | 'devDependencies' + deps: string[] +} + +const cli = require.resolve('create-next-app/dist/index.js') + +/** + * Run the built version of `create-next-app` with the given arguments. + */ +export const createNextApp = (args: string[], options?: SpawnOptions) => { + console.log(`[TEST] $ ${cli} ${args.join(' ')}`, { options }) + return spawn('node', [cli].concat(args), options ?? {}) +} + +/** + * Return a Promise that resolves when the process exits with code 0 and rejects + * otherwise. + */ +export const spawnExitPromise = (childProcess: ChildProcess) => { + return new Promise((resolve, reject) => { + childProcess + .on('exit', (code) => { + if (code === 0) { + resolve(code) + } else { + reject(code) + } + }) + .on('error', reject) + }) +} + +export const projectFilesShouldExist = ({ + cwd, + projectName, + files, +}: ProjectFiles) => { + const projectRoot = resolve(cwd, projectName) + for (const file of files) { + expect(existsSync(resolve(projectRoot, file))).toBe(true) + } +} + +export const projectFilesShouldNotExist = ({ + cwd, + projectName, + files, +}: ProjectFiles) => { + const projectRoot = resolve(cwd, projectName) + for (const file of files) { + expect(existsSync(resolve(projectRoot, file))).toBe(false) + } +} + +export const projectDepsShouldBe = ({ + cwd, + projectName, + type, + deps, +}: ProjectDeps) => { + const projectRoot = resolve(cwd, projectName) + const pkgJson = require(resolve(projectRoot, 'package.json')) + expect(Object.keys(pkgJson[type])).toEqual(deps) +} + +export const shouldBeJavascriptProject = ({ + cwd, + projectName, +}: ProjectOptions) => { + projectFilesShouldExist({ + cwd, + projectName, + files: [...projectFiles.global, ...projectFiles.js], + }) + + projectFilesShouldNotExist({ + cwd, + projectName, + files: projectFiles.ts, + }) + + projectDepsShouldBe({ + cwd, + projectName, + type: 'dependencies', + deps: projectDeps.js, + }) + + projectDepsShouldBe({ + cwd, + projectName, + type: 'devDependencies', + deps: projectDevDeps.js, + }) +} + +export const shouldBeTypescriptProject = ({ + cwd, + projectName, +}: ProjectOptions) => { + projectFilesShouldExist({ + cwd, + projectName, + files: [...projectFiles.global, ...projectFiles.ts], + }) + + projectFilesShouldNotExist({ + cwd, + projectName, + files: projectFiles.js, + }) + + projectDepsShouldBe({ + type: 'dependencies', + cwd, + projectName, + deps: projectDeps.ts, + }) + + projectDepsShouldBe({ + type: 'devDependencies', + cwd, + projectName, + deps: projectDevDeps.ts, + }) +} + +export const shouldBeAppProject = ({ cwd, projectName }: ProjectOptions) => { + projectFilesShouldExist({ + cwd, + projectName, + files: [...projectFiles.global, ...projectFiles.app], + }) + + projectFilesShouldNotExist({ + cwd, + projectName, + files: projectFiles.js, + }) + + projectDepsShouldBe({ + type: 'dependencies', + cwd, + projectName, + deps: projectDeps.ts, + }) + + projectDepsShouldBe({ + type: 'devDependencies', + cwd, + projectName, + deps: projectDevDeps.ts, + }) +} diff --git a/test/integration/create-next-app/templates.test.ts b/test/integration/create-next-app/templates.test.ts new file mode 100644 index 0000000000000..7dee078f076b6 --- /dev/null +++ b/test/integration/create-next-app/templates.test.ts @@ -0,0 +1,88 @@ +/* eslint-env jest */ +/** + * @fileoverview + * + * This file contains tests for `create-next-app` templates, currently + * JavaScript (default), TypeScript, and appDir. + */ + +import { + createNextApp, + projectFilesShouldNotExist, + shouldBeJavascriptProject, + shouldBeAppProject, + spawnExitPromise, + shouldBeTypescriptProject, +} from './lib/utils' + +import { useTempDir } from '../../../test/lib/use-temp-dir' + +describe('create-next-app templates', () => { + it('should prompt user to choose if --ts or --js is not provided', async () => { + useTempDir(async (cwd) => { + const projectName = 'choose-ts-js' + + /** + * Start the create-next-app call. + */ + const childProcess = createNextApp([projectName], { cwd }) + /** + * Wait for the prompt to display. + */ + // await new Promise((resolve) => setTimeout(resolve, 1000)); + /** + * Bind the exit listener. + */ + childProcess.on('exit', (exitCode) => { + expect(exitCode).toBe(0) + /** + * Verify it correctly emitted a TS project by looking for tsconfig. + */ + projectFilesShouldNotExist({ + cwd, + projectName, + files: ['tsconfig.json'], + }) + }) + /** + * Simulate "Y" for TypeScript. + */ + childProcess.stdin.write('N\n') + }) + }) + + it('should create TS projects with --ts, --typescript', async () => { + await useTempDir(async (cwd) => { + const projectName = 'typescript-test' + const childProcess = createNextApp([projectName, '--ts'], { cwd }) + const exitCode = await spawnExitPromise(childProcess) + + expect(exitCode).toBe(0) + shouldBeTypescriptProject({ cwd, projectName }) + }) + }) + + it('should create JS projects with --js, --javascript', async () => { + await useTempDir(async (cwd) => { + const projectName = 'javascript-test' + const childProcess = createNextApp([projectName, '--js'], { cwd }) + const exitCode = await spawnExitPromise(childProcess) + + expect(exitCode).toBe(0) + shouldBeJavascriptProject({ cwd, projectName }) + }) + }) + + it('should create appDir projects with --experimental-app', async () => { + await useTempDir(async (cwd) => { + const projectName = 'appdir-test' + const childProcess = createNextApp([projectName, '--experimental-app'], { + cwd, + }) + + const exitCode = await spawnExitPromise(childProcess) + expect(exitCode).toBe(0) + shouldBeAppProject({ cwd, projectName }) + }) + }) +}) diff --git a/test/lib/use-temp-dir.ts b/test/lib/use-temp-dir.ts new file mode 100644 index 0000000000000..ac5ee243c8e71 --- /dev/null +++ b/test/lib/use-temp-dir.ts @@ -0,0 +1,25 @@ +import fs from 'fs-extra' +import os from 'os' +import path from 'path' + +/** + * Create a randomly-named directory in `os.tmpdir()`, await a function call, + * and delete the directory when finished. + */ +export async function useTempDir( + fn: (folder: string) => void | Promise, + mode?: string | number +) { + const folder = path.join(os.tmpdir(), Math.random().toString(36).slice(2)) + await fs.mkdirp(folder) + + if (mode) { + fs.chmod(folder, mode) + } + + try { + await fn(folder) + } finally { + await fs.remove(folder) + } +}