@nx/js 0.0.0-pr-22179-271588f → 0.0.0-pr-26482-ebe2dba

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.
Files changed (57) hide show
  1. package/LICENSE +1 -1
  2. package/babel.js +36 -16
  3. package/generators.json +6 -0
  4. package/migrations.json +39 -18
  5. package/package.json +8 -7
  6. package/src/executors/node/node.impl.js +24 -4
  7. package/src/executors/release-publish/extract-npm-publish-json-data.d.ts +5 -0
  8. package/src/executors/release-publish/extract-npm-publish-json-data.js +55 -0
  9. package/src/executors/release-publish/release-publish.impl.js +80 -35
  10. package/src/executors/swc/schema.json +7 -1
  11. package/src/executors/swc/swc.impl.js +10 -10
  12. package/src/executors/tsc/schema.json +2 -1
  13. package/src/executors/verdaccio/schema.d.ts +1 -1
  14. package/src/executors/verdaccio/schema.json +1 -2
  15. package/src/executors/verdaccio/verdaccio.impl.js +34 -20
  16. package/src/generators/init/init.js +4 -1
  17. package/src/generators/library/files/jest-config/jest.config.__ext__ +2 -2
  18. package/src/generators/library/library.js +46 -35
  19. package/src/generators/release-version/release-version.js +295 -52
  20. package/src/generators/release-version/schema.json +2 -2
  21. package/src/generators/release-version/utils/resolve-local-package-dependencies.d.ts +1 -2
  22. package/src/generators/release-version/utils/sort-projects-topologically.d.ts +2 -0
  23. package/src/generators/release-version/utils/sort-projects-topologically.js +48 -0
  24. package/src/generators/release-version/utils/update-lock-file.js +2 -0
  25. package/src/generators/sync/schema.d.ts +1 -0
  26. package/src/generators/sync/schema.json +8 -0
  27. package/src/generators/sync/sync.d.ts +3 -0
  28. package/src/generators/sync/sync.js +76 -0
  29. package/src/index.d.ts +2 -0
  30. package/src/index.js +5 -1
  31. package/src/internal.d.ts +1 -1
  32. package/src/internal.js +2 -1
  33. package/src/plugins/jest/start-local-registry.d.ts +3 -1
  34. package/src/plugins/jest/start-local-registry.js +3 -2
  35. package/src/plugins/rollup/type-definitions.d.ts +0 -1
  36. package/src/plugins/typescript/plugin.d.ts +13 -0
  37. package/src/plugins/typescript/plugin.js +348 -0
  38. package/src/utils/assets/copy-assets-handler.js +7 -6
  39. package/src/utils/buildable-libs-utils.js +6 -2
  40. package/src/utils/compiler-helper-dependency.js +1 -1
  41. package/src/utils/find-npm-dependencies.js +6 -4
  42. package/src/utils/is-valid-variable.d.ts +9 -0
  43. package/src/utils/is-valid-variable.js +39 -0
  44. package/src/utils/npm-config.d.ts +25 -0
  45. package/src/utils/npm-config.js +90 -0
  46. package/src/utils/package-json/update-package-json.d.ts +2 -1
  47. package/src/utils/package-json/update-package-json.js +17 -12
  48. package/src/utils/schema.d.ts +5 -0
  49. package/src/utils/swc/compile-swc.js +35 -10
  50. package/src/utils/swc/inline.js +4 -0
  51. package/src/utils/typescript/create-ts-config.js +10 -4
  52. package/src/utils/versions.d.ts +5 -5
  53. package/src/utils/versions.js +5 -5
  54. package/typescript.d.ts +1 -0
  55. package/typescript.js +6 -0
  56. package/src/migrations/update-15-8-0/rename-swcrc-config.d.ts +0 -2
  57. package/src/migrations/update-15-8-0/rename-swcrc-config.js +0 -77
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  (The MIT License)
2
2
 
3
- Copyright (c) 2017-2023 Narwhal Technologies Inc.
3
+ Copyright (c) 2017-2024 Narwhal Technologies Inc.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining
6
6
  a copy of this software and associated documentation files (the
package/babel.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const path_1 = require("path");
4
+ const semver_1 = require("semver");
4
5
  const devkit_1 = require("@nx/devkit");
5
6
  module.exports = function (api, options = {}) {
6
7
  api.assertVersion(7);
@@ -12,10 +13,10 @@ module.exports = function (api, options = {}) {
12
13
  const emitDecoratorMetadata = api.caller((caller) => caller?.emitDecoratorMetadata ?? true);
13
14
  // Determine settings for `@babel//babel-plugin-transform-class-properties`,
14
15
  // so that we can sync the `loose` option with `@babel/preset-env`.
15
- // TODO(v19): Remove classProperties since it's no longer needed, now that the class props transform is in preset-env.
16
+ // TODO(v20): Remove classProperties since it's no longer needed, now that the class props transform is in preset-env.
16
17
  const loose = options.classProperties?.loose ?? options.loose ?? true;
17
18
  if (options.classProperties) {
18
- devkit_1.logger.warn(`Use =\`loose\` option instead of \`classProperties.loose\`. The \`classProperties\` option will be removed in Nx 19`);
19
+ devkit_1.logger.warn(`Use =\`loose\` option instead of \`classProperties.loose\`. The \`classProperties\` option will be removed in Nx 20`);
19
20
  }
20
21
  return {
21
22
  presets: [
@@ -26,20 +27,8 @@ module.exports = function (api, options = {}) {
26
27
  // All other options will fail in Jest since Node does not support some ES features
27
28
  // such as import syntax.
28
29
  isTest || process.env.NODE_ENV === 'test' || process.env.JEST_WORKER_ID
29
- ? { targets: { node: 'current' }, loose: true }
30
- : {
31
- // Allow importing core-js in entrypoint and use browserslist to select polyfills.
32
- useBuiltIns: options.useBuiltIns ?? 'entry',
33
- corejs: options.useBuiltIns !== false ? 3 : null,
34
- // Do not transform modules to CJS
35
- modules: false,
36
- targets: isModern ? { esmodules: 'intersect' } : undefined,
37
- bugfixes: true,
38
- // Exclude transforms that make all code slower
39
- exclude: ['transform-typeof-symbol'],
40
- // This must match the setting for `@babel/plugin-proposal-class-properties`
41
- loose,
42
- },
30
+ ? { targets: { node: 'current' }, loose }
31
+ : createBabelPresetEnvOptions(options.useBuiltIns, isModern, loose),
43
32
  ],
44
33
  [
45
34
  require.resolve('@babel/preset-typescript'),
@@ -89,3 +78,34 @@ module.exports = function (api, options = {}) {
89
78
  ],
90
79
  };
91
80
  };
81
+ function createBabelPresetEnvOptions(useBuiltIns, isModern, loose) {
82
+ const presetOptions = {
83
+ // Do not transform modules to CJS
84
+ modules: false,
85
+ targets: isModern ? { esmodules: 'intersect' } : undefined,
86
+ bugfixes: true,
87
+ // Exclude transforms that make all code slower
88
+ exclude: ['transform-typeof-symbol'],
89
+ // This must match the setting for `@babel/plugin-proposal-class-properties`
90
+ loose,
91
+ };
92
+ // If core-js is installed then set corresponding options, otherwise don't use core-js.
93
+ // Previously, core-js was required for all projects, but it is not longer required when using only stable JS features that does not need to be transpiled.
94
+ const coreJsVersion = findCoreJsVersion();
95
+ if (coreJsVersion) {
96
+ presetOptions.useBuiltIns = useBuiltIns ?? 'entry';
97
+ presetOptions.corejs = useBuiltIns !== false ? coreJsVersion : null;
98
+ }
99
+ return presetOptions;
100
+ }
101
+ function findCoreJsVersion() {
102
+ try {
103
+ // nx-ignore-next-line
104
+ const v = require('core-js/package.json').version;
105
+ const { major, minor } = (0, semver_1.parse)(v);
106
+ return `${major}.${minor}`;
107
+ }
108
+ catch (e) {
109
+ return null;
110
+ }
111
+ }
package/generators.json CHANGED
@@ -41,6 +41,12 @@
41
41
  "schema": "./src/generators/setup-build/schema.json",
42
42
  "alias": ["build"],
43
43
  "description": "setup-build generator"
44
+ },
45
+ "sync": {
46
+ "factory": "./src/generators/sync/sync#syncGenerator",
47
+ "schema": "./src/generators/sync/schema.json",
48
+ "description": "Synchronize TypeScript project references based on the project graph",
49
+ "hidden": true
44
50
  }
45
51
  }
46
52
  }
package/migrations.json CHANGED
@@ -1,11 +1,5 @@
1
1
  {
2
2
  "generators": {
3
- "rename-swcrc-config": {
4
- "cli": "nx",
5
- "version": "15.8.0-beta.0",
6
- "description": "Rename .lib.swcrc to .swcrc for better SWC support throughout the workspace",
7
- "factory": "./src/migrations/update-15-8-0/rename-swcrc-config"
8
- },
9
3
  "update-16-0-0-add-nx-packages": {
10
4
  "cli": "nx",
11
5
  "version": "16.0.0-beta.1",
@@ -32,18 +26,6 @@
32
26
  }
33
27
  },
34
28
  "packageJsonUpdates": {
35
- "15.8.0": {
36
- "version": "15.8.0-beta.2",
37
- "x-prompt": "Do you want to update to TypeScript v4.9?",
38
- "requires": {
39
- "typescript": ">=4.8.2 <4.9.0"
40
- },
41
- "packages": {
42
- "typescript": {
43
- "version": "~4.9.5"
44
- }
45
- }
46
- },
47
29
  "16.0.0": {
48
30
  "version": "16.0.0-beta.3",
49
31
  "packages": {
@@ -154,6 +136,45 @@
154
136
  "alwaysAddToPackageJson": false
155
137
  }
156
138
  }
139
+ },
140
+ "18.2.0": {
141
+ "version": "18.2.0-beta.0",
142
+ "x-prompt": "Do you want to update to TypeScript v5.4?",
143
+ "requires": {
144
+ "typescript": ">=5.3.0 <5.4.0"
145
+ },
146
+ "packages": {
147
+ "typescript": {
148
+ "version": "~5.4.2",
149
+ "alwaysAddToPackageJson": false
150
+ }
151
+ }
152
+ },
153
+ "19.0.0": {
154
+ "version": "19.0.0-beta.0",
155
+ "packages": {
156
+ "@swc/cli": {
157
+ "version": "~0.3.12",
158
+ "alwaysAddToPackageJson": false
159
+ }
160
+ }
161
+ },
162
+ "19.2.0": {
163
+ "version": "19.2.0-beta.0",
164
+ "packages": {
165
+ "@swc/core": {
166
+ "version": "~1.5.7",
167
+ "alwaysAddToPackageJson": false
168
+ },
169
+ "@swc/helpers": {
170
+ "version": "~0.5.11",
171
+ "alwaysAddToPackageJson": false
172
+ },
173
+ "@swc-node/register": {
174
+ "version": "~1.9.1",
175
+ "alwaysAddToPackageJson": false
176
+ }
177
+ }
157
178
  }
158
179
  }
159
180
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/js",
3
- "version": "0.0.0-pr-22179-271588f",
3
+ "version": "0.0.0-pr-26482-ebe2dba",
4
4
  "private": false,
5
5
  "description": "The JS plugin for Nx contains executors and generators that provide the best experience for developing JavaScript and TypeScript projects. ",
6
6
  "repository": {
@@ -14,9 +14,11 @@
14
14
  "Node",
15
15
  "Swc",
16
16
  "Tsc",
17
- "CLI"
17
+ "CLI",
18
+ "Front-end",
19
+ "Backend"
18
20
  ],
19
- "main": "./src/index.js",
21
+ "main": "src/index.js",
20
22
  "typings": "src/index.d.ts",
21
23
  "license": "MIT",
22
24
  "bugs": {
@@ -37,7 +39,6 @@
37
39
  "@babel/preset-env": "^7.23.2",
38
40
  "@babel/preset-typescript": "^7.22.5",
39
41
  "@babel/runtime": "^7.22.6",
40
- "@phenomnomnominal/tsquery": "~5.0.1",
41
42
  "babel-plugin-const-enum": "^1.0.1",
42
43
  "babel-plugin-macros": "^2.8.0",
43
44
  "babel-plugin-transform-typescript-metadata": "^0.3.1",
@@ -57,9 +58,9 @@
57
58
  "semver": "^7.5.3",
58
59
  "source-map-support": "0.5.19",
59
60
  "tslib": "^2.3.0",
60
- "@nx/devkit": "0.0.0-pr-22179-271588f",
61
- "@nx/workspace": "0.0.0-pr-22179-271588f",
62
- "@nrwl/js": "0.0.0-pr-22179-271588f"
61
+ "@nx/devkit": "0.0.0-pr-26482-ebe2dba",
62
+ "@nx/workspace": "0.0.0-pr-26482-ebe2dba",
63
+ "@nrwl/js": "0.0.0-pr-26482-ebe2dba"
63
64
  },
64
65
  "peerDependencies": {
65
66
  "verdaccio": "^5.0.4"
@@ -13,6 +13,7 @@ const buildable_libs_utils_1 = require("../../utils/buildable-libs-utils");
13
13
  const kill_tree_1 = require("./lib/kill-tree");
14
14
  const fileutils_1 = require("nx/src/utils/fileutils");
15
15
  const get_main_file_dir_1 = require("../../utils/get-main-file-dir");
16
+ const utils_1 = require("nx/src/tasks-runner/utils");
16
17
  function debounce(fn, wait) {
17
18
  let timeoutId;
18
19
  return () => {
@@ -36,6 +37,7 @@ async function* nodeExecutor(options, context) {
36
37
  const buildOptions = {
37
38
  ...(0, devkit_1.readTargetOptions)(buildTarget, context),
38
39
  ...options.buildTargetOptions,
40
+ target: buildTarget.target,
39
41
  };
40
42
  if (options.waitUntilTargets && options.waitUntilTargets.length > 0) {
41
43
  const results = await runWaitUntilTargets(options, context);
@@ -61,7 +63,7 @@ async function* nodeExecutor(options, context) {
61
63
  await previousTask?.stop('SIGTERM');
62
64
  await task.start();
63
65
  };
64
- const debouncedProcessQueue = debounce(processQueue, options.debounce ?? 1000);
66
+ const debouncedProcessQueue = debounce(processQueue, options.debounce ?? 1_000);
65
67
  const addToQueue = async (childProcess, buildResult) => {
66
68
  const task = {
67
69
  id: (0, crypto_1.randomUUID)(),
@@ -112,8 +114,14 @@ async function* nodeExecutor(options, context) {
112
114
  if (options.watch && !task.killed) {
113
115
  devkit_1.logger.info(`NX Process exited with code ${code}, waiting for changes to restart...`);
114
116
  }
115
- if (!options.watch)
116
- done();
117
+ if (!options.watch) {
118
+ if (code !== 0) {
119
+ error(new Error(`Process exited with code ${code}`));
120
+ }
121
+ else {
122
+ done();
123
+ }
124
+ }
117
125
  resolve();
118
126
  });
119
127
  next({ success: true, options: buildOptions });
@@ -257,6 +265,18 @@ function getFileToRun(context, project, buildOptions, buildTargetExecutor) {
257
265
  // If using run-commands or another custom executor, then user should set
258
266
  // outputFileName, but we can try the default value that we use.
259
267
  if (!buildOptions?.outputPath && !buildOptions?.outputFileName) {
268
+ // If we are using crystal for infering the target, we can use the output path from the target.
269
+ // Since the output path has a token for the project name, we need to interpolate it.
270
+ // {workspaceRoot}/dist/{projectRoot} -> dist/my-app
271
+ const outputPath = project.data.targets[buildOptions.target]?.outputs?.[0];
272
+ if (outputPath) {
273
+ const outputFilePath = (0, utils_1.interpolate)(outputPath, {
274
+ projectName: project.name,
275
+ projectRoot: project.data.root,
276
+ workspaceRoot: '',
277
+ });
278
+ return path.join(outputFilePath, 'main.js');
279
+ }
260
280
  const fallbackFile = path.join('dist', project.data.root, 'main.js');
261
281
  devkit_1.logger.warn(`Build option ${chalk.bold('outputFileName')} not set for ${chalk.bold(project.name)}. Using fallback value of ${chalk.bold(fallbackFile)}.`);
262
282
  return (0, path_1.join)(context.root, fallbackFile);
@@ -277,7 +297,7 @@ function getFileToRun(context, project, buildOptions, buildTargetExecutor) {
277
297
  function fileToRunCorrectPath(fileToRun) {
278
298
  if ((0, fileutils_1.fileExists)(fileToRun))
279
299
  return fileToRun;
280
- const extensionsToTry = ['.cjs', '.mjs', 'cjs.js', '.esm.js'];
300
+ const extensionsToTry = ['.cjs', '.mjs', '.cjs.js', '.esm.js'];
281
301
  for (const ext of extensionsToTry) {
282
302
  const file = fileToRun.replace(/\.js$/, ext);
283
303
  if ((0, fileutils_1.fileExists)(file))
@@ -0,0 +1,5 @@
1
+ export declare function extractNpmPublishJsonData(str: string): {
2
+ beforeJsonData: string;
3
+ jsonData: Record<string, unknown> | null;
4
+ afterJsonData: string;
5
+ };
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extractNpmPublishJsonData = void 0;
4
+ const expectedNpmPublishJsonKeys = [
5
+ 'id',
6
+ 'name',
7
+ 'version',
8
+ 'size',
9
+ 'filename',
10
+ ];
11
+ // Regular expression to match JSON-like objects, including nested objects (which the expected npm publish output will have, e.g. in its "files" array)
12
+ // /{(?:[^{}]|{[^{}]*})*}/g
13
+ // /{ : Matches the opening brace of a JSON object
14
+ // (?: ) : Non-capturing group to apply quantifiers
15
+ // [^{}] : Matches any character except for braces
16
+ // | : OR
17
+ // {[^{}]*} : Matches nested JSON objects
18
+ // * : The non-capturing group (i.e. any character except for braces OR nested JSON objects) can repeat zero or more times
19
+ // } : Matches the closing brace of a JSON object
20
+ // /g : Global flag to match all occurrences in the string
21
+ const jsonRegex = /{(?:[^{}]|{[^{}]*})*}/g;
22
+ function extractNpmPublishJsonData(str) {
23
+ const jsonMatches = str.match(jsonRegex);
24
+ if (jsonMatches) {
25
+ for (const match of jsonMatches) {
26
+ // Cheap upfront check to see if the stringified JSON data has the expected keys as substrings
27
+ if (!expectedNpmPublishJsonKeys.every((key) => str.includes(key))) {
28
+ continue;
29
+ }
30
+ // Full JSON parsing to identify the JSON object
31
+ try {
32
+ const parsedJson = JSON.parse(match);
33
+ if (!expectedNpmPublishJsonKeys.every((key) => parsedJson[key] !== undefined)) {
34
+ continue;
35
+ }
36
+ const jsonStartIndex = str.indexOf(match);
37
+ return {
38
+ beforeJsonData: str.slice(0, jsonStartIndex),
39
+ jsonData: parsedJson,
40
+ afterJsonData: str.slice(jsonStartIndex + match.length),
41
+ };
42
+ }
43
+ catch {
44
+ // Ignore parsing errors for unrelated JSON blocks
45
+ }
46
+ }
47
+ }
48
+ // No applicable jsonData detected, the whole contents is the beforeJsonData
49
+ return {
50
+ beforeJsonData: str,
51
+ jsonData: null,
52
+ afterJsonData: '',
53
+ };
54
+ }
55
+ exports.extractNpmPublishJsonData = extractNpmPublishJsonData;
@@ -3,8 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const devkit_1 = require("@nx/devkit");
4
4
  const child_process_1 = require("child_process");
5
5
  const npm_run_path_1 = require("npm-run-path");
6
+ const path_1 = require("path");
7
+ const npm_config_1 = require("../../utils/npm-config");
6
8
  const log_tar_1 = require("./log-tar");
7
9
  const chalk = require("chalk");
10
+ const extract_npm_publish_json_data_1 = require("./extract-npm-publish-json-data");
8
11
  const LARGE_BUFFER = 1024 * 1000000;
9
12
  function processEnv(color) {
10
13
  const env = {
@@ -23,40 +26,36 @@ async function runExecutor(options, context) {
23
26
  */
24
27
  const isDryRun = process.env.NX_DRY_RUN === 'true' || options.dryRun || false;
25
28
  const projectConfig = context.projectsConfigurations.projects[context.projectName];
26
- const packageRoot = (0, devkit_1.joinPathFragments)(context.root, options.packageRoot ?? projectConfig.root);
27
- const packageJsonPath = (0, devkit_1.joinPathFragments)(packageRoot, 'package.json');
28
- const projectPackageJson = (0, devkit_1.readJsonFile)(packageJsonPath);
29
- const packageName = projectPackageJson.name;
29
+ const packageRoot = (0, path_1.join)(context.root, options.packageRoot ?? projectConfig.root);
30
+ const packageJsonPath = (0, path_1.join)(packageRoot, 'package.json');
31
+ const packageJson = (0, devkit_1.readJsonFile)(packageJsonPath);
32
+ const packageName = packageJson.name;
30
33
  // If package and project name match, we can make log messages terser
31
34
  let packageTxt = packageName === context.projectName
32
35
  ? `package "${packageName}"`
33
36
  : `package "${packageName}" from project "${context.projectName}"`;
34
- if (projectPackageJson.private === true) {
37
+ if (packageJson.private === true) {
35
38
  console.warn(`Skipped ${packageTxt}, because it has \`"private": true\` in ${packageJsonPath}`);
36
39
  return {
37
40
  success: true,
38
41
  };
39
42
  }
40
- const npmPublishCommandSegments = [`npm publish --json`];
43
+ const warnFn = (message) => {
44
+ console.log(chalk.keyword('orange')(message));
45
+ };
46
+ const { registry, tag, registryConfigKey } = await (0, npm_config_1.parseRegistryOptions)(context.root, {
47
+ packageRoot,
48
+ packageJson,
49
+ }, {
50
+ registry: options.registry,
51
+ tag: options.tag,
52
+ }, warnFn);
41
53
  const npmViewCommandSegments = [
42
- `npm view ${packageName} versions dist-tags --json`,
54
+ `npm view ${packageName} versions dist-tags --json --"${registryConfigKey}=${registry}"`,
55
+ ];
56
+ const npmDistTagAddCommandSegments = [
57
+ `npm dist-tag add ${packageName}@${packageJson.version} ${tag} --"${registryConfigKey}=${registry}"`,
43
58
  ];
44
- if (options.registry) {
45
- npmPublishCommandSegments.push(`--registry=${options.registry}`);
46
- npmViewCommandSegments.push(`--registry=${options.registry}`);
47
- }
48
- if (options.tag) {
49
- npmPublishCommandSegments.push(`--tag=${options.tag}`);
50
- }
51
- if (options.otp) {
52
- npmPublishCommandSegments.push(`--otp=${options.otp}`);
53
- }
54
- if (isDryRun) {
55
- npmPublishCommandSegments.push(`--dry-run`);
56
- }
57
- // Resolve values using the `npm config` command so that things like environment variables and `publishConfig`s are accounted for
58
- const registry = options.registry ?? (0, child_process_1.execSync)(`npm config get registry`).toString().trim();
59
- const tag = options.tag ?? (0, child_process_1.execSync)(`npm config get tag`).toString().trim();
60
59
  /**
61
60
  * In a dry-run scenario, it is most likely that all commands are being run with dry-run, therefore
62
61
  * the most up to date/relevant version might not exist on disk for us to read and make the npm view
@@ -66,11 +65,11 @@ async function runExecutor(options, context) {
66
65
  * perform the npm view step, and just show npm publish's dry-run output.
67
66
  */
68
67
  if (!isDryRun && !options.firstRelease) {
69
- const currentVersion = projectPackageJson.version;
68
+ const currentVersion = packageJson.version;
70
69
  try {
71
70
  const result = (0, child_process_1.execSync)(npmViewCommandSegments.join(' '), {
72
71
  env: processEnv(true),
73
- cwd: packageRoot,
72
+ cwd: context.root,
74
73
  stdio: ['ignore', 'pipe', 'pipe'],
75
74
  });
76
75
  const resultJson = JSON.parse(result.toString());
@@ -81,12 +80,16 @@ async function runExecutor(options, context) {
81
80
  success: true,
82
81
  };
83
82
  }
84
- if (resultJson.versions.includes(currentVersion)) {
83
+ // If only one version of a package exists in the registry, versions will be a string instead of an array.
84
+ const versions = Array.isArray(resultJson.versions)
85
+ ? resultJson.versions
86
+ : [resultJson.versions];
87
+ if (versions.includes(currentVersion)) {
85
88
  try {
86
89
  if (!isDryRun) {
87
- (0, child_process_1.execSync)(`npm dist-tag add ${packageName}@${currentVersion} ${tag} --registry=${registry}`, {
90
+ (0, child_process_1.execSync)(npmDistTagAddCommandSegments.join(' '), {
88
91
  env: processEnv(true),
89
- cwd: packageRoot,
92
+ cwd: context.root,
90
93
  stdio: 'ignore',
91
94
  });
92
95
  console.log(`Added the dist-tag ${tag} to v${currentVersion} for registry ${registry}.\n`);
@@ -148,17 +151,56 @@ async function runExecutor(options, context) {
148
151
  if (options.firstRelease && context.isVerbose) {
149
152
  console.log('Skipped npm view because --first-release was set');
150
153
  }
154
+ /**
155
+ * NOTE: If this is ever changed away from running the command at the workspace root and pointing at the package root (e.g. back
156
+ * to running from the package root directly), then special attention should be paid to the fact that npm publish will nest its
157
+ * JSON output under the name of the package in that case (and it would need to be handled below).
158
+ */
159
+ const npmPublishCommandSegments = [
160
+ `npm publish "${packageRoot}" --json --"${registryConfigKey}=${registry}" --tag=${tag}`,
161
+ ];
162
+ if (options.otp) {
163
+ npmPublishCommandSegments.push(`--otp=${options.otp}`);
164
+ }
165
+ if (isDryRun) {
166
+ npmPublishCommandSegments.push(`--dry-run`);
167
+ }
151
168
  try {
152
169
  const output = (0, child_process_1.execSync)(npmPublishCommandSegments.join(' '), {
153
170
  maxBuffer: LARGE_BUFFER,
154
171
  env: processEnv(true),
155
- cwd: packageRoot,
172
+ cwd: context.root,
156
173
  stdio: ['ignore', 'pipe', 'pipe'],
157
174
  });
158
- const stdoutData = JSON.parse(output.toString());
159
- // If npm workspaces are in use, the publish output will nest the data under the package name, so we normalize it first
160
- const normalizedStdoutData = stdoutData[packageName] ?? stdoutData;
161
- (0, log_tar_1.logTar)(normalizedStdoutData);
175
+ /**
176
+ * We cannot JSON.parse the output directly because if the user is using lifecycle scripts, npm will mix its publish output with the JSON output all on stdout.
177
+ * Additionally, we want to capture and show the lifecycle script outputs as beforeJsonData and afterJsonData and print them accordingly below.
178
+ */
179
+ const { beforeJsonData, jsonData, afterJsonData } = (0, extract_npm_publish_json_data_1.extractNpmPublishJsonData)(output.toString());
180
+ if (!jsonData) {
181
+ console.error('The npm publish output data could not be extracted. Please report this issue on https://github.com/nrwl/nx');
182
+ return {
183
+ success: false,
184
+ };
185
+ }
186
+ // If in dry-run mode, the version on disk will not represent the version that would be published, so we scrub it from the output to avoid confusion.
187
+ const dryRunVersionPlaceholder = 'X.X.X-dry-run';
188
+ if (isDryRun) {
189
+ for (const [key, val] of Object.entries(jsonData)) {
190
+ if (typeof val !== 'string') {
191
+ continue;
192
+ }
193
+ jsonData[key] = val.replace(new RegExp(packageJson.version, 'g'), dryRunVersionPlaceholder);
194
+ }
195
+ }
196
+ if (typeof beforeJsonData === 'string' &&
197
+ beforeJsonData.trim().length > 0) {
198
+ console.log(beforeJsonData);
199
+ }
200
+ (0, log_tar_1.logTar)(jsonData);
201
+ if (typeof afterJsonData === 'string' && afterJsonData.trim().length > 0) {
202
+ console.log(afterJsonData);
203
+ }
162
204
  if (isDryRun) {
163
205
  console.log(`Would publish to ${registry} with tag "${tag}", but ${chalk.keyword('orange')('[dry-run]')} was set`);
164
206
  }
@@ -173,16 +215,19 @@ async function runExecutor(options, context) {
173
215
  try {
174
216
  const stdoutData = JSON.parse(err.stdout?.toString() || '{}');
175
217
  console.error('npm publish error:');
176
- if (stdoutData.error.summary) {
218
+ if (stdoutData.error?.summary) {
177
219
  console.error(stdoutData.error.summary);
178
220
  }
179
- if (stdoutData.error.detail) {
221
+ if (stdoutData.error?.detail) {
180
222
  console.error(stdoutData.error.detail);
181
223
  }
182
224
  if (context.isVerbose) {
183
225
  console.error('npm publish stdout:');
184
226
  console.error(JSON.stringify(stdoutData, null, 2));
185
227
  }
228
+ if (!stdoutData.error) {
229
+ throw err;
230
+ }
186
231
  return {
187
232
  success: false,
188
233
  };
@@ -97,7 +97,8 @@
97
97
  "type": "string"
98
98
  }
99
99
  }
100
- ]
100
+ ],
101
+ "x-deprecated": "Make sure all dependencies are buildable by running `nx g @nx/js:setup-build`. This option will be removed in Nx 20."
101
102
  },
102
103
  "externalBuildTargets": {
103
104
  "type": "array",
@@ -114,6 +115,11 @@
114
115
  "x-priority": "internal"
115
116
  }
116
117
  },
118
+ "stripLeadingPaths": {
119
+ "type": "boolean",
120
+ "description": "Remove leading directory from output (e.g. src). See: https://swc.rs/docs/usage/cli#--strip-leading-paths",
121
+ "default": false
122
+ },
117
123
  "required": ["main", "outputPath", "tsConfig"],
118
124
  "definitions": {
119
125
  "assetPattern": {
@@ -35,19 +35,15 @@ function normalizeOptions(options, root, sourceRoot, projectRoot) {
35
35
  }
36
36
  }
37
37
  const files = (0, assets_1.assetGlobsToFiles)(options.assets, root, outputPath);
38
- const projectRootParts = projectRoot.split('/');
39
- // We pop the last part of the `projectRoot` to pass
40
- // the last part (projectDir) and the remainder (projectRootParts) to swc
41
- const projectDir = projectRootParts.pop();
42
- // default to current directory if projectRootParts is [].
43
- // Eg: when a project is at the root level, outside of layout dir
44
- const swcCwd = projectRootParts.join('/') || '.';
38
+ // Always execute from root of project, same as with SWC CLI.
39
+ const swcCwd = (0, path_1.join)(root, projectRoot);
45
40
  const { swcrcPath, tmpSwcrcPath } = (0, get_swcrc_path_1.getSwcrcPath)(options, root, projectRoot);
46
41
  const swcCliOptions = {
47
- srcPath: projectDir,
48
- destPath: (0, path_1.relative)((0, path_1.join)(root, swcCwd), outputPath),
42
+ srcPath: projectRoot,
43
+ destPath: (0, path_1.relative)(swcCwd, outputPath),
49
44
  swcCwd,
50
45
  swcrcPath,
46
+ stripLeadingPaths: Boolean(options.stripLeadingPaths),
51
47
  };
52
48
  return {
53
49
  ...options,
@@ -76,10 +72,14 @@ async function* swcExecutor(_options, context) {
76
72
  }
77
73
  const inlineProjectGraph = (0, inline_1.handleInliningBuild)(context, options, options.tsConfig);
78
74
  if (!(0, inline_1.isInlineGraphEmpty)(inlineProjectGraph)) {
75
+ if (options.stripLeadingPaths) {
76
+ throw new Error(`Cannot use --strip-leading-paths with inlining.`);
77
+ }
79
78
  options.projectRoot = '.'; // set to root of workspace to include other libs for type check
80
79
  // remap paths for SWC compilation
81
- options.swcCliOptions.srcPath = options.swcCliOptions.swcCwd;
80
+ options.inline = true;
82
81
  options.swcCliOptions.swcCwd = '.';
82
+ options.swcCliOptions.srcPath = options.swcCliOptions.swcCwd;
83
83
  options.swcCliOptions.destPath = (0, path_1.join)(options.swcCliOptions.destPath.split((0, path_1.normalize)('../')).at(-1), options.swcCliOptions.srcPath);
84
84
  // tmp swcrc with dependencies to exclude
85
85
  // - buildable libraries
@@ -85,7 +85,8 @@
85
85
  "type": "string"
86
86
  }
87
87
  }
88
- ]
88
+ ],
89
+ "x-deprecated": "Make sure all dependencies are buildable by running `nx g @nx/js:setup-build`. This option will be removed in Nx 20."
89
90
  },
90
91
  "externalBuildTargets": {
91
92
  "type": "array",
@@ -1,7 +1,7 @@
1
1
  export interface VerdaccioExecutorSchema {
2
2
  location: 'global' | 'user' | 'project' | 'none';
3
3
  storage?: string;
4
- port: number;
4
+ port?: number;
5
5
  config?: string;
6
6
  clear?: boolean;
7
7
  }
@@ -18,8 +18,7 @@
18
18
  },
19
19
  "port": {
20
20
  "type": "number",
21
- "description": "Port of local registry that Verdaccio should listen to",
22
- "default": 4873
21
+ "description": "Port of local registry that Verdaccio should listen to"
23
22
  },
24
23
  "config": {
25
24
  "type": "string",