@storm-software/workspace-tools 1.269.0 → 1.270.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.
Files changed (274) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/README.md +2 -1
  3. package/dist/chunk-A7JGVU4P.js +468 -0
  4. package/dist/chunk-SRN4D7WO.mjs +468 -0
  5. package/dist/executors.js +2 -2
  6. package/dist/executors.mjs +1 -1
  7. package/dist/index.js +2 -2
  8. package/dist/index.mjs +1 -1
  9. package/dist/src/executors/npm-publish/executor.js +2 -2
  10. package/dist/src/executors/npm-publish/executor.mjs +1 -1
  11. package/docs/executors/rollup.md +88 -0
  12. package/executors.ts +23 -0
  13. package/generators.ts +14 -0
  14. package/index.ts +5 -0
  15. package/package.json +4 -4
  16. package/project.json +58 -0
  17. package/src/base/base-executor.ts +200 -0
  18. package/src/base/base-executor.untyped.ts +18 -0
  19. package/src/base/base-generator.ts +130 -0
  20. package/src/base/base-generator.untyped.ts +16 -0
  21. package/src/base/cargo-base-executor.untyped.ts +73 -0
  22. package/src/base/index.ts +8 -0
  23. package/src/base/typescript-build-executor.untyped.ts +153 -0
  24. package/src/base/typescript-library-generator.ts +415 -0
  25. package/src/base/typescript-library-generator.untyped.ts +106 -0
  26. package/src/executors/cargo-build/executor.spec.ts +18 -0
  27. package/src/executors/cargo-build/executor.ts +28 -0
  28. package/src/executors/cargo-build/untyped.ts +18 -0
  29. package/src/executors/cargo-check/executor.spec.ts +18 -0
  30. package/src/executors/cargo-check/executor.ts +27 -0
  31. package/src/executors/cargo-check/untyped.ts +11 -0
  32. package/src/executors/cargo-clippy/executor.spec.ts +18 -0
  33. package/src/executors/cargo-clippy/executor.ts +28 -0
  34. package/src/executors/cargo-clippy/untyped.ts +18 -0
  35. package/src/executors/cargo-doc/executor.spec.ts +18 -0
  36. package/src/executors/cargo-doc/executor.ts +39 -0
  37. package/src/executors/cargo-doc/untyped.ts +44 -0
  38. package/src/executors/cargo-format/executor.spec.ts +18 -0
  39. package/src/executors/cargo-format/executor.ts +28 -0
  40. package/src/executors/cargo-format/untyped.ts +11 -0
  41. package/src/executors/cargo-publish/executor.spec.ts +11 -0
  42. package/src/executors/cargo-publish/executor.ts +139 -0
  43. package/src/executors/cargo-publish/untyped.ts +33 -0
  44. package/src/executors/clean-package/constants.ts +99 -0
  45. package/src/executors/clean-package/executor.spec.ts +18 -0
  46. package/src/executors/clean-package/executor.ts +214 -0
  47. package/src/executors/clean-package/types.ts +6 -0
  48. package/src/executors/clean-package/untyped.ts +60 -0
  49. package/src/executors/clean-package/utils.ts +85 -0
  50. package/src/executors/esbuild/executor.spec.ts +11 -0
  51. package/src/executors/esbuild/executor.ts +67 -0
  52. package/src/executors/esbuild/untyped.ts +20 -0
  53. package/src/executors/npm-publish/executor.spec.ts +11 -0
  54. package/src/executors/npm-publish/executor.ts +681 -0
  55. package/src/executors/npm-publish/untyped.ts +56 -0
  56. package/src/executors/size-limit/executor.spec.ts +18 -0
  57. package/src/executors/size-limit/executor.ts +88 -0
  58. package/src/executors/size-limit/untyped.ts +22 -0
  59. package/src/executors/typia/executor.ts +54 -0
  60. package/src/executors/typia/untyped.ts +48 -0
  61. package/src/executors/unbuild/executor.spec.ts +11 -0
  62. package/src/executors/unbuild/executor.ts +136 -0
  63. package/src/executors/unbuild/untyped.ts +152 -0
  64. package/src/generators/browser-library/generator.spec.ts +20 -0
  65. package/src/generators/browser-library/generator.ts +109 -0
  66. package/src/generators/browser-library/untyped.ts +29 -0
  67. package/src/generators/config-schema/generator.spec.ts +20 -0
  68. package/src/generators/config-schema/generator.ts +90 -0
  69. package/src/generators/config-schema/untyped.ts +19 -0
  70. package/src/generators/init/init.ts +32 -0
  71. package/src/generators/init/untyped.ts +16 -0
  72. package/src/generators/neutral-library/generator.spec.ts +20 -0
  73. package/src/generators/neutral-library/generator.ts +81 -0
  74. package/src/generators/neutral-library/untyped.ts +29 -0
  75. package/src/generators/node-library/generator.spec.ts +20 -0
  76. package/src/generators/node-library/generator.ts +84 -0
  77. package/src/generators/node-library/untyped.ts +29 -0
  78. package/src/generators/preset/files/.all-contributorsrc.template +48 -0
  79. package/src/generators/preset/files/.editorconfig +454 -0
  80. package/src/generators/preset/files/.env.template +38 -0
  81. package/src/generators/preset/files/.gitattributes +52 -0
  82. package/src/generators/preset/files/.github/.nvmrc +1 -0
  83. package/src/generators/preset/files/.github/CODEOWNERS +3 -0
  84. package/src/generators/preset/files/.github/CODE_OF_CONDUCT.md +125 -0
  85. package/src/generators/preset/files/.github/CONTRIBUTING.md.template +15 -0
  86. package/src/generators/preset/files/.github/FUNDING.yml +3 -0
  87. package/src/generators/preset/files/.github/ISSUE_TEMPLATE/bug-report.yml.template +102 -0
  88. package/src/generators/preset/files/.github/ISSUE_TEMPLATE/documentation.yml.template +56 -0
  89. package/src/generators/preset/files/.github/ISSUE_TEMPLATE/feature-request.yml.template +60 -0
  90. package/src/generators/preset/files/.github/PULL_REQUEST_TEMPLATE.md.template +39 -0
  91. package/src/generators/preset/files/.github/SECURITY.md +9 -0
  92. package/src/generators/preset/files/.github/codecov.yml +29 -0
  93. package/src/generators/preset/files/.github/dependabot.yml +64 -0
  94. package/src/generators/preset/files/.github/labels.yml +84 -0
  95. package/src/generators/preset/files/.github/renovate.json +4 -0
  96. package/src/generators/preset/files/.github/renovate.json.template +63 -0
  97. package/src/generators/preset/files/.github/stale.yml +55 -0
  98. package/src/generators/preset/files/.github/workflows/build-release.yml.template +25 -0
  99. package/src/generators/preset/files/.github/workflows/code-review.yml +18 -0
  100. package/src/generators/preset/files/.github/workflows/codeql.yml +84 -0
  101. package/src/generators/preset/files/.github/workflows/dependabot-update.yml +32 -0
  102. package/src/generators/preset/files/.github/workflows/git-guardian.yml +23 -0
  103. package/src/generators/preset/files/.github/workflows/greetings.yml +31 -0
  104. package/src/generators/preset/files/.github/workflows/labels.yml +31 -0
  105. package/src/generators/preset/files/.github/workflows/lock.yml +26 -0
  106. package/src/generators/preset/files/.log4brains.yml.template +5 -0
  107. package/src/generators/preset/files/.markdownlint.json +155 -0
  108. package/src/generators/preset/files/.verdaccio/config.yml.template +40 -0
  109. package/src/generators/preset/files/.vscode/README.md +32 -0
  110. package/src/generators/preset/files/.vscode/cspell.json +3 -0
  111. package/src/generators/preset/files/.vscode/extensions.json +14 -0
  112. package/src/generators/preset/files/.vscode/launch.json +37 -0
  113. package/src/generators/preset/files/.vscode/settings.json +401 -0
  114. package/src/generators/preset/files/.vscode/tasks.json +4 -0
  115. package/src/generators/preset/files/.whitesource +14 -0
  116. package/src/generators/preset/files/assets/diagrams/.gitkeep +0 -0
  117. package/src/generators/preset/files/assets/icons/dark/.gitkeep +0 -0
  118. package/src/generators/preset/files/assets/icons/light/.gitkeep +0 -0
  119. package/src/generators/preset/files/assets/logos/.gitkeep +0 -0
  120. package/src/generators/preset/files/docs/api-reference/.gitkeep +0 -0
  121. package/src/generators/preset/generator.spec.ts +20 -0
  122. package/src/generators/preset/generator.ts +315 -0
  123. package/src/generators/preset/untyped.ts +88 -0
  124. package/src/generators/release-version/generator.spec.ts +20 -0
  125. package/src/generators/release-version/generator.ts +920 -0
  126. package/src/generators/release-version/untyped.ts +156 -0
  127. package/src/plugins/rust/cargo-toml.ts +434 -0
  128. package/src/plugins/rust/index.ts +1 -0
  129. package/src/plugins/typescript/index.ts +1 -0
  130. package/src/plugins/typescript/project-config.ts +564 -0
  131. package/src/plugins/typescript/tsup.ts +198 -0
  132. package/src/types.ts +130 -0
  133. package/src/utils/apply-workspace-tokens.ts +73 -0
  134. package/src/utils/cargo.ts +219 -0
  135. package/src/utils/create-cli-options.ts +23 -0
  136. package/src/utils/get-project-configurations.ts +27 -0
  137. package/src/utils/index.ts +12 -0
  138. package/src/utils/lock-file.ts +159 -0
  139. package/src/utils/package-helpers.ts +54 -0
  140. package/src/utils/plugin-helpers.ts +112 -0
  141. package/src/utils/pnpm-deps-update.ts +111 -0
  142. package/src/utils/project-tags.ts +162 -0
  143. package/src/utils/toml.ts +204 -0
  144. package/src/utils/typia-transform.ts +8 -0
  145. package/src/utils/versions.ts +19 -0
  146. package/tsconfig.json +30 -0
  147. package/tsup.config.ts +36 -0
  148. package/dist/chunk-62LQXZNY.js +0 -282
  149. package/dist/chunk-F3VG4R53.mjs +0 -282
  150. package/dist/src/generators/preset/files/LICENSE +0 -201
  151. package/docs/api/base/base-executor.schema.md +0 -16
  152. package/docs/api/base/base-generator.schema.md +0 -15
  153. package/docs/api/base/cargo-base-executor.schema.md +0 -90
  154. package/docs/api/base/typescript-build-executor.schema.md +0 -126
  155. package/docs/api/base/typescript-library-generator.schema.md +0 -129
  156. package/docs/api/executors/cargo-build/schema.md +0 -89
  157. package/docs/api/executors/cargo-check/schema.md +0 -90
  158. package/docs/api/executors/cargo-clippy/schema.md +0 -99
  159. package/docs/api/executors/cargo-doc/schema.md +0 -130
  160. package/docs/api/executors/cargo-format/schema.md +0 -90
  161. package/docs/api/executors/cargo-publish/schema.md +0 -117
  162. package/docs/api/executors/clean-package/schema.md +0 -65
  163. package/docs/api/executors/esbuild/schema.md +0 -126
  164. package/docs/api/executors/npm-publish/schema.md +0 -64
  165. package/docs/api/executors/size-limit/schema.md +0 -25
  166. package/docs/api/executors/typia/schema.md +0 -46
  167. package/docs/api/executors/unbuild/schema.md +0 -222
  168. package/docs/api/generators/browser-library/files/README.md +0 -58
  169. package/docs/api/generators/browser-library/schema.md +0 -129
  170. package/docs/api/generators/config-schema/schema.md +0 -25
  171. package/docs/api/generators/init/schema.md +0 -15
  172. package/docs/api/generators/neutral-library/files/README.md +0 -58
  173. package/docs/api/generators/neutral-library/schema.md +0 -129
  174. package/docs/api/generators/node-library/files/README.md +0 -63
  175. package/docs/api/generators/node-library/schema.md +0 -129
  176. package/docs/api/generators/preset/schema.md +0 -110
  177. package/docs/api/generators/release-version/schema.md +0 -160
  178. /package/{dist/src → src}/base/base-executor.schema.d.ts +0 -0
  179. /package/{dist/src → src}/base/base-executor.schema.json +0 -0
  180. /package/{dist/src → src}/base/base-executor.schema.md +0 -0
  181. /package/{dist/src → src}/base/base-generator.schema.d.ts +0 -0
  182. /package/{dist/src → src}/base/base-generator.schema.json +0 -0
  183. /package/{dist/src → src}/base/base-generator.schema.md +0 -0
  184. /package/{dist/src → src}/base/cargo-base-executor.schema.d.ts +0 -0
  185. /package/{dist/src → src}/base/cargo-base-executor.schema.json +0 -0
  186. /package/{dist/src → src}/base/cargo-base-executor.schema.md +0 -0
  187. /package/{dist/src → src}/base/typescript-build-executor.schema.d.ts +0 -0
  188. /package/{dist/src → src}/base/typescript-build-executor.schema.json +0 -0
  189. /package/{dist/src → src}/base/typescript-build-executor.schema.md +0 -0
  190. /package/{dist/src → src}/base/typescript-library-generator.schema.d.ts +0 -0
  191. /package/{dist/src → src}/base/typescript-library-generator.schema.json +0 -0
  192. /package/{dist/src → src}/base/typescript-library-generator.schema.md +0 -0
  193. /package/{dist/src → src}/executors/cargo-build/schema.d.ts +0 -0
  194. /package/{dist/src → src}/executors/cargo-build/schema.json +0 -0
  195. /package/{dist/src → src}/executors/cargo-build/schema.md +0 -0
  196. /package/{dist/src → src}/executors/cargo-check/schema.d.ts +0 -0
  197. /package/{dist/src → src}/executors/cargo-check/schema.json +0 -0
  198. /package/{dist/src → src}/executors/cargo-check/schema.md +0 -0
  199. /package/{dist/src → src}/executors/cargo-clippy/schema.d.ts +0 -0
  200. /package/{dist/src → src}/executors/cargo-clippy/schema.json +0 -0
  201. /package/{dist/src → src}/executors/cargo-clippy/schema.md +0 -0
  202. /package/{dist/src → src}/executors/cargo-doc/schema.d.ts +0 -0
  203. /package/{dist/src → src}/executors/cargo-doc/schema.json +0 -0
  204. /package/{dist/src → src}/executors/cargo-doc/schema.md +0 -0
  205. /package/{dist/src → src}/executors/cargo-format/schema.d.ts +0 -0
  206. /package/{dist/src → src}/executors/cargo-format/schema.json +0 -0
  207. /package/{dist/src → src}/executors/cargo-format/schema.md +0 -0
  208. /package/{dist/src → src}/executors/cargo-publish/schema.d.ts +0 -0
  209. /package/{dist/src → src}/executors/cargo-publish/schema.json +0 -0
  210. /package/{dist/src → src}/executors/cargo-publish/schema.md +0 -0
  211. /package/{dist/src → src}/executors/clean-package/schema.d.ts +0 -0
  212. /package/{dist/src → src}/executors/clean-package/schema.json +0 -0
  213. /package/{dist/src → src}/executors/clean-package/schema.md +0 -0
  214. /package/{dist/src → src}/executors/esbuild/schema.d.ts +0 -0
  215. /package/{dist/src → src}/executors/esbuild/schema.json +0 -0
  216. /package/{dist/src → src}/executors/esbuild/schema.md +0 -0
  217. /package/{dist/src → src}/executors/npm-publish/schema.d.ts +0 -0
  218. /package/{dist/src → src}/executors/npm-publish/schema.json +0 -0
  219. /package/{dist/src → src}/executors/npm-publish/schema.md +0 -0
  220. /package/{dist/src → src}/executors/size-limit/schema.d.ts +0 -0
  221. /package/{dist/src → src}/executors/size-limit/schema.json +0 -0
  222. /package/{dist/src → src}/executors/size-limit/schema.md +0 -0
  223. /package/{dist/src → src}/executors/typia/schema.d.ts +0 -0
  224. /package/{dist/src → src}/executors/typia/schema.json +0 -0
  225. /package/{dist/src → src}/executors/typia/schema.md +0 -0
  226. /package/{dist/src → src}/executors/unbuild/schema.d.ts +0 -0
  227. /package/{dist/src → src}/executors/unbuild/schema.json +0 -0
  228. /package/{dist/src → src}/executors/unbuild/schema.md +0 -0
  229. /package/{dist/src → src}/generators/browser-library/files/README.md +0 -0
  230. /package/{dist/src → src}/generators/browser-library/files/jest.config.ts +0 -0
  231. /package/{dist/src → src}/generators/browser-library/files/src/index.ts.template +0 -0
  232. /package/{dist/src → src}/generators/browser-library/files/tsconfig.spec.json +0 -0
  233. /package/{dist/src → src}/generators/browser-library/schema.d.ts +0 -0
  234. /package/{dist/src → src}/generators/browser-library/schema.json +0 -0
  235. /package/{dist/src → src}/generators/browser-library/schema.md +0 -0
  236. /package/{dist/src → src}/generators/config-schema/schema.d.ts +0 -0
  237. /package/{dist/src → src}/generators/config-schema/schema.json +0 -0
  238. /package/{dist/src → src}/generators/config-schema/schema.md +0 -0
  239. /package/{dist/src → src}/generators/init/schema.d.ts +0 -0
  240. /package/{dist/src → src}/generators/init/schema.json +0 -0
  241. /package/{dist/src → src}/generators/init/schema.md +0 -0
  242. /package/{dist/src → src}/generators/neutral-library/files/README.md +0 -0
  243. /package/{dist/src → src}/generators/neutral-library/files/jest.config.ts +0 -0
  244. /package/{dist/src → src}/generators/neutral-library/files/src/index.ts.template +0 -0
  245. /package/{dist/src → src}/generators/neutral-library/files/tsconfig.spec.json +0 -0
  246. /package/{dist/src → src}/generators/neutral-library/schema.d.ts +0 -0
  247. /package/{dist/src → src}/generators/neutral-library/schema.json +0 -0
  248. /package/{dist/src → src}/generators/neutral-library/schema.md +0 -0
  249. /package/{dist/src → src}/generators/node-library/files/README.md +0 -0
  250. /package/{dist/src → src}/generators/node-library/files/jest.config.ts +0 -0
  251. /package/{dist/src → src}/generators/node-library/files/src/index.ts.template +0 -0
  252. /package/{dist/src → src}/generators/node-library/files/tsconfig.spec.json +0 -0
  253. /package/{dist/src → src}/generators/node-library/schema.d.ts +0 -0
  254. /package/{dist/src → src}/generators/node-library/schema.json +0 -0
  255. /package/{dist/src → src}/generators/node-library/schema.md +0 -0
  256. /package/{LICENSE → src/generators/preset/files/LICENSE} +0 -0
  257. /package/{dist/src → src}/generators/preset/files/README.md.template +0 -0
  258. /package/{dist/src → src}/generators/preset/files/docs/readme-templates/README.footer.md.template +0 -0
  259. /package/{dist/src → src}/generators/preset/files/docs/readme-templates/README.header.md.template +0 -0
  260. /package/{dist/src → src}/generators/preset/files/eslint.config.js.template +0 -0
  261. /package/{dist/src → src}/generators/preset/files/knip.json +0 -0
  262. /package/{dist/src → src}/generators/preset/files/lefthook.json +0 -0
  263. /package/{dist/src → src}/generators/preset/files/nx.json +0 -0
  264. /package/{dist/src → src}/generators/preset/files/pnpm-workspace.yaml +0 -0
  265. /package/{dist/src → src}/generators/preset/files/socket.yaml +0 -0
  266. /package/{dist/src → src}/generators/preset/files/storm.json.template +0 -0
  267. /package/{dist/src → src}/generators/preset/files/tsconfig.base.json.template +0 -0
  268. /package/{dist/src → src}/generators/preset/schema.d.ts +0 -0
  269. /package/{dist/src → src}/generators/preset/schema.json +0 -0
  270. /package/{dist/src → src}/generators/preset/schema.md +0 -0
  271. /package/{dist/src → src}/generators/release-version/schema.d.ts +0 -0
  272. /package/{dist/src → src}/generators/release-version/schema.json +0 -0
  273. /package/{dist/src → src}/generators/release-version/schema.md +0 -0
  274. /package/{dist/src → src}/plugins/typescript/untyped-schema.ts +0 -0
@@ -0,0 +1,681 @@
1
+ import {
2
+ detectPackageManager,
3
+ readJsonFile,
4
+ type ExecutorContext
5
+ } from "@nx/devkit";
6
+ import { joinPaths } from "@storm-software/config-tools/utilities/correct-paths";
7
+ import { exec } from "child_process";
8
+ import * as columnify from "columnify";
9
+ import { existsSync } from "fs";
10
+ import { execSync } from "node:child_process";
11
+ import { env as appendLocalEnv } from "npm-run-path";
12
+ import { PackageJson } from "nx/src/utils/package-json";
13
+ import { join, relative } from "path";
14
+ import { pnpmCatalogUpdate } from "../../utils/pnpm-deps-update";
15
+ import type { NpmPublishExecutorSchema } from "./schema.d";
16
+
17
+ export const LARGE_BUFFER = 1024 * 1000000;
18
+
19
+ function processEnv(color: boolean) {
20
+ const env = {
21
+ ...process.env,
22
+ ...appendLocalEnv()
23
+ };
24
+
25
+ if (color) {
26
+ env.FORCE_COLOR = `${color}`;
27
+ }
28
+ return env;
29
+ }
30
+
31
+ export default async function npmPublishExecutorFn(
32
+ options: NpmPublishExecutorSchema,
33
+ context: ExecutorContext
34
+ ) {
35
+ const pm = detectPackageManager();
36
+ /**
37
+ * We need to check both the env var and the option because the executor may have been triggered
38
+ * indirectly via dependsOn, in which case the env var will be set, but the option will not.
39
+ */
40
+ const isDryRun = process.env.NX_DRY_RUN === "true" || options.dryRun || false;
41
+
42
+ const projectConfig =
43
+ context.projectsConfigurations!.projects[context.projectName!]!;
44
+
45
+ const packageRoot = joinPaths(
46
+ context.root,
47
+ options.packageRoot ?? projectConfig.root
48
+ );
49
+
50
+ const packageJsonPath = joinPaths(packageRoot, "package.json");
51
+ const packageJson = readJsonFile(packageJsonPath);
52
+ const packageName = packageJson.name;
53
+
54
+ await pnpmCatalogUpdate(packageRoot, context.root);
55
+
56
+ /**
57
+ * Whether or not dynamically replacing local dependency protocols (such as "workspace:*") is supported during `nx release publish` is
58
+ * dependent on the package manager the user is using.
59
+ *
60
+ * npm does not support the workspace protocol at all, and `npm publish` does not support dynamically updating locally linked packages
61
+ * during its packing phase, so we give the user a clear error message informing them of that.
62
+ *
63
+ * - `pnpm publish` provides ideal support, it has the possibility of providing JSON output consistent with npm
64
+ * - `bun publish`, provides very good support, including all the flags we need apart from the JSON output, so we just have to accept that
65
+ * it will look and feel different and print what it gives us and perform one bit of string manipulation for the dry-run case.
66
+ * - `yarn npm publish`, IS NOT YET SUPPORTED, and will be tricky because it does not support the majority of the flags we need. However, it
67
+ * does support replacing local dependency protocols with the correct version during its packing phase.
68
+ */
69
+ // if (pm === "npm" || pm === "yarn") {
70
+ // const depTypes = ["dependencies", "devDependencies", "peerDependencies"];
71
+ // for (const depType of depTypes) {
72
+ // const deps = packageJson[depType];
73
+ // if (deps) {
74
+ // for (const depName in deps) {
75
+ // if (isLocallyLinkedPackageVersion(deps[depName])) {
76
+ // if (pm === "npm") {
77
+ // console.error(
78
+ // `Error: Cannot publish package "${packageName}" because it contains a local dependency protocol in its "${depType}", and your package manager is npm.
79
+
80
+ // Please update the local dependency on "${depName}" to be a valid semantic version (e.g. using \`nx release\`) before publishing, or switch to pnpm or bun as a package manager, which support dynamically replacing these protocols during publishing.`
81
+ // );
82
+ // } else if (pm === "yarn") {
83
+ // console.error(
84
+ // `Error: Cannot publish package "${packageName}" because it contains a local dependency protocol in its "${depType}", and your package manager is yarn.
85
+
86
+ // Currently, yarn is not supported for this use case because its \`yarn npm publish\` command does not support the customization needed.
87
+
88
+ // Please update the local dependency on "${depName}" to be a valid semantic version (e.g. using \`nx release\`) before publishing, or switch to pnpm or bun as a package manager, which support dynamically replacing these protocols during publishing.`
89
+ // );
90
+ // }
91
+ // return {
92
+ // success: false
93
+ // };
94
+ // }
95
+ // }
96
+ // }
97
+ // }
98
+ // }
99
+
100
+ // If package and project name match, we can make log messages terser
101
+ const packageTxt =
102
+ packageName === context.projectName
103
+ ? `package "${packageName}"`
104
+ : `package "${packageName}" from project "${context.projectName}"`;
105
+
106
+ if (packageJson.private === true) {
107
+ console.warn(
108
+ `Skipped ${packageTxt}, because it has \`"private": true\` in ${packageJsonPath}`
109
+ );
110
+ return {
111
+ success: true
112
+ };
113
+ }
114
+
115
+ const warnFn = (message: string) => {
116
+ console.log(message);
117
+ };
118
+ const { registry, tag, registryConfigKey } = await parseRegistryOptions(
119
+ context.root,
120
+ {
121
+ packageRoot,
122
+ packageJson
123
+ },
124
+ {
125
+ registry: options.registry,
126
+ tag: options.tag
127
+ },
128
+ warnFn
129
+ );
130
+
131
+ const npmViewCommandSegments = [
132
+ `npm view ${packageName} versions dist-tags --json --"${registryConfigKey}=${registry}"`
133
+ ];
134
+ const npmDistTagAddCommandSegments = [
135
+ `npm dist-tag add ${packageName}@${packageJson.version} ${tag} --"${registryConfigKey}=${registry}"`
136
+ ];
137
+
138
+ /**
139
+ * In a dry-run scenario, it is most likely that all commands are being run with dry-run, therefore
140
+ * the most up to date/relevant version might not exist on disk for us to read and make the npm view
141
+ * request with.
142
+ *
143
+ * Therefore, so as to not produce misleading output in dry around dist-tags being altered, we do not
144
+ * perform the npm view step, and just show npm/pnpm publish's dry-run output.
145
+ */
146
+ if (!isDryRun && !options.firstRelease) {
147
+ const currentVersion = packageJson.version;
148
+ try {
149
+ const result = execSync(npmViewCommandSegments.join(" "), {
150
+ env: processEnv(true),
151
+ cwd: context.root,
152
+ stdio: ["ignore", "pipe", "pipe"],
153
+ windowsHide: false
154
+ });
155
+
156
+ const resultJson = JSON.parse(result.toString());
157
+ const distTags = resultJson["dist-tags"] || {};
158
+ if (distTags[tag] === currentVersion) {
159
+ console.warn(
160
+ `Skipped ${packageTxt} because v${currentVersion} already exists in ${registry} with tag "${tag}"`
161
+ );
162
+ return {
163
+ success: true
164
+ };
165
+ }
166
+
167
+ // If only one version of a package exists in the registry, versions will be a string instead of an array.
168
+ const versions = Array.isArray(resultJson.versions)
169
+ ? resultJson.versions
170
+ : [resultJson.versions];
171
+
172
+ if (versions.includes(currentVersion)) {
173
+ try {
174
+ if (!isDryRun) {
175
+ execSync(npmDistTagAddCommandSegments.join(" "), {
176
+ env: processEnv(true),
177
+ cwd: context.root,
178
+ stdio: "ignore",
179
+ windowsHide: false
180
+ });
181
+ console.log(
182
+ `Added the dist-tag ${tag} to v${currentVersion} for registry ${registry}.\n`
183
+ );
184
+ } else {
185
+ console.log(
186
+ `Would add the dist-tag ${tag} to v${currentVersion} for registry ${registry}, but "[dry-run]" was set.\n`
187
+ );
188
+ }
189
+ return {
190
+ success: true
191
+ };
192
+ } catch (err) {
193
+ try {
194
+ const stdoutData = JSON.parse(err.stdout?.toString() || "{}");
195
+
196
+ // If the error is that the package doesn't exist, then we can ignore it because we will be publishing it for the first time in the next step
197
+ if (
198
+ !(
199
+ stdoutData.error?.code?.includes("E404") &&
200
+ stdoutData.error?.summary?.includes("no such package available")
201
+ ) &&
202
+ !(
203
+ err.stderr?.toString().includes("E404") &&
204
+ err.stderr?.toString().includes("no such package available")
205
+ )
206
+ ) {
207
+ console.error("npm dist-tag add error:");
208
+ if (stdoutData.error.summary) {
209
+ console.error(stdoutData.error.summary);
210
+ }
211
+ if (stdoutData.error.detail) {
212
+ console.error(stdoutData.error.detail);
213
+ }
214
+
215
+ if (context.isVerbose) {
216
+ console.error("npm dist-tag add stdout:");
217
+ console.error(JSON.stringify(stdoutData, null, 2));
218
+ }
219
+ return {
220
+ success: false
221
+ };
222
+ }
223
+ } catch (err) {
224
+ console.error(
225
+ "Something unexpected went wrong when processing the npm dist-tag add output\n",
226
+ err
227
+ );
228
+ return {
229
+ success: false
230
+ };
231
+ }
232
+ }
233
+ }
234
+ } catch (err) {
235
+ const stdoutData = JSON.parse(err.stdout?.toString() || "{}");
236
+ // If the error is that the package doesn't exist, then we can ignore it because we will be publishing it for the first time in the next step
237
+ if (
238
+ !(
239
+ stdoutData.error?.code?.includes("E404") &&
240
+ stdoutData.error?.summary?.toLowerCase().includes("not found")
241
+ ) &&
242
+ !(
243
+ err.stderr?.toString().includes("E404") &&
244
+ err.stderr?.toString().toLowerCase().includes("not found")
245
+ )
246
+ ) {
247
+ console.error(
248
+ `Something unexpected went wrong when checking for existing dist-tags.\n`,
249
+ err
250
+ );
251
+ return {
252
+ success: false
253
+ };
254
+ }
255
+ }
256
+ }
257
+
258
+ if (options.firstRelease && context.isVerbose) {
259
+ console.log("Skipped npm view because --first-release was set");
260
+ }
261
+
262
+ /**
263
+ * NOTE: If this is ever changed away from running the command at the workspace root and pointing at the package root (e.g. back
264
+ * to running from the package root directly), then special attention should be paid to the fact that npm/pnpm publish will nest its
265
+ * JSON output under the name of the package in that case (and it would need to be handled below).
266
+ */
267
+ const publishCommandSegments = [
268
+ pm === "bun"
269
+ ? // Unlike npm, bun publish does not support a custom registryConfigKey option
270
+ `bun publish --cwd="${packageRoot}" --json --registry="${registry}" --tag=${tag}`
271
+ : pm === "pnpm"
272
+ ? // Unlike npm, pnpm publish does not support a custom registryConfigKey option, and will error on uncommitted changes by default if --no-git-checks is not set
273
+ `pnpm publish "${packageRoot}" --json --registry="${registry}" --tag=${tag} --no-git-checks`
274
+ : `npm publish "${packageRoot}" --json --"${registryConfigKey}=${registry}" --tag=${tag}`
275
+ ];
276
+
277
+ if (options.otp) {
278
+ publishCommandSegments.push(`--otp=${options.otp}`);
279
+ }
280
+
281
+ publishCommandSegments.push(`--access=public`);
282
+
283
+ if (isDryRun) {
284
+ publishCommandSegments.push(`--dry-run`);
285
+ }
286
+
287
+ try {
288
+ const output = execSync(publishCommandSegments.join(" "), {
289
+ maxBuffer: LARGE_BUFFER,
290
+ env: processEnv(true),
291
+ cwd: context.root,
292
+ stdio: ["ignore", "pipe", "pipe"],
293
+ windowsHide: false
294
+ });
295
+ // 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.
296
+ const dryRunVersionPlaceholder = "X.X.X-dry-run";
297
+
298
+ const publishSummaryMessage = isDryRun
299
+ ? `Would publish to ${registry} with tag "${tag}", but "[dry-run]" was set`
300
+ : `Published to ${registry} with tag "${tag}"`;
301
+
302
+ // bun publish does not support outputting JSON, so we need to modify and print the output string directly
303
+ if (pm === "bun") {
304
+ let outputStr = output.toString();
305
+ if (isDryRun) {
306
+ outputStr = outputStr.replace(
307
+ new RegExp(`${packageJson.name}@${packageJson.version}`, "g"),
308
+ `${packageJson.name}@${dryRunVersionPlaceholder}`
309
+ );
310
+ }
311
+ console.log(outputStr);
312
+ console.log(publishSummaryMessage);
313
+ return {
314
+ success: true
315
+ };
316
+ }
317
+
318
+ /**
319
+ * We cannot JSON.parse the output directly because if the user is using lifecycle scripts, npm/pnpm will mix its publish output with the JSON output all on stdout.
320
+ * Additionally, we want to capture and show the lifecycle script outputs as beforeJsonData and afterJsonData and print them accordingly below.
321
+ */
322
+ const { beforeJsonData, jsonData, afterJsonData } =
323
+ extractNpmPublishJsonData(output.toString());
324
+ if (!jsonData) {
325
+ console.error(
326
+ `The ${pm} publish output data could not be extracted. Please report this issue on https://github.com/nrwl/nx`
327
+ );
328
+ return {
329
+ success: false
330
+ };
331
+ }
332
+
333
+ if (isDryRun) {
334
+ for (const [key, val] of Object.entries(jsonData)) {
335
+ if (typeof val !== "string") {
336
+ continue;
337
+ }
338
+ jsonData[key] = val.replace(
339
+ new RegExp(packageJson.version, "g"),
340
+ dryRunVersionPlaceholder
341
+ );
342
+ }
343
+ }
344
+
345
+ if (
346
+ typeof beforeJsonData === "string" &&
347
+ beforeJsonData.trim().length > 0
348
+ ) {
349
+ console.log(beforeJsonData);
350
+ }
351
+
352
+ logTar(jsonData);
353
+
354
+ if (typeof afterJsonData === "string" && afterJsonData.trim().length > 0) {
355
+ console.log(afterJsonData);
356
+ }
357
+
358
+ // Print the summary message after the JSON data has been printed
359
+ console.log(publishSummaryMessage);
360
+
361
+ return {
362
+ success: true
363
+ };
364
+ } catch (err) {
365
+ try {
366
+ // bun publish does not support outputting JSON, so we cannot perform any further processing
367
+ if (pm === "bun") {
368
+ console.error(`bun publish error:`);
369
+ console.error(err.stderr?.toString() || "");
370
+ console.error(err.stdout?.toString() || "");
371
+ return {
372
+ success: false
373
+ };
374
+ }
375
+
376
+ const stdoutData = JSON.parse(err.stdout?.toString() || "{}");
377
+
378
+ console.error(`${pm} publish error:`);
379
+ if (stdoutData.error?.summary) {
380
+ console.error(stdoutData.error.summary);
381
+ }
382
+ if (stdoutData.error?.detail) {
383
+ console.error(stdoutData.error.detail);
384
+ }
385
+
386
+ if (context.isVerbose) {
387
+ console.error(`${pm} publish stdout:`);
388
+ console.error(JSON.stringify(stdoutData, null, 2));
389
+ }
390
+
391
+ if (!stdoutData.error) {
392
+ throw err;
393
+ }
394
+
395
+ return {
396
+ success: false
397
+ };
398
+ } catch (err) {
399
+ console.error(
400
+ `Something unexpected went wrong when processing the ${pm} publish output\n`,
401
+ err
402
+ );
403
+ return {
404
+ success: false
405
+ };
406
+ }
407
+ }
408
+ }
409
+
410
+ async function parseRegistryOptions(
411
+ cwd: string,
412
+ pkg: {
413
+ packageRoot: string;
414
+ packageJson: PackageJson;
415
+ },
416
+ options: {
417
+ registry?: string;
418
+ tag?: string;
419
+ },
420
+ logWarnFn: (message: string) => void = console.warn
421
+ ): Promise<{
422
+ registry: string;
423
+ tag: string;
424
+ registryConfigKey: string;
425
+ }> {
426
+ const npmRcPath = join(pkg.packageRoot, ".npmrc");
427
+ if (existsSync(npmRcPath)) {
428
+ const relativeNpmRcPath = relative(cwd, npmRcPath);
429
+ logWarnFn(
430
+ `\nIgnoring .npmrc file detected in the package root: ${relativeNpmRcPath}. Nested .npmrc files are not supported by npm. Only the .npmrc file at the root of the workspace will be used. To customize the registry or tag for specific packages, see https://nx.dev/recipes/nx-release/configure-custom-registries\n`
431
+ );
432
+ }
433
+
434
+ const scope = pkg.packageJson.name.startsWith("@")
435
+ ? pkg.packageJson.name.split("/")[0]
436
+ : "";
437
+
438
+ // If the package is scoped, then the registry argument that will
439
+ // correctly override the registry in the .npmrc file must be scoped.
440
+ const registryConfigKey = scope ? `${scope}:registry` : "registry";
441
+
442
+ const publishConfigRegistry =
443
+ pkg.packageJson.publishConfig?.[registryConfigKey];
444
+
445
+ // Even though it won't override the actual registry that's actually used,
446
+ // the user might think otherwise, so we should still warn if the user has
447
+ // set a 'registry' in 'publishConfig' for a scoped package.
448
+ if (publishConfigRegistry || pkg.packageJson.publishConfig?.registry) {
449
+ const relativePackageJsonPath = relative(
450
+ cwd,
451
+ join(pkg.packageRoot, "package.json")
452
+ );
453
+ if (options.registry) {
454
+ logWarnFn(
455
+ `\nRegistry detected in the 'publishConfig' of the package manifest: ${relativePackageJsonPath}. This will override your registry option set in the project configuration or passed via the --registry argument, which is why configuring the registry with 'publishConfig' is not recommended. For details, see https://nx.dev/recipes/nx-release/configure-custom-registries\n`
456
+ );
457
+ } else {
458
+ logWarnFn(
459
+ `\nRegistry detected in the 'publishConfig' of the package manifest: ${relativePackageJsonPath}. Configuring the registry in this way is not recommended because it prevents the registry from being overridden in project configuration or via the --registry argument. To customize the registry for specific packages, see https://nx.dev/recipes/nx-release/configure-custom-registries\n`
460
+ );
461
+ }
462
+ }
463
+
464
+ const registry =
465
+ // `npm publish` will always use the publishConfig registry if it exists, even over the --registry arg
466
+ publishConfigRegistry ||
467
+ options.registry ||
468
+ (await getNpmRegistry(cwd, scope));
469
+ const tag = options.tag || (await getNpmTag(cwd));
470
+ if (!registry || !tag) {
471
+ throw new Error(
472
+ `The registry and tag options are required. Please provide them in the project configuration or via the --registry and --tag arguments.`
473
+ );
474
+ }
475
+
476
+ return { registry, tag, registryConfigKey };
477
+ }
478
+
479
+ /**
480
+ * Returns the npm registry that is used for publishing.
481
+ *
482
+ * @param scope the scope of the package for which to determine the registry
483
+ * @param cwd the directory where the npm config should be read from
484
+ */
485
+ async function getNpmRegistry(
486
+ cwd: string,
487
+ scope?: string
488
+ ): Promise<string | undefined> {
489
+ let registry: string | undefined;
490
+
491
+ if (scope) {
492
+ registry = await getNpmConfigValue(`${scope}:registry`, cwd);
493
+ }
494
+
495
+ if (!registry) {
496
+ registry = await getNpmConfigValue("registry", cwd);
497
+ }
498
+
499
+ return registry;
500
+ }
501
+
502
+ /**
503
+ * Returns the npm tag that is used for publishing.
504
+ *
505
+ * @param cwd the directory where the npm config should be read from
506
+ */
507
+ async function getNpmTag(cwd: string): Promise<string | undefined> {
508
+ // npm does not support '@scope:tag' in the npm config, so we only need to check for 'tag'.
509
+ return getNpmConfigValue("tag", cwd);
510
+ }
511
+
512
+ async function getNpmConfigValue(
513
+ key: string,
514
+ cwd: string
515
+ ): Promise<string | undefined> {
516
+ try {
517
+ const result = await execAsync(`npm config get ${key}`, cwd);
518
+ return result === "undefined" ? undefined : result;
519
+ } catch (_) {
520
+ return Promise.resolve(undefined);
521
+ }
522
+ }
523
+
524
+ async function execAsync(command: string, cwd: string): Promise<string> {
525
+ // Must be non-blocking async to allow spinner to render
526
+ return new Promise<string>((resolve, reject) => {
527
+ exec(command, { cwd, windowsHide: false }, (error, stdout, stderr) => {
528
+ if (error) {
529
+ return reject((stderr ? `${stderr}\n` : "") + error);
530
+ }
531
+ return resolve(stdout.trim());
532
+ });
533
+ });
534
+ }
535
+
536
+ const expectedNpmPublishJsonKeys = [
537
+ "id",
538
+ "name",
539
+ "version",
540
+ "size",
541
+ "filename"
542
+ ];
543
+
544
+ function extractNpmPublishJsonData(str: string): {
545
+ beforeJsonData: string;
546
+ jsonData: Record<string, unknown> | null;
547
+ afterJsonData: string;
548
+ } {
549
+ const jsonMatches = str.match(/{(?:[^{}]|{[^{}]*})*}/g);
550
+ if (jsonMatches) {
551
+ for (const match of jsonMatches) {
552
+ // Cheap upfront check to see if the stringified JSON data has the expected keys as substrings
553
+ if (!expectedNpmPublishJsonKeys.every(key => str.includes(key))) {
554
+ continue;
555
+ }
556
+ // Full JSON parsing to identify the JSON object
557
+ try {
558
+ const parsedJson = JSON.parse(match);
559
+ if (
560
+ !expectedNpmPublishJsonKeys.every(
561
+ key => parsedJson[key] !== undefined
562
+ )
563
+ ) {
564
+ continue;
565
+ }
566
+ const jsonStartIndex = str.indexOf(match);
567
+ return {
568
+ beforeJsonData: str.slice(0, jsonStartIndex),
569
+ jsonData: parsedJson,
570
+ afterJsonData: str.slice(jsonStartIndex + match.length)
571
+ };
572
+ } catch {
573
+ // Ignore parsing errors for unrelated JSON blocks
574
+ }
575
+ }
576
+ }
577
+
578
+ // No applicable jsonData detected, the whole contents is the beforeJsonData
579
+ return {
580
+ beforeJsonData: str,
581
+ jsonData: null,
582
+ afterJsonData: ""
583
+ };
584
+ }
585
+
586
+ const formatBytes = (bytes, space = true) => {
587
+ let spacer = "";
588
+ if (space) {
589
+ spacer = " ";
590
+ }
591
+
592
+ if (bytes < 1000) {
593
+ // B
594
+ return `${bytes}${spacer}B`;
595
+ }
596
+
597
+ if (bytes < 1000000) {
598
+ // kB
599
+ return `${(bytes / 1000).toFixed(1)}${spacer}kB`;
600
+ }
601
+
602
+ if (bytes < 1000000000) {
603
+ // MB
604
+ return `${(bytes / 1000000).toFixed(1)}${spacer}MB`;
605
+ }
606
+
607
+ // GB
608
+ return `${(bytes / 1000000000).toFixed(1)}${spacer}GB`;
609
+ };
610
+
611
+ const logTar = (tarball, opts = {}) => {
612
+ // @ts-expect-error Expected to be a tarball
613
+ const { unicode = true } = opts;
614
+ console.log("");
615
+ console.log(
616
+ `${unicode ? "📦 " : "package:"} ${tarball.name}@${tarball.version}`
617
+ );
618
+ console.log("=== Tarball Contents ===");
619
+ if (tarball.files.length) {
620
+ console.log("");
621
+ const columnData = columnify(
622
+ tarball.files
623
+ .map(f => {
624
+ const bytes = formatBytes(f.size, false);
625
+ return /^node_modules\//.test(f.path)
626
+ ? null
627
+ : { path: f.path, size: `${bytes}` };
628
+ })
629
+ .filter(f => f),
630
+ {
631
+ include: ["size", "path"],
632
+ showHeaders: false
633
+ }
634
+ );
635
+ columnData.split("\n").forEach(line => {
636
+ console.log(line);
637
+ });
638
+ }
639
+ if (tarball.bundled.length) {
640
+ console.log("=== Bundled Dependencies ===");
641
+ tarball.bundled.forEach(name => console.log("", name));
642
+ }
643
+ console.log("=== Tarball Details ===");
644
+ console.log(
645
+ columnify(
646
+ [
647
+ { name: "name:", value: tarball.name },
648
+ { name: "version:", value: tarball.version },
649
+ tarball.filename && { name: "filename:", value: tarball.filename },
650
+ { name: "package size:", value: formatBytes(tarball.size) },
651
+ { name: "unpacked size:", value: formatBytes(tarball.unpackedSize) },
652
+ { name: "shasum:", value: tarball.shasum },
653
+ {
654
+ name: "integrity:",
655
+ value:
656
+ tarball.integrity.toString().slice(0, 20) +
657
+ "[...]" +
658
+ tarball.integrity.toString().slice(80)
659
+ },
660
+ tarball.bundled.length && {
661
+ name: "bundled deps:",
662
+ value: tarball.bundled.length
663
+ },
664
+ tarball.bundled.length && {
665
+ name: "bundled files:",
666
+ value: tarball.entryCount - tarball.files.length
667
+ },
668
+ tarball.bundled.length && {
669
+ name: "own files:",
670
+ value: tarball.files.length
671
+ },
672
+ { name: "total files:", value: tarball.entryCount }
673
+ ].filter(x => x),
674
+ {
675
+ include: ["name", "value"],
676
+ showHeaders: false
677
+ }
678
+ )
679
+ );
680
+ console.log("", "");
681
+ };