create-nx-workspace 23.3.0-rc.1 → 24.0.0-beta.0

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/README.md CHANGED
@@ -1,7 +1,7 @@
1
- <p style="text-align: center;">
1
+ <p align="center">
2
2
  <picture>
3
- <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-dark.svg">
4
- <img alt="Nx - Smart Monorepos · Fast Builds" src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-light.svg" width="100%">
3
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-logo-light.svg">
4
+ <img alt="Nx Logo" src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-logo.svg" width="140">
5
5
  </picture>
6
6
  </p>
7
7
 
@@ -64,6 +64,3 @@ npx nx@latest init
64
64
  - [Official Nx YouTube Channel](https://www.youtube.com/@NxDevtools)
65
65
  - [Blog Posts About Nx](https://nx.dev/blog)
66
66
 
67
- <p style="text-align: center;"><a href="https://nx.dev/#learning-materials" target="_blank" rel="noreferrer"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-courses-and-videos.svg"
68
- width="100%" alt="Nx - Smart Monorepos · Fast Builds"></a></p>
69
-
@@ -213,18 +213,6 @@ else {
213
213
  exports.commandsObject.epilogue(`${chalk_1.default.cyan('Documentation:')}
214
214
  https://nx.dev/getting-started/intro`);
215
215
  }
216
- // Node 24's stricter readline throws ERR_USE_AFTER_CLOSE when a prompt library
217
- // operates on a closed interface. Added for enquirer, which this package no
218
- // longer uses; verify against Node 24 before removing.
219
- // TODO(v24): drop if @clack/prompts proves not to need it.
220
- process.on('uncaughtException', (error) => {
221
- if (error &&
222
- typeof error === 'object' &&
223
- 'code' in error &&
224
- error['code'] === 'ERR_USE_AFTER_CLOSE')
225
- return;
226
- throw error;
227
- });
228
216
  // Handle Ctrl+C gracefully - show helpful message if workspace was already created
229
217
  process.on('SIGINT', async () => {
230
218
  await (0, ab_testing_1.recordStat)({
@@ -272,7 +272,7 @@ async function createWorkspace(preset, options, rawArgs) {
272
272
  nxCloudInfo = await (0, nx_cloud_1.getNxCloudInfo)(connectUrl, pushedToVcs, options.completionMessageKey, name);
273
273
  // Auto-open the Cloud setup URL in the browser when user selected 'yes'
274
274
  if (!options.skipCloudConnect) {
275
- await (0, nx_cloud_1.openCloudSetupUrl)(connectUrl);
275
+ (0, nx_cloud_1.openCloudSetupUrl)({ connectUrl, workspaceDirectory: directory });
276
276
  }
277
277
  }
278
278
  else if (isTemplate && nxCloud === 'skip') {
@@ -66,7 +66,7 @@ export interface SuccessResult {
66
66
  preset?: string;
67
67
  };
68
68
  /** Display these to the user as next steps */
69
- userNextSteps: UserNextSteps;
69
+ userNextSteps?: UserNextSteps;
70
70
  /** Reference documentation */
71
71
  docs: {
72
72
  gettingStarted: string;
@@ -90,7 +90,7 @@ export type AiOutputMessage = ProgressMessage | TemplateRequiredResult | Success
90
90
  /**
91
91
  * Write NDJSON message to stdout.
92
92
  * Each message is a single line of JSON.
93
- * For success results, also outputs plain text instructions at the end.
93
+ * For success results with next steps, also outputs plain text instructions.
94
94
  */
95
95
  export declare function writeAiOutput(message: AiOutputMessage): void;
96
96
  /**
@@ -86,7 +86,7 @@ function detectAiAgentName() {
86
86
  /**
87
87
  * Write NDJSON message to stdout.
88
88
  * Each message is a single line of JSON.
89
- * For success results, also outputs plain text instructions at the end.
89
+ * For success results with next steps, also outputs plain text instructions.
90
90
  */
91
91
  function writeAiOutput(message) {
92
92
  if (isAiAgent()) {
@@ -96,7 +96,10 @@ function writeAiOutput(message) {
96
96
  'success' in message &&
97
97
  message.success) {
98
98
  const successMsg = message;
99
- const steps = successMsg.userNextSteps.steps;
99
+ const steps = successMsg.userNextSteps?.steps;
100
+ if (!steps?.length) {
101
+ return;
102
+ }
100
103
  let plainText = '\n---USER_NEXT_STEPS---\n';
101
104
  plainText +=
102
105
  '[DISPLAY] Show the user these next steps to complete setup:\n\n';
@@ -188,20 +191,21 @@ function buildSuccessResult(options) {
188
191
  note: 'Complete setup to enable remote caching and CI insights',
189
192
  });
190
193
  }
191
- const userNextSteps = {
192
- description: 'CRITICAL: Show the user these exact steps to complete setup.',
193
- steps,
194
- };
195
194
  const successResult = {
196
195
  stage: 'complete',
197
196
  success: true,
198
197
  result: resultData,
199
- userNextSteps,
200
198
  docs: {
201
199
  gettingStarted: 'https://nx.dev/getting-started/intro',
202
200
  nxCloud: 'https://nx.dev/ci/intro/why-nx-cloud',
203
201
  },
204
202
  };
203
+ if (steps.length > 0) {
204
+ successResult.userNextSteps = {
205
+ description: 'CRITICAL: Show the user these exact steps to complete setup.',
206
+ steps,
207
+ };
208
+ }
205
209
  if (nxCloudError) {
206
210
  successResult.nxCloudError = nxCloudError;
207
211
  }
@@ -6,4 +6,7 @@ export declare function readNxCloudToken(directory: string): string;
6
6
  export declare function createNxCloudOnboardingUrl(nxCloud: NxCloud, token: string | undefined, directory: string, useGitHub?: boolean): Promise<string>;
7
7
  export declare function getNxCloudInfo(connectCloudUrl: string, pushedToVcs: VcsPushStatus, completionMessageKey?: CompletionMessageKey, workspaceName?: string): Promise<string>;
8
8
  export declare function getSkippedNxCloudInfo(): string;
9
- export declare function openCloudSetupUrl(connectUrl: string): Promise<void>;
9
+ export declare function openCloudSetupUrl(opts: {
10
+ connectUrl: string;
11
+ workspaceDirectory: string;
12
+ }): void;
@@ -87,15 +87,30 @@ function getSkippedNxCloudInfo() {
87
87
  out.success((0, messages_1.getSkippedCloudMessage)());
88
88
  return out.getOutput();
89
89
  }
90
- async function openCloudSetupUrl(connectUrl) {
90
+ function openCloudSetupUrl(opts) {
91
91
  if ((0, is_ci_1.isCI)()) {
92
92
  return;
93
93
  }
94
94
  try {
95
- const open = require('open');
96
- await open(connectUrl);
95
+ // Open through the workspace's own Nx rather than bundling a second opener
96
+ // here. Only the preset flow installs this CLI's version — `--template` and
97
+ // third-party presets install whatever Nx *they* pin, which may predate
98
+ // `openUrl`, so the optional call no-ops. The banner printed after this
99
+ // carries the URL either way.
100
+ //
101
+ // Load the bindings directly: `nx/src/native` is a loader shim that copies
102
+ // the multi-MB .node into a cache and loads the copy. The key is derived from
103
+ // cwd, which here is the parent of the new workspace, so nothing ever reuses
104
+ // it. Skipping the shim also loses its WASI ExperimentalWarning filter, but
105
+ // that only surfaces on the wasm fallback, where `openUrl` is a stub anyway.
106
+ // nx-ignore-next-line
107
+ const nativePath = require.resolve('nx/src/native/native-bindings.js', {
108
+ paths: [opts.workspaceDirectory],
109
+ });
110
+ const { openUrl } = require(nativePath);
111
+ openUrl?.(opts.connectUrl);
97
112
  }
98
113
  catch {
99
- // Fail gracefully — the URL is already displayed in the terminal banner
114
+ // Fail gracefully — the banner still carries the URL
100
115
  }
101
116
  }
@@ -237,16 +237,19 @@ function getPackageManagerVersion(packageManager, cwd = process.cwd()) {
237
237
  * Default to 'npm'
238
238
  */
239
239
  function detectInvokedPackageManager() {
240
- if (process.env.npm_config_user_agent) {
240
+ // Nested invocations (e.g. pnpm -> npx) can retain the parent's user agent.
241
+ // The executable identifies the manager that actually launched this process.
242
+ const executable = process.env.npm_execpath?.split(/[\\/]/).pop();
243
+ if (executable) {
241
244
  for (const pm of exports.packageManagerList) {
242
- if (process.env.npm_config_user_agent.startsWith(`${pm}/`)) {
245
+ if (new RegExp(`^${pm}(?:-cli|-[\\d.]+)?(?:\\.[cm]?js|\\.exe)?$`).test(executable)) {
243
246
  return pm;
244
247
  }
245
248
  }
246
249
  }
247
- if (process.env.npm_execpath) {
250
+ if (process.env.npm_config_user_agent) {
248
251
  for (const pm of exports.packageManagerList) {
249
- if (process.env.npm_execpath.split(node_path_1.sep).includes(pm)) {
252
+ if (process.env.npm_config_user_agent.startsWith(`${pm}/`)) {
250
253
  return pm;
251
254
  }
252
255
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-nx-workspace",
3
- "version": "23.3.0-rc.1",
3
+ "version": "24.0.0-beta.0",
4
4
  "private": false,
5
5
  "description": "Smart Monorepos · Fast Builds",
6
6
  "repository": {
@@ -40,7 +40,6 @@
40
40
  "@clack/prompts": "^1.7.0",
41
41
  "axios": "1.18.1",
42
42
  "chalk": "^4.1.0",
43
- "open": "^8.4.0",
44
43
  "ora": "^5.3.0",
45
44
  "tar-stream": "~2.2.0",
46
45
  "tmp": "~0.2.7",
@@ -1,7 +1,7 @@
1
- <p style="text-align: center;">
1
+ <p align="center">
2
2
  <picture>
3
- <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-dark.svg">
4
- <img alt="Nx - Smart Monorepos · Fast Builds" src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-light.svg" width="100%">
3
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-logo-light.svg">
4
+ <img alt="Nx Logo" src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-logo.svg" width="140">
5
5
  </picture>
6
6
  </p>
7
7