nx 21.2.1 → 21.2.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nx",
3
- "version": "21.2.1",
3
+ "version": "21.2.2",
4
4
  "private": false,
5
5
  "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.",
6
6
  "repository": {
@@ -83,16 +83,16 @@
83
83
  }
84
84
  },
85
85
  "optionalDependencies": {
86
- "@nx/nx-darwin-arm64": "21.2.1",
87
- "@nx/nx-darwin-x64": "21.2.1",
88
- "@nx/nx-freebsd-x64": "21.2.1",
89
- "@nx/nx-linux-arm-gnueabihf": "21.2.1",
90
- "@nx/nx-linux-arm64-gnu": "21.2.1",
91
- "@nx/nx-linux-arm64-musl": "21.2.1",
92
- "@nx/nx-linux-x64-gnu": "21.2.1",
93
- "@nx/nx-linux-x64-musl": "21.2.1",
94
- "@nx/nx-win32-arm64-msvc": "21.2.1",
95
- "@nx/nx-win32-x64-msvc": "21.2.1"
86
+ "@nx/nx-darwin-arm64": "21.2.2",
87
+ "@nx/nx-darwin-x64": "21.2.2",
88
+ "@nx/nx-freebsd-x64": "21.2.2",
89
+ "@nx/nx-linux-arm-gnueabihf": "21.2.2",
90
+ "@nx/nx-linux-arm64-gnu": "21.2.2",
91
+ "@nx/nx-linux-arm64-musl": "21.2.2",
92
+ "@nx/nx-linux-x64-gnu": "21.2.2",
93
+ "@nx/nx-linux-x64-musl": "21.2.2",
94
+ "@nx/nx-win32-arm64-msvc": "21.2.2",
95
+ "@nx/nx-win32-x64-msvc": "21.2.2"
96
96
  },
97
97
  "nx-migrations": {
98
98
  "migrations": "./migrations.json",
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
+ // TODO(v22): remove this file
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.decorateCli = decorateCli;
4
5
  const fs_1 = require("fs");
5
6
  const output_1 = require("../utils/output");
6
7
  function decorateCli() {
7
8
  output_1.output.warn({
8
- title: `Decoration of the Angular CLI is deprecated and will be removed in a future version`,
9
+ title: `Decoration of the Angular CLI is deprecated and will be removed in Nx v22`,
9
10
  bodyLines: [
10
11
  `Please replace usage of "ng <command>" in any scripts, particularly for CI, with "nx <command>"`,
11
12
  ],
@@ -87,4 +87,15 @@ export declare function wrapAngularDevkitSchematic(collectionName: string, gener
87
87
  [k: string]: any;
88
88
  }) => Promise<GeneratorCallback>;
89
89
  export declare const getLogger: (isVerbose?: boolean) => logging.Logger;
90
+ /**
91
+ * Restores Nx tokens in options when possible by comparing new and previous
92
+ * options.
93
+ * The function preserves tokens in the following cases:
94
+ * 1. When the resolved previous value matches the new value exactly
95
+ * 2. When the previous value used {workspaceRoot}
96
+ * 3. When the previous value used {projectRoot} and the new value starts with
97
+ * the project root path
98
+ * Those are the only safe cases, for all other cases, the new value is used as-is.
99
+ */
100
+ export declare function restoreNxTokensInOptions<T extends Object | Array<unknown>>(newOptions: T, previousOptions: T, project: ProjectConfiguration): T;
90
101
  export {};
@@ -8,6 +8,7 @@ exports.generate = generate;
8
8
  exports.runMigration = runMigration;
9
9
  exports.mockSchematicsForTesting = mockSchematicsForTesting;
10
10
  exports.wrapAngularDevkitSchematic = wrapAngularDevkitSchematic;
11
+ exports.restoreNxTokensInOptions = restoreNxTokensInOptions;
11
12
  const core_1 = require("@angular-devkit/core");
12
13
  const node_1 = require("@angular-devkit/core/node");
13
14
  const chalk = require("chalk");
@@ -28,6 +29,7 @@ const angular_json_1 = require("./angular-json");
28
29
  const executor_utils_1 = require("../command-line/run/executor-utils");
29
30
  const plugins_1 = require("../project-graph/plugins");
30
31
  const schema_utils_1 = require("../config/schema-utils");
32
+ const project_configuration_utils_1 = require("../project-graph/utils/project-configuration-utils");
31
33
  async function createBuilderContext(builderInfo, context) {
32
34
  require('./compat');
33
35
  const fsHost = new NxScopedHostForBuilders(context.root);
@@ -296,10 +298,32 @@ class NxScopedHost extends core_1.virtualFs.ScopedHost {
296
298
  const projects = configV2.projects;
297
299
  const allObservables = [];
298
300
  Object.keys(projects).forEach((projectName) => {
299
- if (projectsInAngularJson.includes(projectName)) {
300
- // ignore updates to angular.json
301
- }
302
- else {
301
+ if (!projectsInAngularJson.includes(projectName)) {
302
+ // Restore tokens in options if they were present before
303
+ const previousProject = existingConfig.projects[projectName];
304
+ const newProject = projects[projectName];
305
+ if (previousProject &&
306
+ newProject.targets &&
307
+ previousProject.targets) {
308
+ for (const [targetName, target] of Object.entries(newProject.targets)) {
309
+ const previousTarget = previousProject.targets[targetName];
310
+ if (target.options &&
311
+ previousTarget &&
312
+ previousTarget.options) {
313
+ target.options = restoreNxTokensInOptions(target.options, previousTarget.options, newProject);
314
+ }
315
+ if (target.configurations &&
316
+ previousTarget &&
317
+ previousTarget.configurations) {
318
+ for (const [configName, config] of Object.entries(target.configurations)) {
319
+ if (previousTarget.configurations[configName]) {
320
+ target.configurations[configName] =
321
+ restoreNxTokensInOptions(config, previousTarget.configurations[configName], newProject);
322
+ }
323
+ }
324
+ }
325
+ }
326
+ }
303
327
  (0, project_configuration_1.updateProjectConfiguration)({
304
328
  root,
305
329
  exists: () => true,
@@ -430,9 +454,23 @@ class NxScopeHostUsedForWrappedSchematics extends NxScopedHost {
430
454
  read(path) {
431
455
  if ((path === 'angular.json' || path === '/angular.json') &&
432
456
  (0, angular_json_1.isAngularPluginInstalled)()) {
433
- const projectJsonConfig = (0, angular_json_1.toOldFormat)({
434
- projects: Object.fromEntries((0, project_configuration_1.getProjects)(this.host)),
435
- });
457
+ // Replace the Nx-specific tokens in all target options
458
+ const projects = Object.fromEntries((0, project_configuration_1.getProjects)(this.host));
459
+ for (const [projectName, project] of Object.entries(projects)) {
460
+ if (project.targets) {
461
+ for (const [targetName, target] of Object.entries(project.targets)) {
462
+ if (target.options) {
463
+ target.options = (0, project_configuration_utils_1.resolveNxTokensInOptions)(target.options, { ...project, name: projectName }, `${projectName}:${targetName}`);
464
+ }
465
+ if (target.configurations) {
466
+ for (const [configName, config] of Object.entries(target.configurations)) {
467
+ target.configurations[configName] = (0, project_configuration_utils_1.resolveNxTokensInOptions)(config, { ...project, name: projectName }, `${projectName}:${targetName}:${configName}`);
468
+ }
469
+ }
470
+ }
471
+ }
472
+ }
473
+ const projectJsonConfig = (0, angular_json_1.toOldFormat)({ projects });
436
474
  return super.readExistingAngularJson().pipe((0, operators_1.map)((angularJson) => {
437
475
  if (angularJson) {
438
476
  return Buffer.from(JSON.stringify({
@@ -852,3 +890,59 @@ async function getWrappedWorkspaceNodeModulesArchitectHost(workspace, root, proj
852
890
  }
853
891
  return new WrappedWorkspaceNodeModulesArchitectHost(workspace, root, projects);
854
892
  }
893
+ /**
894
+ * Restores Nx tokens in options when possible by comparing new and previous
895
+ * options.
896
+ * The function preserves tokens in the following cases:
897
+ * 1. When the resolved previous value matches the new value exactly
898
+ * 2. When the previous value used {workspaceRoot}
899
+ * 3. When the previous value used {projectRoot} and the new value starts with
900
+ * the project root path
901
+ * Those are the only safe cases, for all other cases, the new value is used as-is.
902
+ */
903
+ function restoreNxTokensInOptions(newOptions, previousOptions, project) {
904
+ if (!newOptions || !previousOptions) {
905
+ return newOptions;
906
+ }
907
+ const result = Array.isArray(newOptions)
908
+ ? [...newOptions]
909
+ : { ...newOptions };
910
+ const resolvedPreviousOptions = (0, project_configuration_utils_1.resolveNxTokensInOptions)(previousOptions, project, '');
911
+ for (const key of Object.keys(newOptions)) {
912
+ const newValue = newOptions[key];
913
+ const previousValue = previousOptions[key];
914
+ if (typeof newValue === 'string' && typeof previousValue === 'string') {
915
+ if (resolvedPreviousOptions[key] === newValue) {
916
+ // If the resolved previous value matches the new value, use the previous
917
+ // value (potentially with tokens)
918
+ result[key] = previousValue;
919
+ }
920
+ else if (previousValue.startsWith('{workspaceRoot}/')) {
921
+ // If the previous value started with {workspaceRoot}, prefix the new
922
+ // value with {workspaceRoot}
923
+ result[key] = `{workspaceRoot}/${newValue.replace(/^\//, '')}`;
924
+ }
925
+ else if (previousValue.startsWith('{projectRoot}/') &&
926
+ newValue.startsWith(`${project.root}/`)) {
927
+ // If the previous value started with {projectRoot} and the new value
928
+ // starts with the project root, replace the project root with the
929
+ // {projectRoot} token
930
+ result[key] = newValue.replace(`${project.root}/`, '{projectRoot}/');
931
+ }
932
+ else {
933
+ // Otherwise, use the new value as-is
934
+ result[key] = newValue;
935
+ }
936
+ }
937
+ else if (typeof newValue === 'object' &&
938
+ typeof previousValue === 'object' &&
939
+ newValue &&
940
+ previousValue) {
941
+ result[key] = restoreNxTokensInOptions(newValue, previousValue, project);
942
+ }
943
+ else {
944
+ result[key] = newValue;
945
+ }
946
+ }
947
+ return result;
948
+ }
@@ -1,7 +1,7 @@
1
1
  import type { MigrationDetailsWithId } from '../../config/misc-interfaces';
2
2
  import type { FileChange } from '../../generators/tree';
3
3
  export type MigrationsJsonMetadata = {
4
- completedMigrations?: Record<string, SuccessfulMigration | FailedMigration | SkippedMigration>;
4
+ completedMigrations?: Record<string, SuccessfulMigration | FailedMigration | SkippedMigration | StoppedMigration>;
5
5
  runningMigrations?: string[];
6
6
  initialGitRef?: {
7
7
  ref: string;
@@ -25,6 +25,11 @@ export type FailedMigration = {
25
25
  export type SkippedMigration = {
26
26
  type: 'skipped';
27
27
  };
28
+ export type StoppedMigration = {
29
+ type: 'stopped';
30
+ name: string;
31
+ error: string;
32
+ };
28
33
  export declare function recordInitialMigrationMetadata(workspacePath: string, versionToMigrateTo: string): void;
29
34
  export declare function finishMigrationProcess(workspacePath: string, squashCommits: boolean, commitMessage: string): void;
30
35
  export declare function runSingleMigration(workspacePath: string, migration: MigrationDetailsWithId, configuration: {
@@ -36,7 +41,7 @@ export declare function modifyMigrationsJsonMetadata(workspacePath: string, modi
36
41
  export declare function addSuccessfulMigration(id: string, fileChanges: Omit<FileChange, 'content'>[], ref: string, nextSteps: string[]): (migrationsJsonMetadata: MigrationsJsonMetadata) => MigrationsJsonMetadata;
37
42
  export declare function updateRefForSuccessfulMigration(id: string, ref: string): (migrationsJsonMetadata: MigrationsJsonMetadata) => MigrationsJsonMetadata;
38
43
  export declare function addFailedMigration(id: string, error: string): (migrationsJsonMetadata: MigrationsJsonMetadata) => {
39
- completedMigrations?: Record<string, SuccessfulMigration | FailedMigration | SkippedMigration>;
44
+ completedMigrations?: Record<string, SuccessfulMigration | FailedMigration | SkippedMigration | StoppedMigration>;
40
45
  runningMigrations?: string[];
41
46
  initialGitRef?: {
42
47
  ref: string;
@@ -46,7 +51,17 @@ export declare function addFailedMigration(id: string, error: string): (migratio
46
51
  targetVersion?: string;
47
52
  };
48
53
  export declare function addSkippedMigration(id: string): (migrationsJsonMetadata: MigrationsJsonMetadata) => {
49
- completedMigrations?: Record<string, SuccessfulMigration | FailedMigration | SkippedMigration>;
54
+ completedMigrations?: Record<string, SuccessfulMigration | FailedMigration | SkippedMigration | StoppedMigration>;
55
+ runningMigrations?: string[];
56
+ initialGitRef?: {
57
+ ref: string;
58
+ subject: string;
59
+ };
60
+ confirmedPackageUpdates?: boolean;
61
+ targetVersion?: string;
62
+ };
63
+ export declare function addStoppedMigration(id: string, error: string): (migrationsJsonMetadata: MigrationsJsonMetadata) => {
64
+ completedMigrations?: Record<string, SuccessfulMigration | FailedMigration | SkippedMigration | StoppedMigration>;
50
65
  runningMigrations?: string[];
51
66
  initialGitRef?: {
52
67
  ref: string;
@@ -57,3 +72,5 @@ export declare function addSkippedMigration(id: string): (migrationsJsonMetadata
57
72
  };
58
73
  export declare function readMigrationsJsonMetadata(workspacePath: string): MigrationsJsonMetadata;
59
74
  export declare function undoMigration(workspacePath: string, id: string): (migrationsJsonMetadata: MigrationsJsonMetadata) => MigrationsJsonMetadata;
75
+ export declare function killMigrationProcess(migrationId: string, workspacePath?: string): boolean;
76
+ export declare function stopMigration(migrationId: string): (migrationsJsonMetadata: MigrationsJsonMetadata) => MigrationsJsonMetadata;
@@ -9,12 +9,18 @@ exports.addSuccessfulMigration = addSuccessfulMigration;
9
9
  exports.updateRefForSuccessfulMigration = updateRefForSuccessfulMigration;
10
10
  exports.addFailedMigration = addFailedMigration;
11
11
  exports.addSkippedMigration = addSkippedMigration;
12
+ exports.addStoppedMigration = addStoppedMigration;
12
13
  exports.readMigrationsJsonMetadata = readMigrationsJsonMetadata;
13
14
  exports.undoMigration = undoMigration;
15
+ exports.killMigrationProcess = killMigrationProcess;
16
+ exports.stopMigration = stopMigration;
14
17
  const child_process_1 = require("child_process");
15
18
  const fs_1 = require("fs");
16
19
  const path_1 = require("path");
17
20
  const migrate_1 = require("./migrate");
21
+ let currentMigrationProcess = null;
22
+ let currentMigrationId = null;
23
+ let migrationCancelled = false;
18
24
  function recordInitialMigrationMetadata(workspacePath, versionToMigrateTo) {
19
25
  const migrationsJsonPath = (0, path_1.join)(workspacePath, 'migrations.json');
20
26
  const parsedMigrationsJson = JSON.parse((0, fs_1.readFileSync)(migrationsJsonPath, 'utf-8'));
@@ -63,20 +69,62 @@ function finishMigrationProcess(workspacePath, squashCommits, commitMessage) {
63
69
  }
64
70
  async function runSingleMigration(workspacePath, migration, configuration) {
65
71
  try {
72
+ // Set current migration tracking
73
+ currentMigrationId = migration.id;
74
+ migrationCancelled = false;
66
75
  modifyMigrationsJsonMetadata(workspacePath, addRunningMigration(migration.id));
67
76
  const gitRefBefore = (0, child_process_1.execSync)('git rev-parse HEAD', {
68
77
  cwd: workspacePath,
69
78
  encoding: 'utf-8',
70
79
  }).trim();
71
- // For Migrate UI, this current module is loaded either from:
72
- // 1. The CLI path to the migrated modules. The version of Nx is of the user's choosing. This may or may not have the new migrate API, so Console will check that `runSingleMigration` exists before using it.
73
- // 2. Bundled into Console, so the version is fixed to what we build Console with.
74
- const updatedMigrateModule = await Promise.resolve().then(() => require('./migrate.js'));
75
- const { changes: fileChanges, nextSteps } = await updatedMigrateModule.runNxOrAngularMigration(workspacePath, migration, false, configuration.createCommits, configuration.commitPrefix || 'chore: [nx migration] ', undefined, true);
76
- const gitRefAfter = (0, child_process_1.execSync)('git rev-parse HEAD', {
80
+ // Run migration in a separate process so it can be cancelled
81
+ const runMigrationProcessPath = require.resolve('./run-migration-process.js');
82
+ const migrationProcess = (0, child_process_1.spawn)('node', [
83
+ runMigrationProcessPath,
84
+ workspacePath,
85
+ migration.id,
86
+ migration.package,
87
+ migration.name,
88
+ migration.version,
89
+ configuration.createCommits.toString(),
90
+ configuration.commitPrefix || 'chore: [nx migration] ',
91
+ ], {
77
92
  cwd: workspacePath,
78
- encoding: 'utf-8',
79
- }).trim();
93
+ stdio: ['pipe', 'pipe', 'pipe'],
94
+ });
95
+ // Track the process for cancellation
96
+ currentMigrationProcess = migrationProcess;
97
+ // Handle process output
98
+ let output = '';
99
+ migrationProcess.stdout.on('data', (data) => {
100
+ output += data.toString();
101
+ });
102
+ migrationProcess.stderr.on('data', (data) => {
103
+ console.error('Migration stderr:', data.toString());
104
+ });
105
+ // Wait for the process to complete
106
+ const exitCode = await new Promise((resolve, reject) => {
107
+ migrationProcess.on('close', (code) => {
108
+ resolve(code);
109
+ });
110
+ migrationProcess.on('error', (error) => {
111
+ reject(error);
112
+ });
113
+ });
114
+ currentMigrationProcess = null;
115
+ if (exitCode !== 0) {
116
+ throw new Error(`Migration process exited with code ${exitCode}`);
117
+ }
118
+ // Parse the result from the migration process (extract the JSON output)
119
+ const jsonStr = output
120
+ .trim()
121
+ .split('\n')
122
+ .find((line) => line.startsWith('{'));
123
+ const result = JSON.parse(jsonStr);
124
+ if (result.type === 'error') {
125
+ throw new Error(result.message);
126
+ }
127
+ const { fileChanges, gitRefAfter, nextSteps } = result;
80
128
  modifyMigrationsJsonMetadata(workspacePath, addSuccessfulMigration(migration.id, fileChanges.map((change) => ({
81
129
  path: change.path,
82
130
  type: change.type,
@@ -99,9 +147,21 @@ async function runSingleMigration(workspacePath, migration, configuration) {
99
147
  }
100
148
  }
101
149
  catch (e) {
102
- modifyMigrationsJsonMetadata(workspacePath, addFailedMigration(migration.id, e.message));
150
+ // Check if migration was cancelled/stopped
151
+ if (migrationCancelled && currentMigrationId === migration.id) {
152
+ // Migration was stopped by user, don't add as failed since it's already marked as stopped
153
+ console.log(`Migration ${migration.id} was stopped by user`);
154
+ }
155
+ else {
156
+ // Migration failed normally
157
+ modifyMigrationsJsonMetadata(workspacePath, addFailedMigration(migration.id, e.message));
158
+ }
103
159
  }
104
160
  finally {
161
+ // Clear the tracking variables
162
+ currentMigrationProcess = null;
163
+ currentMigrationId = null;
164
+ migrationCancelled = false;
105
165
  modifyMigrationsJsonMetadata(workspacePath, removeRunningMigration(migration.id));
106
166
  (0, child_process_1.execSync)('git add migrations.json', {
107
167
  cwd: workspacePath,
@@ -187,6 +247,23 @@ function addSkippedMigration(id) {
187
247
  return copied;
188
248
  };
189
249
  }
250
+ function addStoppedMigration(id, error) {
251
+ return (migrationsJsonMetadata) => {
252
+ const copied = { ...migrationsJsonMetadata };
253
+ if (!copied.completedMigrations) {
254
+ copied.completedMigrations = {};
255
+ }
256
+ copied.completedMigrations = {
257
+ ...copied.completedMigrations,
258
+ [id]: {
259
+ type: 'stopped',
260
+ name: id,
261
+ error,
262
+ },
263
+ };
264
+ return copied;
265
+ };
266
+ }
190
267
  function addRunningMigration(id) {
191
268
  return (migrationsJsonMetadata) => {
192
269
  migrationsJsonMetadata.runningMigrations = [
@@ -200,9 +277,6 @@ function removeRunningMigration(id) {
200
277
  return (migrationsJsonMetadata) => {
201
278
  migrationsJsonMetadata.runningMigrations =
202
279
  migrationsJsonMetadata.runningMigrations?.filter((n) => n !== id);
203
- if (migrationsJsonMetadata.runningMigrations?.length === 0) {
204
- delete migrationsJsonMetadata.runningMigrations;
205
- }
206
280
  return migrationsJsonMetadata;
207
281
  };
208
282
  }
@@ -226,3 +300,32 @@ function undoMigration(workspacePath, id) {
226
300
  return migrationsJsonMetadata;
227
301
  };
228
302
  }
303
+ function killMigrationProcess(migrationId, workspacePath) {
304
+ try {
305
+ if (workspacePath) {
306
+ modifyMigrationsJsonMetadata(workspacePath, stopMigration(migrationId));
307
+ }
308
+ // Check if this is the currently running migration and kill the process
309
+ if (currentMigrationId === migrationId && currentMigrationProcess) {
310
+ currentMigrationProcess.kill('SIGTERM');
311
+ // Some processes may not respond to SIGTERM immediately,
312
+ // so we give it a short timeout before forcefully killing it
313
+ setTimeout(() => {
314
+ if (currentMigrationProcess && !currentMigrationProcess.killed) {
315
+ currentMigrationProcess.kill('SIGKILL');
316
+ }
317
+ }, 2000);
318
+ }
319
+ return true;
320
+ }
321
+ catch (error) {
322
+ console.error(`Failed to stop migration ${migrationId}:`, error);
323
+ return false;
324
+ }
325
+ }
326
+ function stopMigration(migrationId) {
327
+ return (migrationsJsonMetadata) => {
328
+ const updated = addStoppedMigration(migrationId, 'Migration was stopped by user')(migrationsJsonMetadata);
329
+ return removeRunningMigration(migrationId)(updated);
330
+ };
331
+ }
@@ -0,0 +1,85 @@
1
+ const { runNxOrAngularMigration } = require('./migrate');
2
+ const { execSync } = require('child_process');
3
+
4
+ async function runMigrationProcess() {
5
+ const [
6
+ ,
7
+ ,
8
+ workspacePath,
9
+ migrationId,
10
+ migrationPackage,
11
+ migrationName,
12
+ migrationVersion,
13
+ createCommits,
14
+ commitPrefix,
15
+ ] = process.argv;
16
+
17
+ const migration = {
18
+ id: migrationId,
19
+ package: migrationPackage,
20
+ name: migrationName,
21
+ version: migrationVersion,
22
+ };
23
+
24
+ const configuration = {
25
+ createCommits: createCommits === 'true',
26
+ commitPrefix: commitPrefix || 'chore: [nx migration] ',
27
+ };
28
+
29
+ try {
30
+ const gitRefBefore = execSync('git rev-parse HEAD', {
31
+ cwd: workspacePath,
32
+ encoding: 'utf-8',
33
+ }).trim();
34
+
35
+ const { changes: fileChanges, nextSteps } = await runNxOrAngularMigration(
36
+ workspacePath,
37
+ migration,
38
+ false,
39
+ configuration.createCommits,
40
+ configuration.commitPrefix,
41
+ undefined,
42
+ true
43
+ );
44
+
45
+ const gitRefAfter = execSync('git rev-parse HEAD', {
46
+ cwd: workspacePath,
47
+ encoding: 'utf-8',
48
+ }).trim();
49
+
50
+ // Report success
51
+ process.stdout.write(
52
+ JSON.stringify({
53
+ type: 'success',
54
+ fileChanges: fileChanges.map((change) => ({
55
+ path: change.path,
56
+ type: change.type,
57
+ })),
58
+ gitRefAfter,
59
+ nextSteps,
60
+ })
61
+ );
62
+
63
+ process.exit(0);
64
+ } catch (error) {
65
+ // Report failure
66
+ process.stdout.write(
67
+ JSON.stringify({
68
+ type: 'error',
69
+ message: error.message,
70
+ })
71
+ );
72
+
73
+ process.exit(1);
74
+ }
75
+ }
76
+
77
+ runMigrationProcess().catch((error) => {
78
+ process.stdout.write(
79
+ JSON.stringify({
80
+ type: 'error',
81
+ message: error.message,
82
+ })
83
+ );
84
+ process.exit(1);
85
+ });