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
|
-
|
|
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
|
-
'
|
|
231
|
-
'
|
|
232
|
-
'
|
|
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
|
-
//
|
|
29
|
-
//
|
|
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
|
-
|
|
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
|
+
"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.
|
|
40
|
+
"axios": "1.18.1",
|
|
41
41
|
"chalk": "^4.1.0",
|
|
42
42
|
"enquirer": "~2.3.6",
|
|
43
43
|
"flat": "^5.0.2",
|