feat(core): update the migrate command to support @nrwl/devkit generators
This commit is contained in:
parent
234ca36385
commit
48bcaf099d
@ -64,16 +64,6 @@ Type: `string`
|
||||
|
||||
The name of the project.
|
||||
|
||||
### unitTestRunner
|
||||
|
||||
Default: `jest`
|
||||
|
||||
Type: `string`
|
||||
|
||||
Possible values: `jest`, `none`
|
||||
|
||||
Test runner to use for unit tests
|
||||
|
||||
### version
|
||||
|
||||
Alias(es): v
|
||||
|
||||
@ -64,16 +64,6 @@ Type: `string`
|
||||
|
||||
The name of the project.
|
||||
|
||||
### unitTestRunner
|
||||
|
||||
Default: `jest`
|
||||
|
||||
Type: `string`
|
||||
|
||||
Possible values: `jest`, `none`
|
||||
|
||||
Test runner to use for unit tests
|
||||
|
||||
### version
|
||||
|
||||
Alias(es): v
|
||||
|
||||
@ -64,16 +64,6 @@ Type: `string`
|
||||
|
||||
The name of the project.
|
||||
|
||||
### unitTestRunner
|
||||
|
||||
Default: `jest`
|
||||
|
||||
Type: `string`
|
||||
|
||||
Possible values: `jest`, `none`
|
||||
|
||||
Test runner to use for unit tests
|
||||
|
||||
### version
|
||||
|
||||
Alias(es): v
|
||||
|
||||
@ -134,7 +134,7 @@ describe('migrate', () => {
|
||||
run20: {
|
||||
version: '2.0.0',
|
||||
description: '2.0.0',
|
||||
factory: './run20',
|
||||
implementation: './run20',
|
||||
},
|
||||
},
|
||||
})
|
||||
@ -154,10 +154,8 @@ describe('migrate', () => {
|
||||
updateFile(
|
||||
`./node_modules/migrate-parent-package/run20.js`,
|
||||
`
|
||||
exports.default = function default_1() {
|
||||
return function(host) {
|
||||
host.create('file-20', 'content20')
|
||||
}
|
||||
exports.default = function (host) {
|
||||
host.write('file-20', 'content20')
|
||||
}
|
||||
`
|
||||
);
|
||||
@ -183,12 +181,13 @@ describe('migrate', () => {
|
||||
if (packageName === 'migrate-parent-package') {
|
||||
return Promise.resolve({
|
||||
version: '2.0.0',
|
||||
schematics: {
|
||||
generators: {
|
||||
'run11': {
|
||||
version: '1.1.0'
|
||||
},
|
||||
'run20': {
|
||||
version: '2.0.0'
|
||||
version: '2.0.0',
|
||||
cli: 'nx'
|
||||
}
|
||||
},
|
||||
packageJsonUpdates: {
|
||||
@ -228,6 +227,7 @@ describe('migrate', () => {
|
||||
package: 'migrate-parent-package',
|
||||
version: '2.0.0',
|
||||
name: 'run20',
|
||||
cli: 'nx',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
@ -91,17 +91,16 @@ describe('Nx Plugin', () => {
|
||||
checkFilesExist(
|
||||
`dist/libs/${plugin}/src/migrations/update-${version}/update-${version}.js`,
|
||||
`dist/libs/${plugin}/src/migrations/update-${version}/update-${version}.ts`,
|
||||
`dist/libs/${plugin}/src/migrations/update-${version}/update-${version}.spec.ts`,
|
||||
`libs/${plugin}/src/migrations/update-${version}/update-${version}.ts`,
|
||||
`libs/${plugin}/src/migrations/update-${version}/update-${version}.spec.ts`
|
||||
`libs/${plugin}/src/migrations/update-${version}/update-${version}.ts`
|
||||
);
|
||||
const migrationsJson = readJson(`libs/${plugin}/migrations.json`);
|
||||
expect(migrationsJson).toMatchObject({
|
||||
schematics: expect.objectContaining({
|
||||
generators: expect.objectContaining({
|
||||
[`update-${version}`]: {
|
||||
version: version,
|
||||
description: `update-${version}`,
|
||||
factory: `./src/migrations/update-${version}/update-${version}`,
|
||||
cli: `nx`,
|
||||
implementation: `./src/migrations/update-${version}/update-${version}`,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
@ -107,7 +107,6 @@ export function runNgNew(): string {
|
||||
* for the currently selected CLI.
|
||||
*/
|
||||
export function newProject(): void {
|
||||
projName = uniq('proj');
|
||||
try {
|
||||
if (!directoryExists(tmpBackupProjPath())) {
|
||||
runCreateWorkspace('proj', { preset: 'empty' });
|
||||
@ -129,8 +128,10 @@ export function newProject(): void {
|
||||
.forEach((p) => {
|
||||
runCLI(`g ${p}:init`, { cwd: `./tmp/${currentCli()}/proj` });
|
||||
});
|
||||
|
||||
execSync(`mv ./tmp/${currentCli()}/proj ${tmpBackupProjPath()}`);
|
||||
}
|
||||
projName = uniq('proj');
|
||||
execSync(`cp -a ${tmpBackupProjPath()} ${tmpProjPath()}`);
|
||||
} catch (e) {
|
||||
console.log(`Failed to set up project for e2e tests.`);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nrwl/nx-source",
|
||||
"version": "11.0.0-beta.4",
|
||||
"version": "999.9.11",
|
||||
"description": "Extensible Dev Tools for Monorepos",
|
||||
"homepage": "https://nx.dev",
|
||||
"main": "index.js",
|
||||
|
||||
@ -10,6 +10,7 @@ export {
|
||||
} from '@nrwl/tao/src/shared/nx';
|
||||
export { TargetContext } from '@nrwl/tao/src/commands/run';
|
||||
export { formatFiles } from './src/schematics/format-files';
|
||||
export { readJson } from './src/utils/read-json';
|
||||
export { generateFiles } from './src/schematics/generate-files';
|
||||
export { installPackagesTask } from './src/tasks/install-packages-task';
|
||||
export { addProjectConfiguration } from './src/schematics/add-project-configuration';
|
||||
|
||||
@ -4,6 +4,11 @@
|
||||
"version": "10.2.0",
|
||||
"description": "Remove deprecated jest builder options",
|
||||
"factory": "./src/migrations/update-10-2-0/update-10-2-0"
|
||||
},
|
||||
"update-11.0.0": {
|
||||
"version": "11.0.0-beta.4",
|
||||
"description": "Rename ng-update into nx-migrate",
|
||||
"factory": "./src/migrations/update-11-0-0/rename-ng-update-into-nx-migrate"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
import { Tree, readJson } from '@nrwl/devkit';
|
||||
|
||||
export default function update(host: Tree) {
|
||||
const p = readJson(host, 'package.json');
|
||||
if (p['ng-update']) {
|
||||
p['ng-migrate'] = p['ng-update'];
|
||||
delete p['ng-update'];
|
||||
}
|
||||
host.write('package.json', JSON.stringify(p, null, 2));
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
import { Tree } from '@angular-devkit/schematics';
|
||||
import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
|
||||
import { readJsonInTree, serializeJson } from '@nrwl/workspace';
|
||||
import { createEmptyWorkspace } from '@nrwl/workspace/testing';
|
||||
import * as path from 'path';
|
||||
|
||||
describe('<%= name %>', () => {
|
||||
let initialTree: Tree;
|
||||
let schematicRunner: SchematicTestRunner;
|
||||
|
||||
beforeEach(async () => {
|
||||
initialTree = createEmptyWorkspace(Tree.empty());
|
||||
|
||||
schematicRunner = new SchematicTestRunner(
|
||||
'@nrwl/nx-plugin',
|
||||
path.join(__dirname, '../../../migrations.json')
|
||||
);
|
||||
|
||||
initialTree.overwrite(
|
||||
'package.json',
|
||||
serializeJson({
|
||||
dependencies: {}
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it(`should update dependencies`, async () => {
|
||||
const result = await schematicRunner
|
||||
.runSchematicAsync('<%= name %>', {}, initialTree)
|
||||
.toPromise();
|
||||
|
||||
const { dependencies } = readJsonInTree(result, '/package.json');
|
||||
expect(dependencies).toEqual({});
|
||||
});
|
||||
});
|
||||
@ -1,12 +1,6 @@
|
||||
import { chain, Rule } from '@angular-devkit/schematics';<% if (packageJsonUpdates) { %>
|
||||
import { updatePackagesInPackageJson } from '@nrwl/workspace';
|
||||
import * as path from 'path';<% } %>
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import { Tree } from '@nrwl/devkit';
|
||||
|
||||
export default function update(): Rule {
|
||||
return chain([<% if (packageJsonUpdates) { %>
|
||||
updatePackagesInPackageJson(
|
||||
path.join(__dirname, '../../../', 'migrations.json'),
|
||||
'<%= version %>'
|
||||
)
|
||||
<% } %>]);
|
||||
export default function update(host: Tree) {
|
||||
// ...
|
||||
}
|
||||
|
||||
@ -17,9 +17,6 @@ export function addFiles(options: NormalizedSchema): Rule {
|
||||
...options,
|
||||
tmpl: '',
|
||||
}),
|
||||
options.unitTestRunner === 'none'
|
||||
? filter((file) => !file.endsWith('.spec.ts'))
|
||||
: noop(),
|
||||
move(`${options.projectSourceRoot}/migrations`),
|
||||
])
|
||||
);
|
||||
|
||||
@ -7,13 +7,19 @@ export function updateMigrationsJson(options: NormalizedSchema): Rule {
|
||||
return updateJsonInTree(
|
||||
path.join(options.projectRoot, 'migrations.json'),
|
||||
(json) => {
|
||||
const schematics = json.schematics ? json.schematics : {};
|
||||
schematics[options.name] = {
|
||||
if (json.schematics) {
|
||||
json.generators = json.schematics;
|
||||
delete json.schematics;
|
||||
}
|
||||
|
||||
const generators = json.generators ? json.generators : {};
|
||||
generators[options.name] = {
|
||||
version: options.version,
|
||||
description: options.description,
|
||||
factory: `./src/migrations/${options.name}/${options.name}`,
|
||||
cli: 'nx',
|
||||
implementation: `./src/migrations/${options.name}/${options.name}`,
|
||||
};
|
||||
json.schematics = schematics;
|
||||
json.generators = generators;
|
||||
|
||||
if (options.packageJsonUpdates) {
|
||||
const packageJsonUpdatesObj = json.packageJsonUpdates
|
||||
|
||||
@ -7,11 +7,11 @@ export function updatePackageJson(options: NormalizedSchema): Rule {
|
||||
return updateJsonInTree(
|
||||
path.join(options.projectRoot, 'package.json'),
|
||||
(json) => {
|
||||
if (!json['ng-update'] || !json['ng-update'].migrations) {
|
||||
if (json['ng-update']) {
|
||||
json['ng-update'].migrations = './migrations.json';
|
||||
if (!json['nx-migrate'] || !json['nx-migrate'].migrations) {
|
||||
if (json['nx-migrate']) {
|
||||
json['nx-migrate'].migrations = './migrations.json';
|
||||
} else {
|
||||
json['ng-update'] = {
|
||||
json['nx-migrate'] = {
|
||||
migrations: './migrations.json',
|
||||
};
|
||||
}
|
||||
|
||||
@ -58,22 +58,17 @@ describe('NxPlugin migration', () => {
|
||||
expect(
|
||||
tree.exists('libs/my-plugin/src/migrations/my-migration/my-migration.ts')
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
tree.exists(
|
||||
'libs/my-plugin/src/migrations/my-migration/my-migration.spec.ts'
|
||||
)
|
||||
).toBeTruthy();
|
||||
|
||||
expect(migrationsJson.schematics['my-migration'].version).toEqual('1.0.0');
|
||||
expect(migrationsJson.schematics['my-migration'].description).toEqual(
|
||||
expect(migrationsJson.generators['my-migration'].version).toEqual('1.0.0');
|
||||
expect(migrationsJson.generators['my-migration'].description).toEqual(
|
||||
'my-migration description'
|
||||
);
|
||||
expect(migrationsJson.schematics['my-migration'].factory).toEqual(
|
||||
expect(migrationsJson.generators['my-migration'].implementation).toEqual(
|
||||
'./src/migrations/my-migration/my-migration'
|
||||
);
|
||||
expect(migrationsJson.packageJsonUpdates).toBeFalsy();
|
||||
|
||||
expect(packageJson['ng-update'].migrations).toEqual('./migrations.json');
|
||||
expect(packageJson['nx-migrate'].migrations).toEqual('./migrations.json');
|
||||
});
|
||||
|
||||
it('should generate files with default name', async () => {
|
||||
@ -96,7 +91,7 @@ describe('NxPlugin migration', () => {
|
||||
tree.exists('libs/my-plugin/src/migrations/update-1.0.0/update-1.0.0.ts')
|
||||
).toBeTruthy();
|
||||
|
||||
expect(migrationsJson.schematics['update-1.0.0'].factory).toEqual(
|
||||
expect(migrationsJson.generators['update-1.0.0'].implementation).toEqual(
|
||||
'./src/migrations/update-1.0.0/update-1.0.0'
|
||||
);
|
||||
});
|
||||
@ -117,7 +112,7 @@ describe('NxPlugin migration', () => {
|
||||
'libs/my-plugin/migrations.json'
|
||||
);
|
||||
|
||||
expect(migrationsJson.schematics['my-migration'].description).toEqual(
|
||||
expect(migrationsJson.generators['my-migration'].description).toEqual(
|
||||
'my-migration'
|
||||
);
|
||||
});
|
||||
@ -146,32 +141,4 @@ describe('NxPlugin migration', () => {
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
describe('--unitTestRunner', () => {
|
||||
describe('none', () => {
|
||||
it('should not generate test files', async () => {
|
||||
const tree = await runSchematic(
|
||||
'migration',
|
||||
{
|
||||
project: projectName,
|
||||
name: 'my-migration',
|
||||
version: '1.0.0',
|
||||
unitTestRunner: 'none',
|
||||
},
|
||||
appTree
|
||||
);
|
||||
|
||||
expect(
|
||||
tree.exists(
|
||||
'libs/my-plugin/src/migrations/my-migration/my-migration.ts'
|
||||
)
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
tree.exists(
|
||||
'libs/my-plugin/src/migrations/my-migration/my-migration.spec.ts'
|
||||
)
|
||||
).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -4,7 +4,6 @@ export interface Schema {
|
||||
description: string;
|
||||
version: string;
|
||||
packageJsonUpdates: boolean;
|
||||
unitTestRunner: 'jest' | 'none';
|
||||
}
|
||||
|
||||
export interface NormalizedSchema extends Schema {
|
||||
|
||||
@ -43,12 +43,6 @@
|
||||
"description": "Whether or not to include package.json updates",
|
||||
"alias": "p",
|
||||
"default": false
|
||||
},
|
||||
"unitTestRunner": {
|
||||
"type": "string",
|
||||
"enum": ["jest", "none"],
|
||||
"description": "Test runner to use for unit tests",
|
||||
"default": "jest"
|
||||
}
|
||||
},
|
||||
"required": ["project", "version"]
|
||||
|
||||
@ -38,6 +38,7 @@
|
||||
"semver": "6.3.0",
|
||||
"tmp": "0.0.33",
|
||||
"tslib": "^2.0.0",
|
||||
"yargs-parser": "20.0.0"
|
||||
"yargs-parser": "20.0.0",
|
||||
"fs-extra": "7.0.1"
|
||||
}
|
||||
}
|
||||
|
||||
@ -388,30 +388,30 @@ describe('Migration', () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
schematics: {
|
||||
generators: {
|
||||
version2: {
|
||||
version: '2.0.0',
|
||||
factory: 'parent-factory',
|
||||
description: 'parent-desc',
|
||||
},
|
||||
},
|
||||
});
|
||||
} else if (p === 'child') {
|
||||
return Promise.resolve({
|
||||
version: '2.0.0',
|
||||
schematics: {
|
||||
generators: {
|
||||
version2: {
|
||||
version: '2.0.0',
|
||||
factory: 'child-factory',
|
||||
description: 'child-desc',
|
||||
},
|
||||
},
|
||||
});
|
||||
} else if (p === 'newChild') {
|
||||
return Promise.resolve({
|
||||
version: '3.0.0',
|
||||
schematics: {
|
||||
generators: {
|
||||
version2: {
|
||||
version: '2.0.0',
|
||||
factory: 'new-child-factory',
|
||||
description: 'new-child-desc',
|
||||
},
|
||||
},
|
||||
});
|
||||
@ -425,16 +425,16 @@ describe('Migration', () => {
|
||||
expect(await migrator.updatePackageJson('parent', '2.0.0')).toEqual({
|
||||
migrations: [
|
||||
{
|
||||
package: 'parent',
|
||||
version: '2.0.0',
|
||||
name: 'version2',
|
||||
factory: 'parent-factory',
|
||||
package: 'parent',
|
||||
description: 'parent-desc',
|
||||
},
|
||||
{
|
||||
package: 'child',
|
||||
version: '2.0.0',
|
||||
name: 'version2',
|
||||
factory: 'child-factory',
|
||||
description: 'child-desc',
|
||||
},
|
||||
],
|
||||
packageJson: {
|
||||
|
||||
@ -1,14 +1,9 @@
|
||||
import { logging, normalize, virtualFs } from '@angular-devkit/core';
|
||||
import { NodeJsSyncHost } from '@angular-devkit/core/node';
|
||||
import { TaskExecutor } from '@angular-devkit/schematics';
|
||||
import { BaseWorkflow } from '@angular-devkit/schematics/src/workflow';
|
||||
import { BuiltinTaskExecutor } from '@angular-devkit/schematics/tasks/node';
|
||||
import { NodePackageName } from '@angular-devkit/schematics/tasks/package-manager/options';
|
||||
import { NodeModulesEngineHost } from '@angular-devkit/schematics/tools';
|
||||
import { logging } from '@angular-devkit/core';
|
||||
import { execSync } from 'child_process';
|
||||
import * as fs from 'fs';
|
||||
import { readFileSync, writeFileSync } from 'fs';
|
||||
import * as minimist from 'minimist';
|
||||
import { dirname, extname, join, resolve } from 'path';
|
||||
import { dirname, join } from 'path';
|
||||
import { gt, lte } from 'semver';
|
||||
import * as stripJsonComments from 'strip-json-comments';
|
||||
import { dirSync } from 'tmp';
|
||||
@ -18,10 +13,15 @@ import {
|
||||
detectPackageManager,
|
||||
getPackageManagerInstallCommand,
|
||||
} from '../shared/detect-package-manager';
|
||||
import { FsTree } from '@nrwl/tao/src/shared/tree';
|
||||
import { flushChanges } from '@nrwl/tao/src/commands/generate';
|
||||
|
||||
export type MigrationsJson = {
|
||||
version: string;
|
||||
schematics?: { [name: string]: { version: string } };
|
||||
collection?: string;
|
||||
generators?: {
|
||||
[name: string]: { version: string; description?: string; cli?: string };
|
||||
};
|
||||
packageJsonUpdates?: {
|
||||
[name: string]: {
|
||||
version: string;
|
||||
@ -107,15 +107,16 @@ export class Migrator {
|
||||
|
||||
const target = versions[c];
|
||||
const migrationsJson = await this.fetch(c, target.version);
|
||||
if (!migrationsJson.schematics) return [];
|
||||
return Object.keys(migrationsJson.schematics)
|
||||
const generators = migrationsJson.generators;
|
||||
if (!generators) return [];
|
||||
return Object.keys(generators)
|
||||
.filter(
|
||||
(r) =>
|
||||
this.gt(migrationsJson.schematics[r].version, currentVersion) &
|
||||
this.lte(migrationsJson.schematics[r].version, target.version)
|
||||
this.gt(generators[r].version, currentVersion) &
|
||||
this.lte(generators[r].version, target.version)
|
||||
)
|
||||
.map((r) => ({
|
||||
...migrationsJson.schematics[r],
|
||||
...migrationsJson.generators[r],
|
||||
package: c,
|
||||
name: r,
|
||||
}));
|
||||
@ -423,46 +424,31 @@ function createFetcher(packageManager: string, logger: logging.Logger) {
|
||||
stdio: [],
|
||||
cwd: dir,
|
||||
});
|
||||
|
||||
const migrationsFilePath = packageToMigrationsFilePath(
|
||||
logger,
|
||||
packageName,
|
||||
dir
|
||||
);
|
||||
const packageJsonPath = require.resolve(`${packageName}/package.json`, {
|
||||
paths: [dir],
|
||||
});
|
||||
const json = JSON.parse(
|
||||
stripJsonComments(readFileSync(packageJsonPath).toString())
|
||||
);
|
||||
let migrationsFile = json['nx-migrations'] || json['ng-update'];
|
||||
|
||||
// migrationsFile is an object
|
||||
if (migrationsFile && migrationsFile.migrations) {
|
||||
migrationsFile = migrationsFile.migrations;
|
||||
}
|
||||
|
||||
// packageVersion can be a tag, resolvedVersion works with semver
|
||||
const resolvedVersion = json.version;
|
||||
|
||||
try {
|
||||
if (migrationsFile && typeof migrationsFile === 'string') {
|
||||
const migrationsFilePath = require.resolve(
|
||||
`${packageName}/${migrationsFile}`,
|
||||
{ paths: [dir] }
|
||||
);
|
||||
|
||||
const json = JSON.parse(
|
||||
stripJsonComments(readFileSync(migrationsFilePath).toString())
|
||||
);
|
||||
cache[`${packageName}-${packageVersion}`] = {
|
||||
version: resolvedVersion,
|
||||
schematics: json.schematics,
|
||||
packageJsonUpdates: json.packageJsonUpdates,
|
||||
};
|
||||
} else {
|
||||
cache[`${packageName}-${packageVersion}`] = {
|
||||
version: resolvedVersion,
|
||||
};
|
||||
}
|
||||
} catch (e) {
|
||||
logger.warn(
|
||||
`Could not find '${migrationsFile}' in '${packageName}'. Skipping it`
|
||||
if (migrationsFilePath) {
|
||||
const json = JSON.parse(
|
||||
stripJsonComments(readFileSync(migrationsFilePath).toString())
|
||||
);
|
||||
cache[`${packageName}-${packageVersion}`] = {
|
||||
version: resolvedVersion,
|
||||
generators: json.generators || json.schematics,
|
||||
packageJsonUpdates: json.packageJsonUpdates,
|
||||
};
|
||||
} else {
|
||||
cache[`${packageName}-${packageVersion}`] = {
|
||||
version: resolvedVersion,
|
||||
};
|
||||
@ -471,15 +457,46 @@ function createFetcher(packageManager: string, logger: logging.Logger) {
|
||||
return cache[`${packageName}-${packageVersion}`];
|
||||
};
|
||||
}
|
||||
|
||||
// testing-fetch-end
|
||||
|
||||
function packageToMigrationsFilePath(
|
||||
logger: logging.Logger,
|
||||
packageName: string,
|
||||
dir: string
|
||||
) {
|
||||
const packageJsonPath = require.resolve(`${packageName}/package.json`, {
|
||||
paths: [dir],
|
||||
});
|
||||
const json = JSON.parse(
|
||||
stripJsonComments(readFileSync(packageJsonPath).toString())
|
||||
);
|
||||
let migrationsFile = json['nx-migrations'] || json['ng-update'];
|
||||
|
||||
// migrationsFile is an object
|
||||
if (migrationsFile && migrationsFile.migrations) {
|
||||
migrationsFile = migrationsFile.migrations;
|
||||
}
|
||||
try {
|
||||
if (migrationsFile && typeof migrationsFile === 'string') {
|
||||
return require.resolve(`${packageName}/${migrationsFile}`, {
|
||||
paths: [dir],
|
||||
});
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (e) {
|
||||
logger.warn(
|
||||
`Could not find '${migrationsFile}' in '${packageName}'. Skipping it`
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function createMigrationsFile(
|
||||
root: string,
|
||||
migrations: {
|
||||
package: string;
|
||||
name: string;
|
||||
version: string;
|
||||
}[]
|
||||
) {
|
||||
writeFileSync(
|
||||
@ -581,118 +598,55 @@ async function generateMigrationsJsonAndUpdatePackageJson(
|
||||
}
|
||||
}
|
||||
|
||||
class MigrationEngineHost extends NodeModulesEngineHost {
|
||||
private nodeInstallLogPrinted = false;
|
||||
|
||||
constructor(logger: logging.Logger) {
|
||||
super();
|
||||
|
||||
// Overwrite the original CLI node package executor with a new one that does basically nothing
|
||||
// since nx migrate doesn't do npm installs by itself
|
||||
// (https://github.com/angular/angular-cli/blob/5df776780deadb6be5048b3ab006a5d3383650dc/packages/angular_devkit/schematics/tools/workflow/node-workflow.ts#L41)
|
||||
this.registerTaskExecutor({
|
||||
name: NodePackageName,
|
||||
create: () =>
|
||||
Promise.resolve<TaskExecutor>(() => {
|
||||
return new Promise((res) => {
|
||||
if (!this.nodeInstallLogPrinted) {
|
||||
logger.warn(
|
||||
`An installation of node_modules has been required. Make sure to run it after the migration`
|
||||
);
|
||||
this.nodeInstallLogPrinted = true;
|
||||
}
|
||||
|
||||
res();
|
||||
});
|
||||
}),
|
||||
});
|
||||
|
||||
this.registerTaskExecutor(BuiltinTaskExecutor.RunSchematic);
|
||||
}
|
||||
|
||||
protected _resolveCollectionPath(name: string): string {
|
||||
let collectionPath: string | undefined = undefined;
|
||||
|
||||
if (name.startsWith('.') || name.startsWith('/')) {
|
||||
name = resolve(name);
|
||||
}
|
||||
|
||||
if (extname(name)) {
|
||||
collectionPath = require.resolve(name);
|
||||
} else {
|
||||
const packageJsonPath = require.resolve(join(name, 'package.json'));
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const packageJson = require(packageJsonPath);
|
||||
let pkgJsonSchematics = packageJson['nx-migrations'];
|
||||
if (!pkgJsonSchematics) {
|
||||
pkgJsonSchematics = packageJson['ng-update'];
|
||||
if (!pkgJsonSchematics) {
|
||||
throw new Error(`Could not find migrations in package: "${name}"`);
|
||||
}
|
||||
}
|
||||
if (typeof pkgJsonSchematics != 'string') {
|
||||
pkgJsonSchematics = pkgJsonSchematics.migrations;
|
||||
}
|
||||
collectionPath = resolve(dirname(packageJsonPath), pkgJsonSchematics);
|
||||
}
|
||||
|
||||
try {
|
||||
if (collectionPath) {
|
||||
JSON.parse(stripJsonComments(readFileSync(collectionPath).toString()));
|
||||
return collectionPath;
|
||||
}
|
||||
} catch (e) {
|
||||
throw new Error(`Invalid migration file in package: "${name}"`);
|
||||
}
|
||||
throw new Error(`Collection cannot be resolved: "${name}"`);
|
||||
}
|
||||
}
|
||||
|
||||
class MigrationsWorkflow extends BaseWorkflow {
|
||||
constructor(host: virtualFs.Host, logger: logging.Logger) {
|
||||
super({
|
||||
host,
|
||||
engineHost: new MigrationEngineHost(logger),
|
||||
force: true,
|
||||
dryRun: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function runMigrations(
|
||||
logger: logging.Logger,
|
||||
root: string,
|
||||
opts: { runMigrations: string }
|
||||
) {
|
||||
const migrationsFile = JSON.parse(
|
||||
const migrations: {
|
||||
package: string;
|
||||
name: string;
|
||||
version: string;
|
||||
cli?: 'nx' | 'angular';
|
||||
}[] = JSON.parse(
|
||||
stripJsonComments(readFileSync(join(root, opts.runMigrations)).toString())
|
||||
);
|
||||
).migrations;
|
||||
|
||||
const host = new virtualFs.ScopedHost(new NodeJsSyncHost(), normalize(root));
|
||||
const workflow = new MigrationsWorkflow(host, logger);
|
||||
let p = Promise.resolve(null);
|
||||
migrationsFile.migrations.forEach((m) => {
|
||||
p = p.then(() => {
|
||||
logger.info(`Running migration ${m.package}:${m.name}`);
|
||||
return workflow
|
||||
.execute({
|
||||
collection: m.package,
|
||||
schematic: m.name,
|
||||
options: {},
|
||||
debug: false,
|
||||
logger,
|
||||
})
|
||||
.toPromise()
|
||||
.then(() => {
|
||||
logger.info(`Successfully finished ${m.package}:${m.name}`);
|
||||
logger.info(
|
||||
`---------------------------------------------------------`
|
||||
);
|
||||
});
|
||||
});
|
||||
for (let m of migrations) {
|
||||
logger.info(`Running migration ${m.name}`);
|
||||
if (m.cli === 'nx') {
|
||||
await runNxMigration(logger, root, m.package, m.name);
|
||||
} else {
|
||||
await (await import('./ngcli-adapter')).runMigration(
|
||||
logger,
|
||||
root,
|
||||
m.package,
|
||||
m.name
|
||||
);
|
||||
}
|
||||
logger.info(`Successfully finished ${m.name}`);
|
||||
logger.info(`---------------------------------------------------------`);
|
||||
}
|
||||
}
|
||||
|
||||
async function runNxMigration(
|
||||
logger: logging.Logger,
|
||||
root: string,
|
||||
packageName: string,
|
||||
name: string
|
||||
) {
|
||||
const collectionPath = packageToMigrationsFilePath(logger, packageName, root);
|
||||
const collection = JSON.parse(fs.readFileSync(collectionPath).toString());
|
||||
const g = collection.generators || collection.schematics;
|
||||
const implRelativePath = g[name].implementation || g[name].factory;
|
||||
const implPath = require.resolve(implRelativePath, {
|
||||
paths: [dirname(collectionPath)],
|
||||
});
|
||||
|
||||
await p;
|
||||
const fn = require(implPath).default;
|
||||
const host = new FsTree(root, false, logger as any);
|
||||
await fn(host, {});
|
||||
const changes = host.listChanges();
|
||||
flushChanges(root, changes);
|
||||
}
|
||||
|
||||
export async function migrate(root: string, args: string[], isVerbose = false) {
|
||||
|
||||
@ -24,16 +24,28 @@ import { printRunHelp, RunOptions } from './run';
|
||||
import {
|
||||
FileSystemCollectionDescription,
|
||||
FileSystemSchematicDescription,
|
||||
NodeModulesEngineHost,
|
||||
NodeWorkflow,
|
||||
validateOptionsWithSchema,
|
||||
} from '@angular-devkit/schematics/tools';
|
||||
import { DryRunEvent, formats, Schematic } from '@angular-devkit/schematics';
|
||||
import {
|
||||
DryRunEvent,
|
||||
formats,
|
||||
Schematic,
|
||||
TaskExecutor,
|
||||
} from '@angular-devkit/schematics';
|
||||
import * as fs from 'fs';
|
||||
import * as inquirer from 'inquirer';
|
||||
import { detectPackageManager } from '../shared/detect-package-manager';
|
||||
import { GenerateOptions, printGenHelp } from './generate';
|
||||
import * as taoTree from '../shared/tree';
|
||||
import { workspaceConfigName } from '@nrwl/tao/src/shared/workspace';
|
||||
import { BaseWorkflow } from '@angular-devkit/schematics/src/workflow';
|
||||
import { NodePackageName } from '@angular-devkit/schematics/tasks/package-manager/options';
|
||||
import { BuiltinTaskExecutor } from '@angular-devkit/schematics/tasks/node';
|
||||
import { dirname, extname, join, resolve } from 'path';
|
||||
import { readFileSync } from 'fs';
|
||||
import * as stripJsonComments from 'strip-json-comments';
|
||||
|
||||
function normalizeOptions(opts: Options, schema: Schema): Options {
|
||||
return convertAliases(coerceTypesInOptions(opts, schema), schema, false);
|
||||
@ -324,6 +336,84 @@ function isTTY(): boolean {
|
||||
return !!process.stdout.isTTY && process.env['CI'] !== 'true';
|
||||
}
|
||||
|
||||
class MigrationEngineHost extends NodeModulesEngineHost {
|
||||
private nodeInstallLogPrinted = false;
|
||||
|
||||
constructor(logger: logging.Logger) {
|
||||
super();
|
||||
|
||||
// Overwrite the original CLI node package executor with a new one that does basically nothing
|
||||
// since nx migrate doesn't do npm installs by itself
|
||||
// (https://github.com/angular/angular-cli/blob/5df776780deadb6be5048b3ab006a5d3383650dc/packages/angular_devkit/schematics/tools/workflow/node-workflow.ts#L41)
|
||||
this.registerTaskExecutor({
|
||||
name: NodePackageName,
|
||||
create: () =>
|
||||
Promise.resolve<TaskExecutor>(() => {
|
||||
return new Promise((res) => {
|
||||
if (!this.nodeInstallLogPrinted) {
|
||||
logger.warn(
|
||||
`An installation of node_modules has been required. Make sure to run it after the migration`
|
||||
);
|
||||
this.nodeInstallLogPrinted = true;
|
||||
}
|
||||
|
||||
res();
|
||||
});
|
||||
}),
|
||||
});
|
||||
|
||||
this.registerTaskExecutor(BuiltinTaskExecutor.RunSchematic);
|
||||
}
|
||||
|
||||
protected _resolveCollectionPath(name: string): string {
|
||||
let collectionPath: string | undefined = undefined;
|
||||
|
||||
if (name.startsWith('.') || name.startsWith('/')) {
|
||||
name = resolve(name);
|
||||
}
|
||||
|
||||
if (extname(name)) {
|
||||
collectionPath = require.resolve(name);
|
||||
} else {
|
||||
const packageJsonPath = require.resolve(join(name, 'package.json'));
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const packageJson = require(packageJsonPath);
|
||||
let pkgJsonSchematics = packageJson['nx-migrations'];
|
||||
if (!pkgJsonSchematics) {
|
||||
pkgJsonSchematics = packageJson['ng-update'];
|
||||
if (!pkgJsonSchematics) {
|
||||
throw new Error(`Could not find migrations in package: "${name}"`);
|
||||
}
|
||||
}
|
||||
if (typeof pkgJsonSchematics != 'string') {
|
||||
pkgJsonSchematics = pkgJsonSchematics.migrations;
|
||||
}
|
||||
collectionPath = resolve(dirname(packageJsonPath), pkgJsonSchematics);
|
||||
}
|
||||
|
||||
try {
|
||||
if (collectionPath) {
|
||||
JSON.parse(stripJsonComments(readFileSync(collectionPath).toString()));
|
||||
return collectionPath;
|
||||
}
|
||||
} catch (e) {
|
||||
throw new Error(`Invalid migration file in package: "${name}"`);
|
||||
}
|
||||
throw new Error(`Collection cannot be resolved: "${name}"`);
|
||||
}
|
||||
}
|
||||
|
||||
class MigrationsWorkflow extends BaseWorkflow {
|
||||
constructor(host: virtualFs.Host, logger: logging.Logger) {
|
||||
super({
|
||||
host,
|
||||
engineHost: new MigrationEngineHost(logger),
|
||||
force: true,
|
||||
dryRun: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export async function generate(
|
||||
logger: logging.Logger,
|
||||
root: string,
|
||||
@ -347,6 +437,25 @@ export async function generate(
|
||||
).status;
|
||||
}
|
||||
|
||||
export async function runMigration(
|
||||
logger: logging.Logger,
|
||||
root: string,
|
||||
collection: string,
|
||||
schematic: string
|
||||
) {
|
||||
const host = new virtualFs.ScopedHost(new NodeJsSyncHost(), normalize(root));
|
||||
const workflow = new MigrationsWorkflow(host, logger);
|
||||
return workflow
|
||||
.execute({
|
||||
collection,
|
||||
schematic,
|
||||
options: {},
|
||||
debug: false,
|
||||
logger,
|
||||
})
|
||||
.toPromise();
|
||||
}
|
||||
|
||||
export function wrapAngularDevkitSchematic(
|
||||
collectionName: string,
|
||||
generatorName: string
|
||||
|
||||
@ -138,7 +138,8 @@
|
||||
"update-decorate-angular-cli": {
|
||||
"version": "11.0.0-beta.3",
|
||||
"description": "Update the decoration script when using Angular CLI",
|
||||
"factory": "./src/migrations/update-11-0-0/update-decorate-angular-cli"
|
||||
"implementation": "./src/migrations/update-11-0-0/update-decorate-angular-cli",
|
||||
"cli": "nx"
|
||||
},
|
||||
"update-node-types": {
|
||||
"version": "11.0.0-beta.3",
|
||||
|
||||
@ -1,21 +1,17 @@
|
||||
import { Rule, Tree } from '@angular-devkit/schematics';
|
||||
import { join as pathJoin } from 'path';
|
||||
import { readFileSync } from 'fs';
|
||||
import { Tree } from '@nrwl/devkit';
|
||||
|
||||
export default function update(): Rule {
|
||||
return (host: Tree) => {
|
||||
const decorateCli = readFileSync(
|
||||
pathJoin(
|
||||
__dirname as any,
|
||||
'..',
|
||||
'..',
|
||||
'schematics',
|
||||
'utils',
|
||||
'decorate-angular-cli.js__tmpl__'
|
||||
)
|
||||
).toString();
|
||||
if (host.exists('/decorate-angular-cli.js')) {
|
||||
host.overwrite('/decorate-angular-cli.js', decorateCli);
|
||||
}
|
||||
};
|
||||
export default function update(host: Tree) {
|
||||
const decorateCli = readFileSync(
|
||||
pathJoin(
|
||||
__dirname as any,
|
||||
'..',
|
||||
'..',
|
||||
'schematics',
|
||||
'utils',
|
||||
'decorate-angular-cli.js__tmpl__'
|
||||
)
|
||||
).toString();
|
||||
host.write('/decorate-angular-cli.js', decorateCli);
|
||||
}
|
||||
|
||||
@ -114,9 +114,12 @@ async function runTest() {
|
||||
execSync(`./scripts/package.sh 9999.0.2 "~10.0.0" "3.9.3" "2.0.4"`, {
|
||||
stdio: [0, 1, 2],
|
||||
});
|
||||
execSync(`rm -rf tmp`);
|
||||
execSync(`mkdir -p tmp/angular`);
|
||||
execSync(`mkdir -p tmp/nx`);
|
||||
|
||||
if (process.argv[5] != '--rerun') {
|
||||
execSync(`rm -rf tmp`);
|
||||
execSync(`mkdir -p tmp/angular`);
|
||||
execSync(`mkdir -p tmp/nx`);
|
||||
}
|
||||
|
||||
try {
|
||||
await setup();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user