create-nx-workspace 23.2.0-beta.3 → 23.2.0-beta.5

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.
@@ -65,6 +65,10 @@ interface UnknownStackArguments extends BaseArguments {
65
65
  }
66
66
  type Arguments = NoneArguments | ReactArguments | AngularArguments | VueArguments | NodeArguments | UnknownStackArguments;
67
67
  export declare const commandsObject: yargs.Argv<Arguments>;
68
+ export declare function applyEmptyPresetAlias(argv: {
69
+ preset?: Preset | 'empty';
70
+ template?: string;
71
+ }): void;
68
72
  /** Workspace names must start with a letter. */
69
73
  export declare function isValidWorkspaceName(name: string): boolean;
70
74
  export declare function validateWorkspaceName(name: string): void;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.commandsObject = void 0;
4
+ exports.applyEmptyPresetAlias = applyEmptyPresetAlias;
4
5
  exports.isValidWorkspaceName = isValidWorkspaceName;
5
6
  exports.validateWorkspaceName = validateWorkspaceName;
6
7
  exports.resolveSpecialFolderName = resolveSpecialFolderName;
@@ -344,30 +345,15 @@ async function handleError(error) {
344
345
  async function normalizeArgsMiddleware(argv) {
345
346
  try {
346
347
  rawArgs = { ...argv };
347
- // Map invalid/legacy presets to templates for all users
348
- // These presets don't exist as npm packages and would fail if not mapped
349
- const invalidPresetToTemplateMap = {
350
- empty: 'nrwl/empty-template',
351
- };
352
- if (rawArgs.preset && !rawArgs.template) {
353
- const mappedTemplate = invalidPresetToTemplateMap[rawArgs.preset];
354
- if (mappedTemplate) {
355
- output_1.output.log({
356
- title: `Mapping preset '${rawArgs.preset}' to template '${mappedTemplate}'`,
357
- });
358
- argv.template = mappedTemplate;
359
- rawArgs.template = mappedTemplate;
360
- delete argv.preset;
361
- delete rawArgs.preset;
362
- }
363
- }
364
348
  // AI Agent Detection: When an AI agent is detected, switch to AI-optimized mode
365
349
  const aiMode = (0, ai_output_1.isAiAgent)();
366
350
  if (aiMode) {
367
351
  // Force non-interactive mode for AI agents
368
352
  argv.interactive = false;
369
353
  // Map legacy presets to templates for AI agents
370
- // Many AI models were trained on old preset syntax, so we convert them
354
+ // Many AI models were trained on old preset syntax, so we convert them.
355
+ // Never add `empty` here - it must stay npm-only as the escape hatch
356
+ // when github.com is unreachable (see applyEmptyPresetAlias).
371
357
  const legacyPresetToTemplateMap = {
372
358
  ts: 'nrwl/empty-template',
373
359
  apps: 'nrwl/empty-template',
@@ -426,6 +412,7 @@ async function normalizeArgsMiddleware(argv) {
426
412
  title: "Let's create a new workspace [https://nx.dev/getting-started/intro]",
427
413
  });
428
414
  }
415
+ applyEmptyPresetAlias(argv);
429
416
  argv.workspaces ??= true;
430
417
  argv.useProjectJson ??= !argv.workspaces;
431
418
  useCloud = argv.nxCloud !== 'skip' && argv.nxCloud !== 'never';
@@ -616,6 +603,15 @@ async function normalizeArgsMiddleware(argv) {
616
603
  handleError(error);
617
604
  }
618
605
  }
606
+ // Map `empty` to the `ts` preset, not the template - sandboxed agents often
607
+ // cannot reach github.com. Wins over --template so appending --preset=empty
608
+ // to a failed command escapes the download.
609
+ function applyEmptyPresetAlias(argv) {
610
+ if (argv.preset === 'empty') {
611
+ argv.preset = preset_1.Preset.TS;
612
+ delete argv.template;
613
+ }
614
+ }
619
615
  function invariant(predicate, errorCode, message) {
620
616
  if (!predicate) {
621
617
  throw new error_utils_1.CnwError(errorCode, message);
@@ -38,7 +38,9 @@ async function createWorkspace(preset, options, rawArgs) {
38
38
  if (options.template) {
39
39
  // Resolve shorthand template names to full GitHub org/repo format
40
40
  options.template = resolveTemplateShorthand(options.template);
41
- if (!options.template.startsWith('nrwl/'))
41
+ // Strict slug match - a bare startsWith('nrwl/') check lets path
42
+ // traversal (`nrwl/../evil`) resolve to another org's repo.
43
+ if (!/^nrwl\/[\w.-]+$/.test(options.template))
42
44
  throw new Error(`Invalid template. Only templates from the 'nrwl' GitHub org are supported.`);
43
45
  const workingDir = (options.workingDir ?? process.cwd()).replace(/\\/g, '/');
44
46
  directory = (0, path_1.join)(workingDir, name);
@@ -113,7 +113,7 @@ function buildTemplateRequiredResult(workspaceName) {
113
113
  stage: 'needs_input',
114
114
  success: false,
115
115
  title: 'Template Selection Required',
116
- message: 'Ask the user which workspace type they want, then run again with --template. If the directory exists, append a number (e.g., my-nx-repo-2).',
116
+ message: 'Ask the user which workspace type they want, then run again with --template. If the directory exists, append a number (e.g., my-nx-repo-2). If this environment cannot reach github.com, run with --preset=empty instead of --template to create a minimal workspace without downloading a template.',
117
117
  suggestedName: name,
118
118
  templates: [
119
119
  {
@@ -227,9 +227,14 @@ function getErrorHints(errorCode) {
227
227
  ];
228
228
  case 'NETWORK_ERROR':
229
229
  return [
230
- 'Check your internet connection',
231
- 'Try again in a few moments',
232
- 'Check if npm/yarn registry is accessible',
230
+ 'Templates download from github.com, which may be blocked or unreachable in this environment',
231
+ 'Check your network and sandbox configuration (allow https://github.com) and try again',
232
+ 'Or re-run with --preset=empty (instead of --template) to create a minimal workspace without downloading a template, then build on top of it',
233
+ ];
234
+ case 'TEMPLATE_CLONE_FAILED':
235
+ return [
236
+ 'Check the template name (e.g. nrwl/empty-template)',
237
+ 'If github.com is restricted in this environment, re-run with --preset=empty',
233
238
  ];
234
239
  case 'PACKAGE_INSTALL_ERROR':
235
240
  return [
@@ -25,8 +25,9 @@ const DEFAULT_BRANCHES = ['main', 'master'];
25
25
  async function downloadTemplate(template, directory) {
26
26
  let body;
27
27
  const attempts = [];
28
- // A thrown fetch is a connectivity problem; a non-ok response is a missing
29
- // branch/repo. Distinguish them so the error code (and its hints) are right.
28
+ // 404 means the repo/branch does not exist; any other failure (thrown fetch,
29
+ // 403 from a sandbox proxy, 407/429/5xx) means blocked or failed egress.
30
+ // The distinction picks the error code and its hints.
30
31
  let networkError = false;
31
32
  for (const branch of DEFAULT_BRANCHES) {
32
33
  const url = `https://github.com/${template}/archive/refs/heads/${branch}.tar.gz`;
@@ -36,6 +37,8 @@ async function downloadTemplate(template, directory) {
36
37
  body = res.body;
37
38
  break;
38
39
  }
40
+ if (res.status !== 404)
41
+ networkError = true;
39
42
  attempts.push(`${branch}: HTTP ${res.status}`);
40
43
  }
41
44
  catch (e) {
@@ -44,7 +47,11 @@ async function downloadTemplate(template, directory) {
44
47
  }
45
48
  }
46
49
  if (!body) {
47
- throw new error_utils_1.CnwError(networkError ? 'NETWORK_ERROR' : 'TEMPLATE_CLONE_FAILED', `Failed to download template '${template}' (${attempts.join('; ')})`);
50
+ if (networkError) {
51
+ throw new error_utils_1.CnwError('NETWORK_ERROR', `Failed to download template '${template}' (${attempts.join('; ')}).\n` +
52
+ `github.com may be blocked or unreachable in this environment. Check your network and sandbox configuration and try again, or run with --preset=empty (instead of --template) to create a minimal workspace without downloading a template.`);
53
+ }
54
+ throw new error_utils_1.CnwError('TEMPLATE_CLONE_FAILED', `Failed to download template '${template}' (${attempts.join('; ')}). Check that the template name is correct.`);
48
55
  }
49
56
  // Only remove the directory on failure if we created it - never delete a
50
57
  // pre-existing dir (e.g. the user's current directory).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-nx-workspace",
3
- "version": "23.2.0-beta.3",
3
+ "version": "23.2.0-beta.5",
4
4
  "private": false,
5
5
  "description": "Smart Monorepos · Fast Builds",
6
6
  "repository": {
@@ -37,7 +37,7 @@
37
37
  },
38
38
  "homepage": "https://nx.dev",
39
39
  "dependencies": {
40
- "axios": "1.16.1",
40
+ "axios": "1.18.1",
41
41
  "chalk": "^4.1.0",
42
42
  "enquirer": "~2.3.6",
43
43
  "flat": "^5.0.2",