nx 13.10.3 → 14.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +1 -1
  2. package/executors.json +9 -0
  3. package/migrations.json +3 -0
  4. package/package.json +32 -3
  5. package/presets/core.json +21 -0
  6. package/presets/npm.json +20 -0
  7. package/src/command-line/connect-to-nx-cloud.d.ts +1 -1
  8. package/src/command-line/connect-to-nx-cloud.js +4 -4
  9. package/src/command-line/connect-to-nx-cloud.js.map +1 -1
  10. package/src/command-line/examples.js +5 -1
  11. package/src/command-line/examples.js.map +1 -1
  12. package/src/command-line/generate.d.ts +1 -1
  13. package/src/command-line/generate.js +6 -5
  14. package/src/command-line/generate.js.map +1 -1
  15. package/src/command-line/migrate.d.ts +18 -38
  16. package/src/command-line/migrate.js +385 -276
  17. package/src/command-line/migrate.js.map +1 -1
  18. package/src/command-line/nx-commands.js +20 -1
  19. package/src/command-line/nx-commands.js.map +1 -1
  20. package/src/command-line/run.js +1 -1
  21. package/src/command-line/run.js.map +1 -1
  22. package/src/config/misc-interfaces.d.ts +58 -0
  23. package/src/config/workspaces.d.ts +1 -0
  24. package/src/config/workspaces.js +6 -1
  25. package/src/config/workspaces.js.map +1 -1
  26. package/src/core/dep-graph/3rdpartylicenses.txt +25 -0
  27. package/src/core/dep-graph/index.html +1 -2
  28. package/src/core/dep-graph/main.esm.js +1 -1
  29. package/src/core/dep-graph/main.esm.js.LICENSE.txt +6 -0
  30. package/src/core/dep-graph/styles.css +1 -1
  31. package/src/executors/run-script/run-script.impl.d.ts +7 -0
  32. package/src/executors/run-script/run-script.impl.js +29 -0
  33. package/src/executors/run-script/run-script.impl.js.map +1 -0
  34. package/src/executors/run-script/schema.json +16 -0
  35. package/src/utils/fileutils.d.ts +1 -1
  36. package/src/utils/fileutils.js +1 -1
  37. package/src/utils/fileutils.js.map +1 -1
  38. package/src/utils/package-json.d.ts +11 -1
  39. package/src/utils/package-json.js +1 -1
  40. package/src/utils/package-json.js.map +1 -1
  41. package/src/utils/package-manager.d.ts +15 -2
  42. package/src/utils/package-manager.js +98 -43
  43. package/src/utils/package-manager.js.map +1 -1
  44. package/src/utils/params.d.ts +4 -0
  45. package/src/utils/params.js.map +1 -1
  46. package/src/utils/print-help.d.ts +1 -0
  47. package/src/utils/print-help.js +205 -34
  48. package/src/utils/print-help.js.map +1 -1
  49. package/src/utils/versions.js +1 -1
@@ -2,91 +2,87 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.migrate = exports.parseMigrationsOptions = exports.Migrator = exports.normalizeVersion = void 0;
4
4
  const tslib_1 = require("tslib");
5
+ const chalk = require("chalk");
5
6
  const child_process_1 = require("child_process");
6
7
  const fs_extra_1 = require("fs-extra");
7
8
  const path_1 = require("path");
8
9
  const semver_1 = require("semver");
9
- const tmp_1 = require("tmp");
10
+ const util_1 = require("util");
10
11
  const tree_1 = require("../config/tree");
11
12
  const fileutils_1 = require("../utils/fileutils");
12
13
  const logger_1 = require("../utils/logger");
13
14
  const package_manager_1 = require("../utils/package-manager");
14
15
  const params_1 = require("../utils/params");
16
+ const connect_to_nx_cloud_1 = require("./connect-to-nx-cloud");
17
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
15
18
  function normalizeVersion(version) {
16
- const [v, t] = version.split('-');
17
- const [major, minor, patch] = v.split('.');
18
- const newV = `${major || 0}.${minor || 0}.${patch || 0}`;
19
- const newVersion = t ? `${newV}-${t}` : newV;
20
- try {
21
- (0, semver_1.gt)(newVersion, '0.0.0');
22
- return newVersion;
23
- }
24
- catch (e) {
19
+ const [semver, prereleaseTag] = version.split('-');
20
+ const [major, minor, patch] = semver.split('.');
21
+ const newSemver = `${major || 0}.${minor || 0}.${patch || 0}`;
22
+ const newVersion = prereleaseTag
23
+ ? `${newSemver}-${prereleaseTag}`
24
+ : newSemver;
25
+ const withoutPatch = `${major || 0}.${minor || 0}.0`;
26
+ const withoutPatchAndMinor = `${major || 0}.0.0`;
27
+ const variationsToCheck = [
28
+ newVersion,
29
+ newSemver,
30
+ withoutPatch,
31
+ withoutPatchAndMinor,
32
+ ];
33
+ for (const variation of variationsToCheck) {
25
34
  try {
26
- (0, semver_1.gt)(newV, '0.0.0');
27
- return newV;
28
- }
29
- catch (e) {
30
- const withoutPatch = `${major || 0}.${minor || 0}.0`;
31
- try {
32
- if ((0, semver_1.gt)(withoutPatch, '0.0.0')) {
33
- return withoutPatch;
34
- }
35
- }
36
- catch (e) {
37
- const withoutPatchAndMinor = `${major || 0}.0.0`;
38
- try {
39
- if ((0, semver_1.gt)(withoutPatchAndMinor, '0.0.0')) {
40
- return withoutPatchAndMinor;
41
- }
42
- }
43
- catch (e) {
44
- return '0.0.0';
45
- }
35
+ if ((0, semver_1.gt)(variation, '0.0.0')) {
36
+ return variation;
46
37
  }
47
38
  }
39
+ catch (_a) { }
48
40
  }
41
+ return '0.0.0';
49
42
  }
50
43
  exports.normalizeVersion = normalizeVersion;
51
- function slash(packageName) {
44
+ function normalizeSlashes(packageName) {
52
45
  return packageName.replace(/\\/g, '/');
53
46
  }
54
47
  class Migrator {
55
48
  constructor(opts) {
49
+ this.collectedVersions = {};
56
50
  this.packageJson = opts.packageJson;
57
51
  this.versions = opts.versions;
58
52
  this.fetch = opts.fetch;
59
- this.from = opts.from;
60
53
  this.to = opts.to;
61
54
  }
62
55
  updatePackageJson(targetPackage, targetVersion) {
63
56
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
64
- const packageJson = yield this._updatePackageJson(targetPackage, { version: targetVersion, addToPackageJson: false }, {});
57
+ const packageJson = yield this._updatePackageJson(targetPackage, {
58
+ version: targetVersion,
59
+ addToPackageJson: false,
60
+ });
65
61
  const migrations = yield this._createMigrateJson(packageJson);
66
62
  return { packageJson, migrations };
67
63
  });
68
64
  }
69
65
  _createMigrateJson(versions) {
70
66
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
71
- const migrations = yield Promise.all(Object.keys(versions).map((c) => tslib_1.__awaiter(this, void 0, void 0, function* () {
72
- const currentVersion = this.versions(c);
67
+ const migrations = yield Promise.all(Object.keys(versions).map((packageName) => tslib_1.__awaiter(this, void 0, void 0, function* () {
68
+ const currentVersion = this.versions(packageName);
73
69
  if (currentVersion === null)
74
70
  return [];
75
- const target = versions[c];
76
- const migrationsJson = yield this.fetch(c, target.version);
77
- const generators = migrationsJson.generators;
71
+ const { version } = versions[packageName];
72
+ const { generators } = yield this.fetch(packageName, version);
78
73
  if (!generators)
79
74
  return [];
80
- return Object.keys(generators)
81
- .filter((r) => generators[r].version &&
82
- this.gt(generators[r].version, currentVersion) &&
83
- this.lte(generators[r].version, target.version))
84
- .map((r) => (Object.assign(Object.assign({}, migrationsJson.generators[r]), { package: c, name: r })));
75
+ return Object.entries(generators)
76
+ .filter(([, migration]) => migration.version &&
77
+ this.gt(migration.version, currentVersion) &&
78
+ this.lte(migration.version, version))
79
+ .map(([migrationName, migration]) => (Object.assign(Object.assign({}, migration), { package: packageName, name: migrationName })));
85
80
  })));
86
- return migrations.reduce((m, c) => [...m, ...c], []);
81
+ return migrations.flat();
87
82
  });
88
83
  }
89
- _updatePackageJson(targetPackage, target, collectedVersions) {
84
+ _updatePackageJson(targetPackage, target) {
85
+ var _a;
90
86
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
91
87
  let targetVersion = target.version;
92
88
  if (this.to[targetPackage]) {
@@ -104,9 +100,10 @@ class Migrator {
104
100
  try {
105
101
  migrationsJson = yield this.fetch(targetPackage, targetVersion);
106
102
  targetVersion = migrationsJson.version;
103
+ this.collectedVersions[targetPackage] = targetVersion;
107
104
  }
108
105
  catch (e) {
109
- if (e.message.indexOf('No matching version') > -1) {
106
+ if ((_a = e === null || e === void 0 ? void 0 : e.message) === null || _a === void 0 ? void 0 : _a.includes('No matching version')) {
110
107
  throw new Error(`${e.message}\nRun migrate with --to="package1@version1,package2@version2"`);
111
108
  }
112
109
  else {
@@ -114,19 +111,18 @@ class Migrator {
114
111
  }
115
112
  }
116
113
  const packages = this.collapsePackages(targetPackage, targetVersion, migrationsJson);
117
- const childCalls = yield Promise.all(Object.keys(packages)
118
- .filter((r) => {
119
- return (!collectedVersions[r] ||
120
- this.gt(packages[r].version, collectedVersions[r].version));
121
- })
122
- .map((u) => this._updatePackageJson(u, packages[u], Object.assign(Object.assign({}, collectedVersions), { [targetPackage]: target }))));
123
- return childCalls.reduce((m, c) => {
124
- Object.keys(c).forEach((r) => {
125
- if (!m[r] || this.gt(c[r].version, m[r].version)) {
126
- m[r] = c[r];
114
+ const childPackageMigrations = yield Promise.all(Object.keys(packages)
115
+ .filter((packageName) => !this.collectedVersions[packageName] ||
116
+ this.gt(packages[packageName].version, this.collectedVersions[packageName]))
117
+ .map((packageName) => this._updatePackageJson(packageName, packages[packageName])));
118
+ return childPackageMigrations.reduce((migrations, childMigrations) => {
119
+ for (const migrationName of Object.keys(childMigrations)) {
120
+ if (!migrations[migrationName] ||
121
+ this.gt(childMigrations[migrationName].version, migrations[migrationName].version)) {
122
+ migrations[migrationName] = childMigrations[migrationName];
127
123
  }
128
- });
129
- return m;
124
+ }
125
+ return migrations;
130
126
  }, {
131
127
  [targetPackage]: {
132
128
  version: migrationsJson.version,
@@ -135,66 +131,77 @@ class Migrator {
135
131
  });
136
132
  });
137
133
  }
138
- collapsePackages(packageName, targetVersion, m) {
134
+ collapsePackages(packageName, targetVersion, migration) {
139
135
  // this should be used to know what version to include
140
136
  // we should use from everywhere we use versions
141
- if (packageName === '@nrwl/workspace') {
142
- if (!m.packageJsonUpdates)
143
- m.packageJsonUpdates = {};
144
- m.packageJsonUpdates[`${targetVersion}-defaultPackages`] = {
137
+ var _a;
138
+ // Support Migrating to older versions of Nx
139
+ // Use the packageGroup of the latest version of Nx instead of the one from the target version which could be older.
140
+ if (packageName === '@nrwl/workspace' &&
141
+ (0, semver_1.lt)(targetVersion, '14.0.0-beta.0')) {
142
+ migration.packageGroup = {
143
+ '@nrwl/workspace': targetVersion,
144
+ '@nrwl/angular': targetVersion,
145
+ '@nrwl/cypress': targetVersion,
146
+ '@nrwl/devkit': targetVersion,
147
+ '@nrwl/eslint-plugin-nx': targetVersion,
148
+ '@nrwl/express': targetVersion,
149
+ '@nrwl/jest': targetVersion,
150
+ '@nrwl/linter': targetVersion,
151
+ '@nrwl/nest': targetVersion,
152
+ '@nrwl/next': targetVersion,
153
+ '@nrwl/node': targetVersion,
154
+ '@nrwl/nx-plugin': targetVersion,
155
+ '@nrwl/react': targetVersion,
156
+ '@nrwl/storybook': targetVersion,
157
+ '@nrwl/web': targetVersion,
158
+ '@nrwl/js': targetVersion,
159
+ '@nrwl/cli': targetVersion,
160
+ '@nrwl/nx-cloud': 'latest',
161
+ '@nrwl/react-native': targetVersion,
162
+ '@nrwl/detox': targetVersion,
163
+ };
164
+ }
165
+ if (migration.packageGroup) {
166
+ (_a = migration.packageJsonUpdates) !== null && _a !== void 0 ? _a : (migration.packageJsonUpdates = {});
167
+ const packageGroup = normalizePackageGroup(migration.packageGroup);
168
+ migration.packageJsonUpdates[targetVersion + '--PackageGroup'] = {
145
169
  version: targetVersion,
146
- packages: [
147
- 'nx',
148
- '@nrwl/angular',
149
- '@nrwl/cypress',
150
- '@nrwl/devkit',
151
- '@nrwl/eslint-plugin-nx',
152
- '@nrwl/express',
153
- '@nrwl/jest',
154
- '@nrwl/js',
155
- '@nrwl/cli',
156
- '@nrwl/linter',
157
- '@nrwl/nest',
158
- '@nrwl/next',
159
- '@nrwl/node',
160
- '@nrwl/nx-cloud',
161
- '@nrwl/nx-plugin',
162
- '@nrwl/react',
163
- '@nrwl/storybook',
164
- '@nrwl/web',
165
- '@nrwl/react-native',
166
- '@nrwl/detox',
167
- ].reduce((m, c) => (Object.assign(Object.assign({}, m), { [c]: {
168
- version: c === '@nrwl/nx-cloud' ? 'latest' : targetVersion,
169
- alwaysAddToPackageJson: false,
170
- } })), {}),
170
+ packages: packageGroup.reduce((acc, packageConfig) => {
171
+ const { package: pkg, version } = typeof packageConfig === 'string'
172
+ ? { package: packageConfig, version: targetVersion }
173
+ : packageConfig;
174
+ return Object.assign(Object.assign({}, acc), { [pkg]: {
175
+ version,
176
+ alwaysAddToPackageJson: false,
177
+ } });
178
+ }, {}),
171
179
  };
172
180
  }
173
- if (!m.packageJsonUpdates || !this.versions(packageName))
181
+ if (!migration.packageJsonUpdates || !this.versions(packageName))
174
182
  return {};
175
- return Object.keys(m.packageJsonUpdates)
176
- .filter((r) => {
177
- return (this.gt(m.packageJsonUpdates[r].version, this.versions(packageName)) && this.lte(m.packageJsonUpdates[r].version, targetVersion));
183
+ return Object.values(migration.packageJsonUpdates)
184
+ .filter(({ version, packages }) => {
185
+ return (packages &&
186
+ this.gt(version, this.versions(packageName)) &&
187
+ this.lte(version, targetVersion));
178
188
  })
179
- .map((r) => m.packageJsonUpdates[r].packages)
180
- .map((packages) => {
181
- if (!packages)
182
- return {};
183
- return Object.keys(packages)
184
- .filter((pkg) => {
185
- const { dependencies, devDependencies } = this.packageJson;
186
- return ((!packages[pkg].ifPackageInstalled ||
187
- this.versions(packages[pkg].ifPackageInstalled)) &&
188
- (packages[pkg].alwaysAddToPackageJson ||
189
- packages[pkg].addToPackageJson ||
190
- !!(dependencies === null || dependencies === void 0 ? void 0 : dependencies[pkg]) ||
191
- !!(devDependencies === null || devDependencies === void 0 ? void 0 : devDependencies[pkg])));
189
+ .map(({ packages }) => {
190
+ const { dependencies, devDependencies } = this.packageJson;
191
+ return Object.entries(packages)
192
+ .filter(([packageName, packageUpdate]) => {
193
+ return ((!packageUpdate.ifPackageInstalled ||
194
+ this.versions(packageUpdate.ifPackageInstalled)) &&
195
+ (packageUpdate.alwaysAddToPackageJson ||
196
+ packageUpdate.addToPackageJson ||
197
+ !!(dependencies === null || dependencies === void 0 ? void 0 : dependencies[packageName]) ||
198
+ !!(devDependencies === null || devDependencies === void 0 ? void 0 : devDependencies[packageName])));
192
199
  })
193
- .reduce((m, c) => (Object.assign(Object.assign({}, m), { [c]: {
194
- version: packages[c].version,
195
- addToPackageJson: packages[c].alwaysAddToPackageJson
200
+ .reduce((acc, [packageName, packageUpdate]) => (Object.assign(Object.assign({}, acc), { [packageName]: {
201
+ version: packageUpdate.version,
202
+ addToPackageJson: packageUpdate.alwaysAddToPackageJson
196
203
  ? 'dependencies'
197
- : packages[c].addToPackageJson || false,
204
+ : packageUpdate.addToPackageJson || false,
198
205
  } })), {});
199
206
  })
200
207
  .reduce((m, c) => (Object.assign(Object.assign({}, m), c)), {});
@@ -207,6 +214,15 @@ class Migrator {
207
214
  }
208
215
  }
209
216
  exports.Migrator = Migrator;
217
+ function normalizePackageGroup(packageGroup) {
218
+ if (!Array.isArray(packageGroup)) {
219
+ return Object.entries(packageGroup).map(([pkg, version]) => ({
220
+ package: pkg,
221
+ version,
222
+ }));
223
+ }
224
+ return packageGroup;
225
+ }
210
226
  function normalizeVersionWithTagCheck(version) {
211
227
  if (version === 'latest' || version === 'next')
212
228
  return version;
@@ -224,13 +240,14 @@ function versionOverrides(overrides, param) {
224
240
  if (!selectedPackage || !selectedVersion) {
225
241
  throw new Error(`Incorrect '${param}' section. Use --${param}="package@version"`);
226
242
  }
227
- res[slash(selectedPackage)] = normalizeVersionWithTagCheck(selectedVersion);
243
+ res[normalizeSlashes(selectedPackage)] =
244
+ normalizeVersionWithTagCheck(selectedVersion);
228
245
  });
229
246
  return res;
230
247
  }
231
248
  function parseTargetPackageAndVersion(args) {
232
249
  if (!args) {
233
- throw new Error(`Provide the correct package name and version. E.g., @nrwl/workspace@9.0.0.`);
250
+ throw new Error(`Provide the correct package name and version. E.g., my-package@9.0.0.`);
234
251
  }
235
252
  if (args.indexOf('@') > -1) {
236
253
  const i = args.lastIndexOf('@');
@@ -243,7 +260,7 @@ function parseTargetPackageAndVersion(args) {
243
260
  const targetPackage = args.substring(0, i);
244
261
  const maybeVersion = args.substring(i + 1);
245
262
  if (!targetPackage || !maybeVersion) {
246
- throw new Error(`Provide the correct package name and version. E.g., @nrwl/workspace@9.0.0.`);
263
+ throw new Error(`Provide the correct package name and version. E.g., my-package@9.0.0.`);
247
264
  }
248
265
  const targetVersion = normalizeVersionWithTagCheck(maybeVersion);
249
266
  return { targetPackage, targetVersion };
@@ -253,9 +270,14 @@ function parseTargetPackageAndVersion(args) {
253
270
  if (args.match(/^\d+(?:\.\d+)?(?:\.\d+)?$/) ||
254
271
  args === 'latest' ||
255
272
  args === 'next') {
273
+ const targetVersion = normalizeVersionWithTagCheck(args);
274
+ const targetPackage = args.match(/^\d+(?:\.\d+)?(?:\.\d+)?$/) &&
275
+ (0, semver_1.lt)(targetVersion, '14.0.0-beta.0')
276
+ ? '@nrwl/workspace'
277
+ : 'nx';
256
278
  return {
257
- targetPackage: '@nrwl/workspace',
258
- targetVersion: normalizeVersionWithTagCheck(args),
279
+ targetPackage,
280
+ targetVersion,
259
281
  };
260
282
  }
261
283
  else {
@@ -278,7 +300,7 @@ function parseMigrationsOptions(options) {
278
300
  const { targetPackage, targetVersion } = parseTargetPackageAndVersion(options['packageAndVersion']);
279
301
  return {
280
302
  type: 'generateMigrations',
281
- targetPackage: slash(targetPackage),
303
+ targetPackage: normalizeSlashes(targetPackage),
282
304
  targetVersion,
283
305
  from,
284
306
  to,
@@ -293,15 +315,19 @@ function parseMigrationsOptions(options) {
293
315
  }
294
316
  exports.parseMigrationsOptions = parseMigrationsOptions;
295
317
  function versions(root, from) {
318
+ const cache = {};
296
319
  return (packageName) => {
297
320
  try {
298
321
  if (from[packageName]) {
299
322
  return from[packageName];
300
323
  }
301
- const packageJsonPath = require.resolve(`${packageName}/package.json`, {
302
- paths: [root],
303
- });
304
- return (0, fileutils_1.readJsonFile)(packageJsonPath).version;
324
+ if (!cache[packageName]) {
325
+ const packageJsonPath = require.resolve(`${packageName}/package.json`, {
326
+ paths: [root],
327
+ });
328
+ cache[packageName] = (0, fileutils_1.readJsonFile)(packageJsonPath).version;
329
+ }
330
+ return cache[packageName];
305
331
  }
306
332
  catch (_a) {
307
333
  return null;
@@ -310,177 +336,177 @@ function versions(root, from) {
310
336
  }
311
337
  // testing-fetch-start
312
338
  function createFetcher() {
313
- const cache = {};
314
- return function f(packageName, packageVersion) {
315
- var _a;
316
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
317
- if (cache[`${packageName}-${packageVersion}`]) {
318
- return cache[`${packageName}-${packageVersion}`];
319
- }
320
- let resolvedVersion;
321
- let migrations;
322
- try {
323
- resolvedVersion = (0, package_manager_1.resolvePackageVersionUsingRegistry)(packageName, packageVersion);
324
- if (cache[`${packageName}-${resolvedVersion}`]) {
325
- return cache[`${packageName}-${resolvedVersion}`];
326
- }
327
- logger_1.logger.info(`Fetching ${packageName}@${packageVersion}`);
328
- migrations = yield getPackageMigrations(packageName, resolvedVersion);
339
+ const migrationsCache = {};
340
+ const resolvedVersionCache = {};
341
+ function fetchMigrations(packageName, packageVersion, setCache) {
342
+ const cacheKey = packageName + '-' + packageVersion;
343
+ return Promise.resolve(resolvedVersionCache[cacheKey])
344
+ .then((cachedResolvedVersion) => {
345
+ if (cachedResolvedVersion) {
346
+ return cachedResolvedVersion;
329
347
  }
330
- catch (_b) {
331
- logger_1.logger.info(`Fetching ${packageName}@${packageVersion}`);
332
- const result = yield installPackageAndGetVersionAngMigrations(packageName, packageVersion);
333
- resolvedVersion = result.resolvedVersion;
334
- migrations = result.migrations;
335
- }
336
- if (migrations) {
337
- cache[`${packageName}-${packageVersion}`] = cache[`${packageName}-${resolvedVersion}`] = {
338
- version: resolvedVersion,
339
- generators: (_a = migrations.generators) !== null && _a !== void 0 ? _a : migrations.schematics,
340
- packageJsonUpdates: migrations.packageJsonUpdates,
341
- };
348
+ resolvedVersionCache[cacheKey] = (0, package_manager_1.resolvePackageVersionUsingRegistry)(packageName, packageVersion);
349
+ return resolvedVersionCache[cacheKey];
350
+ })
351
+ .then((resolvedVersion) => {
352
+ if (resolvedVersion !== packageVersion &&
353
+ migrationsCache[`${packageName}-${resolvedVersion}`]) {
354
+ return migrationsCache[`${packageName}-${resolvedVersion}`];
342
355
  }
343
- else {
344
- cache[`${packageName}-${packageVersion}`] = cache[`${packageName}-${resolvedVersion}`] = {
345
- version: resolvedVersion,
346
- };
356
+ setCache(packageName, resolvedVersion);
357
+ return getPackageMigrationsUsingRegistry(packageName, resolvedVersion);
358
+ })
359
+ .catch(() => {
360
+ logger_1.logger.info(`Fetching ${packageName}@${packageVersion}`);
361
+ return getPackageMigrationsUsingInstall(packageName, packageVersion);
362
+ });
363
+ }
364
+ return function nxMigrateFetcher(packageName, packageVersion) {
365
+ if (migrationsCache[`${packageName}-${packageVersion}`]) {
366
+ return migrationsCache[`${packageName}-${packageVersion}`];
367
+ }
368
+ let resolvedVersion = packageVersion;
369
+ let migrations;
370
+ function setCache(packageName, packageVersion) {
371
+ migrationsCache[packageName + '-' + packageVersion] = migrations;
372
+ }
373
+ migrations = fetchMigrations(packageName, packageVersion, setCache).then((result) => {
374
+ if (result.schematics) {
375
+ result.generators = result.schematics;
376
+ delete result.schematics;
347
377
  }
348
- return cache[`${packageName}-${packageVersion}`];
378
+ resolvedVersion = result.version;
379
+ return result;
349
380
  });
381
+ setCache(packageName, packageVersion);
382
+ return migrations;
350
383
  };
351
384
  }
352
385
  // testing-fetch-end
353
- function getPackageMigrations(packageName, packageVersion) {
386
+ function getPackageMigrationsUsingRegistry(packageName, packageVersion) {
354
387
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
355
- try {
356
- // check if there are migrations in the packages by looking at the
357
- // registry directly
358
- const migrationsPath = getPackageMigrationsPathFromRegistry(packageName, packageVersion);
359
- if (!migrationsPath) {
360
- return null;
361
- }
362
- // try to obtain the migrations from the registry directly
363
- return yield getPackageMigrationsUsingRegistry(packageName, packageVersion, migrationsPath);
388
+ // check if there are migrations in the packages by looking at the
389
+ // registry directly
390
+ const migrationsConfig = yield getPackageMigrationsConfigFromRegistry(packageName, packageVersion);
391
+ if (!migrationsConfig) {
392
+ return {
393
+ version: packageVersion,
394
+ };
364
395
  }
365
- catch (_a) {
366
- // fall back to installing the package
367
- const { migrations } = yield installPackageAndGetVersionAngMigrations(packageName, packageVersion);
368
- return migrations;
396
+ if (!migrationsConfig.migrations) {
397
+ return {
398
+ version: packageVersion,
399
+ packageGroup: migrationsConfig.packageGroup,
400
+ };
369
401
  }
402
+ logger_1.logger.info(`Fetching ${packageName}@${packageVersion}`);
403
+ // try to obtain the migrations from the registry directly
404
+ return yield downloadPackageMigrationsFromRegistry(packageName, packageVersion, migrationsConfig);
370
405
  });
371
406
  }
372
- function getPackageMigrationsPathFromRegistry(packageName, packageVersion) {
373
- var _a, _b;
374
- let pm = (0, package_manager_1.detectPackageManager)();
375
- if (pm === 'yarn') {
376
- pm = 'npm';
377
- }
378
- const result = (0, child_process_1.execSync)(`${pm} view ${packageName}@${packageVersion} nx-migrations ng-update --json`, {
379
- stdio: [],
380
- })
381
- .toString()
382
- .trim();
383
- if (!result) {
384
- return null;
385
- }
386
- const json = JSON.parse(result);
387
- let migrationsFilePath = (_b = (_a = json['nx-migrations']) !== null && _a !== void 0 ? _a : json['ng-update']) !== null && _b !== void 0 ? _b : json;
388
- if (typeof json === 'object') {
389
- migrationsFilePath = migrationsFilePath.migrations;
390
- }
391
- return migrationsFilePath;
407
+ function resolveNxMigrationConfig(json) {
408
+ const parseNxMigrationsConfig = (fromJson) => {
409
+ if (!fromJson) {
410
+ return {};
411
+ }
412
+ if (typeof fromJson === 'string') {
413
+ return { migrations: fromJson, packageGroup: [] };
414
+ }
415
+ return Object.assign(Object.assign({}, (fromJson.migrations ? { migrations: fromJson.migrations } : {})), (fromJson.packageGroup ? { packageGroup: fromJson.packageGroup } : {}));
416
+ };
417
+ const config = Object.assign(Object.assign(Object.assign({}, parseNxMigrationsConfig(json['ng-update'])), parseNxMigrationsConfig(json['nx-migrations'])), parseNxMigrationsConfig(json));
418
+ return config;
392
419
  }
393
- function getPackageMigrationsUsingRegistry(packageName, packageVersion, migrationsFilePath) {
420
+ function getPackageMigrationsConfigFromRegistry(packageName, packageVersion) {
394
421
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
395
- const dir = (0, tmp_1.dirSync)().name;
396
- createNPMRC(dir);
397
- let pm = (0, package_manager_1.detectPackageManager)();
398
- if (pm === 'yarn') {
399
- pm = 'npm';
400
- }
401
- const tarballPath = (0, child_process_1.execSync)(`${pm} pack ${packageName}@${packageVersion}`, {
402
- cwd: dir,
403
- stdio: [],
404
- })
405
- .toString()
406
- .trim();
407
- let migrations = null;
408
- migrationsFilePath = (0, path_1.join)('package', migrationsFilePath);
409
- const migrationDestinationPath = (0, path_1.join)(dir, migrationsFilePath);
422
+ const result = yield (0, package_manager_1.packageRegistryView)(packageName, packageVersion, 'nx-migrations ng-update --json');
423
+ if (!result) {
424
+ return null;
425
+ }
426
+ return resolveNxMigrationConfig(JSON.parse(result));
427
+ });
428
+ }
429
+ function downloadPackageMigrationsFromRegistry(packageName, packageVersion, { migrations: migrationsFilePath, packageGroup }) {
430
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
431
+ const dir = (0, package_manager_1.createTempNpmDirectory)();
432
+ let result;
410
433
  try {
411
- yield (0, fileutils_1.extractFileFromTarball)((0, path_1.join)(dir, tarballPath), migrationsFilePath, migrationDestinationPath);
412
- migrations = (0, fileutils_1.readJsonFile)(migrationDestinationPath);
434
+ const { tarballPath } = yield (0, package_manager_1.packageRegistryPack)(dir, packageName, packageVersion);
435
+ const migrations = yield (0, fileutils_1.extractFileFromTarball)((0, path_1.join)(dir, tarballPath), (0, path_1.join)('package', migrationsFilePath), (0, path_1.join)(dir, migrationsFilePath)).then((path) => (0, fileutils_1.readJsonFile)(path));
436
+ result = Object.assign(Object.assign({}, migrations), { packageGroup, version: packageVersion });
413
437
  }
414
438
  catch (_a) {
415
439
  throw new Error(`Failed to find migrations file "${migrationsFilePath}" in package "${packageName}@${packageVersion}".`);
416
440
  }
417
- try {
418
- (0, fs_extra_1.removeSync)(dir);
419
- }
420
- catch (_b) {
421
- // It's okay if this fails, the OS will clean it up eventually
441
+ finally {
442
+ try {
443
+ yield (0, fs_extra_1.remove)(dir);
444
+ }
445
+ catch (_b) {
446
+ // It's okay if this fails, the OS will clean it up eventually
447
+ }
422
448
  }
423
- return migrations;
449
+ return result;
424
450
  });
425
451
  }
426
- function installPackageAndGetVersionAngMigrations(packageName, packageVersion) {
452
+ function getPackageMigrationsUsingInstall(packageName, packageVersion) {
427
453
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
428
- const dir = (0, tmp_1.dirSync)().name;
429
- createNPMRC(dir);
430
- const pmc = (0, package_manager_1.getPackageManagerCommand)();
431
- (0, child_process_1.execSync)(`${pmc.add} ${packageName}@${packageVersion}`, {
432
- stdio: [],
433
- cwd: dir,
434
- });
435
- const packageJsonPath = require.resolve(`${packageName}/package.json`, {
436
- paths: [dir],
437
- });
438
- const { version: resolvedVersion } = (0, fileutils_1.readJsonFile)(packageJsonPath);
439
- const migrationsFilePath = packageToMigrationsFilePath(packageName, dir);
440
- let migrations = null;
441
- if (migrationsFilePath) {
442
- migrations = (0, fileutils_1.readJsonFile)(migrationsFilePath);
443
- }
454
+ const dir = (0, package_manager_1.createTempNpmDirectory)();
455
+ let result;
444
456
  try {
445
- (0, fs_extra_1.removeSync)(dir);
457
+ const pmc = (0, package_manager_1.getPackageManagerCommand)();
458
+ yield execAsync(`${pmc.add} ${packageName}@${packageVersion}`, {
459
+ cwd: dir,
460
+ });
461
+ const { migrations: migrationsFilePath, packageGroup, packageJson, } = readPackageMigrationConfig(packageName, dir);
462
+ let migrations = undefined;
463
+ if (migrationsFilePath) {
464
+ migrations = (0, fileutils_1.readJsonFile)(migrationsFilePath);
465
+ }
466
+ result = Object.assign(Object.assign({}, migrations), { packageGroup, version: packageJson.version });
446
467
  }
447
- catch (_a) {
448
- // It's okay if this fails, the OS will clean it up eventually
468
+ finally {
469
+ try {
470
+ yield (0, fs_extra_1.remove)(dir);
471
+ }
472
+ catch (_a) {
473
+ // It's okay if this fails, the OS will clean it up eventually
474
+ }
449
475
  }
450
- return { migrations, resolvedVersion };
476
+ return result;
451
477
  });
452
478
  }
453
- function createNPMRC(dir) {
454
- // A package.json is needed for pnpm pack and for .npmrc to resolve
455
- (0, fileutils_1.writeJsonFile)(`${dir}/package.json`, {});
456
- const npmrc = (0, package_manager_1.checkForNPMRC)();
457
- if (npmrc) {
458
- // Copy npmrc if it exists, so that npm still follows it.
459
- (0, fs_extra_1.copyFileSync)(npmrc, `${dir}/.npmrc`);
460
- }
461
- }
462
- function packageToMigrationsFilePath(packageName, dir) {
479
+ function readPackageMigrationConfig(packageName, dir) {
463
480
  const packageJsonPath = require.resolve(`${packageName}/package.json`, {
464
481
  paths: [dir],
465
482
  });
466
483
  const json = (0, fileutils_1.readJsonFile)(packageJsonPath);
467
- let migrationsFile = json['nx-migrations'] || json['ng-update'];
468
- // migrationsFile is an object
469
- if (migrationsFile && migrationsFile.migrations) {
470
- migrationsFile = migrationsFile.migrations;
484
+ const migrationConfigOrFile = json['nx-migrations'] || json['ng-update'];
485
+ if (!migrationConfigOrFile) {
486
+ return { packageJson: json, migrations: null, packageGroup: [] };
471
487
  }
472
- try {
473
- if (migrationsFile && typeof migrationsFile === 'string') {
474
- return require.resolve(migrationsFile, {
475
- paths: [(0, path_1.dirname)(packageJsonPath)],
476
- });
477
- }
478
- else {
479
- return null;
488
+ const migrationsConfig = typeof migrationConfigOrFile === 'string'
489
+ ? {
490
+ migrations: migrationConfigOrFile,
491
+ packageGroup: [],
480
492
  }
493
+ : migrationConfigOrFile;
494
+ try {
495
+ const migrationFile = require.resolve(migrationsConfig.migrations, {
496
+ paths: [(0, path_1.dirname)(packageJsonPath)],
497
+ });
498
+ return {
499
+ packageJson: json,
500
+ migrations: migrationFile,
501
+ packageGroup: migrationsConfig.packageGroup,
502
+ };
481
503
  }
482
504
  catch (_a) {
483
- return null;
505
+ return {
506
+ packageJson: json,
507
+ migrations: null,
508
+ packageGroup: migrationsConfig.packageGroup,
509
+ };
484
510
  }
485
511
  }
486
512
  function createMigrationsFile(root, migrations) {
@@ -491,41 +517,56 @@ function updatePackageJson(root, updatedPackages) {
491
517
  const parseOptions = {};
492
518
  const json = (0, fileutils_1.readJsonFile)(packageJsonPath, parseOptions);
493
519
  Object.keys(updatedPackages).forEach((p) => {
494
- if (json.devDependencies && json.devDependencies[p]) {
520
+ var _a, _b, _c;
521
+ if ((_a = json.devDependencies) === null || _a === void 0 ? void 0 : _a[p]) {
495
522
  json.devDependencies[p] = updatedPackages[p].version;
523
+ return;
496
524
  }
497
- else if (json.dependencies && json.dependencies[p]) {
525
+ if ((_b = json.dependencies) === null || _b === void 0 ? void 0 : _b[p]) {
498
526
  json.dependencies[p] = updatedPackages[p].version;
527
+ return;
499
528
  }
500
- else if (updatedPackages[p].addToPackageJson) {
501
- if (updatedPackages[p].addToPackageJson === 'dependencies') {
502
- if (!json.dependencies)
503
- json.dependencies = {};
504
- json.dependencies[p] = updatedPackages[p].version;
505
- }
506
- else if (updatedPackages[p].addToPackageJson === 'devDependencies') {
507
- if (!json.devDependencies)
508
- json.devDependencies = {};
509
- json.devDependencies[p] = updatedPackages[p].version;
510
- }
529
+ const dependencyType = updatedPackages[p].addToPackageJson;
530
+ if (typeof dependencyType === 'string') {
531
+ (_c = json[dependencyType]) !== null && _c !== void 0 ? _c : (json[dependencyType] = {});
532
+ json[dependencyType][p] = updatedPackages[p].version;
511
533
  }
512
534
  });
513
535
  (0, fileutils_1.writeJsonFile)(packageJsonPath, json, {
514
536
  appendNewLine: parseOptions.endsWithNewline,
515
537
  });
516
538
  }
539
+ function isMigratingToNewMajor(from, to) {
540
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
541
+ from = normalizeVersion(from);
542
+ to = ['latest', 'next'].includes(to) ? to : normalizeVersion(to);
543
+ if (!(0, semver_1.valid)(from)) {
544
+ from = yield (0, package_manager_1.resolvePackageVersionUsingRegistry)('nx', from);
545
+ }
546
+ if (!(0, semver_1.valid)(to)) {
547
+ to = yield (0, package_manager_1.resolvePackageVersionUsingRegistry)('nx', to);
548
+ }
549
+ console.log({ from, to });
550
+ return (0, semver_1.major)(from) < (0, semver_1.major)(to);
551
+ });
552
+ }
517
553
  function generateMigrationsJsonAndUpdatePackageJson(root, opts) {
554
+ var _a, _b, _c;
518
555
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
519
556
  const pmc = (0, package_manager_1.getPackageManagerCommand)();
520
557
  try {
558
+ let originalPackageJson = (0, fileutils_1.readJsonFile)((0, path_1.join)(root, 'package.json'));
559
+ if (['nx', '@nrwl/workspace'].includes(opts.targetPackage) &&
560
+ (yield isMigratingToNewMajor((_b = (_a = originalPackageJson.devDependencies) === null || _a === void 0 ? void 0 : _a['nx']) !== null && _b !== void 0 ? _b : (_c = originalPackageJson.devDependencies) === null || _c === void 0 ? void 0 : _c['@nrwl/workspace'], opts.targetVersion))) {
561
+ yield (0, connect_to_nx_cloud_1.connectToNxCloudCommand)('We noticed you are migrating to a new major version, but are not taking advantage of Nx Cloud. Nx Cloud can make your CI up to 10 times faster. Learn more about it here: nx.app. Would you like to add it?');
562
+ originalPackageJson = (0, fileutils_1.readJsonFile)((0, path_1.join)(root, 'package.json'));
563
+ }
521
564
  logger_1.logger.info(`Fetching meta data about packages.`);
522
565
  logger_1.logger.info(`It may take a few minutes.`);
523
- const originalPackageJson = (0, fileutils_1.readJsonFile)((0, path_1.join)(root, 'package.json'));
524
566
  const migrator = new Migrator({
525
567
  packageJson: originalPackageJson,
526
568
  versions: versions(root, opts.from),
527
569
  fetch: createFetcher(),
528
- from: opts.from,
529
570
  to: opts.to,
530
571
  });
531
572
  const { migrations, packageJson } = yield migrator.updatePackageJson(opts.targetPackage, opts.targetVersion);
@@ -544,11 +585,12 @@ function generateMigrationsJsonAndUpdatePackageJson(root, opts) {
544
585
  logger_1.logger.info(`NX Next steps:`);
545
586
  logger_1.logger.info(`- Make sure package.json changes make sense and then run '${pmc.install}'`);
546
587
  if (migrations.length > 0) {
547
- logger_1.logger.info(`- Run 'nx migrate --run-migrations'`);
588
+ logger_1.logger.info(`- Run '${pmc.run('nx', 'migrate --run-migrations')}'`);
548
589
  }
549
590
  logger_1.logger.info(`- To learn more go to https://nx.dev/using-nx/updating-nx`);
550
591
  if (showConnectToCloudMessage()) {
551
- logger_1.logger.info(`- You may run "nx connect-to-nx-cloud" to get faster builds, GitHub integration, and more. Check out https://nx.app`);
592
+ const cmd = pmc.run('nx', 'connect-to-nx-cloud');
593
+ logger_1.logger.info(`- You may run '${cmd}' to get faster builds, GitHub integration, and more. Check out https://nx.app`);
552
594
  }
553
595
  }
554
596
  catch (e) {
@@ -573,14 +615,16 @@ function runInstall() {
573
615
  logger_1.logger.info(`NX Running '${pmCommands.install}' to make sure necessary packages are installed`);
574
616
  (0, child_process_1.execSync)(pmCommands.install, { stdio: [0, 1, 2] });
575
617
  }
576
- function runMigrations(root, opts, isVerbose) {
618
+ const NO_CHANGES = 'NO_CHANGES';
619
+ function runMigrations(root, opts, isVerbose, shouldCreateCommits = false, commitPrefix) {
577
620
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
578
621
  if (!process.env.NX_MIGRATE_SKIP_INSTALL) {
579
622
  runInstall();
580
623
  }
581
- logger_1.logger.info(`NX Running migrations from '${opts.runMigrations}'`);
624
+ logger_1.logger.info(`NX Running migrations from '${opts.runMigrations}'` +
625
+ (shouldCreateCommits ? ', with each applied in a dedicated commit' : ''));
582
626
  const migrations = (0, fileutils_1.readJsonFile)((0, path_1.join)(root, opts.runMigrations)).migrations;
583
- for (let m of migrations) {
627
+ for (const m of migrations) {
584
628
  logger_1.logger.info(`Running migration ${m.name}`);
585
629
  if (m.cli === 'nx') {
586
630
  yield runNxMigration(root, m.package, m.name);
@@ -589,14 +633,79 @@ function runMigrations(root, opts, isVerbose) {
589
633
  yield (yield Promise.resolve().then(() => require('../adapter/ngcli-adapter'))).runMigration(root, m.package, m.name, isVerbose);
590
634
  }
591
635
  logger_1.logger.info(`Successfully finished ${m.name}`);
636
+ if (shouldCreateCommits) {
637
+ const commitMessage = `${commitPrefix}${m.name}`;
638
+ const { sha: committedSha, reasonForNoCommit } = commitChangesIfAny(commitMessage);
639
+ if (committedSha) {
640
+ logger_1.logger.info(chalk.dim(`- Commit created for changes: ${committedSha}`));
641
+ }
642
+ else {
643
+ switch (true) {
644
+ // Isolate the NO_CHANGES case so that we can render it differently to errors
645
+ case reasonForNoCommit === NO_CHANGES:
646
+ logger_1.logger.info(chalk.dim(`- There were no changes to commit`));
647
+ break;
648
+ case typeof reasonForNoCommit === 'string': // Any other string is a specific error we captured
649
+ logger_1.logger.info(chalk.red(`- ${reasonForNoCommit}`));
650
+ break;
651
+ default:
652
+ logger_1.logger.info(chalk.red(`- A commit could not be created/retrieved for an unknown reason`));
653
+ }
654
+ }
655
+ }
592
656
  logger_1.logger.info(`---------------------------------------------------------`);
593
657
  }
594
658
  logger_1.logger.info(`NX Successfully finished running migrations from '${opts.runMigrations}'`);
595
659
  });
596
660
  }
661
+ function commitChangesIfAny(commitMessage) {
662
+ try {
663
+ if ((0, child_process_1.execSync)('git ls-files -m -d -o --exclude-standard').toString() === '') {
664
+ return {
665
+ sha: null,
666
+ reasonForNoCommit: NO_CHANGES,
667
+ };
668
+ }
669
+ }
670
+ catch (err) {
671
+ return {
672
+ sha: null,
673
+ reasonForNoCommit: `Error determining git changes:\n${err.stderr}`,
674
+ };
675
+ }
676
+ try {
677
+ (0, child_process_1.execSync)('git add -A', { encoding: 'utf8', stdio: 'pipe' });
678
+ (0, child_process_1.execSync)('git commit --no-verify -F -', {
679
+ encoding: 'utf8',
680
+ stdio: 'pipe',
681
+ input: commitMessage,
682
+ });
683
+ }
684
+ catch (err) {
685
+ return {
686
+ sha: null,
687
+ reasonForNoCommit: `Error committing changes:\n${err.stderr}`,
688
+ };
689
+ }
690
+ return {
691
+ sha: getLatestCommitSha(),
692
+ reasonForNoCommit: null,
693
+ };
694
+ }
695
+ function getLatestCommitSha() {
696
+ try {
697
+ return (0, child_process_1.execSync)('git rev-parse HEAD', {
698
+ encoding: 'utf8',
699
+ stdio: 'pipe',
700
+ }).trim();
701
+ }
702
+ catch (_a) {
703
+ return null;
704
+ }
705
+ }
597
706
  function runNxMigration(root, packageName, name) {
598
707
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
599
- const collectionPath = packageToMigrationsFilePath(packageName, root);
708
+ const collectionPath = readPackageMigrationConfig(packageName, root).migrations;
600
709
  const collection = (0, fileutils_1.readJsonFile)(collectionPath);
601
710
  const g = collection.generators || collection.schematics;
602
711
  const implRelativePath = g[name].implementation || g[name].factory;
@@ -625,7 +734,7 @@ function migrate(root, args) {
625
734
  yield generateMigrationsJsonAndUpdatePackageJson(root, opts);
626
735
  }
627
736
  else {
628
- yield runMigrations(root, opts, args['verbose']);
737
+ yield runMigrations(root, opts, args['verbose'], args['createCommits'], args['commitPrefix']);
629
738
  }
630
739
  }));
631
740
  });