diff --git a/.changeset/eight-bats-double.md b/.changeset/eight-bats-double.md new file mode 100644 index 000000000..f1dbb2adf --- /dev/null +++ b/.changeset/eight-bats-double.md @@ -0,0 +1,7 @@ +--- +'modular-scripts': major +'@modular-scripts/workspace-resolver': major +--- + +Modular's workspace resolver now ignores a workspace if covered by a +.modularignore or .gitignore (.modularignore overrides .gitignore) diff --git a/.changeset/moody-mayflies-lick.md b/.changeset/moody-mayflies-lick.md new file mode 100644 index 000000000..e4d01817e --- /dev/null +++ b/.changeset/moody-mayflies-lick.md @@ -0,0 +1,7 @@ +--- +'modular-scripts': major +--- + +Standardized lint and typecheck commands to bring them in line with other +modular selective behaviour. Now lints and typechecks non-modular packages by +default diff --git a/.changeset/spotty-hornets-hug.md b/.changeset/spotty-hornets-hug.md new file mode 100644 index 000000000..74a6249fe --- /dev/null +++ b/.changeset/spotty-hornets-hug.md @@ -0,0 +1,7 @@ +--- +'create-modular-react-app': major +'eslint-config-modular-app': major +'modular-scripts': major +--- + +Dropped Node 14 support, added Node 20 support. Changed target to ES2017 diff --git a/.eslintignore b/.eslintignore index 0a2a278d9..9866cc9cb 100644 --- a/.eslintignore +++ b/.eslintignore @@ -9,10 +9,6 @@ packages/sample-esbuild-app packages/sample-view packages/sample-package -# created by tests in modular-views.macro -packages/view-1 -packages/view-2 - # Build output /packages/**/build/ /packages/**/dist-cjs/ diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index f5f1bff01..159a50ac5 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -24,7 +24,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - node-version: ['14.18.0', '16.x', '18.x'] + node-version: ['16.x', '18.x', '20.x'] yarn-version: ['1.22.19', '3.5.0'] steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2de272ccc..abfe230a7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: - name: Use Node.js uses: actions/setup-node@v3.3.0 with: - node-version: '14.18.0' + node-version: '18.x' registry-url: https://registry.npmjs.org/ cache: 'yarn' diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index 30baebf9d..a5eac57a0 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -29,7 +29,7 @@ jobs: - name: Use Node.js uses: actions/setup-node@v3.3.0 with: - node-version: '14.18.0' + node-version: '18.x' cache: 'yarn' - name: 'Install Dependencies' diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index 265e447e6..d49e4de1e 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -20,7 +20,7 @@ jobs: fail-fast: false matrix: os: [windows-latest] - node-version: ['14.18.0', '16.x', '18.x'] + node-version: ['16.x', '18.x', '20.x'] steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3feb22e46..9c8403967 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,7 +22,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - node-version: ['14.18.0', '16.x', '18.x'] + node-version: ['16.x', '18.x', '20.x'] steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 722185a63..1f73ec5c5 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -12,10 +12,10 @@ jobs: steps: - name: Checkout uses: actions/checkout@v3 - - name: Use Node.js 14 + - name: Use Node.js 18 uses: actions/setup-node@v3.3.0 with: - node-version: 14 + node-version: 18 cache: 'yarn' - name: Install Dependencies run: yarn --frozen-lockfile diff --git a/.gitignore b/.gitignore index df3450219..f00dced50 100644 --- a/.gitignore +++ b/.gitignore @@ -20,13 +20,6 @@ packages/sample-renamable-depending-package # example app packages/esbuild-app -# created by tests in modular-views.macro -packages/view-1 -packages/view-2 -packages/scoped -packages/node-env-app - - # Build output /packages/*/build/ /packages/*/dist-cjs/ diff --git a/.modularignore b/.modularignore new file mode 100644 index 000000000..e69de29bb diff --git a/__fixtures__/non-modular/packages/non-modular-typecheckable/.gitignore b/__fixtures__/non-modular/packages/non-modular-typecheckable/.gitignore new file mode 100644 index 000000000..53c37a166 --- /dev/null +++ b/__fixtures__/non-modular/packages/non-modular-typecheckable/.gitignore @@ -0,0 +1 @@ +dist \ No newline at end of file diff --git a/__fixtures__/non-modular/packages/non-modular-typecheckable/package.json b/__fixtures__/non-modular/packages/non-modular-typecheckable/package.json new file mode 100644 index 000000000..dc63b4ee2 --- /dev/null +++ b/__fixtures__/non-modular/packages/non-modular-typecheckable/package.json @@ -0,0 +1,14 @@ +{ + "name": "non-modular-typecheckable", + "private": false, + "scripts": { + "typecheck": "echo 'non-modular-typecheckable was typechecked'" + }, + "files": [ + "dist", + "src" + ], + "license": "UNLICENSED", + "main": "./dist/index.js", + "version": "1.0.0" +} diff --git a/__fixtures__/non-modular/packages/non-modular-typecheckable/src/__tests__/index.test.ts b/__fixtures__/non-modular/packages/non-modular-typecheckable/src/__tests__/index.test.ts new file mode 100644 index 000000000..131d34e71 --- /dev/null +++ b/__fixtures__/non-modular/packages/non-modular-typecheckable/src/__tests__/index.test.ts @@ -0,0 +1,5 @@ +import add from '../index'; + +test('it should add two numbers', () => { + expect(add(1, 2)).toBe(3); +}); diff --git a/__fixtures__/non-modular/packages/non-modular-typecheckable/src/index.ts b/__fixtures__/non-modular/packages/non-modular-typecheckable/src/index.ts new file mode 100644 index 000000000..b92ce9fdf --- /dev/null +++ b/__fixtures__/non-modular/packages/non-modular-typecheckable/src/index.ts @@ -0,0 +1,3 @@ +export default function add(a: number, b: number): number { + return a + b; +} diff --git a/__fixtures__/non-modular/packages/non-modular-typecheckable/tsconfig.json b/__fixtures__/non-modular/packages/non-modular-typecheckable/tsconfig.json new file mode 100644 index 000000000..b3f8529fe --- /dev/null +++ b/__fixtures__/non-modular/packages/non-modular-typecheckable/tsconfig.json @@ -0,0 +1,13 @@ +{ + "include": ["src"], + "compilerOptions": { + "target": "es2018", + "outDir": "dist", + "lib": ["dom", "esnext"], + "declaration": true, + "moduleResolution": "node", + "sourceMap": true, + "strict": true, + "esModuleInterop": true + } +} diff --git a/babel.config.js b/babel.config.js index 78a9d5831..35ccd849d 100644 --- a/babel.config.js +++ b/babel.config.js @@ -13,7 +13,7 @@ module.exports = (api) => { { targets: { // TODO: can we get this to read from package.json somehow..? - node: '14', + node: '16', }, }, ], diff --git a/docs/commands/lint.md b/docs/commands/lint.md index 0c4559493..1918479ab 100644 --- a/docs/commands/lint.md +++ b/docs/commands/lint.md @@ -3,62 +3,69 @@ parent: Commands title: modular lint --- -# `modular lint [options] [regexes...]` - -`modular lint` without arguments or options will check the diff between the -current branch and your remote origin default branch (i.e. `master` or `main`) -and only lint the `.ts`, `.tsx`, `.js`, `.jsx` files that have changes. When in -CI without arguments or options or when the `--all` option is provided, it will -lint the entire codebase. When `--staged` is provided, it will only lint the -files staged on git. - -Alternatively, when it is invoked with one or more selective options -(`--packages`, `--ancestors`, `--descendants` or `--changed`), it will lint all -the source code files in the provided `--packages`, optionally agumenting the -set of packages by adding their ancestors (`--ancestors`), their descendants +# `modular lint [options] [packages...]` + +`modular lint` without arguments or options will lint all modular packages in +the repository, and run any `lint` scripts specified in the `package.json` of +any non-modular packages. + +`--diff` will check the diff between the current branch and your remote origin +default branch (i.e. `master` or `main`) and only lint the `.ts`, `.tsx`, `.js`, +`.jsx` files that have changes. When `--staged` is provided, it will only lint +the files staged on git. + +Alternatively, when it is invoked with one or more selective options (packages +provided, `--ancestors`, `--descendants` or `--changed`), it will lint all the +source code files in the provided packages, optionally agumenting the set of +packages by adding their ancestors (`--ancestors`), their descendants (`--descendants`) or the files that have changed (`--changed`), calculated comparing the current state of the git repository with the branch specified by `--compareBranch` or, if `--compareBranch` is not set, with the default branch. +Non modular packages will also be linted if they have a `lint` script specified +in their `package.json`. It uses your project eslint config to lint and jest runner to report on the lint status of each file (`PASS` or `FAIL`). If a file has a lint warning, the command will be marked as failed, with printed eslint errors for each warning/error. -## Default behaviour - -`modular lint` without arguments or options will: +## Default behavior -- default to lint the `git diff` between the current branch and the remote - origin's default branch when not in CI -- default to lint everything (essentially like `--all`) when in CI +`modular lint` without arguments or options will lint all packages in the +repository, and run any `lint` scripts specified in the `package.json` of any +non-modular packages. -## Options: +### Lint Unique Options: -`--all`: Lints the entire codebase (not compatible with `--staged` and with the -Selective Options) - -`--staged`: Lints only files staged on git (not compatible with `--all` and with -the Selective Options) +These options are unique to the lint command and differ to other Modular command +options. `--fix`: Allows eslint to fix the errors and warnings that do not require manual intervention wherever possible. Restages any fixed files that were previously -staged when used in combination with `--staged`. +staged when used in combination with `--staged`. Can be combined with any other +option. -`--includeNonModular`: Allows modular to run the `lint` script of non Modular -packages included in the selection, if one is provided in the package's -package.json +`--compareBranch `: Specify the comparison branch used to determine +which files have changed when using the `changed` or `diff` option. If this +option is used without `changed` or `diff`, the command will fail. -### Selective Options +The following options are not compatible with selective options, and cannot be +combined with each other. -`--packages [packages...]`: A list of one or more packages to lint. Can be -combined with all the other selective options. +`--staged`: Lints only files staged on git -`--ancestors`: Take the packages specified via `--packages` or `--changed` and +`--diff`: Lints only files that have changed compared to the default branch or +branch specified with `--compareBranch` + +`--regex [regexes...]`: A list of one or more regexes to select files to lint. + +### Selective Options + +`--ancestors`: Take the packages specified with the command or `--changed` and add their ancestors (i.e. the packages that have a direct or indirect dependency on them) to the lint list. -`--descendants`: Take the packages specified via `--packages` or `--changed` and +`--descendants`: Take the packages specified with the command or `--changed` and add their descendants (i.e. the packages they directly or indirectly depend on) to the lint list. @@ -66,7 +73,3 @@ to the lint list. changed, calculated comparing the current state of the git repository with the branch specified by `compareBranch` or, if `compareBranch` is not set, with the default branch. - -`--compareBranch `: Specify the comparison branch used to determine -which files have changed when using the `changed` option. If this option is used -without `changed`, the command will fail. diff --git a/docs/commands/test.md b/docs/commands/test.md index 46ab62851..afaf02b68 100644 --- a/docs/commands/test.md +++ b/docs/commands/test.md @@ -7,28 +7,25 @@ title: modular test Search workspaces based on their `name` field in the `package.json` and test: -- Modular packages, according to their respective `modular.type`. In this case, +- Modular packages (packages with a `modular` field in their `package.json`). `modular test` will act as an opinionated wrapper around - [`jest`](https://jestjs.io/), which comes with out-of-the-box configuration. -- Non-Modular packages (i.e. packages without a `modular` configuration), only - if they have a `test` + [`jest`](https://jestjs.io/), with a predefined Modular configuration. +- Non-Modular packages (packages without a `modular` field in their + `package.json`), only if they have a `test` [script](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#scripts), by running `yarn test` on the package's [workspace](https://classic.yarnpkg.com/en/docs/cli/workspace). When the `[packages...]` argument is empty and no selective option has been -specified (for example when running `yarn modular test`), tests will be run for -all testable packages in the repo. When the `[packages...]` argument contains -one or more non-existing package name, the non-existing packages will be ignored -without an error. If any package or selective option have been defined but -Modular can't find any package to test, Modular will warn on `stdout` and exit -with code `0`. - -Test order is unspecified by design, so please don't rely on the assumption that -certain tests will run before others, that Modular tests will run before -non-Modular tests, or that they will run sequentially. An exception to this, -valid only for Modular tests (that are run by Jest), is when -[the `--runinband` option is specified](https://jestjs.io/docs/cli#--runinband). +specified (ie `yarn modular test`), all packages will be tested. When the +`[packages...]` argument contains one or more non-existing package name, the +non-existing packages will be ignored without an error. If Modular can't find +any package to test, Modular will warn on `stdout` and exit with code `0`. + +Test order is unspecified, so don't rely on Modular to run certain tests before +others, that Modular tests will run before non-Modular tests, or that they will +run sequentially unless running Modular tests with +[the `--runinband` option](https://jestjs.io/docs/cli#--runinband). ## Configuration @@ -46,20 +43,16 @@ This contains the setup for tests corresponding to ### Arguments -`[packages ...]`: List of packages to test. Can be combined with multiple -selective options (`--ancestors`, `--descendants`, `--changed` and `--regex`). -Modular will generate a list of regular expressions that satisfies all options -passed which are then passed to Jest. The tests will run in non-predictable -order. When `packages` is empty and no selective options have been specified -(for example when running `yarn modular test`), all tests in the monorepo will -be executed. When `packages` contains one or more non-existing package name, the -non-existing packages will be ignored without an error. If any package or -selective option have been defined but the final set of regular expressions is -empty, Modular will write a message to `stdout` and exit with code `0`. +`[packages ...]`: Packages to test. Can be combined with multiple selective +options (`--ancestors`, `--descendants`, `--changed` and `--regex`). Modular +will pass a list of regular expressions that satisfies all options to Jest. + +### Test Unique Options: -### Modular-specific options +These options are unique to the test command and differ to other Modular command +options. -`--bypass`: Bypass Modular selective behaviour and flags, and send all provided +`--bypass`: Bypass Modular selective behavior and flags, and send all provided flags and options directly to the Jest process with Modular configuration. Useful when running `modular test` from IntelliJ. @@ -68,6 +61,24 @@ of babel + ts-jest. Brings significant performance improvements, but ignores ts-config in favour of its own configuration file, [.swcrc](https://swc.rs/docs/configuration/swcrc). +`--debug`: Add the `--inspect-brk` option to the Node.js process executing Jest +to allow a debugger to be attached to the running process. For more information, +[see the Node.js debugging guide](https://nodejs.org/en/docs/guides/debugging-getting-started/). + +`--compareBranch `: Specify the comparison branch used to determine +which files have changed when using the `changed` option. If this option is used +without `changed`, the command will fail. + +`--verbose`: Activate debug logging. Useful to see which packages have been +selected and which regular expression and arguments have been passed to the +underlying Jest process. + +`--regex `: Select all the test files matching the specified regular +expressions. When combined with selective options, it will run all tests +matching the selective options, and tests that match the regexes provided. + +### Selective Options + `--ancestors`: Take the packages specified by the user via arguments or options and add their ancestors (i.e. the packages that have a direct or indirect dependency on them) to the test list. @@ -82,21 +93,6 @@ calculated comparing the current state of the git repository with the branch specified by `compareBranch` or, if `compareBranch` is not set, with the default branch. -`--debug`: Add the `--inspect-brk` option to the Node.js process executing Jest -to allow a debugger to be attached to the running process. For more information, -[see the Node.js debugging guide](https://nodejs.org/en/docs/guides/debugging-getting-started/). - -`--compareBranch `: Specify the comparison branch used to determine -which files have changed when using the `changed` option. If this option is used -without `changed`, the command will fail. - -`--regex `: Select all the test files matching the specified regular -expressions. Can be combined with all the other selective options. - -`--verbose`: Activate debug logging. Useful to see which packages have been -selected and which regular expression and arguments have been passed to the -underlying Jest process. - ### Jest CLI Options `modular test` additionally supports passing diff --git a/docs/commands/typecheck.md b/docs/commands/typecheck.md index f21435e8b..99177ba4d 100644 --- a/docs/commands/typecheck.md +++ b/docs/commands/typecheck.md @@ -47,9 +47,19 @@ There are certain exceptions for practical use cases. The current allowlist is: Some use cases may warrant new exceptions. If this is you, please file an issue with the project for consideration. -## Options: +## Command line options and arguments -`--verbose`: Enables verbose logging within modular +### Default Behavior + +`modular typecheck` without any options will typecheck all packages + +### Non Modular Packages + +If non modular packages (packages without a `modular` field in their +`package.json`) are included in the selection, Modular will attempt to run the +`typecheck` script in their `package.json` if specified. + +### Selective Options `--descendants`: Typecheck the packages specified by the `[packages...]` argument and/or the `--changed` option and additionally typecheck all their @@ -67,3 +77,7 @@ of the repository with the branch specified by `compareBranch` or, if `--compareBranch`: Specify the comparison branch used to determine which files have changed when using the `changed` option. If this option is used without `changed`, the command will fail. + +### Other options + +`--verbose`: Enables verbose logging within modular diff --git a/docs/compatibility.md b/docs/compatibility.md index 7b69ecb52..bc1c01aca 100644 --- a/docs/compatibility.md +++ b/docs/compatibility.md @@ -38,17 +38,16 @@ If you find any example of v3 features which cause Modular to fail, please ### Yarn v4 and beyond -We aim to support future versions of Yarn, and we've sucessuflly useds Modular +We aim to support future versions of Yarn, and we've successfully used Modular with an unstable release candidate of Yarn 4. If there's something we don't support properly, please [let us know](https://github.com/jpmorganchase/modular/issues). ## Node versions -Modular is tested on the latest three -[Long Term Support versions of Node.js (v14, v16 and v18)](https://github.com/nodejs/release#release-schedule). -Node.js v14 is supported from version `14.18.0` onwards, while Node 16 is -supported from version `16.10.0` onwards. +Modular is tested on the current +[Long Term Support versions of Node.js: v16, v18 and v20](https://github.com/nodejs/release#release-schedule). +Node 16 is supported from version `16.10.0` onwards. ## Platforms diff --git a/docs/configuration.md b/docs/configuration.md index de0079828..a2ef48f54 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -121,3 +121,9 @@ _e.g._ The `package.json#modular.type` can be `"root"`, `"app"`, `"view"`, `"esm-view"`, `"source"`, `"template"` or `"package"`. Read more about Modular types in [this explainer](/docs/package-types). + +## `.modularignore` & `.gitignore` + +Modular respects `.gitignore` when identifying workspaces in the repository, +ignoring any workspaces covered by the repo's `.gitignore`. This behavior can be +overridden by providing a `.modularignore`. diff --git a/docs/releases/5.0.x.md b/docs/releases/5.0.x.md new file mode 100644 index 000000000..06179f710 --- /dev/null +++ b/docs/releases/5.0.x.md @@ -0,0 +1,47 @@ +--- +parent: Release Notes +title: 5.0.x +--- + +# Modular 5.0.0 + +## New Features + +- Node 20 Support. Modular is now tested against Node 20, and has added it to + the supported engines field +- Build output now targets ES2017 (Previously ES2016) +- Standardized Modular command behavior: + - [`modular lint`](../commands/lint.md) now fully supports selective behavior, + taking packages instead of regexes as the default arguments, bringing it in + line with other modular commands + - [`modular lint`](../commands/lint.md) now runs `lint` script on selected + non-modular packages by default, if specified in the package's + `package.json` + - [`modular typecheck`](../commands/typecheck.md) now runs `typecheck` script + selected non-modular packages, if specified in the package's `package.json` + - Modular's workspace resolver now respects a repo's `.gitignore`, overridden + by an optional `.modularignore`. Ignored workspaces will be skipped by + Modular commands and won't cause errors from Modular checks + +## Breaking Changes + +- Dropped Node 14 from supported engines in line with the end of + [LTS](https://github.com/nodejs/release#release-schedule). Modular is no + longer tested against Node 14 and can't guarantee compatibility +- Build output now targets ES2017 (Previously ES2016) +- Changed default behavior and options for [`modular lint`](../commands/lint.md) + and [`modular typecheck`](../commands/typecheck.md). All functionality has + been retained, but the command interface has been changed +- Modular's workspace resolver now respects `.gitignore`. This behavior, if + breaking, can be overridden by adding an empty `.modularignore` to the repos's + root. + +# Merged Changes + +TODO: fill + +# Patch Versions + +Patch versions of this release do not have a dedicated summary. For details of +patch releases, please visit +[the GitHub releases page](https://github.com/jpmorganchase/modular/releases). diff --git a/package.json b/package.json index 34e8aed13..be7f2cd35 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "packages/**" ], "engines": { - "node": "^14.18.0 || >=16.10.0 || >=18.0.0" + "node": ">=16.10.0 || >=18.0.0 || >=20.0.0" }, "repository": "https://github.com/jpmorganchase/modular.git", "scripts": { @@ -15,7 +15,7 @@ "create-modular-react-app": "ts-node packages/create-modular-react-app/src/cli.ts", "modular": "ts-node packages/modular-scripts/src/cli.ts", "test": "cross-env NODE_OPTIONS=--max_old_space_size=5120 yarn modular test --swc --runInBand --env=node", - "build": "yarn workspace @modular-scripts/workspace-resolver build && yarn workspace create-modular-react-app build && yarn workspace modular-scripts build && yarn workspace modular-views.macro build && yarn modular build @modular-scripts/remote-view && yarn prepare:remote-view", + "build": "yarn workspace @modular-scripts/workspace-resolver build && yarn workspace create-modular-react-app build && yarn workspace modular-scripts build && yarn modular build @modular-scripts/remote-view && yarn prepare:remote-view", "prepare": "is-ci || husky install", "prepare:remote-view:copy": "cp -R dist/modular-scripts-remote-view packages/remote-view/dist", "prepare:remote-view:prepublish": "node scripts/remote-view-prepublish.js", @@ -50,7 +50,6 @@ "@testing-library/jest-dom": "5.16.5", "@testing-library/react": "12.1.5", "@testing-library/user-event": "14.4.3", - "@types/babel-plugin-macros": "2.8.5", "@types/babel__code-frame": "^7.0.3", "@types/cross-spawn": "^6.0.2", "@types/dedent": "0.7.0", @@ -102,8 +101,7 @@ "jest": { "coveragePathIgnorePatterns": [ "/__fixtures__/", - "/node_modules/", - "/modular-views.macro/" + "/node_modules/" ], "coverageProvider": "v8" }, diff --git a/packages/create-modular-react-app/package.json b/packages/create-modular-react-app/package.json index 92e49bb3e..97eb0546d 100644 --- a/packages/create-modular-react-app/package.json +++ b/packages/create-modular-react-app/package.json @@ -11,7 +11,7 @@ "./package.json": "./package.json" }, "engines": { - "node": "^14.18.0 || >=16.10.0 || >=18.0.0" + "node": ">=16.10.0 || >=18.0.0 || >=20.0.0" }, "scripts": { "create-modular-react-app": "ts-node src/cli.ts", diff --git a/packages/eslint-config-modular-app/package.json b/packages/eslint-config-modular-app/package.json index a277efa6a..3af8f8cd1 100644 --- a/packages/eslint-config-modular-app/package.json +++ b/packages/eslint-config-modular-app/package.json @@ -4,7 +4,7 @@ "license": "Apache-2.0", "main": "index.js", "engines": { - "node": "^14.18.0 || >=16.10.0 || >=18.0.0" + "node": ">=16.10.0 || >=18.0.0 || >=20.0.0" }, "exports": { ".": "./index.js", diff --git a/packages/modular-scripts/package.json b/packages/modular-scripts/package.json index 95e2583de..4ec8753b3 100644 --- a/packages/modular-scripts/package.json +++ b/packages/modular-scripts/package.json @@ -18,7 +18,7 @@ "./tsconfig.json": "./tsconfig.json" }, "engines": { - "node": "^14.18.0 || >=16.10.0 || >=18.0.0" + "node": ">=16.10.0 || >=18.0.0 || >=20.0.0" }, "scripts": { "modular": "ts-node src/cli.ts", diff --git a/packages/modular-scripts/src/__tests__/build.test.ts b/packages/modular-scripts/src/__tests__/build.test.ts index cf9dc1b54..6e1e2940c 100644 --- a/packages/modular-scripts/src/__tests__/build.test.ts +++ b/packages/modular-scripts/src/__tests__/build.test.ts @@ -34,7 +34,7 @@ describe('WHEN building with preserve modules', () => { { "dependencies": {}, "engines": { - "node": "^14.18.0 || >=16.10.0 || >=18.0.0", + "node": ">=16.10.0 || >=18.0.0 || >=20.0.0", }, "files": [ "dist-cjs", diff --git a/packages/modular-scripts/src/__tests__/index.test.ts b/packages/modular-scripts/src/__tests__/index.test.ts index 3c137379d..6b9f22ce6 100644 --- a/packages/modular-scripts/src/__tests__/index.test.ts +++ b/packages/modular-scripts/src/__tests__/index.test.ts @@ -207,7 +207,7 @@ describe('modular-scripts', () => { "react": "17.0.2", }, "engines": { - "node": "^14.18.0 || >=16.10.0 || >=18.0.0", + "node": ">=16.10.0 || >=18.0.0 || >=20.0.0", }, "files": [ "dist-cjs", @@ -362,7 +362,7 @@ describe('modular-scripts', () => { { "dependencies": {}, "engines": { - "node": "^14.18.0 || >=16.10.0 || >=18.0.0", + "node": ">=16.10.0 || >=18.0.0 || >=20.0.0", }, "files": [ "dist-cjs", @@ -446,7 +446,7 @@ describe('modular-scripts', () => { { "dependencies": {}, "engines": { - "node": "^14.18.0 || >=16.10.0 || >=18.0.0", + "node": ">=16.10.0 || >=18.0.0 || >=20.0.0", }, "files": [ "dist-cjs", diff --git a/packages/modular-scripts/src/__tests__/lint.test.ts b/packages/modular-scripts/src/__tests__/lint.test.ts index 9f8213074..c79acb852 100644 --- a/packages/modular-scripts/src/__tests__/lint.test.ts +++ b/packages/modular-scripts/src/__tests__/lint.test.ts @@ -60,7 +60,7 @@ describe('Modular lint', () => { } let modularLogs: string[] = []; try { - await runYarnModular(tempModularRepo, 'lint __fixtures__/lint'); + await runYarnModular(tempModularRepo, 'lint --regex __fixtures__/lint'); } catch ({ stderr }) { modularLogs = (stderr as string).split('\n'); } @@ -71,7 +71,7 @@ describe('Modular lint', () => { it('should not pass lint test', async () => { let modularLogs: string[] = []; try { - await runYarnModular(tempModularRepo, 'lint __fixtures__/lint'); + await runYarnModular(tempModularRepo, 'lint --regex __fixtures__/lint'); } catch ({ stderr }) { modularLogs = (stderr as string).split('\n'); } @@ -88,7 +88,7 @@ describe('Modular lint', () => { const files = fs.readdirSync(fixturesFolder); const result = await runYarnModular( modularRoot, - 'lint __fixtures__/lint', + 'lint --regex __fixtures__/lint', ); const modularLogs: string[] = result.stderr.split('\n'); expect(modularLogs).toContain( @@ -128,7 +128,7 @@ describe('lint command can successfully do selective tests based on selected pac it('finds test after specifying a valid package', () => { const resultPackages = runModularPipeLogs( randomOutputFolder, - 'lint --packages beta-lint gamma-lint', + 'lint beta-lint gamma-lint', 'true', ); expect(resultPackages.stderr).toContain('packages/beta-lint/src/'); @@ -141,7 +141,7 @@ describe('lint command can successfully do selective tests based on selected pac it('finds ancestors using --ancestors', () => { const resultPackagesWithAncestors = runModularPipeLogs( randomOutputFolder, - 'lint --packages beta-lint gamma-lint --ancestors', + 'lint beta-lint gamma-lint --ancestors', 'true', ); expect(resultPackagesWithAncestors.stderr).toContain( @@ -164,7 +164,7 @@ describe('lint command can successfully do selective tests based on selected pac it('finds descendants using --descendants', () => { const resultPackagesWithDescendants = runModularPipeLogs( randomOutputFolder, - 'lint --packages beta-lint gamma-lint --descendants', + 'lint beta-lint gamma-lint --descendants', 'true', ); expect(resultPackagesWithDescendants.stderr).toContain( diff --git a/packages/modular-scripts/src/__tests__/typecheck.test.ts b/packages/modular-scripts/src/__tests__/typecheck.test.ts index aa943da35..c723ef1d3 100644 --- a/packages/modular-scripts/src/__tests__/typecheck.test.ts +++ b/packages/modular-scripts/src/__tests__/typecheck.test.ts @@ -34,6 +34,18 @@ describe('Modular typecheck', () => { path.join(tempFixturesFolder, 'InvalidTyping.ts'), invalidTsContent, ); + // Must be recognized as a modular workspace to be type-checked + fs.writeJsonSync( + path.join(tempModularRepo, 'packages', 'app', 'package.json'), + { + name: 'modular-template-app', + version: '2.0.0', + modular: { + type: 'template', + templateType: 'app', + }, + }, + ); fs.copyFileSync( path.join(modularRoot, 'tsconfig.json'), path.join(tempModularRepo, 'tsconfig.json'), diff --git a/packages/modular-scripts/src/__tests__/unobtrusiveModular.test.ts b/packages/modular-scripts/src/__tests__/unobtrusiveModular.test.ts index 65a57d03f..e43c516b5 100644 --- a/packages/modular-scripts/src/__tests__/unobtrusiveModular.test.ts +++ b/packages/modular-scripts/src/__tests__/unobtrusiveModular.test.ts @@ -74,10 +74,10 @@ describe('When there is a non-Modular package with a build script', () => { expect(result.stdout).toContain('\nnon-modular-testable was tested'); }); - it('lints non-modular packages when the --includeNonModular flag is provided', () => { + it('lints non-modular packages', () => { const result = runModularPipeLogs( tempModularRepo, - 'lint --packages non-modular-lintable --includeNonModular --verbose', + 'lint non-modular-lintable --verbose', ); expect(result.stderr).toBeFalsy(); expect(result.stdout).toContain( @@ -85,4 +85,18 @@ describe('When there is a non-Modular package with a build script', () => { ); expect(result.stdout).toContain('non-modular-lintable was linted'); }); + + it('typechecks non-modular packages', () => { + const result = runModularPipeLogs( + tempModularRepo, + 'typecheck non-modular-typecheckable --verbose', + ); + expect(result.stderr).toBeFalsy(); + expect(result.stdout).toContain( + 'Running typecheck command in the following non-modular packages: ["non-modular-typecheckable"]', + ); + expect(result.stdout).toContain( + 'non-modular-typecheckable was typechecked', + ); + }); }); diff --git a/packages/modular-scripts/src/__tests__/utils/__snapshots__/getWorkspaceInfo.test.ts.snap b/packages/modular-scripts/src/__tests__/utils/__snapshots__/getWorkspaceInfo.test.ts.snap index d56c9b3d1..854b59190 100644 --- a/packages/modular-scripts/src/__tests__/utils/__snapshots__/getWorkspaceInfo.test.ts.snap +++ b/packages/modular-scripts/src/__tests__/utils/__snapshots__/getWorkspaceInfo.test.ts.snap @@ -93,13 +93,6 @@ exports[`getWorkspaceInfo 1`] = ` "type": "template", "workspaceDependencies": [], }, - "modular-views.macro": { - "location": "packages/modular-views.macro", - "mismatchedWorkspaceDependencies": [], - "public": true, - "type": "unknown", - "workspaceDependencies": [], - }, "remote-view-demos": { "location": "packages/remote-view-demos", "mismatchedWorkspaceDependencies": [], diff --git a/packages/modular-scripts/src/__tests__/utils/createEsbuildBrowserslistTarget.test.ts b/packages/modular-scripts/src/__tests__/utils/createEsbuildBrowserslistTarget.test.ts index fd8d077ee..613ae0680 100644 --- a/packages/modular-scripts/src/__tests__/utils/createEsbuildBrowserslistTarget.test.ts +++ b/packages/modular-scripts/src/__tests__/utils/createEsbuildBrowserslistTarget.test.ts @@ -34,9 +34,9 @@ describe('createEsbuildBrowserslistTarget', () => { const result = createEsbuildBrowserslistTarget(process.cwd()); expect(result).toMatchInlineSnapshot(` [ - "chrome107", - "firefox107", - "safari16.1", + "chrome113", + "firefox113", + "safari16.4", ] `); }); @@ -59,9 +59,9 @@ describe('createEsbuildBrowserslistTarget', () => { const result = createEsbuildBrowserslistTarget(process.cwd()); expect(result).toMatchInlineSnapshot(` [ - "chrome107", - "firefox107", - "safari16.1", + "chrome113", + "firefox113", + "safari16.4", ] `); }); @@ -84,9 +84,9 @@ describe('createEsbuildBrowserslistTarget', () => { const result = createEsbuildBrowserslistTarget(process.cwd()); expect(result).toMatchInlineSnapshot(` [ - "chrome107", - "firefox107", - "safari16.1", + "chrome113", + "firefox113", + "safari16.4", ] `); }); diff --git a/packages/modular-scripts/src/lint.ts b/packages/modular-scripts/src/lint.ts index bebf5896c..9a29fa861 100644 --- a/packages/modular-scripts/src/lint.ts +++ b/packages/modular-scripts/src/lint.ts @@ -1,5 +1,4 @@ import * as path from 'path'; -import isCI from 'is-ci'; import { ExecaError } from 'execa'; import actionPreflightCheck from './utils/actionPreflightCheck'; import { resolveAsBin } from './utils/resolveAsBin'; @@ -15,121 +14,128 @@ import { partitionPackages, } from './utils/unobtrusiveModular'; export interface LintOptions { - all: boolean; fix: boolean; staged: boolean; - packages?: string[]; + regex?: string[]; ancestors?: boolean; descendants?: boolean; changed?: boolean; - includeNonModular?: boolean; compareBranch?: string; + diff?: boolean; } async function lint( options: LintOptions, - userRegexes: string[] = [], + packages: string[] = [], ): Promise { const { - all = false, fix = false, staged = false, - packages = [], + regex: userRegexes = [], ancestors = false, descendants = false, changed = false, - includeNonModular = false, compareBranch, + diff = false, } = options; const modularRoot = getModularRoot(); const lintExtensions = ['.ts', '.tsx', '.js', '.jsx']; const [workspaceMap] = await getAllWorkspaces(); - const isSelective = - packages?.length || ancestors || descendants || changed || compareBranch; - let selectedTargets: string[]; + const isSelective = changed || ancestors || descendants || packages.length; - if (!isSelective) { - selectedTargets = [...workspaceMap.keys()]; - } else { - // Otherwise, calculate which packages are selected - selectedTargets = await selectWorkspaces({ - targets: packages, - changed, - ancestors, - descendants, - compareBranch, - }); - } - - // Split packages into modular and non-modular testable. Make sure that "root" is not there. - const [modularTargets, nonModularTargets] = partitionPackages( - selectedTargets, - workspaceMap, - 'lint', - ); - - // Compute patterns to pass Jest for the packages that we want to test - const selectedPackageRegexes = await computeRegexesFromPackageNames( - modularTargets, - ); - - // Only set regexes if all or selective options have been specified - let processedPackageRegexes = selectedPackageRegexes.map( - (regex) => `/${regex}/src/**/*.{js,jsx,ts,tsx}`, - ); - - let lintRegexes = isSelective || all ? processedPackageRegexes : []; - - if (all && isSelective) { - logger.warn( - 'You specified --all already; selective options are redundant.', + if ((staged || diff || userRegexes.length) && isSelective) { + logger.error( + "Can't specify --staged, --diff or --regex along with selective options", ); + process.exit(-1); } - if (staged && isSelective) { - logger.error("Can't specify --staged along with selective options"); + if ( + (staged && diff) || + (staged && userRegexes.length) || + (diff && userRegexes.length) + ) { + logger.error( + "--regex, --diff and --staged are mutually exclusive options that can't be used together", + ); process.exit(-1); } - // Not selective, not --all and no regexes; - // TODO: Bring this in line with behaviour of other commands, too 'unpredictable' from a user point of view - if (!all && !isSelective && userRegexes.length === 0) { - if (staged || !isCI) { - // If --staged or not in CI, calculate the file regexes of --diff or --staged - let diffedFiles: null | string[]; - - try { - // This can throw in case there is no git directory; in this case, we need to continue like nothing happened - diffedFiles = staged ? getStagedFiles() : getDiffedFiles(); - } catch { - diffedFiles = null; - logger.log( - 'Getting staged or diffed files failed - are you sure this is a git repo? Falling back to `--all`.', - ); - lintRegexes = processedPackageRegexes; - } - if (diffedFiles !== null) { - if (diffedFiles.length === 0) { - logger.log( - 'No diffed files detected. Use the `--all` option to lint the entire codebase', - ); - } else { - processedPackageRegexes = diffedFiles - .filter((p: string) => lintExtensions.includes(path.extname(p))) - .map((p: string) => `/${p}`); - - // if none of the diffed files meet the extension criteria, do not lint - // end the process early with a success - if (!processedPackageRegexes.length) { - logger.warn('No diffed target files to lint found'); - } + let modularTargets: string[]; + let nonModularTargets: string[]; + + // If --diff or --staged, lint only diffed or staged files, + // otherwise lint selected packages or all packages if nothing selected + let lintRegexes: string[]; + + if (diff || staged) { + // Calculate the file regexes of --diff or --staged + try { + // This can throw in case there is no git directory; in this case, we need to continue like nothing happened + const diffedFiles = staged + ? getStagedFiles() + : getDiffedFiles(compareBranch); + + if (diffedFiles.length === 0) { + logger.warn(`No staged or diffed files detected.`); + process.exit(0); + } else { + lintRegexes = diffedFiles + .filter((p: string) => lintExtensions.includes(path.extname(p))) + .map((p: string) => `/${p}`); + + // if none of the diffed files meet the extension criteria, do not lint + // end the process early with a success + if (!lintRegexes.length) { + logger.warn('No lintable diffed or staged target files found'); + process.exit(0); } } + } catch { + logger.error( + 'Getting staged or diffed files failed - are you sure this is a git repo?', + ); + process.exit(1); + } + nonModularTargets = []; + } else if (userRegexes.length) { + // Don't calculate any regexes or non-modular targets - only use the user provided regexes + lintRegexes = []; + nonModularTargets = []; + } else { + // Compute selected packages or run on all modular & non-modular packages + let selectedTargets: string[]; + + if (isSelective) { + selectedTargets = await selectWorkspaces({ + targets: packages, + changed, + compareBranch, + descendants, + ancestors, + }); } else { - // If in CI, then lint all - lintRegexes = processedPackageRegexes; + selectedTargets = [...workspaceMap.keys()]; } + + // Split packages into modular and non-modular testable. Make sure that "root" is not there. + [modularTargets, nonModularTargets] = partitionPackages( + selectedTargets, + workspaceMap, + 'lint', + ); + + // Compute patterns to pass Jest for the packages that we want to test + const selectedPackageRegexes = await computeRegexesFromPackageNames( + modularTargets, + ); + + const processedPackageRegexes = selectedPackageRegexes.map( + (regex) => `/${regex}/src/**/*.{js,jsx,ts,tsx}`, + ); + + lintRegexes = processedPackageRegexes; } // If we computed no regexes and there are no non-modular packages to lint, bail out @@ -188,8 +194,7 @@ async function lint( } } - // Lint non-modular packages - TODO: Remove conditional & flag in next major release of Modular (5.0.0) - if (includeNonModular) { + if (nonModularTargets.length) { try { logger.debug( `Running lint command in the following non-modular packages: ${JSON.stringify( diff --git a/packages/modular-scripts/src/program.ts b/packages/modular-scripts/src/program.ts index 75c8fc916..59a042a61 100755 --- a/packages/modular-scripts/src/program.ts +++ b/packages/modular-scripts/src/program.ts @@ -207,7 +207,7 @@ program ) .option( '--regex ', - 'Specifies one or more test name regular expression', + 'Specifies one or more test name regular expression. When combined with selective options, it will run tests matching the regex as well as those matching the selective options', ) .option('--coverage', testOptions.coverage.description) .option('--forceExit', testOptions.forceExit.description) @@ -285,25 +285,27 @@ program const lintStagedFlag = '--staged'; program - .command('lint [regexes...]') + .command('lint [packages...]') + .description( + 'lint provided packages. When run without any arguments, lints the whole repository', + ) .option( - '--all', - 'Only lint diffed files from your remote origin default branch (e.g. main or master)', + '--regex [regexes...]', + 'Only lint packages matching the provided regexes', ) - .option('--packages [packages...]', 'Only lint selected packages') .option( '--ancestors', - 'Lint workspaces that depend on workspaces that have changed', + 'Additionally lint workspaces that depend on workspaces that have changed', false, ) .option( '--descendants', - 'Lint workspaces that directly or indirectly depend on the specified packages', + 'Additionally lint workspaces that directly or indirectly depend on the specified packages', false, ) .option( '--changed', - 'Lint workspaces that have changed compared to the branch specified in --compareBranch', + 'Additionally lint workspaces that have changed compared to the branch specified in --compareBranch', ) .option( '--compareBranch ', @@ -315,9 +317,8 @@ program ) .option('--verbose', 'Enables verbose logging within modular.') .option( - '--includeNonModular', - "Runs 'lint' script if specified in the package.json of any non-modular package included - Will be removed and true as default in Modular 5.0.0", - false, + '--diff', + 'Only lint files that have changed compared to the compare branch', ) .addOption( new Option( @@ -326,14 +327,16 @@ program ).conflicts('all'), ) .description('Lints the codebase') - .action(async (regexes: string[], options: LintOptions) => { + .action(async (packages: string[], options: LintOptions) => { const { default: lint } = await import('./lint'); - await lint(options, regexes); + await lint(options, packages); }); program .command('typecheck [packages...]') - .description('Typechecks the entire project') + .description( + 'Typecheck provided packages. If run without any additional arguments, typechecks the entire project', + ) .option('--verbose', 'Enables verbose logging within modular.') .option( '--ancestors', diff --git a/packages/modular-scripts/src/test/config.ts b/packages/modular-scripts/src/test/config.ts index 5891a4a25..780281c58 100644 --- a/packages/modular-scripts/src/test/config.ts +++ b/packages/modular-scripts/src/test/config.ts @@ -63,7 +63,7 @@ export function createJestConfig( module: { type: 'commonjs', strictMode: true, noInterop: false }, jsc: { externalHelpers: false, - target: 'es2016', + target: 'es2017', parser: { syntax: 'typescript', tsx: true, diff --git a/packages/modular-scripts/src/test/mockFunctions.ts b/packages/modular-scripts/src/test/mockFunctions.ts index 8721009a8..8444d4073 100644 --- a/packages/modular-scripts/src/test/mockFunctions.ts +++ b/packages/modular-scripts/src/test/mockFunctions.ts @@ -98,7 +98,6 @@ interface LintOptionsForTests { ancestors?: boolean; descendants?: boolean; changed?: boolean; - includeNonModular?: boolean; compareBranch?: string; } @@ -115,7 +114,6 @@ export async function runLintForTests( ancestors = false, descendants = false, changed = false, - includeNonModular = false, compareBranch, }: LintOptionsForTests, regexes: string[] = [], @@ -133,7 +131,6 @@ export async function runLintForTests( ancestors, descendants, changed, - includeNonModular, compareBranch, }, regexes, diff --git a/packages/modular-scripts/src/test/utils.ts b/packages/modular-scripts/src/test/utils.ts index 99e5bde57..9231ac01f 100644 --- a/packages/modular-scripts/src/test/utils.ts +++ b/packages/modular-scripts/src/test/utils.ts @@ -267,7 +267,7 @@ export async function runModularForTestsAsync( path.join(modularRoot, '/node_modules/.bin/ts-node'), [ path.join(modularRoot, '/packages/modular-scripts/src/cli.ts'), - ...args.split(' '), + ...args.split(/ +(?=(?:(?:[^"]*"){2})*[^"]*$)/g), ], { cwd, @@ -293,10 +293,14 @@ export async function runYarnModular( args: string, opts: Record = {}, ) { - return execa('yarnpkg', ['modular', ...args.split(' ')], { - cwd, - all: true, - cleanup: true, - ...opts, - }); + return execa( + 'yarnpkg', + ['modular', ...args.split(/ +(?=(?:(?:[^"]*"){2})*[^"]*$)/g)], + { + cwd, + all: true, + cleanup: true, + ...opts, + }, + ); } diff --git a/packages/modular-scripts/src/typecheck.ts b/packages/modular-scripts/src/typecheck.ts index 37c241db3..a072a9bf1 100644 --- a/packages/modular-scripts/src/typecheck.ts +++ b/packages/modular-scripts/src/typecheck.ts @@ -7,6 +7,8 @@ import getModularRoot from './utils/getModularRoot'; import actionPreflightCheck from './utils/actionPreflightCheck'; import { getAllWorkspaces } from './utils/getAllWorkspaces'; import { selectWorkspaces } from './utils/selectWorkspaces'; +import { partitionPackages } from './utils/unobtrusiveModular'; +import execAsync from './utils/execAsync'; import type { CompilerOptionsDefinition, JSONSchemaForTheTypeScriptCompilerSConfigurationFile as TSConfig, @@ -83,97 +85,121 @@ async function typecheck( const { ancestors, descendants, changed, compareBranch } = options; const isSelective = changed || ancestors || descendants || packages.length; const modularRoot = getModularRoot(); - const [allWorkspacePackages] = await getAllWorkspaces(modularRoot); - const targets = isSelective ? packages : [...allWorkspacePackages.keys()]; - let replaceInclude: undefined | string[]; + const [workspaceMap] = await getAllWorkspaces(); + let selectedTargets: string[]; if (isSelective) { - const selectedTargets = await selectWorkspaces({ - targets, + selectedTargets = await selectWorkspaces({ + targets: packages, changed, compareBranch, descendants, ancestors, }); + } else { + selectedTargets = [...workspaceMap.keys()]; + } - const targetLocations: string[] = []; - for (const [pkgName, pkg] of allWorkspacePackages) { - if (selectedTargets.includes(pkgName)) { - targetLocations.push(pkg.location); - } - } + // Split packages into modular and non-modular testable. Make sure that "root" is not there. + const [modularTargets, nonModularTargets] = partitionPackages( + selectedTargets, + workspaceMap, + 'typecheck', + ); - if (targetLocations.length) { - replaceInclude = targetLocations; + const targetLocations: string[] = []; + for (const [pkgName, pkg] of workspaceMap) { + if (modularTargets.includes(pkgName)) { + targetLocations.push(pkg.location); } } - const { typescriptConfig } = await getPackageMetadata(); - const tsConfig = restrictUserTsconfig(typescriptConfig, replaceInclude); - - const diagnosticHost = { - getCurrentDirectory: (): string => getModularRoot(), - getNewLine: (): string => ts.sys.newLine, - getCanonicalFileName: (file: string): string => - ts.sys.useCaseSensitiveFileNames ? file : toFileNameLowerCase(file), - }; - - // Parse all config except for compilerOptions - const configParseResult = ts.parseJsonConfigFileContent( - tsConfig, - ts.sys, - modularRoot, + logger.debug( + `Typechecking the following locations: ${JSON.stringify(targetLocations)}`, ); - if (configParseResult.errors.length > 0) { - logger.error('Failed to parse your tsconfig.json'); - throw new Error( - ts.formatDiagnostics(configParseResult.errors, diagnosticHost), + const { typescriptConfig } = await getPackageMetadata(); + const tsConfig = restrictUserTsconfig(typescriptConfig, targetLocations); + + if (modularTargets.length) { + const diagnosticHost = { + getCurrentDirectory: (): string => getModularRoot(), + getNewLine: (): string => ts.sys.newLine, + getCanonicalFileName: (file: string): string => + ts.sys.useCaseSensitiveFileNames ? file : toFileNameLowerCase(file), + }; + + // Parse all config except for compilerOptions + const configParseResult = ts.parseJsonConfigFileContent( + tsConfig, + ts.sys, + modularRoot, ); - } - const program = ts.createProgram( - configParseResult.fileNames, - configParseResult.options, - ); - - // Pulled from typescript's getCanonicalFileName logic - // eslint-disable-next-line no-useless-escape - const fileNameLowerCaseRegExp = /[^\u0130\u0131\u00DFa-z0-9\\/:\-_\. ]+/g; + if (configParseResult.errors.length > 0) { + logger.error('Failed to parse your tsconfig.json'); + throw new Error( + ts.formatDiagnostics(configParseResult.errors, diagnosticHost), + ); + } - function toFileNameLowerCase(x: string) { - return fileNameLowerCaseRegExp.test(x) - ? x.replace(fileNameLowerCaseRegExp, x.toLowerCase()) - : x; - } + const program = ts.createProgram( + configParseResult.fileNames, + configParseResult.options, + ); - program - .getSourceFiles() - .map((f) => f.fileName) - .sort() - .forEach((f) => { - logger.debug(f); - }); + // Pulled from typescript's getCanonicalFileName logic + // eslint-disable-next-line no-useless-escape + const fileNameLowerCaseRegExp = /[^\u0130\u0131\u00DFa-z0-9\\/:\-_\. ]+/g; - // Does not emit files or typings but will add declaration diagnostics to our errors - // This will ensure that makeTypings will be successful in CI before actually attempting to build - const emitResult = program.emit(); + function toFileNameLowerCase(x: string) { + return fileNameLowerCaseRegExp.test(x) + ? x.replace(fileNameLowerCaseRegExp, x.toLowerCase()) + : x; + } - const diagnostics = ts - .getPreEmitDiagnostics(program) - .concat(emitResult.diagnostics); + program + .getSourceFiles() + .map((f) => f.fileName) + .sort() + .forEach((f) => { + logger.debug(f); + }); + + // Does not emit files or typings but will add declaration diagnostics to our errors + // This will ensure that makeTypings will be successful in CI before actually attempting to build + const emitResult = program.emit(); + + const diagnostics = ts + .getPreEmitDiagnostics(program) + .concat(emitResult.diagnostics); + + if (diagnostics.length) { + if (isCI) { + // formatDiagnostics will return a readable list of error messages, each with its own line + throw new Error(ts.formatDiagnostics(diagnostics, diagnosticHost)); + } - if (diagnostics.length) { - if (isCI) { - // formatDiagnostics will return a readable list of error messages, each with its own line - throw new Error(ts.formatDiagnostics(diagnostics, diagnosticHost)); + // formatDiagnosticsWithColorAndContext will return a list of errors, each with its own line + // and provide an expanded snapshot of the line with the error + throw new Error( + ts.formatDiagnosticsWithColorAndContext(diagnostics, diagnosticHost), + ); } + } - // formatDiagnosticsWithColorAndContext will return a list of errors, each with its own line - // and provide an expanded snapshot of the line with the error - throw new Error( - ts.formatDiagnosticsWithColorAndContext(diagnostics, diagnosticHost), + if (nonModularTargets.length) { + logger.debug( + `Running typecheck command in the following non-modular packages: ${JSON.stringify( + nonModularTargets, + )}`, ); + for (const target of nonModularTargets) { + await execAsync(`yarn`, ['workspace', target, 'typecheck'], { + cwd: getModularRoot(), + log: false, + }); + } } // "✓ Typecheck passed" diff --git a/packages/modular-scripts/tsconfig.json b/packages/modular-scripts/tsconfig.json index d79bf80af..384d4b249 100644 --- a/packages/modular-scripts/tsconfig.json +++ b/packages/modular-scripts/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es2016", + "target": "es2017", "downlevelIteration": true, "lib": ["dom", "dom.iterable", "esnext", "WebWorker"], "allowJs": true, diff --git a/packages/modular-views.macro/CHANGELOG.md b/packages/modular-views.macro/CHANGELOG.md deleted file mode 100644 index f8a063e8e..000000000 --- a/packages/modular-views.macro/CHANGELOG.md +++ /dev/null @@ -1,138 +0,0 @@ -# modular-views.macro - -## 3.1.1 - -### Patch Changes - -- [#1590](https://github.com/jpmorganchase/modular/pull/1590) - [`f1e352e`](https://github.com/jpmorganchase/modular/commit/f1e352e70a1f61f20918538c36f7c1d9a97ec9cd) - Thanks [@dependabot](https://github.com/apps/dependabot)! - Bump fs-extra from - 10.0.1 to 10.1.0 - -## 3.1.0 - -### Minor Changes - -- [#1112](https://github.com/jpmorganchase/modular/pull/1112) - [`d08e4c2`](https://github.com/jpmorganchase/modular/commit/d08e4c2b15db93ef2adde961651254491db94140) - Thanks [@joshwooding](https://github.com/joshwooding)! - Support yarn v3 - -### Patch Changes - -- [#1283](https://github.com/jpmorganchase/modular/pull/1283) - [`918d1f1`](https://github.com/jpmorganchase/modular/commit/918d1f15b7ae27141ad180ff634aade6ca524117) - Thanks [@LukeSheard](https://github.com/LukeSheard)! - Upgrade @babel scope - packages in modular. - -* [#1411](https://github.com/jpmorganchase/modular/pull/1411) - [`1fa4e8e`](https://github.com/jpmorganchase/modular/commit/1fa4e8ea3c21449328e1927561a31d6da438b058) - Thanks [@dependabot](https://github.com/apps/dependabot)! - Bump @babel/core - from 7.17.4 to 7.17.5 - -- [#1326](https://github.com/jpmorganchase/modular/pull/1326) - [`9c6cfe2`](https://github.com/jpmorganchase/modular/commit/9c6cfe2609f82d60d0237cdc110d9278526a27c1) - Thanks [@dependabot](https://github.com/apps/dependabot)! - Bump @babel/core - from 7.16.7 to 7.16.12 - -## 3.0.1 - -### Patch Changes - -- [#1033](https://github.com/jpmorganchase/modular/pull/1033) - [`d9f42fe`](https://github.com/jpmorganchase/modular/commit/d9f42fea338b0bf70968e4690bf2b5aa2ba108ff) - Thanks [@steveukx](https://github.com/steveukx)! - Add extraneous dependencies - and add lint rule to ensure dependencies always added - -## 3.0.0 - -### Major Changes - -- [#908](https://github.com/jpmorganchase/modular/pull/908) - [`226ad45`](https://github.com/jpmorganchase/modular/commit/226ad45251ab1955bd955fac97407e263af9de76) - Thanks [@LukeSheard](https://github.com/LukeSheard)! - Add exports fields to - all packages. - -## 2.0.0 - -### Major Changes - -- af8f49f: Remove react-scripts as a dependency and release major change. - -### Patch Changes - -- d78cfa8: Bump @types/babel-plugin-macros from 2.8.4 to 2.8.5 - -## 1.2.7 - -### Patch Changes - -- ab4aa76: Bump execa from 5.0.1 to 5.1.0 -- 9585460: Bump execa from 5.1.0 to 5.1.1 - -## 1.2.6 - -### Patch Changes - -- 18aea9d: Bump execa from 5.0.0 to 5.0.1 - -## 1.2.5 - -### Patch Changes - -- 308847e: Bumping versions for actually landing/releasing - -## 1.2.4 - -### Patch Changes - -- ecb9880: Bumping versions to overcome a bad prelease publish. - -## 1.2.4-next.0 - -### Patch Changes - -- ecb9880: Bumping versions to overcome a bad prelease publish. - -## 1.2.3 - -### Patch Changes - -- f035528: Allow arbitrary directory structures for packages - -## 1.2.3-next.0 - -### Patch Changes - -- f035528: Allow arbitrary directory structures for packages - -## 1.2.2 - -### Patch Changes - -- 84ef2db: Enhance eslint-config-modular-app, add .prettierignore and - .eslintignore files in templates - -## 1.2.1 - -### Patch Changes - -- 7c14fdb: Fix the macro's type generation, and avoid some console spam when - installing. - -## 1.2.0 - -### Minor Changes - -- 0412940: Migrate codebase to TypeScript with internal typings - -## 1.1.1 - -### Patch Changes - -- 8c681a7: Allow multiple references in one file - -## 1.1.0 - -### Minor Changes - -- 48aa4d1: Implement modular-views.macro diff --git a/packages/modular-views.macro/README.md b/packages/modular-views.macro/README.md deleted file mode 100644 index 89031781c..000000000 --- a/packages/modular-views.macro/README.md +++ /dev/null @@ -1,46 +0,0 @@ -## modular-views.macro - -When used in a modular repository, this macro will scan all the available -packages, find the ones marked as 'views', and generates a map of names to the -views, each wrapped in `React.lazy`. - -### usage - -Suppose you have a modular repository, with a directory structure like so - - -``` -my-modular-repo - packages - app - pkg-1 - pkg-2 - view-1 - view-2 - view-3 - view-4 - ... - view-n -``` - -Then you can write code like this - - -```jsx -import views from 'modular-views.macro'; - -console.log(views); - -/* -The above call would log this object - - -{ - 'view-1': React.lazy(() => import('view-1')), - 'view-2': React.lazy(() => import('view-2')), - 'view-3': React.lazy(() => import('view-3')), - 'view-4': React.lazy(() => import('view-4')), - // ... - 'view-n': React.lazy(() => import('view-n')), -} - -Like magic! -*/ -``` diff --git a/packages/modular-views.macro/package.json b/packages/modular-views.macro/package.json deleted file mode 100644 index 5ceb829c1..000000000 --- a/packages/modular-views.macro/package.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "modular-views.macro", - "version": "3.1.1", - "main": "build/index.macro.js", - "exports": { - ".": "./build/index.macro.js", - "./package.json": "./package.json" - }, - "typings": "build/index.macro.d.ts", - "license": "Apache-2.0", - "dependencies": { - "@babel/core": "^7.17.9", - "@babel/template": "^7.16.7", - "@babel/types": "^7.19.0", - "babel-plugin-macros": "3.1.0", - "execa": "5.1.1", - "find-up": "5.0.0", - "fs-extra": "10.1.0", - "react": "17.0.2" - }, - "devDependencies": { - "@schemastore/package": "0.0.6" - }, - "scripts": { - "clean": "rimraf build", - "prebuild": "yarn clean", - "build": "yarn build:lib && yarn build:types", - "build:lib": "babel --root-mode upward src --out-dir build --extensions .ts --ignore 'src/**/*.test.ts'", - "build:types": "tsc --emitDeclarationOnly --declarationDir build" - } -} diff --git a/packages/modular-views.macro/src/__tests__/.eslintrc.json b/packages/modular-views.macro/src/__tests__/.eslintrc.json deleted file mode 100644 index 5b0200296..000000000 --- a/packages/modular-views.macro/src/__tests__/.eslintrc.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "overrides": [ - { - "files": "fixture.js", - "parserOptions": { - "sourceType": "module" - } - } - ] -} diff --git a/packages/modular-views.macro/src/__tests__/fixture.js b/packages/modular-views.macro/src/__tests__/fixture.js deleted file mode 100644 index ad3f31889..000000000 --- a/packages/modular-views.macro/src/__tests__/fixture.js +++ /dev/null @@ -1,3 +0,0 @@ -import views from '../../build/index.macro'; - -console.log(views); diff --git a/packages/modular-views.macro/src/__tests__/index.test.ts b/packages/modular-views.macro/src/__tests__/index.test.ts deleted file mode 100644 index f0911268d..000000000 --- a/packages/modular-views.macro/src/__tests__/index.test.ts +++ /dev/null @@ -1,77 +0,0 @@ -import * as path from 'path'; -import execa from 'execa'; -import * as rimraf from 'rimraf'; - -const modularRoot = path.join(__dirname, '../../../../'); -const packagesPath = path.join(modularRoot, 'packages'); - -async function transform() { - const result = await execa( - 'babel', - ['fixture.js', '--plugins', 'babel-plugin-macros'], - { - cleanup: true, - all: true, - cwd: __dirname, - }, - ); - return result.all; -} - -async function modularAddView(name: string) { - return await execa( - 'yarnpkg', - `modular add ${name} --unstable-type view`.split(' '), - { - cleanup: true, - cwd: modularRoot, - stderr: process.stderr, - stdout: process.stdout, - }, - ); -} - -beforeAll(async () => { - await execa('yarnpkg', ['build'], { - cleanup: true, - cwd: path.join(__dirname, '..', '..'), - stderr: process.stderr, - stdout: process.stdout, - }); -}); - -afterAll(async () => { - rimraf.sync(path.join(packagesPath, 'view-1')); - rimraf.sync(path.join(packagesPath, 'view-2')); - // run yarn so yarn.lock gets reset - await execa('yarnpkg', [], { - cwd: modularRoot, - stderr: process.stderr, - stdout: process.stdout, - }); -}); - -it('outputs a plain object when no views are available', async () => { - const output = await transform(); - expect(output).toMatchInlineSnapshot(` - "const __views__map__ = {}; - console.log(__views__map__); - " - `); -}); - -it('outputs a mapping of names to lazy components when views are available', async () => { - await modularAddView('view-1'); - await modularAddView('view-2'); - - const output = await transform(); - expect(output).toMatchInlineSnapshot(` - "import { lazy as __lazy__ } from 'react'; - const __views__map__ = { - 'view-1': __lazy__(() => import('view-1')), - 'view-2': __lazy__(() => import('view-2')) - }; - console.log(__views__map__); - " - `); -}); diff --git a/packages/modular-views.macro/src/index.macro.ts b/packages/modular-views.macro/src/index.macro.ts deleted file mode 100644 index 7fa25f8ad..000000000 --- a/packages/modular-views.macro/src/index.macro.ts +++ /dev/null @@ -1,137 +0,0 @@ -import * as path from 'path'; -import { ComponentType, LazyExoticComponent } from 'react'; -import fs from 'fs-extra'; -import findUp from 'find-up'; -import * as Babel from '@babel/core'; -import { ImportDeclaration, Program, Statement } from '@babel/types'; -import { default as _template } from '@babel/template'; -import { createMacro, MacroHandler } from 'babel-plugin-macros'; -import execa from 'execa'; -import type { JSONSchemaForNPMPackageJsonFiles as PackageJson } from '@schemastore/package'; - -type PackageType = 'app' | 'view' | 'root' | 'package'; - -type ModularPackageJson = PackageJson & { - modular?: { - type: PackageType; - }; -}; - -function getWorkspaces(): Array<[string, { location: string }]> { - const { stdout: yarnVersion } = execa.sync('yarnpkg', ['--version']); - - if (yarnVersion.startsWith('1.')) { - const output = execa.sync('yarnpkg', ['workspaces', 'info'], { - all: true, - reject: false, - cwd: modularRootDir, - cleanup: true, - }); - - const workspaces: Array<[string, { location: string }]> = Object.entries( - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - JSON.parse(output.stdout), - ); - - return workspaces; - } - - const output = execa.sync('yarnpkg', ['workspaces', 'list', '--json'], { - all: true, - reject: false, - cwd: modularRootDir, - cleanup: true, - }); - - const workspaces = output.stdout - .split(/\r?\n/) - .reduce((acc, workspaceString) => { - const workspaceObject = JSON.parse(workspaceString) as { - name: string; - location: string; - }; - acc.push([workspaceObject.name, workspaceObject]); - - return acc; - }, [] as Array<[string, { location: string }]>); - - return workspaces; -} - -const modularRoot = findUp.sync((directory) => { - const packageJsonPath = path.join(directory, 'package.json'); - if (fs.existsSync(packageJsonPath)) { - const pkgJSON = fs.readJsonSync(packageJsonPath) as ModularPackageJson; - if (pkgJSON.modular && pkgJSON.modular.type === 'root') { - return packageJsonPath; - } - } - return; -}); - -if (!modularRoot) { - throw new Error('This macro can only be used inside a modular project.'); -} - -const packageNames = []; - -const modularRootDir = path.dirname(modularRoot); -const workspaces = getWorkspaces(); - -for (const [name, { location }] of workspaces) { - const pkgJson = fs.readJSONSync( - path.join(modularRootDir, location, 'package.json'), - ) as ModularPackageJson; - if ( - pkgJson && - pkgJson.private !== true && - pkgJson.modular && - pkgJson.modular.type === 'view' - ) { - packageNames.push(name); - } -} - -const viewsMap = `({ - ${packageNames - .map( - (packageName) => - `'${packageName}': __lazy__(() => import('${packageName}'))`, - ) - .join(',\n ')} -})`; - -const views: MacroHandler = ({ references, babel }) => { - const r = references as { default?: Babel.NodePath[] }; - if (!r.default || r.default.length === 0) { - return; - } - - const template = (babel as { template: typeof _template }).template; - - const nodePath = r.default[0]; - const hub = nodePath.hub; - const node = hub.getScope()?.path.node as Program; - const body = node.body; - const rootStatement: Statement = template.ast( - `const __views__map__ = ${viewsMap};`, - ) as Statement; - body.unshift(rootStatement); - - if (packageNames.length > 0) { - const packageStatement: Statement = template.ast( - "import {lazy as __lazy__} from 'react';", - ) as Statement; - body.unshift(packageStatement); - } - - r.default.forEach((ref) => ref.replaceWithSourceString(`__views__map__`)); -}; - -interface ViewMap { - [packageName: string]: LazyExoticComponent>; -} - -const viewMap = createMacro(views) as ViewMap; - -export default viewMap; diff --git a/packages/modular-views.macro/tsconfig.json b/packages/modular-views.macro/tsconfig.json deleted file mode 100644 index 6a2dff2af..000000000 --- a/packages/modular-views.macro/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "modular-scripts/tsconfig.json", - "compilerOptions": { - "rootDir": "./src", - "noEmit": false, - "declaration": true, - "declarationDir": "types" - }, - "include": ["src/**/*"], - "exclude": ["**/__tests__"] -} diff --git a/packages/workspace-resolver/package.json b/packages/workspace-resolver/package.json index c5dafe0c9..0e69310a3 100644 --- a/packages/workspace-resolver/package.json +++ b/packages/workspace-resolver/package.json @@ -4,8 +4,8 @@ "license": "Apache-2.0", "main": "src/index.ts", "dependencies": { + "@esm2cjs/globby": "13.1.4", "fs-extra": "^10.1.0", - "globby": "11.1.0", "semver": "7.3.7" }, "devDependencies": { diff --git a/packages/workspace-resolver/src/resolve-workspace.ts b/packages/workspace-resolver/src/resolve-workspace.ts index 2f7b38465..2a69b82ac 100644 --- a/packages/workspace-resolver/src/resolve-workspace.ts +++ b/packages/workspace-resolver/src/resolve-workspace.ts @@ -1,6 +1,6 @@ import path, { join } from 'path'; -import { readJson } from 'fs-extra'; -import globby from 'globby'; +import { existsSync, readJson } from 'fs-extra'; +import { globbySync } from '@esm2cjs/globby'; import semver from 'semver'; import type { ModularPackageJson, @@ -17,26 +17,27 @@ function packageJsonPath(dir: string) { } function resolveWorkspacesDefinition( - cwd: string, + root: string, def: ModularPackageJson['workspaces'], + ignoreFiles: string[], ): string[] { if (!def) { return []; } - if (Array.isArray(def)) { return def.flatMap((path: string) => { - return globby.sync( + return globbySync( [`${path}/package.json`, '!**/node_modules/**/*', '!**/__tests__/**/*'], { absolute: false, - cwd, + cwd: root, + ignoreFiles: ignoreFiles, }, ); }); } - return resolveWorkspacesDefinition(cwd, def.packages); + return resolveWorkspacesDefinition(root, def.packages, ignoreFiles); } function readPackageJson( @@ -128,7 +129,23 @@ export async function resolveWorkspace( } } - for (const link of resolveWorkspacesDefinition(root, json.workspaces)) { + // Filter out workspaces covered by .modularignore or .gitignore + const ignoreFiles: string[] = []; + + const modularIgnorePath = path.join(root, '.modularignore'); + const gitIgnore = path.join(root, '.gitignore'); + + if (existsSync(modularIgnorePath)) { + ignoreFiles.push('.modularignore'); + } else if (existsSync(gitIgnore)) { + ignoreFiles.push('.gitignore'); + } + + for (const link of resolveWorkspacesDefinition( + root, + json.workspaces, + ignoreFiles, + )) { const [, child] = await resolveWorkspace( link, workingDirToUse, diff --git a/yarn.lock b/yarn.lock index 3ea23f11f..deea1c01b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -64,7 +64,7 @@ json5 "^2.2.1" semver "^6.3.0" -"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.15.5", "@babel/core@^7.16.0", "@babel/core@^7.17.9", "@babel/core@^7.19.6": +"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.15.5", "@babel/core@^7.16.0", "@babel/core@^7.19.6": version "7.20.2" resolved "https://registry.npmjs.org/@babel/core/-/core-7.20.2.tgz" integrity sha512-w7DbG8DtMrJcFOi4VrLm+8QM4az8Mo+PuLBKLp2zrYRCow8W/f9xiXm5sN53C8HksCyDQwCKha9JiDoIyPjT2g== @@ -1645,6 +1645,22 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" +"@esm2cjs/globby@13.1.4": + version "13.1.4" + resolved "https://registry.yarnpkg.com/@esm2cjs/globby/-/globby-13.1.4.tgz#38794c6b560654cb94e413b78ab568acf594bd6f" + integrity sha512-JES/VBjQfk78esAY7SSVk2c77v94UKVlOPPTP5HBFRjY5IIr0hjE6B3LzYzY98oaO9ygYVy5CURGdxasDVGv1g== + dependencies: + "@esm2cjs/slash" "^4.0.0" + dir-glob "^3.0.1" + fast-glob "^3.2.11" + ignore "^5.2.0" + merge2 "^1.4.1" + +"@esm2cjs/slash@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@esm2cjs/slash/-/slash-4.0.0.tgz#5101e35a912eeb308c34f448c81cf353048d59b5" + integrity sha512-UUTg4pcAaq1D3R4yj0T+up/eBnZko6nE0ToBq6m6c0rHmpYPIGh/UrNMEeZV2hkLKpXBg6i1Zr9tJgmXq1T2BA== + "@floating-ui/core@^0.7.3": version "0.7.3" resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-0.7.3.tgz#d274116678ffae87f6b60e90f88cc4083eefab86" @@ -2725,19 +2741,12 @@ resolved "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz" integrity sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig== -"@types/babel-plugin-macros@2.8.5": - version "2.8.5" - resolved "https://registry.npmjs.org/@types/babel-plugin-macros/-/babel-plugin-macros-2.8.5.tgz" - integrity sha512-+NcIm/VBaSb4xaycov9f4Vmk4hMVPrgISoHEk+kalgVK6BlkwDZbXkW9kt1jCXVczTKXldL5RHIacExaWzxAkA== - dependencies: - "@types/babel__core" "*" - "@types/babel__code-frame@^7.0.3": version "7.0.3" resolved "https://registry.npmjs.org/@types/babel__code-frame/-/babel__code-frame-7.0.3.tgz" integrity sha512-2TN6oiwtNjOezilFVl77zwdNPwQWaDBBCCWWxyo1ctiO3vAtd7H/aB/CBJdw9+kqq3+latD0SXoedIuHySSZWw== -"@types/babel__core@*", "@types/babel__core@^7.1.14": +"@types/babel__core@^7.1.14": version "7.1.20" resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.20.tgz" integrity sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ== @@ -4064,7 +4073,7 @@ babel-plugin-jest-hoist@^29.5.0: "@types/babel__core" "^7.1.14" "@types/babel__traverse" "^7.0.6" -babel-plugin-macros@3.1.0, babel-plugin-macros@^3.1.0: +babel-plugin-macros@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz" integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==