create-nx-workspace 22.3.0-canary.20251211-205daee → 22.3.0-canary.20251215-e864b6a

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.
@@ -40,6 +40,7 @@ interface AngularArguments extends BaseArguments {
40
40
  bundler: 'webpack' | 'rspack' | 'esbuild';
41
41
  ssr: boolean;
42
42
  prefix: string;
43
+ zoneless: boolean;
43
44
  }
44
45
  interface VueArguments extends BaseArguments {
45
46
  stack: 'vue';
@@ -1 +1 @@
1
- {"version":3,"file":"create-nx-workspace.d.ts","sourceRoot":"","sources":["../../../../packages/create-nx-workspace/bin/create-nx-workspace.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EACL,sBAAsB,EAEvB,MAAM,iCAAiC,CAAC;AAKzC,OAAO,EAAiB,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAmCnE,UAAU,aAAc,SAAQ,sBAAsB;IACpD,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IAChC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,UAAU,aAAc,SAAQ,aAAa;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,eAAe,GAAG,YAAY,GAAG,YAAY,CAAC;IAC9D,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B;AAED,UAAU,cAAe,SAAQ,aAAa;IAC5C,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,EAAE,YAAY,GAAG,YAAY,CAAC;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;IACvC,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,cAAc,EAAE,OAAO,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC3C,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,YAAY,CAAC;CAClD;AAED,UAAU,gBAAiB,SAAQ,aAAa;IAC9C,KAAK,EAAE,SAAS,CAAC;IACjB,aAAa,EAAE,YAAY,GAAG,YAAY,CAAC;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC3C,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,YAAY,CAAC;IACjD,OAAO,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC1C,GAAG,EAAE,OAAO,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,YAAa,SAAQ,aAAa;IAC1C,KAAK,EAAE,KAAK,CAAC;IACb,aAAa,EAAE,YAAY,GAAG,YAAY,CAAC;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,GAAG,QAAQ,CAAC;IAClC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,YAAY,CAAC;CAClD;AAED,UAAU,aAAc,SAAQ,aAAa;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,YAAY,GAAG,YAAY,CAAC;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,KAAK,GAAG,MAAM,CAAC;IAC3D,MAAM,EAAE,OAAO,CAAC;IAChB,cAAc,EAAE,MAAM,GAAG,MAAM,CAAC;CACjC;AAED,UAAU,qBAAsB,SAAQ,aAAa;IACnD,KAAK,EAAE,SAAS,CAAC;CAClB;AAED,KAAK,SAAS,GACV,aAAa,GACb,cAAc,GACd,gBAAgB,GAChB,YAAY,GACZ,aAAa,GACb,qBAAqB,CAAC;AAE1B,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,IAAI,CAAC,SAAS,CA8IrB,CAAC;AA2L7B,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAaxD"}
1
+ {"version":3,"file":"create-nx-workspace.d.ts","sourceRoot":"","sources":["../../../../packages/create-nx-workspace/bin/create-nx-workspace.ts"],"names":[],"mappings":"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"}
@@ -12,14 +12,31 @@ const output_1 = require("../src/utils/output");
12
12
  const nx_version_1 = require("../src/utils/nx/nx-version");
13
13
  const decorator_1 = require("./decorator");
14
14
  const get_third_party_preset_1 = require("../src/utils/preset/get-third-party-preset");
15
+ const package_manager_1 = require("../src/utils/package-manager");
15
16
  const prompts_1 = require("../src/internal-utils/prompts");
16
17
  const yargs_options_1 = require("../src/internal-utils/yargs-options");
17
18
  const ab_testing_1 = require("../src/utils/nx/ab-testing");
18
19
  const error_utils_1 = require("../src/utils/error-utils");
19
20
  const fs_1 = require("fs");
20
21
  const is_ci_1 = require("../src/utils/ci/is-ci");
22
+ function extractErrorFile(error) {
23
+ if (!error.stack)
24
+ return undefined;
25
+ const lines = error.stack.split('\n');
26
+ // Find the first line with a file path (typically line 1 after the error message)
27
+ const fileLine = lines.find((line) => line.includes('at ') && line.includes('/'));
28
+ if (!fileLine)
29
+ return undefined;
30
+ // Extract just the file path portion
31
+ const match = fileLine.match(/\(([^)]+)\)/) || fileLine.match(/at\s+(.+)/);
32
+ return match?.[1]?.trim();
33
+ }
21
34
  // For template-based CNW we want to know if user picked empty vs react vs angular etc.
22
35
  let chosenTemplate;
36
+ // Also track old custom presets so we know which ones users want.
37
+ let chosenPreset;
38
+ // Track whether user opted into cloud or not for SIGINT handler.
39
+ let useCloud;
23
40
  exports.commandsObject = yargs
24
41
  .wrap(yargs.terminalWidth())
25
42
  .parserConfiguration({
@@ -123,18 +140,48 @@ exports.commandsObject = yargs
123
140
  .option('prefix', {
124
141
  describe: chalk.dim `Prefix to use for Angular component and directive selectors.`,
125
142
  type: 'string',
143
+ })
144
+ .option('zoneless', {
145
+ describe: chalk.dim `Generate an application that does not use 'zone.js'.`,
146
+ type: 'boolean',
147
+ default: true,
126
148
  })
127
149
  .option('aiAgents', {
128
150
  describe: chalk.dim `List of AI agents to configure.`,
129
151
  type: 'array',
130
152
  choices: [...create_workspace_options_1.supportedAgents],
131
153
  }), yargs_options_1.withNxCloud, yargs_options_1.withUseGitHub, yargs_options_1.withAllPrompts, yargs_options_1.withPackageManager, yargs_options_1.withGitOptions), async function handler(argv) {
132
- await main(argv).catch((error) => {
154
+ await main(argv).catch(async (error) => {
133
155
  const { version } = require('../package.json');
134
- output_1.output.error({
135
- title: `Failed to create workspace (v${version})`,
136
- bodyLines: (0, error_utils_1.mapErrorToBodyLines)(error),
156
+ // Record error stat for telemetry
157
+ const errorCode = error instanceof error_utils_1.CnwError ? error.code : 'UNKNOWN';
158
+ const errorMessage = error instanceof Error ? error.message : String(error);
159
+ const errorFile = error instanceof Error ? extractErrorFile(error) : undefined;
160
+ useCloud = argv.nxCloud !== 'skip';
161
+ await (0, ab_testing_1.recordStat)({
162
+ nxVersion: nx_version_1.nxVersion,
163
+ command: 'create-nx-workspace',
164
+ useCloud,
165
+ meta: {
166
+ type: 'error',
167
+ flowVariant: (0, ab_testing_1.getFlowVariant)(),
168
+ errorCode,
169
+ errorMessage,
170
+ errorFile,
171
+ },
137
172
  });
173
+ if (error instanceof error_utils_1.CnwError) {
174
+ output_1.output.error({
175
+ title: `Failed to create workspace`,
176
+ bodyLines: error.message.split('\n').filter((line) => line.trim()),
177
+ });
178
+ }
179
+ else {
180
+ output_1.output.error({
181
+ title: `Failed to create workspace (v${version})`,
182
+ bodyLines: (0, error_utils_1.mapErrorToBodyLines)(error),
183
+ });
184
+ }
138
185
  process.exit(1);
139
186
  });
140
187
  }, [normalizeArgsMiddleware])
@@ -152,7 +199,7 @@ process.on('uncaughtException', (error) => {
152
199
  throw error;
153
200
  });
154
201
  // Handle Ctrl+C gracefully - show helpful message if workspace was already created
155
- process.on('SIGINT', () => {
202
+ process.on('SIGINT', async () => {
156
203
  const { directory, connectUrl } = (0, create_workspace_1.getInterruptedWorkspaceState)();
157
204
  if (directory) {
158
205
  console.log(''); // New line after ^C
@@ -181,18 +228,18 @@ async function main(parsedArgs) {
181
228
  nxVersion: nx_version_1.nxVersion,
182
229
  command: 'create-nx-workspace',
183
230
  useCloud: parsedArgs.nxCloud !== 'skip',
184
- meta: [
185
- // User sees one of: setupCI (preset flow) or setupNxCloudV2 (template flow)
186
- ab_testing_1.messages.codeOfSelectedPromptMessage('setupCI'),
187
- // User sees one of: setupNxCloud (preset flow) or setupNxCloudV2 (template flow)
188
- ab_testing_1.messages.codeOfSelectedPromptMessage('setupNxCloudV2') ||
231
+ meta: {
232
+ type: 'complete',
233
+ flowVariant: (0, ab_testing_1.getFlowVariant)(),
234
+ setupCIPrompt: ab_testing_1.messages.codeOfSelectedPromptMessage('setupCI'),
235
+ setupCloudPrompt: ab_testing_1.messages.codeOfSelectedPromptMessage('setupNxCloudV2') ||
189
236
  ab_testing_1.messages.codeOfSelectedPromptMessage('setupNxCloud'),
190
- parsedArgs.nxCloud,
191
- rawArgs.nxCloud,
192
- workspaceInfo.pushedToVcs,
193
- chosenTemplate,
194
- `flow-variant-${(0, ab_testing_1.getFlowVariant)()}`,
195
- ],
237
+ nxCloudArg: parsedArgs.nxCloud ?? '',
238
+ nxCloudArgRaw: rawArgs.nxCloud ?? '',
239
+ pushedToVcs: workspaceInfo.pushedToVcs ?? '',
240
+ template: chosenTemplate ?? '',
241
+ preset: chosenPreset ?? '',
242
+ },
196
243
  });
197
244
  if (parsedArgs.nxCloud && workspaceInfo.nxCloudInfo) {
198
245
  process.stdout.write(workspaceInfo.nxCloudInfo);
@@ -218,20 +265,21 @@ async function normalizeArgsMiddleware(argv) {
218
265
  });
219
266
  argv.workspaces ??= true;
220
267
  argv.useProjectJson ??= !argv.workspaces;
221
- // Old (start) vs new (start-v2) flows
222
- const startVariant = (0, ab_testing_1.getFlowVariant)() === '1' ? 'start-v2' : 'start';
223
268
  await (0, ab_testing_1.recordStat)({
224
269
  nxVersion: nx_version_1.nxVersion,
225
270
  command: 'create-nx-workspace',
226
- meta: [startVariant],
227
271
  useCloud: argv.nxCloud !== 'skip',
272
+ meta: {
273
+ type: 'start',
274
+ flowVariant: (0, ab_testing_1.getFlowVariant)(),
275
+ },
228
276
  });
229
277
  try {
230
278
  argv.name = await determineFolder(argv);
231
279
  const template = await (0, prompts_1.determineTemplate)(argv);
232
280
  chosenTemplate = template;
233
281
  if (template !== 'custom') {
234
- // Template flow - uses npm and 'main' branch by default
282
+ // Template flow - uses detected package manager (from invoking command) and 'main' branch by default
235
283
  argv.template = template;
236
284
  const aiAgents = await (0, prompts_1.determineAiAgents)(argv);
237
285
  const nxCloud = argv.skipGit === true ? 'skip' : await (0, prompts_1.determineNxCloudV2)(argv);
@@ -242,7 +290,7 @@ async function normalizeArgsMiddleware(argv) {
242
290
  nxCloud,
243
291
  useGitHub: nxCloud !== 'skip',
244
292
  completionMessageKey,
245
- packageManager: 'npm',
293
+ packageManager: (0, package_manager_1.detectInvokedPackageManager)(),
246
294
  defaultBase: 'main',
247
295
  aiAgents,
248
296
  });
@@ -259,16 +307,8 @@ async function normalizeArgsMiddleware(argv) {
259
307
  (0, get_third_party_preset_1.getPackageNameFromThirdPartyPreset)(argv.preset);
260
308
  }
261
309
  catch (e) {
262
- if (e instanceof Error) {
263
- output_1.output.error({
264
- title: `Could not find preset "${argv.preset}"`,
265
- bodyLines: (0, error_utils_1.mapErrorToBodyLines)(e),
266
- });
267
- }
268
- else {
269
- console.error(e);
270
- }
271
- process.exit(1);
310
+ const message = e instanceof Error ? e.message : String(e);
311
+ throw new error_utils_1.CnwError('INVALID_PRESET', `Could not find preset "${argv.preset}": ${message}`);
272
312
  }
273
313
  }
274
314
  const packageManager = await (0, prompts_1.determinePackageManager)(argv);
@@ -285,17 +325,20 @@ async function normalizeArgsMiddleware(argv) {
285
325
  defaultBase,
286
326
  aiAgents,
287
327
  });
328
+ chosenPreset = argv.preset;
288
329
  }
289
330
  }
290
331
  catch (e) {
291
- console.error(e);
292
- process.exit(1);
332
+ if (e instanceof error_utils_1.CnwError) {
333
+ throw e;
334
+ }
335
+ const message = e instanceof Error ? e.message : String(e);
336
+ throw new error_utils_1.CnwError('UNKNOWN', message);
293
337
  }
294
338
  }
295
- function invariant(predicate, message) {
339
+ function invariant(predicate, errorCode, message) {
296
340
  if (!predicate) {
297
- output_1.output.error(message);
298
- process.exit(1);
341
+ throw new error_utils_1.CnwError(errorCode, message);
299
342
  }
300
343
  }
301
344
  function validateWorkspaceName(name) {
@@ -329,14 +372,9 @@ async function determineFolder(parsedArgs) {
329
372
  skip: !parsedArgs.interactive || (0, is_ci_1.isCI)(),
330
373
  },
331
374
  ]);
332
- invariant(reply.folderName, {
333
- title: 'Invalid folder name',
334
- bodyLines: [`Folder name cannot be empty`],
335
- });
375
+ invariant(reply.folderName, 'INVALID_FOLDER_NAME', 'Folder name cannot be empty');
336
376
  validateWorkspaceName(reply.folderName);
337
- invariant(!(0, fs_1.existsSync)(reply.folderName), {
338
- title: 'That folder is already taken',
339
- });
377
+ invariant(!(0, fs_1.existsSync)(reply.folderName), 'DIRECTORY_EXISTS', `The folder '${reply.folderName}' already exists`);
340
378
  return reply.folderName;
341
379
  }
342
380
  async function determineStack(parsedArgs) {
@@ -795,18 +833,13 @@ async function determineAngularOptions(parsedArgs) {
795
833
  const standaloneApi = parsedArgs.standaloneApi;
796
834
  const routing = parsedArgs.routing;
797
835
  const prefix = parsedArgs.prefix;
836
+ const zoneless = parsedArgs.zoneless;
798
837
  if (prefix) {
799
838
  // https://github.com/angular/angular-cli/blob/main/packages/schematics/angular/utility/validation.ts#L11-L14
800
839
  const htmlSelectorRegex = /^[a-zA-Z][.0-9a-zA-Z]*((:?-[0-9]+)*|(:?-[a-zA-Z][.0-9a-zA-Z]*(:?-[0-9]+)*)*)$/;
801
840
  // validate whether component/directive selectors will be valid with the provided prefix
802
841
  if (!htmlSelectorRegex.test(`${prefix}-placeholder`)) {
803
- output_1.output.error({
804
- title: `Failed to create a workspace.`,
805
- bodyLines: [
806
- `The provided "${prefix}" prefix is invalid. It must be a valid HTML selector.`,
807
- ],
808
- });
809
- process.exit(1);
842
+ throw new error_utils_1.CnwError('ANGULAR_PREFIX_INVALID', `The provided "${prefix}" prefix is invalid. It must be a valid HTML selector.`);
810
843
  }
811
844
  }
812
845
  if (parsedArgs.preset && parsedArgs.preset !== preset_1.Preset.Angular) {
@@ -918,6 +951,7 @@ async function determineAngularOptions(parsedArgs) {
918
951
  bundler,
919
952
  ssr,
920
953
  prefix,
954
+ zoneless,
921
955
  };
922
956
  }
923
957
  async function determineNodeOptions(parsedArgs) {
@@ -1031,12 +1065,7 @@ async function determinePackageBasedOrIntegratedOrStandalone() {
1031
1065
  ],
1032
1066
  },
1033
1067
  ]);
1034
- invariant(workspaceType, {
1035
- title: 'Invalid workspace type',
1036
- bodyLines: [
1037
- `It must be one of the following: standalone, integrated. Got ${workspaceType}`,
1038
- ],
1039
- });
1068
+ invariant(workspaceType, 'INVALID_WORKSPACE_TYPE', `Invalid workspace type. It must be one of the following: standalone, integrated. Got ${workspaceType}`);
1040
1069
  return workspaceType;
1041
1070
  }
1042
1071
  async function determineStandaloneOrMonorepo() {
@@ -1058,12 +1087,7 @@ async function determineStandaloneOrMonorepo() {
1058
1087
  ],
1059
1088
  },
1060
1089
  ]);
1061
- invariant(workspaceType, {
1062
- title: 'Invalid workspace type',
1063
- bodyLines: [
1064
- `It must be one of the following: standalone, integrated. Got ${workspaceType}`,
1065
- ],
1066
- });
1090
+ invariant(workspaceType, 'INVALID_WORKSPACE_TYPE', `Invalid workspace type. It must be one of the following: standalone, integrated. Got ${workspaceType}`);
1067
1091
  return workspaceType;
1068
1092
  }
1069
1093
  async function determineAppName(parsedArgs) {
@@ -1078,10 +1102,7 @@ async function determineAppName(parsedArgs) {
1078
1102
  skip: !parsedArgs.interactive || (0, is_ci_1.isCI)(),
1079
1103
  },
1080
1104
  ]);
1081
- invariant(appName, {
1082
- title: 'Invalid name',
1083
- bodyLines: [`Name cannot be empty`],
1084
- });
1105
+ invariant(appName, 'INVALID_APP_NAME', 'App name cannot be empty');
1085
1106
  return appName;
1086
1107
  }
1087
1108
  async function determineReactFramework(parsedArgs) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-nx-workspace",
3
- "version": "22.3.0-canary.20251211-205daee",
3
+ "version": "22.3.0-canary.20251215-e864b6a",
4
4
  "private": false,
5
5
  "description": "Smart Repos · Fast Builds",
6
6
  "repository": {
@@ -1 +1 @@
1
- {"version":3,"file":"create-empty-workspace.d.ts","sourceRoot":"","sources":["../../../../packages/create-nx-workspace/src/create-empty-workspace.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAIpE,OAAO,EAGL,cAAc,EACf,MAAM,yBAAyB,CAAC;AAGjC;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CAAC,CAAC,SAAS,sBAAsB,EACzE,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,cAAc,EAC9B,OAAO,EAAE,CAAC,GACT,OAAO,CAAC,MAAM,CAAC,CAiEjB"}
1
+ {"version":3,"file":"create-empty-workspace.d.ts","sourceRoot":"","sources":["../../../../packages/create-nx-workspace/src/create-empty-workspace.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAGpE,OAAO,EAGL,cAAc,EACf,MAAM,yBAAyB,CAAC;AAGjC;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CAAC,CAAC,SAAS,sBAAsB,EACzE,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,cAAc,EAC9B,OAAO,EAAE,CAAC,GACT,OAAO,CAAC,MAAM,CAAC,CA6DjB"}
@@ -5,7 +5,6 @@ const ora = require("ora");
5
5
  const path_1 = require("path");
6
6
  const child_process_utils_1 = require("./utils/child-process-utils");
7
7
  const error_utils_1 = require("./utils/error-utils");
8
- const output_1 = require("./utils/output");
9
8
  const package_manager_1 = require("./utils/package-manager");
10
9
  const unparse_1 = require("./utils/unparse");
11
10
  /**
@@ -52,16 +51,8 @@ async function createEmptyWorkspace(tmpDir, name, packageManager, options) {
52
51
  }
53
52
  catch (e) {
54
53
  workspaceSetupSpinner.fail();
55
- if (e instanceof Error) {
56
- output_1.output.error({
57
- title: `Failed to create a workspace.`,
58
- bodyLines: (0, error_utils_1.mapErrorToBodyLines)(e),
59
- });
60
- }
61
- else {
62
- console.error(e);
63
- }
64
- process.exit(1);
54
+ const message = e instanceof Error ? e.message : String(e);
55
+ throw new error_utils_1.CnwError('WORKSPACE_CREATION_FAILED', `Failed to create a workspace: ${message}`);
65
56
  }
66
57
  finally {
67
58
  workspaceSetupSpinner.stop();
@@ -1 +1 @@
1
- {"version":3,"file":"create-preset.d.ts","sourceRoot":"","sources":["../../../../packages/create-nx-workspace/src/create-preset.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAEpE,OAAO,EAGL,cAAc,EACf,MAAM,yBAAyB,CAAC;AAIjC,wBAAsB,YAAY,CAAC,CAAC,SAAS,sBAAsB,EACjE,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,CAAC,EACb,cAAc,EAAE,cAAc,EAC9B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAwDf"}
1
+ {"version":3,"file":"create-preset.d.ts","sourceRoot":"","sources":["../../../../packages/create-nx-workspace/src/create-preset.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAEpE,OAAO,EAGL,cAAc,EACf,MAAM,yBAAyB,CAAC;AAIjC,wBAAsB,YAAY,CAAC,CAAC,SAAS,sBAAsB,EACjE,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,CAAC,EACb,cAAc,EAAE,cAAc,EAC9B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAoDf"}
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createPreset = createPreset;
4
- const output_1 = require("./utils/output");
4
+ const error_utils_1 = require("./utils/error-utils");
5
5
  const package_manager_1 = require("./utils/package-manager");
6
6
  const child_process_utils_1 = require("./utils/child-process-utils");
7
7
  const unparse_1 = require("./utils/unparse");
@@ -38,10 +38,6 @@ async function createPreset(preset, parsedArgs, packageManager, directory) {
38
38
  await (0, child_process_utils_1.spawnAndWait)(exec, args, directory);
39
39
  }
40
40
  catch (e) {
41
- output_1.output.error({
42
- title: `Failed to apply preset: ${preset}`,
43
- bodyLines: ['See above'],
44
- });
45
- process.exit(1);
41
+ throw new error_utils_1.CnwError('PRESET_FAILED', `Failed to apply preset: ${preset}`);
46
42
  }
47
43
  }
@@ -1 +1 @@
1
- {"version":3,"file":"create-sandbox.d.ts","sourceRoot":"","sources":["../../../../packages/create-nx-workspace/src/create-sandbox.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,cAAc,EACf,MAAM,yBAAyB,CAAC;AAMjC;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,cAAc,EAAE,cAAc,mBA4CjE"}
1
+ {"version":3,"file":"create-sandbox.d.ts","sourceRoot":"","sources":["../../../../packages/create-nx-workspace/src/create-sandbox.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,cAAc,EACf,MAAM,yBAAyB,CAAC;AAKjC;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,cAAc,EAAE,cAAc,mBAwCjE"}
@@ -7,7 +7,6 @@ const ora = require("ora");
7
7
  const path_1 = require("path");
8
8
  const package_manager_1 = require("./utils/package-manager");
9
9
  const child_process_utils_1 = require("./utils/child-process-utils");
10
- const output_1 = require("./utils/output");
11
10
  const nx_version_1 = require("./utils/nx/nx-version");
12
11
  const error_utils_1 = require("./utils/error-utils");
13
12
  /**
@@ -36,16 +35,8 @@ async function createSandbox(packageManager) {
36
35
  }
37
36
  catch (e) {
38
37
  installSpinner.fail();
39
- if (e instanceof Error) {
40
- output_1.output.error({
41
- title: `Failed to install dependencies`,
42
- bodyLines: (0, error_utils_1.mapErrorToBodyLines)(e),
43
- });
44
- }
45
- else {
46
- console.error(e);
47
- }
48
- process.exit(1);
38
+ const message = e instanceof Error ? e.message : String(e);
39
+ throw new error_utils_1.CnwError('SANDBOX_FAILED', `Failed to install dependencies: ${message}`);
49
40
  }
50
41
  finally {
51
42
  installSpinner.stop();
@@ -1 +1 @@
1
- {"version":3,"file":"create-workspace.d.ts","sourceRoot":"","sources":["../../../../packages/create-nx-workspace/src/create-workspace.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAGpE,OAAO,EAGL,aAAa,EACd,MAAM,iBAAiB,CAAC;AAkBzB,wBAAgB,4BAA4B,IAAI;IAC9C,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC,CAEA;AAED,wBAAsB,eAAe,CAAC,CAAC,SAAS,sBAAsB,EACpE,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,CAAC,EACV,OAAO,CAAC,EAAE,CAAC;;;;GAgKZ;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI7D"}
1
+ {"version":3,"file":"create-workspace.d.ts","sourceRoot":"","sources":["../../../../packages/create-nx-workspace/src/create-workspace.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAGpE,OAAO,EAGL,aAAa,EACd,MAAM,iBAAiB,CAAC;AAsBzB,wBAAgB,4BAA4B,IAAI;IAC9C,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC,CAEA;AAED,wBAAsB,eAAe,CAAC,CAAC,SAAS,sBAAsB,EACpE,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,CAAC,EACV,OAAO,CAAC,EAAE,CAAC;;;;GA6KZ;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI7D"}
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getInterruptedWorkspaceState = getInterruptedWorkspaceState;
4
4
  exports.createWorkspace = createWorkspace;
5
5
  exports.extractConnectUrl = extractConnectUrl;
6
+ const node_fs_1 = require("node:fs");
6
7
  const path_1 = require("path");
7
8
  const create_empty_workspace_1 = require("./create-empty-workspace");
8
9
  const create_preset_1 = require("./create-preset");
@@ -16,6 +17,7 @@ const get_third_party_preset_1 = require("./utils/preset/get-third-party-preset"
16
17
  const preset_1 = require("./utils/preset/preset");
17
18
  const clone_template_1 = require("./utils/template/clone-template");
18
19
  const child_process_utils_1 = require("./utils/child-process-utils");
20
+ const package_manager_1 = require("./utils/package-manager");
19
21
  // State for SIGINT handler - only set after workspace is fully installed
20
22
  let workspaceDirectory;
21
23
  let cloudConnectUrl;
@@ -38,8 +40,19 @@ async function createWorkspace(preset, options, rawArgs) {
38
40
  const workspaceSetupSpinner = ora(`Creating workspace from template`).start();
39
41
  try {
40
42
  await (0, clone_template_1.cloneTemplate)(templateUrl, name);
41
- // Install dependencies (template flow always uses npm)
42
- await (0, child_process_utils_1.execAndWait)('npm install --silent --ignore-scripts', directory);
43
+ // Remove npm lockfile from template since we'll generate the correct one
44
+ const npmLockPath = (0, path_1.join)(directory, 'package-lock.json');
45
+ if ((0, node_fs_1.existsSync)(npmLockPath)) {
46
+ (0, node_fs_1.unlinkSync)(npmLockPath);
47
+ }
48
+ // Generate package manager specific files (e.g., .yarnrc.yml for Yarn Berry)
49
+ (0, package_manager_1.generatePackageManagerFiles)(directory, packageManager);
50
+ // Install dependencies with the user's package manager
51
+ const pmc = (0, package_manager_1.getPackageManagerCommand)(packageManager);
52
+ if (pmc.preInstall) {
53
+ await (0, child_process_utils_1.execAndWait)(pmc.preInstall, directory);
54
+ }
55
+ await (0, child_process_utils_1.execAndWait)(pmc.install, directory);
43
56
  // Mark workspace as ready for SIGINT handler
44
57
  workspaceDirectory = directory;
45
58
  workspaceSetupSpinner.succeed(`Successfully created the workspace: ${directory}`);
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../../../packages/create-nx-workspace/src/internal-utils/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAW/B,OAAO,EAEL,cAAc,EAEf,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAE/C,OAAO,EACL,KAAK,EAGN,MAAM,6BAA6B,CAAC;AAErC,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,GAChD,OAAO,CAAC,OAAO,CAAC,CAQlB;AAED,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,GACvE,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,CAiC5B;AAED,wBAAsB,2BAA2B,CAC/C,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,GACrE,OAAO,CAAC,OAAO,CAAC,CAelB;AA4BD,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC,GACD,OAAO,CAAC,MAAM,GAAG,QAAQ,CAAC,CA2C5B;AAED,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC;IAAE,QAAQ,CAAC,EAAE,KAAK,EAAE,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,GACzE,OAAO,CAAC,KAAK,EAAE,CAAC,CAElB;AAqBD,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GACpD,OAAO,CAAC,MAAM,CAAC,CAyBjB;AAED,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC;IAAE,cAAc,EAAE,MAAM,CAAA;CAAE,CAAC,GACtD,OAAO,CAAC,cAAc,CAAC,CAoCzB"}
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../../../packages/create-nx-workspace/src/internal-utils/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAU/B,OAAO,EAEL,cAAc,EAEf,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAE/C,OAAO,EACL,KAAK,EAGN,MAAM,6BAA6B,CAAC;AAGrC,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,GAChD,OAAO,CAAC,OAAO,CAAC,CAQlB;AAED,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,GACvE,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,CAiC5B;AAED,wBAAsB,2BAA2B,CAC/C,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,GACrE,OAAO,CAAC,OAAO,CAAC,CAelB;AA4BD,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC,GACD,OAAO,CAAC,MAAM,GAAG,QAAQ,CAAC,CA0C5B;AAED,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC;IAAE,QAAQ,CAAC,EAAE,KAAK,EAAE,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,GACzE,OAAO,CAAC,KAAK,EAAE,CAAC,CAElB;AAqBD,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GACpD,OAAO,CAAC,MAAM,CAAC,CAwBjB;AAED,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC;IAAE,cAAc,EAAE,MAAM,CAAA;CAAE,CAAC,GACtD,OAAO,CAAC,cAAc,CAAC,CAiCzB"}
@@ -10,12 +10,12 @@ exports.determinePackageManager = determinePackageManager;
10
10
  const enquirer = require("enquirer");
11
11
  const chalk = require("chalk");
12
12
  const ab_testing_1 = require("../utils/nx/ab-testing");
13
- const output_1 = require("../utils/output");
14
13
  const default_base_1 = require("../utils/git/default-base");
15
14
  const package_manager_1 = require("../utils/package-manager");
16
15
  const string_utils_1 = require("../utils/string-utils");
17
16
  const is_ci_1 = require("../utils/ci/is-ci");
18
17
  const create_workspace_options_1 = require("../create-workspace-options");
18
+ const error_utils_1 = require("../utils/error-utils");
19
19
  async function determineNxCloud(parsedArgs) {
20
20
  if (parsedArgs.nxCloud) {
21
21
  return parsedArgs.nxCloud;
@@ -113,11 +113,7 @@ async function determineTemplate(parsedArgs) {
113
113
  choices: [
114
114
  {
115
115
  name: 'nrwl/empty-template',
116
- message: 'TypeScript (minimal TypeScript monorepo without projects)',
117
- },
118
- {
119
- name: 'nrwl/typescript-template',
120
- message: 'NPM Packages (monorepo with TypeScript packages ready to publish)',
116
+ message: 'Minimal (empty monorepo without projects)',
121
117
  },
122
118
  {
123
119
  name: 'nrwl/react-template',
@@ -127,9 +123,13 @@ async function determineTemplate(parsedArgs) {
127
123
  name: 'nrwl/angular-template',
128
124
  message: 'Angular (fullstack monorepo with Angular and Express)',
129
125
  },
126
+ {
127
+ name: 'nrwl/typescript-template',
128
+ message: 'NPM Packages (monorepo with TypeScript packages ready to publish)',
129
+ },
130
130
  {
131
131
  name: 'custom',
132
- message: 'Custom (more options for frameworks, test runners, etc.)',
132
+ message: 'Custom (advanced setup with additional frameworks)',
133
133
  },
134
134
  ],
135
135
  initial: 0,
@@ -169,11 +169,7 @@ async function determineDefaultBase(parsedArgs) {
169
169
  ])
170
170
  .then((a) => {
171
171
  if (!a.DefaultBase) {
172
- output_1.output.error({
173
- title: 'Invalid branch name',
174
- bodyLines: [`Branch name cannot be empty`],
175
- });
176
- process.exit(1);
172
+ throw new error_utils_1.CnwError('INVALID_BRANCH_NAME', 'Branch name cannot be empty');
177
173
  }
178
174
  return a.DefaultBase;
179
175
  });
@@ -186,15 +182,9 @@ async function determinePackageManager(parsedArgs) {
186
182
  if (package_manager_1.packageManagerList.includes(packageManager)) {
187
183
  return packageManager;
188
184
  }
189
- output_1.output.error({
190
- title: 'Invalid package manager',
191
- bodyLines: [
192
- `Package manager must be one of ${(0, string_utils_1.stringifyCollection)([
193
- ...package_manager_1.packageManagerList,
194
- ])}`,
195
- ],
196
- });
197
- process.exit(1);
185
+ throw new error_utils_1.CnwError('INVALID_PACKAGE_MANAGER', `Package manager must be one of ${(0, string_utils_1.stringifyCollection)([
186
+ ...package_manager_1.packageManagerList,
187
+ ])}`);
198
188
  }
199
189
  else if (parsedArgs.allPrompts) {
200
190
  return enquirer
@@ -1 +1 @@
1
- {"version":3,"file":"setup-ci.d.ts","sourceRoot":"","sources":["../../../../../../packages/create-nx-workspace/src/utils/ci/setup-ci.ts"],"names":[],"mappings":"AAKA,OAAO,EAA4B,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAE9E,wBAAsB,OAAO,CAC3B,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,MAAM,EACV,cAAc,EAAE,cAAc;;;GA0B/B"}
1
+ {"version":3,"file":"setup-ci.d.ts","sourceRoot":"","sources":["../../../../../../packages/create-nx-workspace/src/utils/ci/setup-ci.ts"],"names":[],"mappings":"AAIA,OAAO,EAA4B,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAE9E,wBAAsB,OAAO,CAC3B,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,MAAM,EACV,cAAc,EAAE,cAAc;;;GAqB/B"}
@@ -4,7 +4,6 @@ exports.setupCI = setupCI;
4
4
  const ora = require("ora");
5
5
  const child_process_utils_1 = require("../child-process-utils");
6
6
  const error_utils_1 = require("../error-utils");
7
- const output_1 = require("../output");
8
7
  const package_manager_1 = require("../package-manager");
9
8
  async function setupCI(directory, ci, packageManager) {
10
9
  const ciSpinner = ora(`Generating CI workflow`).start();
@@ -16,16 +15,8 @@ async function setupCI(directory, ci, packageManager) {
16
15
  }
17
16
  catch (e) {
18
17
  ciSpinner.fail();
19
- if (e instanceof Error) {
20
- output_1.output.error({
21
- title: `Failed to generate CI workflow`,
22
- bodyLines: (0, error_utils_1.mapErrorToBodyLines)(e),
23
- });
24
- }
25
- else {
26
- console.error(e);
27
- }
28
- process.exit(1);
18
+ const message = e instanceof Error ? e.message : String(e);
19
+ throw new error_utils_1.CnwError('CI_WORKFLOW_FAILED', `Failed to generate CI workflow: ${message}`);
29
20
  }
30
21
  finally {
31
22
  ciSpinner.stop();
@@ -1,3 +1,21 @@
1
+ /**
2
+ * Error codes for CNW errors.
3
+ * These are used for telemetry and error tracking.
4
+ */
5
+ export type CnwErrorCode = 'DIRECTORY_EXISTS' | 'INVALID_WORKSPACE_NAME' | 'INVALID_FOLDER_NAME' | 'INVALID_BRANCH_NAME' | 'INVALID_PACKAGE_MANAGER' | 'INVALID_PRESET' | 'INVALID_WORKSPACE_TYPE' | 'INVALID_APP_NAME' | 'PRESET_FAILED' | 'SANDBOX_FAILED' | 'TEMPLATE_CLONE_FAILED' | 'CI_WORKFLOW_FAILED' | 'WORKSPACE_CREATION_FAILED' | 'ANGULAR_PREFIX_INVALID' | 'UNKNOWN';
6
+ /**
7
+ * Custom error class for CNW errors.
8
+ * Used for structured error reporting and telemetry.
9
+ */
10
+ export declare class CnwError extends Error {
11
+ readonly code: CnwErrorCode;
12
+ readonly logFile?: string;
13
+ readonly exitCode?: number;
14
+ constructor(code: CnwErrorCode, message: string, logFile?: string, exitCode?: number);
15
+ }
16
+ /**
17
+ * @deprecated Use CnwError instead
18
+ */
1
19
  export declare class CreateNxWorkspaceError extends Error {
2
20
  logMessage: string;
3
21
  code: number | null | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"error-utils.d.ts","sourceRoot":"","sources":["../../../../../packages/create-nx-workspace/src/utils/error-utils.ts"],"names":[],"mappings":"AAAA,qBAAa,sBAAuB,SAAQ,KAAK;IAEtC,UAAU,EAAE,MAAM;IAClB,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;IAC/B,OAAO,EAAE,MAAM;gBAFf,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/B,OAAO,EAAE,MAAM;CAKzB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,EAAE,CAoB1D"}
1
+ {"version":3,"file":"error-utils.d.ts","sourceRoot":"","sources":["../../../../../packages/create-nx-workspace/src/utils/error-utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,YAAY,GACpB,kBAAkB,GAClB,wBAAwB,GACxB,qBAAqB,GACrB,qBAAqB,GACrB,yBAAyB,GACzB,gBAAgB,GAChB,wBAAwB,GACxB,kBAAkB,GAClB,eAAe,GACf,gBAAgB,GAChB,uBAAuB,GACvB,oBAAoB,GACpB,2BAA2B,GAC3B,wBAAwB,GACxB,SAAS,CAAC;AAEd;;;GAGG;AACH,qBAAa,QAAS,SAAQ,KAAK;aAEf,IAAI,EAAE,YAAY;aAElB,OAAO,CAAC,EAAE,MAAM;aAChB,QAAQ,CAAC,EAAE,MAAM;gBAHjB,IAAI,EAAE,YAAY,EAClC,OAAO,EAAE,MAAM,EACC,OAAO,CAAC,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM;CAKpC;AAED;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IAEtC,UAAU,EAAE,MAAM;IAClB,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;IAC/B,OAAO,EAAE,MAAM;gBAFf,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/B,OAAO,EAAE,MAAM;CAKzB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,EAAE,CAsB1D"}
@@ -1,7 +1,24 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CreateNxWorkspaceError = void 0;
3
+ exports.CreateNxWorkspaceError = exports.CnwError = void 0;
4
4
  exports.mapErrorToBodyLines = mapErrorToBodyLines;
5
+ /**
6
+ * Custom error class for CNW errors.
7
+ * Used for structured error reporting and telemetry.
8
+ */
9
+ class CnwError extends Error {
10
+ constructor(code, message, logFile, exitCode) {
11
+ super(message);
12
+ this.code = code;
13
+ this.logFile = logFile;
14
+ this.exitCode = exitCode;
15
+ this.name = 'CnwError';
16
+ }
17
+ }
18
+ exports.CnwError = CnwError;
19
+ /**
20
+ * @deprecated Use CnwError instead
21
+ */
5
22
  class CreateNxWorkspaceError extends Error {
6
23
  constructor(logMessage, code, logFile) {
7
24
  super(logMessage);
@@ -23,7 +40,9 @@ function mapErrorToBodyLines(error) {
23
40
  }
24
41
  const lines = error instanceof CreateNxWorkspaceError
25
42
  ? [`Exit code: ${error.code}`, `Log file: ${error.logFile}`]
26
- : [];
43
+ : error instanceof CnwError && error.logFile
44
+ ? [`Log file: ${error.logFile}`]
45
+ : [];
27
46
  if (process.env.NX_VERBOSE_LOGGING === 'true') {
28
47
  lines.push(`Error: ${error.message}`);
29
48
  lines.push(`Stack: ${error.stack}`);
@@ -37,6 +37,29 @@ export declare class PromptMessages {
37
37
  completionMessageOfSelectedPrompt(key: MessageKey): CompletionMessageKey;
38
38
  }
39
39
  export declare const messages: PromptMessages;
40
+ /**
41
+ * Meta payload types for recordStat telemetry.
42
+ */
43
+ export interface RecordStatMetaStart {
44
+ type: 'start';
45
+ [key: string]: string;
46
+ }
47
+ export interface RecordStatMetaComplete {
48
+ type: 'complete';
49
+ [key: string]: string;
50
+ }
51
+ export interface RecordStatMetaError {
52
+ type: 'error';
53
+ errorCode: string;
54
+ flowVariant?: string;
55
+ errorMessage?: string;
56
+ errorFile?: string;
57
+ }
58
+ export interface RecordStatMetaCancel {
59
+ type: 'cancel';
60
+ flowVariant?: string;
61
+ }
62
+ export type RecordStatMeta = RecordStatMetaStart | RecordStatMetaComplete | RecordStatMetaError | RecordStatMetaCancel;
40
63
  /**
41
64
  * We are incrementing a counter to track how often create-nx-workspace is used in CI
42
65
  * vs dev environments. No personal information is collected.
@@ -45,7 +68,7 @@ export declare function recordStat(opts: {
45
68
  command: string;
46
69
  nxVersion: string;
47
70
  useCloud: boolean;
48
- meta: string[];
71
+ meta: RecordStatMeta;
49
72
  }): Promise<void>;
50
73
  export {};
51
74
  //# sourceMappingURL=ab-testing.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ab-testing.d.ts","sourceRoot":"","sources":["../../../../../../packages/create-nx-workspace/src/utils/nx/ab-testing.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAsDvD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAO/C;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAKvC;AAED,eAAO,MAAM,cAAc,UAQ1B,CAAC;AAEF,QAAA,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,CAsGjD,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,cAAc,CAAC;AACrD,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,UAAU,CAAA;KAAE,CAAC;IAC9C,iBAAiB,EAAE,oBAAoB,CAAC;CACzC;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,gBAAgB,CAAwC;IAEhE,SAAS,CAAC,GAAG,EAAE,UAAU,GAAG,WAAW;IAavC,2BAA2B,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM;IAQpD,iCAAiC,CAAC,GAAG,EAAE,UAAU,GAAG,oBAAoB;CAQzE;AAED,eAAO,MAAM,QAAQ,gBAAuB,CAAC;AAS7C;;;GAGG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB,iBAuBA"}
1
+ {"version":3,"file":"ab-testing.d.ts","sourceRoot":"","sources":["../../../../../../packages/create-nx-workspace/src/utils/nx/ab-testing.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAsDvD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAO/C;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAKvC;AAED,eAAO,MAAM,cAAc,UAQ1B,CAAC;AAEF,QAAA,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,CAsGjD,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,cAAc,CAAC;AACrD,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,UAAU,CAAA;KAAE,CAAC;IAC9C,iBAAiB,EAAE,oBAAoB,CAAC;CACzC;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,gBAAgB,CAAwC;IAEhE,SAAS,CAAC,GAAG,EAAE,UAAU,GAAG,WAAW;IAavC,2BAA2B,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM;IAQpD,iCAAiC,CAAC,GAAG,EAAE,UAAU,GAAG,oBAAoB;CAQzE;AAED,eAAO,MAAM,QAAQ,gBAAuB,CAAC;AAS7C;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,OAAO,CAAC;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,UAAU,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,QAAQ,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,cAAc,GACtB,mBAAmB,GACnB,sBAAsB,GACtB,mBAAmB,GACnB,oBAAoB,CAAC;AAEzB;;;GAGG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,cAAc,CAAC;CACtB,iBAuBA"}
@@ -133,42 +133,45 @@ const messageOptions = {
133
133
  * Simplified Cloud prompt for template flow
134
134
  */
135
135
  setupNxCloudV2: [
136
- {
137
- code: 'cloud-v2-remote-cache-visit',
138
- message: 'Enable remote caching with Nx Cloud?',
139
- initial: 0,
140
- choices: [
141
- { value: 'yes', name: 'Yes' },
142
- { value: 'skip', name: 'Skip' },
143
- ],
144
- footer: '\nRemote caching makes your builds faster for development and in CI: https://nx.dev/ci/features/remote-cache',
145
- fallback: undefined,
146
- completionMessage: 'cache-setup',
147
- },
148
- {
149
- code: 'cloud-v2-fast-ci-visit',
150
- message: 'Speed up CI and reduce compute costs with Nx Cloud?',
151
- initial: 0,
152
- choices: [
153
- { value: 'yes', name: 'Yes' },
154
- { value: 'skip', name: 'Skip' },
155
- ],
156
- footer: '\n70% faster CI, 60% less compute, Automatically fix broken PRs: https://nx.dev/nx-cloud',
157
- fallback: undefined,
158
- completionMessage: 'ci-setup',
159
- },
160
- {
161
- code: 'cloud-v2-green-prs-visit',
162
- message: 'Get to green PRs faster with Nx Cloud?',
163
- initial: 0,
164
- choices: [
165
- { value: 'yes', name: 'Yes' },
166
- { value: 'skip', name: 'Skip' },
167
- ],
168
- footer: '\nAutomatically fix broken PRs, 70% faster CI: https://nx.dev/nx-cloud',
169
- fallback: undefined,
170
- completionMessage: 'ci-setup',
171
- },
136
+ //{
137
+ // code: 'cloud-v2-remote-cache-visit',
138
+ // message: 'Enable remote caching with Nx Cloud?',
139
+ // initial: 0,
140
+ // choices: [
141
+ // { value: 'yes', name: 'Yes' },
142
+ // { value: 'skip', name: 'Skip' },
143
+ // ],
144
+ // footer:
145
+ // '\nRemote caching makes your builds faster for development and in CI: https://nx.dev/ci/features/remote-cache',
146
+ // fallback: undefined,
147
+ // completionMessage: 'cache-setup',
148
+ //},
149
+ //{
150
+ // code: 'cloud-v2-fast-ci-visit',
151
+ // message: 'Speed up CI and reduce compute costs with Nx Cloud?',
152
+ // initial: 0,
153
+ // choices: [
154
+ // { value: 'yes', name: 'Yes' },
155
+ // { value: 'skip', name: 'Skip' },
156
+ // ],
157
+ // footer:
158
+ // '\n70% faster CI, 60% less compute, Automatically fix broken PRs: https://nx.dev/nx-cloud',
159
+ // fallback: undefined,
160
+ // completionMessage: 'ci-setup',
161
+ //},
162
+ //{
163
+ // code: 'cloud-v2-green-prs-visit',
164
+ // message: 'Get to green PRs faster with Nx Cloud?',
165
+ // initial: 0,
166
+ // choices: [
167
+ // { value: 'yes', name: 'Yes' },
168
+ // { value: 'skip', name: 'Skip' },
169
+ // ],
170
+ // footer:
171
+ // '\nAutomatically fix broken PRs, 70% faster CI: https://nx.dev/nx-cloud',
172
+ // fallback: undefined,
173
+ // completionMessage: 'ci-setup',
174
+ //},
172
175
  {
173
176
  code: 'cloud-v2-full-platform-visit',
174
177
  message: 'Try the full Nx platform?',
@@ -241,7 +244,7 @@ async function recordStat(opts) {
241
244
  command: opts.command,
242
245
  isCI: (0, is_ci_1.isCI)(),
243
246
  useCloud: opts.useCloud,
244
- meta: [opts.nxVersion, ...opts.meta].filter((v) => !!v).join(','),
247
+ meta: JSON.stringify({ nxVersion: opts.nxVersion, ...opts.meta }),
245
248
  });
246
249
  }
247
250
  catch (e) {
@@ -21,6 +21,14 @@ export declare function getPackageManagerCommand(packageManager?: PackageManager
21
21
  getRegistryUrl?: string;
22
22
  };
23
23
  export declare function generatePackageManagerFiles(root: string, packageManager?: PackageManager): void;
24
+ /**
25
+ * Converts an array of workspace globs to pnpm-workspace.yaml content.
26
+ */
27
+ export declare function workspacesToPnpmYaml(workspaces: string[]): string;
28
+ /**
29
+ * Finds all package names from packages, libs, and apps directories.
30
+ */
31
+ export declare function findWorkspacePackages(root: string): string[];
24
32
  export declare function getPackageManagerVersion(packageManager: PackageManager, cwd?: string): string;
25
33
  /**
26
34
  * Detects which package manager was used to invoke create-nx-{plugin|workspace} command
@@ -1 +1 @@
1
- {"version":3,"file":"package-manager.d.ts","sourceRoot":"","sources":["../../../../../packages/create-nx-workspace/src/utils/package-manager.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,kBAAkB,yCAA0C,CAAC;AAE1E,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjE,wBAAgB,oBAAoB,CAAC,GAAG,GAAE,MAAW,GAAG,cAAc,CAQrE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CACtC,cAAc,GAAE,cAAuC,GACtD;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAElB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAgDA;AAED,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,MAAM,EACZ,cAAc,GAAE,cAAuC,QAexD;AAID,wBAAgB,wBAAwB,CACtC,cAAc,EAAE,cAAc,EAC9B,GAAG,SAAgB,GAClB,MAAM,CAWR;AAED;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,IAAI,cAAc,CAiB5D"}
1
+ {"version":3,"file":"package-manager.d.ts","sourceRoot":"","sources":["../../../../../packages/create-nx-workspace/src/utils/package-manager.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,kBAAkB,yCAA0C,CAAC;AAE1E,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjE,wBAAgB,oBAAoB,CAAC,GAAG,GAAE,MAAW,GAAG,cAAc,CAQrE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CACtC,cAAc,GAAE,cAAuC,GACtD;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAElB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAgDA;AAED,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,MAAM,EACZ,cAAc,GAAE,cAAuC,QAmBxD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,CAEjE;AAwCD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAyB5D;AAID,wBAAgB,wBAAwB,CACtC,cAAc,EAAE,cAAc,EAC9B,GAAG,SAAgB,GAClB,MAAM,CAWR;AAED;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,IAAI,cAAc,CAiB5D"}
@@ -4,6 +4,8 @@ exports.packageManagerList = void 0;
4
4
  exports.detectPackageManager = detectPackageManager;
5
5
  exports.getPackageManagerCommand = getPackageManagerCommand;
6
6
  exports.generatePackageManagerFiles = generatePackageManagerFiles;
7
+ exports.workspacesToPnpmYaml = workspacesToPnpmYaml;
8
+ exports.findWorkspacePackages = findWorkspacePackages;
7
9
  exports.getPackageManagerVersion = getPackageManagerVersion;
8
10
  exports.detectInvokedPackageManager = detectInvokedPackageManager;
9
11
  const node_child_process_1 = require("node:child_process");
@@ -84,6 +86,10 @@ function getPackageManagerCommand(packageManager = detectPackageManager()) {
84
86
  function generatePackageManagerFiles(root, packageManager = detectPackageManager()) {
85
87
  const [pmMajor] = getPackageManagerVersion(packageManager).split('.');
86
88
  switch (packageManager) {
89
+ case 'pnpm':
90
+ // pnpm doesn't support "workspaces" in package.json, needs pnpm-workspace.yaml
91
+ convertToWorkspaceYaml(root);
92
+ break;
87
93
  case 'yarn':
88
94
  if (+pmMajor >= 2) {
89
95
  (0, node_fs_1.writeFileSync)((0, node_path_1.join)(root, '.yarnrc.yml'), 'nodeLinker: node-modules\nenableScripts: false');
@@ -93,6 +99,70 @@ function generatePackageManagerFiles(root, packageManager = detectPackageManager
93
99
  break;
94
100
  }
95
101
  }
102
+ /**
103
+ * Converts an array of workspace globs to pnpm-workspace.yaml content.
104
+ */
105
+ function workspacesToPnpmYaml(workspaces) {
106
+ return `packages:\n${workspaces.map((p) => ` - '${p}'`).join('\n')}\n`;
107
+ }
108
+ /**
109
+ * Converts package.json "workspaces" field to pnpm-workspace.yaml
110
+ * and removes the workspaces field from package.json.
111
+ * Also adds workspace packages as devDependencies since pnpm doesn't
112
+ * automatically symlink workspace packages like npm/yarn.
113
+ */
114
+ function convertToWorkspaceYaml(root) {
115
+ const packageJsonPath = (0, node_path_1.join)(root, 'package.json');
116
+ if (!(0, node_fs_1.existsSync)(packageJsonPath)) {
117
+ return;
118
+ }
119
+ const packageJson = JSON.parse((0, node_fs_1.readFileSync)(packageJsonPath, 'utf-8'));
120
+ const workspaces = packageJson.workspaces;
121
+ if (!workspaces || workspaces.length === 0) {
122
+ return;
123
+ }
124
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(root, 'pnpm-workspace.yaml'), workspacesToPnpmYaml(workspaces));
125
+ // Find all workspace packages and add as devDependencies
126
+ const workspacePackages = findWorkspacePackages(root);
127
+ if (workspacePackages.length > 0) {
128
+ packageJson.devDependencies = packageJson.devDependencies || {};
129
+ for (const pkg of workspacePackages) {
130
+ packageJson.devDependencies[pkg] = 'workspace:*';
131
+ }
132
+ }
133
+ // Remove workspaces from package.json
134
+ delete packageJson.workspaces;
135
+ (0, node_fs_1.writeFileSync)(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n');
136
+ }
137
+ /**
138
+ * Finds all package names from packages, libs, and apps directories.
139
+ */
140
+ function findWorkspacePackages(root) {
141
+ const packages = [];
142
+ for (const dir of ['packages', 'libs', 'apps']) {
143
+ const fullPath = (0, node_path_1.join)(root, dir);
144
+ if (!(0, node_fs_1.existsSync)(fullPath))
145
+ continue;
146
+ const entries = (0, node_fs_1.readdirSync)(fullPath, { withFileTypes: true });
147
+ for (const entry of entries) {
148
+ if (!entry.isDirectory())
149
+ continue;
150
+ const pkgJsonPath = (0, node_path_1.join)(fullPath, entry.name, 'package.json');
151
+ if ((0, node_fs_1.existsSync)(pkgJsonPath)) {
152
+ try {
153
+ const pkgJson = JSON.parse((0, node_fs_1.readFileSync)(pkgJsonPath, 'utf-8'));
154
+ if (pkgJson.name) {
155
+ packages.push(pkgJson.name);
156
+ }
157
+ }
158
+ catch {
159
+ // Skip invalid package.json files
160
+ }
161
+ }
162
+ }
163
+ }
164
+ return packages.sort();
165
+ }
96
166
  const pmVersionCache = new Map();
97
167
  function getPackageManagerVersion(packageManager, cwd = process.cwd()) {
98
168
  if (pmVersionCache.has(packageManager)) {
@@ -1 +1 @@
1
- {"version":3,"file":"clone-template.d.ts","sourceRoot":"","sources":["../../../../../../packages/create-nx-workspace/src/utils/template/clone-template.ts"],"names":[],"mappings":"AAOA,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC,CA6Bf"}
1
+ {"version":3,"file":"clone-template.d.ts","sourceRoot":"","sources":["../../../../../../packages/create-nx-workspace/src/utils/template/clone-template.ts"],"names":[],"mappings":"AAMA,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC,CA0Bf"}
@@ -5,11 +5,10 @@ const child_process_utils_1 = require("../child-process-utils");
5
5
  const fs_1 = require("fs");
6
6
  const promises_1 = require("fs/promises");
7
7
  const path_1 = require("path");
8
- const output_1 = require("../output");
9
8
  const error_utils_1 = require("../error-utils");
10
9
  async function cloneTemplate(templateUrl, targetDirectory) {
11
10
  if ((0, fs_1.existsSync)(targetDirectory)) {
12
- throw new Error(`The directory '${targetDirectory}' already exists and is not empty. Choose a different name or remove the existing directory.`);
11
+ throw new error_utils_1.CnwError('DIRECTORY_EXISTS', `The directory '${targetDirectory}' already exists and is not empty. Choose a different name or remove the existing directory.`);
13
12
  }
14
13
  try {
15
14
  await (0, child_process_utils_1.execAndWait)(`git clone --depth 1 "${templateUrl}" "${targetDirectory}"`, process.cwd());
@@ -20,15 +19,7 @@ async function cloneTemplate(templateUrl, targetDirectory) {
20
19
  }
21
20
  }
22
21
  catch (e) {
23
- if (e instanceof Error) {
24
- output_1.output.error({
25
- title: 'Failed to create starter workspace',
26
- bodyLines: (0, error_utils_1.mapErrorToBodyLines)(e),
27
- });
28
- }
29
- else {
30
- console.error(e);
31
- }
32
- process.exit(1);
22
+ const message = e instanceof Error ? e.message : String(e);
23
+ throw new error_utils_1.CnwError('TEMPLATE_CLONE_FAILED', `Failed to create starter workspace: ${message}`);
33
24
  }
34
25
  }