feat(core): add metagenerator for convert-to-inferred (#27672)
<!-- Please make sure you have read the submission guidelines before posting an PR --> <!-- https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr --> <!-- Please make sure that your commit message follows our format --> <!-- Example: `fix(nx): must begin with lowercase` --> <!-- If this is a particularly complex change or feature addition, you can request a dedicated Nx release for this pull request branch. Mention someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they will confirm if the PR warrants its own release for testing purposes, and generate it for you if appropriate. --> ## Current Behavior The DX to migrate to project crystal isn't great right now - people have to run `convert-to-inferred` generators manually. ## Expected Behavior We should provide a smoother way to migrate, so we introduced an `@nx/workspace:infer-targets` generator that can handle multiple conversions at once, either for the whole workspace or at a project level. --------- Co-authored-by: Jack Hsu <jack.hsu@gmail.com>
This commit is contained in:
parent
7232b392ba
commit
5bbaffbda8
@ -10391,6 +10391,14 @@
|
|||||||
"children": [],
|
"children": [],
|
||||||
"isExternal": false,
|
"isExternal": false,
|
||||||
"disableCollapsible": false
|
"disableCollapsible": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "infer-targets",
|
||||||
|
"path": "/nx-api/workspace/generators/infer-targets",
|
||||||
|
"name": "infer-targets",
|
||||||
|
"children": [],
|
||||||
|
"isExternal": false,
|
||||||
|
"disableCollapsible": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"isExternal": false,
|
"isExternal": false,
|
||||||
|
|||||||
@ -3487,6 +3487,15 @@
|
|||||||
"originalFilePath": "/packages/workspace/src/generators/ci-workflow/schema.json",
|
"originalFilePath": "/packages/workspace/src/generators/ci-workflow/schema.json",
|
||||||
"path": "/nx-api/workspace/generators/ci-workflow",
|
"path": "/nx-api/workspace/generators/ci-workflow",
|
||||||
"type": "generator"
|
"type": "generator"
|
||||||
|
},
|
||||||
|
"/nx-api/workspace/generators/infer-targets": {
|
||||||
|
"description": "Convert Nx projects to use inferred targets.",
|
||||||
|
"file": "generated/packages/workspace/generators/infer-targets.json",
|
||||||
|
"hidden": false,
|
||||||
|
"name": "infer-targets",
|
||||||
|
"originalFilePath": "/packages/workspace/src/generators/infer-targets/schema.json",
|
||||||
|
"path": "/nx-api/workspace/generators/infer-targets",
|
||||||
|
"type": "generator"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"path": "/nx-api/workspace"
|
"path": "/nx-api/workspace"
|
||||||
|
|||||||
@ -3451,6 +3451,15 @@
|
|||||||
"originalFilePath": "/packages/workspace/src/generators/ci-workflow/schema.json",
|
"originalFilePath": "/packages/workspace/src/generators/ci-workflow/schema.json",
|
||||||
"path": "workspace/generators/ci-workflow",
|
"path": "workspace/generators/ci-workflow",
|
||||||
"type": "generator"
|
"type": "generator"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Convert Nx projects to use inferred targets.",
|
||||||
|
"file": "generated/packages/workspace/generators/infer-targets.json",
|
||||||
|
"hidden": false,
|
||||||
|
"name": "infer-targets",
|
||||||
|
"originalFilePath": "/packages/workspace/src/generators/infer-targets/schema.json",
|
||||||
|
"path": "workspace/generators/infer-targets",
|
||||||
|
"type": "generator"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"githubRoot": "https://github.com/nrwl/nx/blob/master",
|
"githubRoot": "https://github.com/nrwl/nx/blob/master",
|
||||||
|
|||||||
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "infer-targets",
|
||||||
|
"factory": "./src/generators/infer-targets/infer-targets",
|
||||||
|
"schema": {
|
||||||
|
"$schema": "https://json-schema.org/schema",
|
||||||
|
"$id": "InferTargets",
|
||||||
|
"title": "",
|
||||||
|
"type": "object",
|
||||||
|
"description": "Convert Nx projects to use inferred targets.",
|
||||||
|
"properties": {
|
||||||
|
"project": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The project to convert to use inferred targets.",
|
||||||
|
"x-priority": "important"
|
||||||
|
},
|
||||||
|
"plugins": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "The plugins used to infer targets. For example @nx/eslint or @nx/jest",
|
||||||
|
"items": { "type": "string" }
|
||||||
|
},
|
||||||
|
"skipFormat": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to format files.",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"presets": []
|
||||||
|
},
|
||||||
|
"description": "Convert Nx projects to use inferred targets.",
|
||||||
|
"implementation": "/packages/workspace/src/generators/infer-targets/infer-targets.ts",
|
||||||
|
"aliases": [],
|
||||||
|
"hidden": false,
|
||||||
|
"path": "/packages/workspace/src/generators/infer-targets/schema.json",
|
||||||
|
"type": "generator"
|
||||||
|
}
|
||||||
@ -19,7 +19,17 @@ For the best experience, we recommend that you [migrate](/features/automate-upda
|
|||||||
npx nx migrate latest
|
npx nx migrate latest
|
||||||
```
|
```
|
||||||
|
|
||||||
## Migrate a Plugin
|
## Migrate All Plugins
|
||||||
|
|
||||||
|
You can use the `infer-targets` generator to quickly migrate all available plugins to use inferred tasks. See the sections below for more details on the individual plugins' migration processes.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
npx nx g infer-targets
|
||||||
|
```
|
||||||
|
|
||||||
|
The generator will automatically detect all available `convert-to-inferred` generators and run the ones you choose. If you only want to try it on a single project, pass the `--project` option.
|
||||||
|
|
||||||
|
## Migrate a Single Plugin
|
||||||
|
|
||||||
Most of the official plugins come with a `convert-to-inferred` generator. This generator will
|
Most of the official plugins come with a `convert-to-inferred` generator. This generator will
|
||||||
|
|
||||||
@ -42,7 +52,7 @@ None of the above
|
|||||||
For third-party plugins that provide `convert-to-inferred` generators, you should pick the `None of the above` option and type in the name of the package manually. Alternatively, you can also provide the package explicitly with `nx g <plugin>:convert-to-inferred`.
|
For third-party plugins that provide `convert-to-inferred` generators, you should pick the `None of the above` option and type in the name of the package manually. Alternatively, you can also provide the package explicitly with `nx g <plugin>:convert-to-inferred`.
|
||||||
{% /callout %}
|
{% /callout %}
|
||||||
|
|
||||||
We recommend that you migrate the plugins one at a time, and check that the configurations are correct before continuing to the next plugin. If you only want to try it on a single project, pass the `--project` option.
|
We recommend that you check that the configurations are correct before continuing to the next plugin. If you only want to try it on a single project, pass the `--project` option.
|
||||||
|
|
||||||
## Understand the Migration Process
|
## Understand the Migration Process
|
||||||
|
|
||||||
@ -96,7 +106,7 @@ For example, if we migrated the `@nx/vite` plugin for a single app (i.e. `nx g @
|
|||||||
You'll notice that the `serve` and `build` tasks are running the [Vite CLI](https://vitejs.dev/guide/cli.html) and there are no references to Nx executors. Since the targets directly invoke the Vite CLI, any options that may be passed to it can be passed via Nx commands. e.g. `nx serve demo --cors --port 8888` enables CORs and uses port `8888` using [Vite CLI options](https://vitejs.dev/guide/cli.html#options)
|
You'll notice that the `serve` and `build` tasks are running the [Vite CLI](https://vitejs.dev/guide/cli.html) and there are no references to Nx executors. Since the targets directly invoke the Vite CLI, any options that may be passed to it can be passed via Nx commands. e.g. `nx serve demo --cors --port 8888` enables CORs and uses port `8888` using [Vite CLI options](https://vitejs.dev/guide/cli.html#options)
|
||||||
The same CLI setup applies to other plugins as well.
|
The same CLI setup applies to other plugins as well.
|
||||||
|
|
||||||
- `@nx/cypess` calls the [Cypress CLI](https://docs.cypress.io/guides/guides/command-line)
|
- `@nx/cypress` calls the [Cypress CLI](https://docs.cypress.io/guides/guides/command-line)
|
||||||
- `@nx/playwright` calls the [Playwright CLI](https://playwright.dev/docs/test-cli)
|
- `@nx/playwright` calls the [Playwright CLI](https://playwright.dev/docs/test-cli)
|
||||||
- `@nx/webpack` calls the [Webpack CLI](https://webpack.js.org/api/cli/)
|
- `@nx/webpack` calls the [Webpack CLI](https://webpack.js.org/api/cli/)
|
||||||
- etc.
|
- etc.
|
||||||
|
|||||||
@ -755,3 +755,4 @@
|
|||||||
- [fix-configuration](/nx-api/workspace/generators/fix-configuration)
|
- [fix-configuration](/nx-api/workspace/generators/fix-configuration)
|
||||||
- [npm-package](/nx-api/workspace/generators/npm-package)
|
- [npm-package](/nx-api/workspace/generators/npm-package)
|
||||||
- [ci-workflow](/nx-api/workspace/generators/ci-workflow)
|
- [ci-workflow](/nx-api/workspace/generators/ci-workflow)
|
||||||
|
- [infer-targets](/nx-api/workspace/generators/infer-targets)
|
||||||
|
|||||||
@ -13,11 +13,150 @@ import {
|
|||||||
tmpProjPath,
|
tmpProjPath,
|
||||||
uniq,
|
uniq,
|
||||||
updateFile,
|
updateFile,
|
||||||
|
updateJson,
|
||||||
} from '@nx/e2e/utils';
|
} from '@nx/e2e/utils';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
|
|
||||||
let proj: string;
|
let proj: string;
|
||||||
|
|
||||||
|
describe('@nx/workspace:infer-targets', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
proj = newProject({
|
||||||
|
packages: ['@nx/playwright', '@nx/remix', '@nx/eslint', '@nx/jest'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => cleanupProject());
|
||||||
|
|
||||||
|
it('should run or skip conversions depending on whether executors are present', async () => {
|
||||||
|
// default case, everything is generated with crystal, everything should be skipped
|
||||||
|
const remixApp = uniq('remix');
|
||||||
|
runCLI(
|
||||||
|
`generate @nx/remix:app ${remixApp} --dir apps --unitTestRunner jest --e2eTestRunner=playwright --projectNameAndDirectoryFormat=as-provided --no-interactive`
|
||||||
|
);
|
||||||
|
|
||||||
|
const output = runCLI(`generate infer-targets --no-interactive`);
|
||||||
|
|
||||||
|
expect(output).toContain('@nx/remix:convert-to-inferred - Skipped');
|
||||||
|
expect(output).toContain('@nx/playwright:convert-to-inferred - Skipped');
|
||||||
|
expect(output).toContain('@nx/eslint:convert-to-inferred - Skipped');
|
||||||
|
expect(output).toContain('@nx/jest:convert-to-inferred - Skipped');
|
||||||
|
|
||||||
|
// if we make sure there are executors to convert, conversions will run
|
||||||
|
updateJson('nx.json', (json) => {
|
||||||
|
json.plugins = [];
|
||||||
|
return json;
|
||||||
|
});
|
||||||
|
|
||||||
|
updateJson(join('apps', remixApp, 'project.json'), (json) => {
|
||||||
|
json.targets = {
|
||||||
|
build: {
|
||||||
|
executor: '@nx/remix:build',
|
||||||
|
},
|
||||||
|
lint: {
|
||||||
|
executor: '@nx/eslint:lint',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return json;
|
||||||
|
});
|
||||||
|
|
||||||
|
const output2 = runCLI(`generate infer-targets --no-interactive`);
|
||||||
|
|
||||||
|
expect(output2).toContain('@nx/remix:convert-to-inferred - Success');
|
||||||
|
expect(output2).toContain('@nx/eslint:convert-to-inferred - Success');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should run or skip only specific conversions if --plugins is passed', async () => {
|
||||||
|
// default case, everything is generated with crystal, relevant plugins should be skipped
|
||||||
|
const remixApp = uniq('remix');
|
||||||
|
runCLI(
|
||||||
|
`generate @nx/remix:app ${remixApp} --dir apps --unitTestRunner jest --e2eTestRunner=playwright --projectNameAndDirectoryFormat=as-provided --no-interactive`
|
||||||
|
);
|
||||||
|
|
||||||
|
const output = runCLI(
|
||||||
|
`generate infer-targets --plugins=@nx/eslint,@nx/jest --no-interactive`
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(output).toContain('@nx/eslint:convert-to-inferred - Skipped');
|
||||||
|
expect(output).toContain('@nx/jest:convert-to-inferred - Skipped');
|
||||||
|
|
||||||
|
expect(output).not.toContain('@nx/remix');
|
||||||
|
expect(output).not.toContain('@nx/playwright');
|
||||||
|
|
||||||
|
// if we make sure there are executors to convert, relevant conversions will run
|
||||||
|
updateJson('nx.json', (json) => {
|
||||||
|
json.plugins = [];
|
||||||
|
return json;
|
||||||
|
});
|
||||||
|
|
||||||
|
updateJson(join('apps', remixApp, 'project.json'), (json) => {
|
||||||
|
json.targets = {
|
||||||
|
build: {
|
||||||
|
executor: '@nx/remix:build',
|
||||||
|
},
|
||||||
|
lint: {
|
||||||
|
executor: '@nx/eslint:lint',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return json;
|
||||||
|
});
|
||||||
|
|
||||||
|
const output2 = runCLI(
|
||||||
|
`generate infer-targets --plugins=@nx/remix,@nx/eslint --no-interactive`
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(output2).toContain('@nx/remix:convert-to-inferred - Success');
|
||||||
|
expect(output2).toContain('@nx/eslint:convert-to-inferred - Success');
|
||||||
|
|
||||||
|
expect(output2).not.toContain('@nx/jest');
|
||||||
|
expect(output2).not.toContain('@nx/playwright');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should run only specific conversions for a specific project if --project is passed', async () => {
|
||||||
|
// even if we make sure there are executors for remix & remix-e2e, only remix conversions will run with --project option
|
||||||
|
const remixApp = uniq('remix');
|
||||||
|
runCLI(
|
||||||
|
`generate @nx/remix:app ${remixApp} --dir apps --unitTestRunner jest --e2eTestRunner=playwright --projectNameAndDirectoryFormat=as-provided --no-interactive`
|
||||||
|
);
|
||||||
|
|
||||||
|
updateJson('nx.json', (json) => {
|
||||||
|
json.plugins = [];
|
||||||
|
return json;
|
||||||
|
});
|
||||||
|
|
||||||
|
updateJson(join('apps', remixApp, 'project.json'), (json) => {
|
||||||
|
json.targets = {
|
||||||
|
build: {
|
||||||
|
executor: '@nx/remix:build',
|
||||||
|
},
|
||||||
|
lint: {
|
||||||
|
executor: '@nx/eslint:lint',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return json;
|
||||||
|
});
|
||||||
|
|
||||||
|
updateJson(join('apps', `${remixApp}-e2e`, 'project.json'), (json) => {
|
||||||
|
json.targets = {
|
||||||
|
e2e: {
|
||||||
|
executor: '@nx/playwright:playwright',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return json;
|
||||||
|
});
|
||||||
|
|
||||||
|
const output2 = runCLI(
|
||||||
|
`generate infer-targets --project ${remixApp} --no-interactive`
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(output2).toContain('@nx/remix:convert-to-inferred - Success');
|
||||||
|
expect(output2).toContain('@nx/eslint:convert-to-inferred - Success');
|
||||||
|
|
||||||
|
expect(output2).toContain('@nx/jest:convert-to-inferred - Skipped');
|
||||||
|
expect(output2).toContain('@nx/playwright:convert-to-inferred - Skipped');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('@nx/workspace:convert-to-monorepo', () => {
|
describe('@nx/workspace:convert-to-monorepo', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
proj = newProject({ packages: ['@nx/react', '@nx/js'] });
|
proj = newProject({ packages: ['@nx/react', '@nx/js'] });
|
||||||
|
|||||||
@ -4,7 +4,10 @@ import {
|
|||||||
type TargetConfiguration,
|
type TargetConfiguration,
|
||||||
type Tree,
|
type Tree,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { migrateProjectExecutorsToPlugin } from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
import {
|
||||||
|
migrateProjectExecutorsToPlugin,
|
||||||
|
NoTargetsToMigrateError,
|
||||||
|
} from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
||||||
import {
|
import {
|
||||||
processTargetOutputs,
|
processTargetOutputs,
|
||||||
toProjectRelativePath,
|
toProjectRelativePath,
|
||||||
@ -46,7 +49,7 @@ export async function convertToInferred(tree: Tree, options: Schema) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (migratedProjects.size === 0) {
|
if (migratedProjects.size === 0) {
|
||||||
throw new Error('Could not find any targets to migrate.');
|
throw new NoTargetsToMigrateError();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.skipFormat) {
|
if (!options.skipFormat) {
|
||||||
|
|||||||
@ -7,7 +7,10 @@ import {
|
|||||||
updateNxJson,
|
updateNxJson,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { AggregatedLog } from '@nx/devkit/src/generators/plugin-migrations/aggregate-log-util';
|
import { AggregatedLog } from '@nx/devkit/src/generators/plugin-migrations/aggregate-log-util';
|
||||||
import { migrateProjectExecutorsToPluginV1 } from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
import {
|
||||||
|
migrateProjectExecutorsToPluginV1,
|
||||||
|
NoTargetsToMigrateError,
|
||||||
|
} from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
||||||
import { createNodes } from '../../plugins/plugin';
|
import { createNodes } from '../../plugins/plugin';
|
||||||
import { processBuildOptions } from './lib/process-build-options';
|
import { processBuildOptions } from './lib/process-build-options';
|
||||||
import { postTargetTransformer } from './lib/post-target-transformer';
|
import { postTargetTransformer } from './lib/post-target-transformer';
|
||||||
@ -97,7 +100,7 @@ export async function convertToInferred(tree: Tree, options: Schema) {
|
|||||||
updateNxJson(tree, nxJson);
|
updateNxJson(tree, nxJson);
|
||||||
|
|
||||||
if (migratedProjects.size === 0) {
|
if (migratedProjects.size === 0) {
|
||||||
throw new Error('Could not find any targets to migrate.');
|
throw new NoTargetsToMigrateError();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.skipFormat) {
|
if (!options.skipFormat) {
|
||||||
|
|||||||
@ -28,6 +28,7 @@ import type { RunCommandsOptions } from 'nx/src/executors/run-commands/run-comma
|
|||||||
import type { ConfigurationResult } from 'nx/src/project-graph/utils/project-configuration-utils';
|
import type { ConfigurationResult } from 'nx/src/project-graph/utils/project-configuration-utils';
|
||||||
import { forEachExecutorOptions } from '../executor-options-utils';
|
import { forEachExecutorOptions } from '../executor-options-utils';
|
||||||
import { deleteMatchingProperties } from './plugin-migration-utils';
|
import { deleteMatchingProperties } from './plugin-migration-utils';
|
||||||
|
import { logger as devkitLogger } from 'nx/src/devkit-exports';
|
||||||
|
|
||||||
export type InferredTargetConfiguration = TargetConfiguration & {
|
export type InferredTargetConfiguration = TargetConfiguration & {
|
||||||
name: string;
|
name: string;
|
||||||
@ -57,6 +58,7 @@ class ExecutorToPluginMigrator<T> {
|
|||||||
readonly #skipTargetFilter: SkipTargetFilter;
|
readonly #skipTargetFilter: SkipTargetFilter;
|
||||||
readonly #skipProjectFilter: SkipProjectFilter;
|
readonly #skipProjectFilter: SkipProjectFilter;
|
||||||
readonly #specificProjectToMigrate: string;
|
readonly #specificProjectToMigrate: string;
|
||||||
|
readonly #logger: typeof devkitLogger;
|
||||||
#nxJson: NxJsonConfiguration;
|
#nxJson: NxJsonConfiguration;
|
||||||
#targetDefaultsForExecutor: Partial<TargetConfiguration>;
|
#targetDefaultsForExecutor: Partial<TargetConfiguration>;
|
||||||
#targetAndProjectsToMigrate: Map<string, Set<string>>;
|
#targetAndProjectsToMigrate: Map<string, Set<string>>;
|
||||||
@ -78,7 +80,8 @@ class ExecutorToPluginMigrator<T> {
|
|||||||
filters?: {
|
filters?: {
|
||||||
skipProjectFilter?: SkipProjectFilter;
|
skipProjectFilter?: SkipProjectFilter;
|
||||||
skipTargetFilter?: SkipTargetFilter;
|
skipTargetFilter?: SkipTargetFilter;
|
||||||
}
|
},
|
||||||
|
logger?: typeof devkitLogger
|
||||||
) {
|
) {
|
||||||
this.tree = tree;
|
this.tree = tree;
|
||||||
this.#projectGraph = projectGraph;
|
this.#projectGraph = projectGraph;
|
||||||
@ -92,6 +95,7 @@ class ExecutorToPluginMigrator<T> {
|
|||||||
this.#skipProjectFilter =
|
this.#skipProjectFilter =
|
||||||
filters?.skipProjectFilter ?? ((...args) => false);
|
filters?.skipProjectFilter ?? ((...args) => false);
|
||||||
this.#skipTargetFilter = filters?.skipTargetFilter ?? ((...args) => false);
|
this.#skipTargetFilter = filters?.skipTargetFilter ?? ((...args) => false);
|
||||||
|
this.#logger = logger ?? devkitLogger;
|
||||||
}
|
}
|
||||||
|
|
||||||
async run(): Promise<Map<string, Set<string>>> {
|
async run(): Promise<Map<string, Set<string>>> {
|
||||||
@ -255,7 +259,7 @@ class ExecutorToPluginMigrator<T> {
|
|||||||
throw new Error(errorMsg);
|
throw new Error(errorMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.warn(errorMsg);
|
this.#logger.warn(errorMsg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,7 +272,7 @@ class ExecutorToPluginMigrator<T> {
|
|||||||
if (this.#specificProjectToMigrate) {
|
if (this.#specificProjectToMigrate) {
|
||||||
throw new Error(errorMsg);
|
throw new Error(errorMsg);
|
||||||
} else {
|
} else {
|
||||||
console.warn(errorMsg);
|
this.#logger.warn(errorMsg);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -336,6 +340,12 @@ class ExecutorToPluginMigrator<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class NoTargetsToMigrateError extends Error {
|
||||||
|
constructor() {
|
||||||
|
super('Could not find any targets to migrate.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function migrateProjectExecutorsToPlugin<T>(
|
export async function migrateProjectExecutorsToPlugin<T>(
|
||||||
tree: Tree,
|
tree: Tree,
|
||||||
projectGraph: ProjectGraph,
|
projectGraph: ProjectGraph,
|
||||||
@ -349,7 +359,8 @@ export async function migrateProjectExecutorsToPlugin<T>(
|
|||||||
skipProjectFilter?: SkipProjectFilter;
|
skipProjectFilter?: SkipProjectFilter;
|
||||||
skipTargetFilter?: SkipTargetFilter;
|
skipTargetFilter?: SkipTargetFilter;
|
||||||
}>,
|
}>,
|
||||||
specificProjectToMigrate?: string
|
specificProjectToMigrate?: string,
|
||||||
|
logger?: typeof devkitLogger
|
||||||
): Promise<Map<string, Record<string, string>>> {
|
): Promise<Map<string, Record<string, string>>> {
|
||||||
const projects = await migrateProjects(
|
const projects = await migrateProjects(
|
||||||
tree,
|
tree,
|
||||||
@ -359,7 +370,8 @@ export async function migrateProjectExecutorsToPlugin<T>(
|
|||||||
createNodesV2,
|
createNodesV2,
|
||||||
defaultPluginOptions,
|
defaultPluginOptions,
|
||||||
migrations,
|
migrations,
|
||||||
specificProjectToMigrate
|
specificProjectToMigrate,
|
||||||
|
logger
|
||||||
);
|
);
|
||||||
|
|
||||||
return projects;
|
return projects;
|
||||||
@ -408,7 +420,8 @@ async function migrateProjects<T>(
|
|||||||
skipProjectFilter?: SkipProjectFilter;
|
skipProjectFilter?: SkipProjectFilter;
|
||||||
skipTargetFilter?: SkipTargetFilter;
|
skipTargetFilter?: SkipTargetFilter;
|
||||||
}>,
|
}>,
|
||||||
specificProjectToMigrate?: string
|
specificProjectToMigrate?: string,
|
||||||
|
logger?: typeof devkitLogger
|
||||||
): Promise<Map<string, Record<string, string>>> {
|
): Promise<Map<string, Record<string, string>>> {
|
||||||
const projects = new Map<string, Record<string, string>>();
|
const projects = new Map<string, Record<string, string>>();
|
||||||
|
|
||||||
@ -427,7 +440,8 @@ async function migrateProjects<T>(
|
|||||||
{
|
{
|
||||||
skipProjectFilter: migration.skipProjectFilter,
|
skipProjectFilter: migration.skipProjectFilter,
|
||||||
skipTargetFilter: migration.skipTargetFilter,
|
skipTargetFilter: migration.skipTargetFilter,
|
||||||
}
|
},
|
||||||
|
logger
|
||||||
);
|
);
|
||||||
|
|
||||||
const result = await migrator.run();
|
const result = await migrator.run();
|
||||||
|
|||||||
@ -5,7 +5,10 @@ import {
|
|||||||
type TargetConfiguration,
|
type TargetConfiguration,
|
||||||
type Tree,
|
type Tree,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { migrateProjectExecutorsToPlugin } from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
import {
|
||||||
|
migrateProjectExecutorsToPlugin,
|
||||||
|
NoTargetsToMigrateError,
|
||||||
|
} from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
||||||
import { processTargetOutputs } from '@nx/devkit/src/generators/plugin-migrations/plugin-migration-utils';
|
import { processTargetOutputs } from '@nx/devkit/src/generators/plugin-migrations/plugin-migration-utils';
|
||||||
import { basename, dirname, relative } from 'node:path/posix';
|
import { basename, dirname, relative } from 'node:path/posix';
|
||||||
import { interpolate } from 'nx/src/tasks-runner/utils';
|
import { interpolate } from 'nx/src/tasks-runner/utils';
|
||||||
@ -40,7 +43,7 @@ export async function convertToInferred(tree: Tree, options: Schema) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (migratedProjects.size === 0) {
|
if (migratedProjects.size === 0) {
|
||||||
throw new Error('Could not find any targets to migrate.');
|
throw new NoTargetsToMigrateError();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.skipFormat) {
|
if (!options.skipFormat) {
|
||||||
|
|||||||
@ -5,7 +5,10 @@ import {
|
|||||||
type Tree,
|
type Tree,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { AggregatedLog } from '@nx/devkit/src/generators/plugin-migrations/aggregate-log-util';
|
import { AggregatedLog } from '@nx/devkit/src/generators/plugin-migrations/aggregate-log-util';
|
||||||
import { migrateProjectExecutorsToPluginV1 } from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
import {
|
||||||
|
migrateProjectExecutorsToPluginV1,
|
||||||
|
NoTargetsToMigrateError,
|
||||||
|
} from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
||||||
import { createNodes } from '../../../plugins/plugin';
|
import { createNodes } from '../../../plugins/plugin';
|
||||||
import { processBuildOptions } from './lib/process-build-options';
|
import { processBuildOptions } from './lib/process-build-options';
|
||||||
import { postTargetTransformer } from './lib/post-target-transformer';
|
import { postTargetTransformer } from './lib/post-target-transformer';
|
||||||
@ -140,7 +143,7 @@ export async function convertToInferred(tree: Tree, options: Schema) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (migratedProjects.size === 0) {
|
if (migratedProjects.size === 0) {
|
||||||
throw new Error('Could not find any targets to migrate.');
|
throw new NoTargetsToMigrateError();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.skipFormat) {
|
if (!options.skipFormat) {
|
||||||
|
|||||||
@ -5,7 +5,10 @@ import {
|
|||||||
type TargetConfiguration,
|
type TargetConfiguration,
|
||||||
type Tree,
|
type Tree,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { migrateProjectExecutorsToPlugin } from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
import {
|
||||||
|
migrateProjectExecutorsToPlugin,
|
||||||
|
NoTargetsToMigrateError,
|
||||||
|
} from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
||||||
import {
|
import {
|
||||||
processTargetOutputs,
|
processTargetOutputs,
|
||||||
toProjectRelativePath,
|
toProjectRelativePath,
|
||||||
@ -40,7 +43,7 @@ export async function convertToInferred(tree: Tree, options: Schema) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (migratedProjects.size === 0) {
|
if (migratedProjects.size === 0) {
|
||||||
throw new Error('Could not find any targets to migrate.');
|
throw new NoTargetsToMigrateError();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.skipFormat) {
|
if (!options.skipFormat) {
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
import { createProjectGraphAsync, formatFiles, Tree } from '@nx/devkit';
|
import { createProjectGraphAsync, formatFiles, Tree } from '@nx/devkit';
|
||||||
import { AggregatedLog } from '@nx/devkit/src/generators/plugin-migrations/aggregate-log-util';
|
import { AggregatedLog } from '@nx/devkit/src/generators/plugin-migrations/aggregate-log-util';
|
||||||
import { migrateProjectExecutorsToPluginV1 } from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
import {
|
||||||
|
migrateProjectExecutorsToPluginV1,
|
||||||
|
NoTargetsToMigrateError,
|
||||||
|
} from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
||||||
import { createNodes } from '../../plugins/plugin';
|
import { createNodes } from '../../plugins/plugin';
|
||||||
import { buildPostTargetTransformer } from './lib/build-post-target-transformer';
|
import { buildPostTargetTransformer } from './lib/build-post-target-transformer';
|
||||||
import { servePosTargetTransformer } from './lib/serve-post-target-tranformer';
|
import { servePosTargetTransformer } from './lib/serve-post-target-tranformer';
|
||||||
@ -45,7 +48,7 @@ export async function convertToInferred(tree: Tree, options: Schema) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (migratedProjects.size === 0) {
|
if (migratedProjects.size === 0) {
|
||||||
throw new Error('Could not find any targets to migrate');
|
throw new NoTargetsToMigrateError();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.skipFormat) {
|
if (!options.skipFormat) {
|
||||||
|
|||||||
@ -12,12 +12,7 @@ import {
|
|||||||
import { readJsonFile } from '../../utils/fileutils';
|
import { readJsonFile } from '../../utils/fileutils';
|
||||||
import { readPluginPackageJson } from '../../project-graph/plugins';
|
import { readPluginPackageJson } from '../../project-graph/plugins';
|
||||||
|
|
||||||
export function getGeneratorInformation(
|
export type GeneratorInformation = {
|
||||||
collectionName: string,
|
|
||||||
generatorName: string,
|
|
||||||
root: string | null,
|
|
||||||
projects: Record<string, ProjectConfiguration>
|
|
||||||
): {
|
|
||||||
resolvedCollectionName: string;
|
resolvedCollectionName: string;
|
||||||
normalizedGeneratorName: string;
|
normalizedGeneratorName: string;
|
||||||
schema: any;
|
schema: any;
|
||||||
@ -25,7 +20,14 @@ export function getGeneratorInformation(
|
|||||||
isNgCompat: boolean;
|
isNgCompat: boolean;
|
||||||
isNxGenerator: boolean;
|
isNxGenerator: boolean;
|
||||||
generatorConfiguration: GeneratorsJsonEntry;
|
generatorConfiguration: GeneratorsJsonEntry;
|
||||||
} {
|
};
|
||||||
|
|
||||||
|
export function getGeneratorInformation(
|
||||||
|
collectionName: string,
|
||||||
|
generatorName: string,
|
||||||
|
root: string | null,
|
||||||
|
projects: Record<string, ProjectConfiguration>
|
||||||
|
): GeneratorInformation {
|
||||||
try {
|
try {
|
||||||
const {
|
const {
|
||||||
generatorsFilePath,
|
generatorsFilePath,
|
||||||
|
|||||||
@ -6,7 +6,10 @@ import {
|
|||||||
type Tree,
|
type Tree,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { createNodesV2, PlaywrightPluginOptions } from '../../plugins/plugin';
|
import { createNodesV2, PlaywrightPluginOptions } from '../../plugins/plugin';
|
||||||
import { migrateProjectExecutorsToPlugin } from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
import {
|
||||||
|
migrateProjectExecutorsToPlugin,
|
||||||
|
NoTargetsToMigrateError,
|
||||||
|
} from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
||||||
|
|
||||||
interface Schema {
|
interface Schema {
|
||||||
project?: string;
|
project?: string;
|
||||||
@ -34,7 +37,7 @@ export async function convertToInferred(tree: Tree, options: Schema) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (migratedProjects.size === 0) {
|
if (migratedProjects.size === 0) {
|
||||||
throw new Error('Could not find any targets to migrate.');
|
throw new NoTargetsToMigrateError();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.skipFormat) {
|
if (!options.skipFormat) {
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
import { createProjectGraphAsync, formatFiles, type Tree } from '@nx/devkit';
|
import { createProjectGraphAsync, formatFiles, type Tree } from '@nx/devkit';
|
||||||
import { AggregatedLog } from '@nx/devkit/src/generators/plugin-migrations/aggregate-log-util';
|
import { AggregatedLog } from '@nx/devkit/src/generators/plugin-migrations/aggregate-log-util';
|
||||||
import { migrateProjectExecutorsToPluginV1 } from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
import {
|
||||||
|
migrateProjectExecutorsToPluginV1,
|
||||||
|
NoTargetsToMigrateError,
|
||||||
|
} from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
||||||
import { createNodes } from '../../../plugins/plugin';
|
import { createNodes } from '../../../plugins/plugin';
|
||||||
import { postTargetTransformer } from './lib/post-target-transformer';
|
import { postTargetTransformer } from './lib/post-target-transformer';
|
||||||
import { processStartOptions } from './lib/process-start-options';
|
import { processStartOptions } from './lib/process-start-options';
|
||||||
@ -123,7 +126,7 @@ export async function convertToInferred(tree: Tree, options: Schema) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (migratedProjects.size === 0) {
|
if (migratedProjects.size === 0) {
|
||||||
throw new Error('Could not find any targets to migrate.');
|
throw new NoTargetsToMigrateError();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.skipFormat) {
|
if (!options.skipFormat) {
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
import { createProjectGraphAsync, formatFiles, type Tree } from '@nx/devkit';
|
import { createProjectGraphAsync, formatFiles, type Tree } from '@nx/devkit';
|
||||||
import { AggregatedLog } from '@nx/devkit/src/generators/plugin-migrations/aggregate-log-util';
|
import { AggregatedLog } from '@nx/devkit/src/generators/plugin-migrations/aggregate-log-util';
|
||||||
import { migrateProjectExecutorsToPluginV1 } from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
import {
|
||||||
|
migrateProjectExecutorsToPluginV1,
|
||||||
|
NoTargetsToMigrateError,
|
||||||
|
} from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
||||||
import { createNodes } from '../../plugins/plugin';
|
import { createNodes } from '../../plugins/plugin';
|
||||||
import { buildPostTargetTransformer } from './lib/build-post-target-transformer';
|
import { buildPostTargetTransformer } from './lib/build-post-target-transformer';
|
||||||
import { servePostTargetTransformer } from './lib/serve-post-target-transformer';
|
import { servePostTargetTransformer } from './lib/serve-post-target-transformer';
|
||||||
@ -45,7 +48,7 @@ export async function convertToInferred(tree: Tree, options: Schema) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (migratedProjects.size === 0) {
|
if (migratedProjects.size === 0) {
|
||||||
throw new Error('Could not find any targets to migrate.');
|
throw new NoTargetsToMigrateError();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.skipFormat) {
|
if (!options.skipFormat) {
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import type { RollupExecutorOptions } from '../../executors/rollup/schema';
|
|||||||
import type { RollupPluginOptions } from '../../plugins/plugin';
|
import type { RollupPluginOptions } from '../../plugins/plugin';
|
||||||
import { extractRollupConfigFromExecutorOptions } from './lib/extract-rollup-config-from-executor-options';
|
import { extractRollupConfigFromExecutorOptions } from './lib/extract-rollup-config-from-executor-options';
|
||||||
import { addPluginRegistrations } from './lib/add-plugin-registrations';
|
import { addPluginRegistrations } from './lib/add-plugin-registrations';
|
||||||
|
import { NoTargetsToMigrateError } from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
||||||
|
|
||||||
interface Schema {
|
interface Schema {
|
||||||
project?: string;
|
project?: string;
|
||||||
@ -100,7 +101,7 @@ export async function convertToInferred(tree: Tree, options: Schema) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (migratedProjects.size === 0) {
|
if (migratedProjects.size === 0) {
|
||||||
throw new Error('Could not find any targets to migrate.');
|
throw new NoTargetsToMigrateError();
|
||||||
}
|
}
|
||||||
|
|
||||||
projects = getProjects(tree);
|
projects = getProjects(tree);
|
||||||
|
|||||||
@ -6,7 +6,10 @@ import {
|
|||||||
type Tree,
|
type Tree,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { AggregatedLog } from '@nx/devkit/src/generators/plugin-migrations/aggregate-log-util';
|
import { AggregatedLog } from '@nx/devkit/src/generators/plugin-migrations/aggregate-log-util';
|
||||||
import { migrateProjectExecutorsToPluginV1 } from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
import {
|
||||||
|
migrateProjectExecutorsToPluginV1,
|
||||||
|
NoTargetsToMigrateError,
|
||||||
|
} from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
||||||
import { buildPostTargetTransformer } from './lib/build-post-target-transformer';
|
import { buildPostTargetTransformer } from './lib/build-post-target-transformer';
|
||||||
import { servePostTargetTransformer } from './lib/serve-post-target-transformer';
|
import { servePostTargetTransformer } from './lib/serve-post-target-transformer';
|
||||||
import { createNodes } from '../../plugins/plugin';
|
import { createNodes } from '../../plugins/plugin';
|
||||||
@ -51,7 +54,7 @@ export async function convertToInferred(tree: Tree, options: Schema) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (migratedProjects.size === 0) {
|
if (migratedProjects.size === 0) {
|
||||||
throw new Error('Could not find any targets to migrate.');
|
throw new NoTargetsToMigrateError();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.skipFormat) {
|
if (!options.skipFormat) {
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
import { createProjectGraphAsync, formatFiles, type Tree } from '@nx/devkit';
|
import { createProjectGraphAsync, formatFiles, type Tree } from '@nx/devkit';
|
||||||
import { migrateProjectExecutorsToPlugin } from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
import {
|
||||||
|
migrateProjectExecutorsToPlugin,
|
||||||
|
NoTargetsToMigrateError,
|
||||||
|
} from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
||||||
import { createNodesV2, VitePluginOptions } from '../../plugins/plugin';
|
import { createNodesV2, VitePluginOptions } from '../../plugins/plugin';
|
||||||
import { buildPostTargetTransformer } from './lib/build-post-target-transformer';
|
import { buildPostTargetTransformer } from './lib/build-post-target-transformer';
|
||||||
import { servePostTargetTransformer } from './lib/serve-post-target-transformer';
|
import { servePostTargetTransformer } from './lib/serve-post-target-transformer';
|
||||||
@ -55,7 +58,7 @@ export async function convertToInferred(tree: Tree, options: Schema) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (migratedProjects.size === 0) {
|
if (migratedProjects.size === 0) {
|
||||||
throw new Error('Could not find any targets to migrate.');
|
throw new NoTargetsToMigrateError();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.skipFormat) {
|
if (!options.skipFormat) {
|
||||||
|
|||||||
@ -7,7 +7,10 @@ import {
|
|||||||
type Tree,
|
type Tree,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { AggregatedLog } from '@nx/devkit/src/generators/plugin-migrations/aggregate-log-util';
|
import { AggregatedLog } from '@nx/devkit/src/generators/plugin-migrations/aggregate-log-util';
|
||||||
import { migrateProjectExecutorsToPlugin } from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
import {
|
||||||
|
migrateProjectExecutorsToPlugin,
|
||||||
|
NoTargetsToMigrateError,
|
||||||
|
} from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
||||||
import { tsquery } from '@phenomnomnominal/tsquery';
|
import { tsquery } from '@phenomnomnominal/tsquery';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
import { createNodesV2, type WebpackPluginOptions } from '../../plugins/plugin';
|
import { createNodesV2, type WebpackPluginOptions } from '../../plugins/plugin';
|
||||||
@ -17,6 +20,7 @@ import {
|
|||||||
servePostTargetTransformerFactory,
|
servePostTargetTransformerFactory,
|
||||||
type MigrationContext,
|
type MigrationContext,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
|
import { logger as devkitLogger } from 'nx/src/devkit-exports';
|
||||||
|
|
||||||
interface Schema {
|
interface Schema {
|
||||||
project?: string;
|
project?: string;
|
||||||
@ -31,6 +35,8 @@ export async function convertToInferred(tree: Tree, options: Schema) {
|
|||||||
workspaceRoot: tree.root,
|
workspaceRoot: tree.root,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const logger = createCollectingLogger();
|
||||||
|
|
||||||
const migratedProjects =
|
const migratedProjects =
|
||||||
await migrateProjectExecutorsToPlugin<WebpackPluginOptions>(
|
await migrateProjectExecutorsToPlugin<WebpackPluginOptions>(
|
||||||
tree,
|
tree,
|
||||||
@ -59,11 +65,24 @@ export async function convertToInferred(tree: Tree, options: Schema) {
|
|||||||
skipProjectFilter: skipProjectFilterFactory(tree),
|
skipProjectFilter: skipProjectFilterFactory(tree),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
options.project
|
options.project,
|
||||||
|
logger
|
||||||
);
|
);
|
||||||
|
|
||||||
if (migratedProjects.size === 0) {
|
if (migratedProjects.size === 0) {
|
||||||
throw new Error('Could not find any targets to migrate.');
|
const convertMessage = [...logger.loggedMessages.values()]
|
||||||
|
.flat()
|
||||||
|
.find((v) => v.includes('@nx/webpack:convert-config-to-webpack-plugin'));
|
||||||
|
|
||||||
|
if (convertMessage.length > 0) {
|
||||||
|
logger.flushLogs((message) => !convertMessage.includes(message));
|
||||||
|
throw new Error(convertMessage);
|
||||||
|
} else {
|
||||||
|
logger.flushLogs();
|
||||||
|
throw new NoTargetsToMigrateError();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.flushLogs();
|
||||||
}
|
}
|
||||||
|
|
||||||
const installCallback = addDependenciesToPackageJson(
|
const installCallback = addDependenciesToPackageJson(
|
||||||
@ -125,3 +144,42 @@ function skipProjectFilterFactory(tree: Tree) {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function createCollectingLogger(): typeof devkitLogger & {
|
||||||
|
loggedMessages: Map<string, string[]>;
|
||||||
|
flushLogs: (filter?: (message: string) => boolean) => void;
|
||||||
|
} {
|
||||||
|
const loggedMessages = new Map<string, string[]>();
|
||||||
|
|
||||||
|
const flushLogs = (filter?: (message: string) => boolean) => {
|
||||||
|
loggedMessages.forEach((messages, method) => {
|
||||||
|
messages.forEach((message) => {
|
||||||
|
if (!filter || filter(message)) {
|
||||||
|
devkitLogger[method](message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Proxy(
|
||||||
|
{ ...devkitLogger, loggedMessages, flushLogs },
|
||||||
|
{
|
||||||
|
get(target, property) {
|
||||||
|
const originalMethod = target[property];
|
||||||
|
|
||||||
|
if (typeof originalMethod === 'function') {
|
||||||
|
return (...args) => {
|
||||||
|
const message = args.join(' ');
|
||||||
|
const propertyString = String(property);
|
||||||
|
if (!loggedMessages.has(message)) {
|
||||||
|
loggedMessages.set(propertyString, []);
|
||||||
|
}
|
||||||
|
loggedMessages.get(propertyString).push(message);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return originalMethod;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@ -54,6 +54,11 @@
|
|||||||
"factory": "./src/generators/ci-workflow/ci-workflow#ciWorkflowGenerator",
|
"factory": "./src/generators/ci-workflow/ci-workflow#ciWorkflowGenerator",
|
||||||
"schema": "./src/generators/ci-workflow/schema.json",
|
"schema": "./src/generators/ci-workflow/schema.json",
|
||||||
"description": "Generate a CI workflow."
|
"description": "Generate a CI workflow."
|
||||||
|
},
|
||||||
|
"infer-targets": {
|
||||||
|
"factory": "./src/generators/infer-targets/infer-targets",
|
||||||
|
"schema": "./src/generators/infer-targets/schema.json",
|
||||||
|
"description": "Convert Nx projects to use inferred targets."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
146
packages/workspace/src/generators/infer-targets/infer-targets.ts
Normal file
146
packages/workspace/src/generators/infer-targets/infer-targets.ts
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
import {
|
||||||
|
createProjectGraphAsync,
|
||||||
|
formatFiles,
|
||||||
|
GeneratorCallback,
|
||||||
|
output,
|
||||||
|
readProjectsConfigurationFromProjectGraph,
|
||||||
|
runTasksInSerial,
|
||||||
|
Tree,
|
||||||
|
workspaceRoot,
|
||||||
|
} from '@nx/devkit';
|
||||||
|
import { NoTargetsToMigrateError } from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
||||||
|
import { prompt } from 'enquirer';
|
||||||
|
import {
|
||||||
|
GeneratorInformation,
|
||||||
|
getGeneratorInformation,
|
||||||
|
} from 'nx/src/command-line/generate/generator-utils';
|
||||||
|
import { findInstalledPlugins } from 'nx/src/utils/plugins/installed-plugins';
|
||||||
|
|
||||||
|
interface Schema {
|
||||||
|
project?: string;
|
||||||
|
plugins?: string[];
|
||||||
|
skipFormat?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function convertToInferredGenerator(tree: Tree, options: Schema) {
|
||||||
|
const generatorCollectionChoices =
|
||||||
|
await getPossibleConvertToInferredGenerators();
|
||||||
|
|
||||||
|
if (generatorCollectionChoices.size === 0) {
|
||||||
|
output.error({
|
||||||
|
title:
|
||||||
|
'No inference plugin found. For information on this migration, see https://nx.dev/recipes/running-tasks/convert-to-inferred',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let generatorsToRun: string[];
|
||||||
|
if (options.plugins && options.plugins.filter((p) => !!p).length > 0) {
|
||||||
|
generatorsToRun = Array.from(generatorCollectionChoices.values())
|
||||||
|
.filter((generator) =>
|
||||||
|
options.plugins.includes(generator.resolvedCollectionName)
|
||||||
|
)
|
||||||
|
.map((generator) => generator.resolvedCollectionName);
|
||||||
|
} else if (process.argv.includes('--no-interactive')) {
|
||||||
|
generatorsToRun = Array.from(generatorCollectionChoices.keys());
|
||||||
|
} else {
|
||||||
|
const allChoices = Array.from(generatorCollectionChoices.keys());
|
||||||
|
|
||||||
|
generatorsToRun = (
|
||||||
|
await prompt<{ generatorsToRun: string[] }>({
|
||||||
|
type: 'multiselect',
|
||||||
|
name: 'generatorsToRun',
|
||||||
|
message: 'Which inference plugin do you want to use?',
|
||||||
|
choices: allChoices,
|
||||||
|
initial: allChoices,
|
||||||
|
validate: (result: string[]) => {
|
||||||
|
if (result.length === 0) {
|
||||||
|
return 'Please select at least one plugin.';
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
} as any)
|
||||||
|
).generatorsToRun;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (generatorsToRun.length === 0) {
|
||||||
|
output.error({
|
||||||
|
title: 'Please select at least one plugin.',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tasks: GeneratorCallback[] = [];
|
||||||
|
for (const generatorCollection of generatorsToRun) {
|
||||||
|
try {
|
||||||
|
const generator = generatorCollectionChoices.get(generatorCollection);
|
||||||
|
if (generator) {
|
||||||
|
const generatorFactory = generator.implementationFactory();
|
||||||
|
const callback = await generatorFactory(tree, {
|
||||||
|
project: options.project,
|
||||||
|
skipFormat: options.skipFormat,
|
||||||
|
});
|
||||||
|
if (callback) {
|
||||||
|
const task = await callback();
|
||||||
|
if (typeof task === 'function') tasks.push(task);
|
||||||
|
}
|
||||||
|
output.success({
|
||||||
|
title: `${generatorCollection}:convert-to-inferred - Success`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof NoTargetsToMigrateError) {
|
||||||
|
output.note({
|
||||||
|
title: `${generatorCollection}:convert-to-inferred - Skipped (No targets to migrate)`,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
output.error({
|
||||||
|
title: `${generatorCollection}:convert-to-inferred - Failed`,
|
||||||
|
});
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!options.skipFormat) {
|
||||||
|
await formatFiles(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
return runTasksInSerial(...tasks);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getPossibleConvertToInferredGenerators() {
|
||||||
|
const installedCollections = Array.from(
|
||||||
|
new Set(findInstalledPlugins().map((x) => x.name))
|
||||||
|
);
|
||||||
|
|
||||||
|
const projectGraph = await createProjectGraphAsync();
|
||||||
|
const projectsConfigurations =
|
||||||
|
readProjectsConfigurationFromProjectGraph(projectGraph);
|
||||||
|
|
||||||
|
const choices = new Map<string, GeneratorInformation>();
|
||||||
|
|
||||||
|
for (const collectionName of installedCollections) {
|
||||||
|
try {
|
||||||
|
const generator = getGeneratorInformation(
|
||||||
|
collectionName,
|
||||||
|
'convert-to-inferred',
|
||||||
|
workspaceRoot,
|
||||||
|
projectsConfigurations.projects
|
||||||
|
);
|
||||||
|
if (
|
||||||
|
generator.generatorConfiguration.hidden ||
|
||||||
|
generator.generatorConfiguration['x-deprecated']
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
choices.set(generator.resolvedCollectionName, generator);
|
||||||
|
} catch {
|
||||||
|
// this just means that no convert-to-inferred generator exists for a given collection, ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return choices;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default convertToInferredGenerator;
|
||||||
26
packages/workspace/src/generators/infer-targets/schema.json
Normal file
26
packages/workspace/src/generators/infer-targets/schema.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json-schema.org/schema",
|
||||||
|
"$id": "InferTargets",
|
||||||
|
"title": "",
|
||||||
|
"type": "object",
|
||||||
|
"description": "Convert Nx projects to use inferred targets.",
|
||||||
|
"properties": {
|
||||||
|
"project": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The project to convert to use inferred targets.",
|
||||||
|
"x-priority": "important"
|
||||||
|
},
|
||||||
|
"plugins": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "The plugins used to infer targets. For example @nx/eslint or @nx/jest",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"skipFormat": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to format files.",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user