@codefast/cli 0.9.0 → 0.11.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 (279) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/README.md +345 -151
  3. package/dist/arrange/command.d.ts +7 -0
  4. package/dist/arrange/command.js +96 -132
  5. package/dist/arrange/domain/ast/ast-node.d.ts +394 -0
  6. package/dist/arrange/domain/ast/collectors-cn.d.ts +26 -0
  7. package/dist/arrange/domain/ast/collectors-jsx.d.ts +8 -0
  8. package/dist/arrange/domain/ast/collectors-tv.d.ts +34 -0
  9. package/dist/arrange/domain/ast/helpers.d.ts +36 -0
  10. package/dist/arrange/domain/ast/helpers.js +1 -0
  11. package/dist/arrange/domain/ast/simplify-targets.d.ts +22 -0
  12. package/dist/arrange/domain/ast/simplify-targets.js +18 -23
  13. package/dist/arrange/domain/ast/targets.d.ts +20 -0
  14. package/dist/arrange/domain/ast/translator.d.ts +32 -0
  15. package/dist/arrange/{typescript-ast-translator.js → domain/ast/translator.js} +19 -22
  16. package/dist/arrange/domain/constants.d.ts +111 -0
  17. package/dist/arrange/domain/grouping-service.d.ts +100 -0
  18. package/dist/arrange/domain/grouping.d.ts +21 -0
  19. package/dist/arrange/domain/imports.d.ts +14 -0
  20. package/dist/arrange/domain/source-text-formatters.d.ts +33 -0
  21. package/dist/arrange/domain/tailwind-token.d.ts +24 -0
  22. package/dist/arrange/domain/token-classifier.d.ts +47 -0
  23. package/dist/arrange/domain/types.d.ts +208 -0
  24. package/dist/arrange/group/cli-result.d.ts +7 -0
  25. package/dist/arrange/group/cli-result.js +12 -0
  26. package/dist/arrange/group/cli-schema.d.ts +17 -0
  27. package/dist/arrange/group/cli-schema.js +13 -0
  28. package/dist/arrange/group/output.d.ts +7 -0
  29. package/dist/arrange/group/output.js +10 -0
  30. package/dist/arrange/group/suggest.d.ts +8 -0
  31. package/dist/arrange/inspect/cli-result.d.ts +7 -0
  32. package/dist/arrange/inspect/cli-result.js +8 -0
  33. package/dist/arrange/inspect/cli-schema.d.ts +15 -0
  34. package/dist/arrange/inspect/cli-schema.js +9 -0
  35. package/dist/arrange/inspect/domain/analyze-service.d.ts +18 -0
  36. package/dist/arrange/inspect/output.d.ts +7 -0
  37. package/dist/arrange/inspect/output.js +42 -0
  38. package/dist/arrange/inspect/run.d.ts +10 -0
  39. package/dist/arrange/{analyze.js → inspect/run.js} +2 -2
  40. package/dist/arrange/prepare.d.ts +13 -0
  41. package/dist/arrange/{workspace.js → prepare.js} +5 -8
  42. package/dist/arrange/regroup/cli-result.d.ts +13 -0
  43. package/dist/arrange/regroup/cli-result.js +23 -0
  44. package/dist/arrange/regroup/cli-schema.d.ts +20 -0
  45. package/dist/arrange/regroup/cli-schema.js +14 -0
  46. package/dist/arrange/regroup/output.d.ts +14 -0
  47. package/dist/arrange/regroup/output.js +72 -0
  48. package/dist/arrange/regroup/process-file.d.ts +11 -0
  49. package/dist/arrange/regroup/run.d.ts +11 -0
  50. package/dist/arrange/{sync.js → regroup/run.js} +2 -2
  51. package/dist/arrange/resolve-target.d.ts +10 -0
  52. package/dist/arrange/resolve-target.js +3 -16
  53. package/dist/arrange/scan-target.d.ts +7 -0
  54. package/dist/arrange/simplify/cli-result.d.ts +7 -0
  55. package/dist/arrange/simplify/cli-result.js +8 -0
  56. package/dist/arrange/simplify/cli-schema.d.ts +17 -0
  57. package/dist/arrange/simplify/cli-schema.js +11 -0
  58. package/dist/arrange/simplify/fold-targets.d.ts +13 -0
  59. package/dist/arrange/simplify/fold-targets.js +139 -0
  60. package/dist/arrange/simplify/output.d.ts +7 -0
  61. package/dist/arrange/simplify/output.js +15 -0
  62. package/dist/arrange/simplify/process-file.d.ts +13 -0
  63. package/dist/arrange/simplify/process-file.js +49 -0
  64. package/dist/arrange/simplify/run.d.ts +14 -0
  65. package/dist/arrange/simplify/run.js +38 -0
  66. package/dist/arrange/simplify/variant-classname-probe.d.ts +35 -0
  67. package/dist/arrange/simplify/variant-classname-probe.js +95 -0
  68. package/dist/arrange/source-parse.d.ts +7 -0
  69. package/dist/arrange/source-parse.js +1 -1
  70. package/dist/audit/command.d.ts +8 -0
  71. package/dist/audit/command.js +134 -211
  72. package/dist/audit/comments/cli-result.d.ts +13 -0
  73. package/dist/audit/comments/cli-result.js +22 -0
  74. package/dist/audit/comments/cli-schema.d.ts +19 -0
  75. package/dist/audit/comments/cli-schema.js +13 -0
  76. package/dist/audit/comments/domain/comment-content.d.ts +26 -0
  77. package/dist/audit/comments/domain/comment-dividers.d.ts +62 -0
  78. package/dist/audit/comments/domain/link-references.d.ts +40 -0
  79. package/dist/audit/comments/domain/since-versions.d.ts +26 -0
  80. package/dist/audit/comments/domain/tsdoc-syntax.d.ts +20 -0
  81. package/dist/audit/comments/output.d.ts +7 -0
  82. package/dist/audit/comments/output.js +27 -0
  83. package/dist/audit/comments/prepare.d.ts +16 -0
  84. package/dist/audit/comments/prepare.js +12 -0
  85. package/dist/audit/comments/run.d.ts +17 -0
  86. package/dist/audit/{run-comments.js → comments/run.js} +5 -5
  87. package/dist/audit/display-names/cli-result.d.ts +13 -0
  88. package/dist/audit/display-names/cli-result.js +22 -0
  89. package/dist/audit/display-names/cli-schema.d.ts +18 -0
  90. package/dist/audit/display-names/cli-schema.js +12 -0
  91. package/dist/audit/display-names/domain/display-names.d.ts +11 -0
  92. package/dist/audit/display-names/output.d.ts +7 -0
  93. package/dist/audit/display-names/output.js +21 -0
  94. package/dist/audit/display-names/prepare.d.ts +16 -0
  95. package/dist/audit/display-names/prepare.js +12 -0
  96. package/dist/audit/display-names/run.d.ts +14 -0
  97. package/dist/audit/{run-display-names.js → display-names/run.js} +1 -1
  98. package/dist/audit/domain/types.d.ts +171 -0
  99. package/dist/audit/imports/cli-result.d.ts +13 -0
  100. package/dist/audit/imports/cli-result.js +22 -0
  101. package/dist/audit/imports/cli-schema.d.ts +18 -0
  102. package/dist/audit/imports/cli-schema.js +12 -0
  103. package/dist/audit/imports/domain/import-policy.d.ts +34 -0
  104. package/dist/audit/imports/domain/import-policy.js +140 -0
  105. package/dist/audit/imports/output.d.ts +7 -0
  106. package/dist/audit/imports/output.js +21 -0
  107. package/dist/audit/imports/prepare.d.ts +16 -0
  108. package/dist/audit/imports/prepare.js +12 -0
  109. package/dist/audit/imports/run.d.ts +14 -0
  110. package/dist/audit/{run-react.js → imports/run.js} +15 -5
  111. package/dist/audit/links/cli-result.d.ts +13 -0
  112. package/dist/audit/links/cli-result.js +22 -0
  113. package/dist/audit/links/cli-schema.d.ts +18 -0
  114. package/dist/audit/links/cli-schema.js +12 -0
  115. package/dist/audit/links/domain/markdown-links.d.ts +44 -0
  116. package/dist/audit/links/output.d.ts +7 -0
  117. package/dist/audit/links/output.js +21 -0
  118. package/dist/audit/links/prepare.d.ts +16 -0
  119. package/dist/audit/links/prepare.js +12 -0
  120. package/dist/audit/links/run.d.ts +14 -0
  121. package/dist/audit/{run-links.js → links/run.js} +1 -1
  122. package/dist/audit/prepare.d.ts +31 -0
  123. package/dist/audit/prepare.js +11 -134
  124. package/dist/audit/rtl/cli-result.d.ts +13 -0
  125. package/dist/audit/rtl/cli-result.js +22 -0
  126. package/dist/audit/rtl/cli-schema.d.ts +18 -0
  127. package/dist/audit/rtl/cli-schema.js +12 -0
  128. package/dist/audit/rtl/domain/audit-file.d.ts +7 -0
  129. package/dist/audit/{domain → rtl/domain}/audit-file.js +2 -2
  130. package/dist/audit/rtl/domain/mappings.d.ts +45 -0
  131. package/dist/audit/rtl/domain/tokenize.d.ts +14 -0
  132. package/dist/audit/rtl/output.d.ts +7 -0
  133. package/dist/audit/rtl/output.js +21 -0
  134. package/dist/audit/rtl/prepare.d.ts +13 -0
  135. package/dist/audit/rtl/prepare.js +41 -0
  136. package/dist/audit/rtl/run.d.ts +14 -0
  137. package/dist/audit/{run.js → rtl/run.js} +1 -1
  138. package/dist/bin.d.ts +2 -0
  139. package/dist/cli.d.ts +6 -0
  140. package/dist/core/cli/command-pipeline.d.ts +91 -0
  141. package/dist/core/cli/command-pipeline.js +83 -0
  142. package/dist/core/cli/format-error.d.ts +7 -0
  143. package/dist/core/cli/global-options.d.ts +15 -0
  144. package/dist/core/cli/global-options.js +1 -1
  145. package/dist/core/cli/positional.d.ts +6 -0
  146. package/dist/core/cli/resolve-root.d.ts +9 -0
  147. package/dist/core/cli/resolve-root.js +16 -0
  148. package/dist/core/cli/result-handle.d.ts +13 -0
  149. package/dist/core/cli/result-handle.js +0 -13
  150. package/dist/core/config/define-config.d.ts +7 -0
  151. package/dist/core/config/define-config.js +8 -0
  152. package/dist/core/config/loader.d.ts +18 -0
  153. package/dist/core/config/loader.js +2 -7
  154. package/dist/core/config/schema.d.ts +99 -0
  155. package/dist/core/config/schema.js +8 -86
  156. package/dist/core/config/warnings.d.ts +6 -0
  157. package/dist/core/config.d.ts +12 -0
  158. package/dist/core/errors.d.ts +25 -0
  159. package/dist/core/exit-codes.d.ts +18 -0
  160. package/dist/core/filesystem/filesystem.d.ts +44 -0
  161. package/dist/core/filesystem/node.d.ts +7 -0
  162. package/dist/core/filesystem/node.js +2 -1
  163. package/dist/core/glob.d.ts +19 -0
  164. package/dist/core/logger.d.ts +9 -0
  165. package/dist/core/result.d.ts +30 -0
  166. package/dist/core/schema-parse.d.ts +9 -0
  167. package/dist/core/source-text-edit.d.ts +47 -0
  168. package/dist/core/source-text-edit.js +22 -0
  169. package/dist/core/verbose-diagnostics.d.ts +6 -0
  170. package/dist/core/workspace/ancestor-directories.d.ts +12 -0
  171. package/dist/core/workspace/ancestor-directories.js +30 -0
  172. package/dist/core/workspace/markdown-walk.d.ts +7 -0
  173. package/dist/core/workspace/markdown-walk.js +2 -20
  174. package/dist/core/workspace/package-version.d.ts +9 -0
  175. package/dist/core/workspace/package-version.js +8 -12
  176. package/dist/core/workspace/resolver.d.ts +39 -0
  177. package/dist/core/workspace/resolver.js +58 -75
  178. package/dist/core/workspace/skip-directories.d.ts +6 -0
  179. package/dist/core/workspace/source-walk.d.ts +16 -0
  180. package/dist/core/workspace/source-walk.js +2 -19
  181. package/dist/core/workspace/typescript-walk.d.ts +7 -0
  182. package/dist/core/workspace/typescript-walk.js +2 -23
  183. package/dist/core/workspace/walk-files.d.ts +7 -0
  184. package/dist/core/workspace/walk-files.js +27 -0
  185. package/dist/core/workspace/well-known-files.d.ts +18 -0
  186. package/dist/core/workspace/well-known-files.js +18 -0
  187. package/dist/index.d.ts +6 -0
  188. package/dist/index.js +5 -0
  189. package/dist/mirror/cli-result.d.ts +13 -0
  190. package/dist/mirror/cli-schema.d.ts +8 -0
  191. package/dist/mirror/cli-schema.js +1 -1
  192. package/dist/mirror/command.d.ts +7 -0
  193. package/dist/mirror/command.js +31 -60
  194. package/dist/mirror/dist-filesystem-node.d.ts +8 -0
  195. package/dist/mirror/{dist-filesystem-impl.js → dist-filesystem-node.js} +1 -1
  196. package/dist/mirror/domain/constants.d.ts +18 -0
  197. package/dist/mirror/domain/constants.js +0 -12
  198. package/dist/mirror/domain/dirent-guard.d.ts +10 -0
  199. package/dist/mirror/domain/dist-filesystem.d.ts +9 -0
  200. package/dist/mirror/domain/errors.d.ts +24 -0
  201. package/dist/mirror/domain/exports.d.ts +36 -0
  202. package/dist/mirror/domain/package-display-name.d.ts +8 -0
  203. package/dist/mirror/domain/path-normalizer.d.ts +6 -0
  204. package/dist/mirror/domain/types.d.ts +188 -0
  205. package/dist/mirror/output.d.ts +21 -0
  206. package/dist/mirror/output.js +126 -1
  207. package/dist/mirror/package-path.d.ts +19 -0
  208. package/dist/mirror/prepare.d.ts +15 -0
  209. package/dist/mirror/prepare.js +6 -10
  210. package/dist/mirror/run.d.ts +12 -0
  211. package/dist/mirror/{sync.js → run.js} +5 -3
  212. package/dist/mirror/supplement-exports.d.ts +27 -0
  213. package/dist/mirror/supplement-exports.js +2 -2
  214. package/dist/mirror/sync-workspace-package.d.ts +9 -0
  215. package/dist/mirror/sync-workspace-package.js +4 -4
  216. package/dist/mirror/write-exports.d.ts +15 -0
  217. package/dist/pack-slim/cli-result.d.ts +13 -0
  218. package/dist/pack-slim/cli-schema.d.ts +17 -0
  219. package/dist/pack-slim/cli-schema.js +1 -1
  220. package/dist/pack-slim/command.d.ts +7 -0
  221. package/dist/pack-slim/command.js +31 -66
  222. package/dist/pack-slim/domain/transform.d.ts +69 -0
  223. package/dist/pack-slim/domain/types.d.ts +46 -0
  224. package/dist/pack-slim/output.d.ts +15 -0
  225. package/dist/pack-slim/prepare.d.ts +21 -0
  226. package/dist/pack-slim/prepare.js +14 -0
  227. package/dist/pack-slim/run.d.ts +23 -0
  228. package/dist/pack-slim/{sync.js → run.js} +4 -4
  229. package/dist/pack-slim/working-tree.d.ts +20 -0
  230. package/dist/tag/cli-result.d.ts +13 -0
  231. package/dist/tag/cli-result.js +14 -1
  232. package/dist/tag/cli-schema.d.ts +8 -0
  233. package/dist/tag/cli-schema.js +3 -4
  234. package/dist/tag/command.d.ts +7 -0
  235. package/dist/tag/command.js +33 -60
  236. package/dist/tag/domain/skip-filter.d.ts +13 -0
  237. package/dist/tag/domain/skip-filter.js +29 -0
  238. package/dist/tag/domain/types.d.ts +131 -0
  239. package/dist/tag/domain/version-summary.d.ts +13 -0
  240. package/dist/tag/domain/version-summary.js +24 -0
  241. package/dist/tag/output.d.ts +17 -0
  242. package/dist/tag/output.js +6 -9
  243. package/dist/tag/prepare.d.ts +13 -0
  244. package/dist/tag/prepare.js +4 -4
  245. package/dist/tag/run.d.ts +10 -0
  246. package/dist/tag/{sync.js → run.js} +20 -50
  247. package/dist/tag/target/candidates.d.ts +8 -0
  248. package/dist/tag/{target-candidates.js → target/candidates.js} +2 -2
  249. package/dist/tag/target/resolve-path.d.ts +10 -0
  250. package/dist/tag/target/runner.d.ts +8 -0
  251. package/dist/tag/{target-runner.js → target/runner.js} +2 -2
  252. package/dist/tag/writer/since-writer.d.ts +32 -0
  253. package/dist/tag/writer/version-resolver.d.ts +7 -0
  254. package/package.json +21 -2
  255. package/dist/arrange/cli-schema.js +0 -34
  256. package/dist/arrange/output.js +0 -127
  257. package/dist/arrange/simplify-process-file.js +0 -30
  258. package/dist/arrange/simplify-sync.js +0 -30
  259. package/dist/audit/cli-schema.js +0 -66
  260. package/dist/audit/domain/react-imports.js +0 -91
  261. package/dist/audit/output.js +0 -213
  262. package/dist/mirror/sync-reporter.js +0 -124
  263. package/dist/mirror/sync-types.js +0 -1
  264. /package/dist/arrange/{suggest.js → group/suggest.js} +0 -0
  265. /package/dist/arrange/{domain → inspect/domain}/analyze-service.js +0 -0
  266. /package/dist/arrange/{process-file.js → regroup/process-file.js} +0 -0
  267. /package/dist/audit/{domain → comments/domain}/comment-content.js +0 -0
  268. /package/dist/audit/{domain → comments/domain}/comment-dividers.js +0 -0
  269. /package/dist/audit/{domain → comments/domain}/link-references.js +0 -0
  270. /package/dist/audit/{domain → comments/domain}/since-versions.js +0 -0
  271. /package/dist/audit/{domain → comments/domain}/tsdoc-syntax.js +0 -0
  272. /package/dist/audit/{domain → display-names/domain}/display-names.js +0 -0
  273. /package/dist/audit/{domain → links/domain}/markdown-links.js +0 -0
  274. /package/dist/audit/{domain → rtl/domain}/mappings.js +0 -0
  275. /package/dist/audit/{domain → rtl/domain}/tokenize.js +0 -0
  276. /package/dist/core/filesystem/{port.js → filesystem.js} +0 -0
  277. /package/dist/tag/{resolve-target-path.js → target/resolve-path.js} +0 -0
  278. /package/dist/tag/{since-writer.js → writer/since-writer.js} +0 -0
  279. /package/dist/tag/{version-resolver.js → writer/version-resolver.js} +0 -0
@@ -1,80 +1,45 @@
1
- import process from "node:process";
2
1
  import { Command } from "commander";
3
- import { globalCliCommanderOptionsSchema } from "#/core/cli/global-options";
4
- import { readOptionalPositionalArg } from "#/core/cli/positional";
5
- import { consumeCliAppError } from "#/core/cli/result-handle";
6
- import { AppError, messageFrom } from "#/core/errors";
2
+ import { applyCommandPipeline } from "#/core/cli/command-pipeline";
7
3
  import { nodeFilesystem } from "#/core/filesystem/node";
8
- import { logger } from "#/core/logger";
9
- import { err } from "#/core/result";
10
- import { parseWithSchema } from "#/core/schema-parse";
11
- import { findRepoRoot } from "#/core/workspace/resolver";
4
+ import { ok } from "#/core/result";
12
5
  import { exitCodeForPackSlimResult, formatPackSlimJsonOutput } from "#/pack-slim/cli-result";
13
6
  import { packSlimRunRequestSchema } from "#/pack-slim/cli-schema";
14
7
  import { PackSlimProgressPresenter } from "#/pack-slim/output";
15
- import { runPackSlim } from "#/pack-slim/sync";
8
+ import { preparePackSlim } from "#/pack-slim/prepare";
9
+ import { runPackSlim } from "#/pack-slim/run";
16
10
  import { ensureWorkingTreeClean } from "#/pack-slim/working-tree";
11
+ const packSlimPipeline = {
12
+ positional: { name: "[package]", help: "Optional package path relative to repo root (e.g. packages/ui)" },
13
+ schema: packSlimRunRequestSchema,
14
+ configureArgv: (command) => {
15
+ command.option("--dry-run", "Report what would change without touching any file", false);
16
+ command.option("--force", "Run even if the git working tree has uncommitted tracked changes", false);
17
+ },
18
+ prepare: (fs, input) => preparePackSlim(fs, { currentWorkingDirectory: input.currentWorkingDirectory, packageArg: input.rawArg }),
19
+ // A destructive slim must never land on uncommitted work; --dry-run writes nothing, so it is exempt.
20
+ guard: async ({ prelude, opts }) => !opts.dryRun && !opts.force ? ensureWorkingTreeClean(prelude.rootDir) : ok(undefined),
21
+ buildRequest: ({ prelude, opts }) => ({
22
+ rootDir: prelude.rootDir,
23
+ packageFilter: prelude.packageFilter,
24
+ write: !opts.dryRun,
25
+ }),
26
+ createPresenter: ({ opts }) => {
27
+ const presenter = new PackSlimProgressPresenter();
28
+ presenter.configure({ dryRun: !!opts.dryRun });
29
+ return presenter;
30
+ },
31
+ run: (fs, request, presenter) => runPackSlim(fs, { ...request, listener: presenter }),
32
+ formatJson: ({ result, opts, elapsedSeconds }) => formatPackSlimJsonOutput(result, elapsedSeconds, !opts.dryRun),
33
+ exitCode: exitCodeForPackSlimResult,
34
+ };
17
35
  /**
18
36
  * Creates the `pack-slim` subcommand, which slims published packages down to what a consumer reads before publish.
19
37
  *
20
38
  * @since 0.8.1
21
39
  */
22
40
  export function createPackSlimCommand() {
23
- const cmd = new Command("pack-slim")
24
- .description("Strip src, source conditions, unshipped imports, dev-only scripts, devDependencies, and dist source maps from " +
25
- "published packages before publish")
26
- .argument("[package]", "Optional package path relative to repo root (e.g. packages/ui)")
27
- .option("--dry-run", "Report what would change without touching any file", false)
28
- .option("--force", "Run even if the git working tree has uncommitted tracked changes", false)
29
- .option("--json", "Print one JSON summary on stdout (suppresses human progress)", false)
30
- .action(async (packageArg, opts, command) => {
31
- const globalsOptionCarrier = command.optsWithGlobals?.() ??
32
- command.opts();
33
- const globalOptionsOutcome = parseWithSchema(globalCliCommanderOptionsSchema, globalsOptionCarrier);
34
- if (!consumeCliAppError(globalOptionsOutcome)) {
35
- return;
36
- }
37
- let rootDir;
38
- try {
39
- rootDir = findRepoRoot(process.cwd(), nodeFilesystem);
40
- }
41
- catch (caughtError) {
42
- consumeCliAppError(err(new AppError("INFRA_FAILURE", messageFrom(caughtError), caughtError)));
43
- return;
44
- }
45
- const write = !opts.dryRun;
46
- // A destructive slim must never land on a developer's uncommitted work; --dry-run writes nothing, so it is exempt.
47
- if (write && !opts.force) {
48
- const cleanCheck = ensureWorkingTreeClean(rootDir);
49
- if (!consumeCliAppError(cleanCheck)) {
50
- return;
51
- }
52
- }
53
- const parsed = parseWithSchema(packSlimRunRequestSchema, {
54
- rootDir,
55
- packageFilter: readOptionalPositionalArg(packageArg),
56
- write,
57
- });
58
- if (!consumeCliAppError(parsed)) {
59
- return;
60
- }
61
- const json = !!opts.json;
62
- const presenter = new PackSlimProgressPresenter();
63
- if (!json) {
64
- presenter.configure({ dryRun: !write });
65
- }
66
- const startTime = performance.now();
67
- const outcome = await runPackSlim(nodeFilesystem, {
68
- ...parsed.value,
69
- listener: json ? undefined : presenter,
70
- });
71
- if (!consumeCliAppError(outcome)) {
72
- return;
73
- }
74
- if (json) {
75
- logger.out(formatPackSlimJsonOutput(outcome.value, (performance.now() - startTime) / 1000, write));
76
- }
77
- process.exitCode = exitCodeForPackSlimResult(outcome.value);
78
- });
41
+ const cmd = new Command("pack-slim").description("Strip src, source conditions, unshipped imports, dev-only scripts, devDependencies, and dist source maps from " +
42
+ "published packages before publish");
43
+ applyCommandPipeline(cmd, nodeFilesystem, packSlimPipeline);
79
44
  return cmd;
80
45
  }
@@ -0,0 +1,69 @@
1
+ /** Pure transforms that slim a package's manifest and dist for publish. */
2
+ /**
3
+ * What slimming one manifest removed.
4
+ */
5
+ interface ManifestSlimReport {
6
+ readonly filesSrcRemoved: boolean;
7
+ readonly exportsSourceRemoved: number;
8
+ readonly importsSourceRemoved: number;
9
+ readonly importsUnshippedRemoved: number;
10
+ readonly scriptsRemoved: number;
11
+ readonly devDependenciesRemoved: number;
12
+ readonly changed: boolean;
13
+ }
14
+ /**
15
+ * The slimmed manifest paired with the report of what it dropped.
16
+ *
17
+ * @since 0.8.1
18
+ */
19
+ export interface SlimManifestResult {
20
+ readonly manifest: Record<string, unknown>;
21
+ readonly report: ManifestSlimReport;
22
+ }
23
+ /**
24
+ * The result of stripping the `sourceMappingURL` directive from an emitted file's text.
25
+ *
26
+ * @since 0.8.1
27
+ */
28
+ export interface StripCommentResult {
29
+ readonly text: string;
30
+ readonly stripped: boolean;
31
+ }
32
+ /**
33
+ * Whether a dist entry is a source-map sidecar (`*.map`).
34
+ *
35
+ * @since 0.8.1
36
+ */
37
+ export declare function isSourceMapFile(fileName: string): boolean;
38
+ /**
39
+ * Whether a dist entry is an emitted file that may carry a `sourceMappingURL` directive.
40
+ *
41
+ * @since 0.8.1
42
+ */
43
+ export declare function isMapAnnotatedFile(fileName: string): boolean;
44
+ /**
45
+ * Whether a script name is an install or publish lifecycle hook, with or without its `pre`/`post` prefix.
46
+ *
47
+ * @remarks Publish hooks stay because `pnpm publish` runs them right after pack-slim; install hooks stay because a
48
+ * consumer's package manager runs them.
49
+ *
50
+ * @since 0.9.0
51
+ */
52
+ export declare function isLifecycleScript(name: string): boolean;
53
+ /**
54
+ * Produces a publish manifest carrying only what a consumer's `tsc` and Node read.
55
+ *
56
+ * @remarks Operates on a structural clone, so the caller's manifest is left intact. A consumer never enables `source`
57
+ * and resolves `#/` through `types`/`default` to `dist`, so dropping the source lane, the `imports` left pointing
58
+ * outside `files`, the scripts that are not lifecycle hooks, and `devDependencies` leaves the published surface whole.
59
+ *
60
+ * @since 0.8.1
61
+ */
62
+ export declare function slimPublishManifest(manifest: Record<string, unknown>): SlimManifestResult;
63
+ /**
64
+ * Strips every `sourceMappingURL` directive line from an emitted file's text.
65
+ *
66
+ * @since 0.8.1
67
+ */
68
+ export declare function stripSourceMappingComment(text: string): StripCommentResult;
69
+ export {};
@@ -0,0 +1,46 @@
1
+ /** Stats and progress types for a pack-slim run. */
2
+ /**
3
+ * The outcome of slimming one workspace package.
4
+ *
5
+ * @since 0.8.1
6
+ */
7
+ export interface PackSlimPackageStats {
8
+ name: string;
9
+ path: string;
10
+ skipped: boolean;
11
+ skipReason: string;
12
+ error: string | null;
13
+ filesSrcRemoved: boolean;
14
+ exportsSourceRemoved: number;
15
+ importsSourceRemoved: number;
16
+ importsUnshippedRemoved: number;
17
+ scriptsRemoved: number;
18
+ devDependenciesRemoved: number;
19
+ mapFilesDeleted: number;
20
+ sourceCommentsStripped: number;
21
+ changed: boolean;
22
+ }
23
+ /**
24
+ * The aggregate stats of a pack-slim run across every targeted package.
25
+ *
26
+ * @since 0.8.1
27
+ */
28
+ export interface PackSlimRunStats {
29
+ packagesFound: number;
30
+ packagesProcessed: number;
31
+ packagesSkipped: number;
32
+ packagesErrored: number;
33
+ packagesChanged: number;
34
+ totalMapFilesDeleted: number;
35
+ packageDetails: Array<PackSlimPackageStats>;
36
+ }
37
+ /**
38
+ * The progress events a pack-slim run emits as it works through the packages.
39
+ *
40
+ * @since 0.8.1
41
+ */
42
+ export interface PackSlimProgressListener {
43
+ onBanner?(): void;
44
+ onPackageComplete?(stats: PackSlimPackageStats, ordinal: number, total: number): void;
45
+ onComplete?(stats: PackSlimRunStats, elapsedSeconds: number): void;
46
+ }
@@ -0,0 +1,15 @@
1
+ import type { PackSlimPackageStats, PackSlimProgressListener, PackSlimRunStats } from "#/pack-slim/domain/types";
2
+ /**
3
+ * A progress listener that renders pack-slim run events as human-readable CLI lines.
4
+ *
5
+ * @since 0.8.1
6
+ */
7
+ export declare class PackSlimProgressPresenter implements PackSlimProgressListener {
8
+ private dryRun;
9
+ configure(options: {
10
+ readonly dryRun: boolean;
11
+ }): void;
12
+ onBanner(): void;
13
+ onPackageComplete(stats: PackSlimPackageStats, ordinal: number, total: number): void;
14
+ onComplete(stats: PackSlimRunStats, elapsedSeconds: number): void;
15
+ }
@@ -0,0 +1,21 @@
1
+ import type { AppError } from "#/core/errors";
2
+ import type { Filesystem } from "#/core/filesystem/filesystem";
3
+ import type { Result } from "#/core/result";
4
+ /**
5
+ * The repo root and package filter a pack-slim run starts from.
6
+ *
7
+ * @since 0.8.1
8
+ */
9
+ export interface PackSlimCommandPrelude {
10
+ readonly rootDir: string;
11
+ readonly packageFilter: string | undefined;
12
+ }
13
+ /**
14
+ * Resolves the repo root and optional package filter into the prelude a pack-slim run starts from.
15
+ *
16
+ * @since 0.8.1
17
+ */
18
+ export declare function preparePackSlim(fs: Filesystem, args: {
19
+ readonly currentWorkingDirectory: string;
20
+ readonly packageArg: string | undefined;
21
+ }): Promise<Result<PackSlimCommandPrelude, AppError>>;
@@ -0,0 +1,14 @@
1
+ import { resolveProjectRootResult } from "#/core/cli/resolve-root";
2
+ import { ok } from "#/core/result";
3
+ /**
4
+ * Resolves the repo root and optional package filter into the prelude a pack-slim run starts from.
5
+ *
6
+ * @since 0.8.1
7
+ */
8
+ export async function preparePackSlim(fs, args) {
9
+ const rootOutcome = resolveProjectRootResult(fs, args.currentWorkingDirectory);
10
+ if (!rootOutcome.ok) {
11
+ return rootOutcome;
12
+ }
13
+ return ok({ rootDir: rootOutcome.value, packageFilter: args.packageArg });
14
+ }
@@ -0,0 +1,23 @@
1
+ import { AppError } from "#/core/errors";
2
+ import type { Filesystem } from "#/core/filesystem/filesystem";
3
+ import type { Result } from "#/core/result";
4
+ import type { PackSlimRunRequest } from "#/pack-slim/cli-schema";
5
+ import type { PackSlimProgressListener, PackSlimRunStats } from "#/pack-slim/domain/types";
6
+ /**
7
+ * A pack-slim run request paired with an optional progress listener.
8
+ *
9
+ * @since 0.8.1
10
+ */
11
+ export type PackSlimRunInput = PackSlimRunRequest & {
12
+ readonly listener?: PackSlimProgressListener | undefined;
13
+ };
14
+ /**
15
+ * Slims every published package's manifest and build output for publish and returns the aggregate stats.
16
+ *
17
+ * @remarks Meant to run on an ephemeral CI checkout right before `changeset publish`: it rewrites `package.json` down to
18
+ * what a consumer reads, drops `dist` source maps, and clears their now-dangling `sourceMappingURL` directives, so the
19
+ * tarball ships only `dist` runtime and types. Private packages are skipped because `changeset publish` never publishes them.
20
+ *
21
+ * @since 0.8.1
22
+ */
23
+ export declare function runPackSlim(fs: Filesystem, input: PackSlimRunInput): Promise<Result<PackSlimRunStats, AppError>>;
@@ -2,7 +2,7 @@ import path from "node:path";
2
2
  import { AppError, messageFrom } from "#/core/errors";
3
3
  import { err, ok } from "#/core/result";
4
4
  import { listWorkspacePackageDirectories } from "#/core/workspace/resolver";
5
- import { DIST_DIR, PACKAGE_JSON } from "#/mirror/domain/constants";
5
+ import { distDirName, packageJsonFileName } from "#/core/workspace/well-known-files";
6
6
  import { isMapAnnotatedFile, isSourceMapFile, slimPublishManifest, stripSourceMappingComment, } from "#/pack-slim/domain/transform";
7
7
  /**
8
8
  * Slims every published package's manifest and build output for publish and returns the aggregate stats.
@@ -47,7 +47,7 @@ export async function runPackSlim(fs, input) {
47
47
  async function resolveTargets(fs, rootDir, packageFilter) {
48
48
  if (packageFilter !== undefined) {
49
49
  const packageDir = path.resolve(rootDir, packageFilter);
50
- if (!fs.existsSync(path.join(packageDir, PACKAGE_JSON))) {
50
+ if (!fs.existsSync(path.join(packageDir, packageJsonFileName))) {
51
51
  throw new Error(`No package.json under "${packageFilter}"`);
52
52
  }
53
53
  return [packageDir];
@@ -56,7 +56,7 @@ async function resolveTargets(fs, rootDir, packageFilter) {
56
56
  return [...layout.packageDirectoryPathsAbsolute].sort((left, right) => left.localeCompare(right));
57
57
  }
58
58
  async function slimWorkspacePackage(fs, packageDir, write) {
59
- const packageJsonPath = path.join(packageDir, PACKAGE_JSON);
59
+ const packageJsonPath = path.join(packageDir, packageJsonFileName);
60
60
  const pkgStats = {
61
61
  name: path.basename(packageDir),
62
62
  path: packageDir,
@@ -103,7 +103,7 @@ async function slimWorkspacePackage(fs, packageDir, write) {
103
103
  if (report.changed && write) {
104
104
  await fs.writeFile(packageJsonPath, `${JSON.stringify(slimmed, null, 2)}\n`, "utf8");
105
105
  }
106
- await pruneDist(fs, path.join(packageDir, DIST_DIR), write, pkgStats);
106
+ await pruneDist(fs, path.join(packageDir, distDirName), write, pkgStats);
107
107
  pkgStats.changed = report.changed || pkgStats.mapFilesDeleted > 0 || pkgStats.sourceCommentsStripped > 0;
108
108
  }
109
109
  catch (caughtError) {
@@ -0,0 +1,20 @@
1
+ import { AppError } from "#/core/errors";
2
+ import type { Result } from "#/core/result";
3
+ /**
4
+ * Whether git's tracked-only porcelain output reports any uncommitted change.
5
+ *
6
+ * @remarks The output is read with `--untracked-files=no`, so untracked and gitignored paths (like the freshly built
7
+ * `dist`) never appear — any non-blank line is a staged or unstaged change to a tracked file.
8
+ *
9
+ * @since 0.8.1
10
+ */
11
+ export declare function hasUncommittedTrackedChanges(porcelainOutput: string): boolean;
12
+ /**
13
+ * Refuses when the git working tree carries uncommitted tracked changes, so a destructive slim never lands on real work.
14
+ *
15
+ * @remarks pack-slim rewrites tracked `package.json` files and deletes build output; its result must never be committed.
16
+ * A caller passing `--force` skips this, and `--dry-run` never reaches it because it writes nothing.
17
+ *
18
+ * @since 0.8.1
19
+ */
20
+ export declare function ensureWorkingTreeClean(rootDir: string): Result<void, AppError>;
@@ -0,0 +1,13 @@
1
+ import type { TagResult } from "#/tag/domain/types";
2
+ /**
3
+ * Maps a tag run's result to the process exit code.
4
+ *
5
+ * @since 0.3.16-canary.0
6
+ */
7
+ export declare function exitCodeForTagResult(result: TagResult): number;
8
+ /**
9
+ * Serializes a tag run's result as the `--json` output string.
10
+ *
11
+ * @since 0.11.0
12
+ */
13
+ export declare function formatTagJsonOutput(result: TagResult, rootDir: string): string;
@@ -4,10 +4,23 @@ import { CLI_EXIT_GENERAL_ERROR, CLI_EXIT_SUCCESS } from "#/core/exit-codes";
4
4
  *
5
5
  * @since 0.3.16-canary.0
6
6
  */
7
- export function exitCodeForTagSyncResult(result) {
7
+ export function exitCodeForTagResult(result) {
8
8
  if (result.selectedTargets.length === 0) {
9
9
  return CLI_EXIT_GENERAL_ERROR;
10
10
  }
11
11
  const hasRunErrors = result.targetResults.some((targetResult) => targetResult.runError !== null);
12
12
  return hasRunErrors || result.hookError !== null ? CLI_EXIT_GENERAL_ERROR : CLI_EXIT_SUCCESS;
13
+ }
14
+ /**
15
+ * Serializes a tag run's result as the `--json` output string.
16
+ *
17
+ * @since 0.11.0
18
+ */
19
+ export function formatTagJsonOutput(result, rootDir) {
20
+ return JSON.stringify({
21
+ schemaVersion: 1,
22
+ ok: result.hookError === null,
23
+ cwd: rootDir,
24
+ result,
25
+ });
13
26
  }
@@ -0,0 +1,8 @@
1
+ import * as z from "zod";
2
+ import type { TagRunRequest } from "#/tag/domain/types";
3
+ /**
4
+ * Zod schema validating a `TagRunRequest`.
5
+ *
6
+ * @since 0.3.16-canary.0
7
+ */
8
+ export declare const tagRunRequestSchema: z.ZodType<TagRunRequest>;
@@ -1,13 +1,12 @@
1
- import { z } from "zod";
1
+ import * as z from "zod";
2
2
  /**
3
- * Zod schema validating a `TagSyncRunRequest`.
3
+ * Zod schema validating a `TagRunRequest`.
4
4
  *
5
5
  * @since 0.3.16-canary.0
6
6
  */
7
- export const tagSyncRunRequestSchema = z.object({
7
+ export const tagRunRequestSchema = z.object({
8
8
  rootDir: z.string().min(1),
9
9
  write: z.boolean(),
10
- json: z.boolean().optional(),
11
10
  targetPath: z.string().optional(),
12
11
  skipPackages: z.array(z.string()).optional(),
13
12
  config: z.unknown().optional(),
@@ -0,0 +1,7 @@
1
+ import { Command } from "commander";
2
+ /**
3
+ * Creates the `tag` subcommand, which stamps `@since` tags on exported declarations.
4
+ *
5
+ * @since 0.3.16-canary.0
6
+ */
7
+ export declare function createTagCommand(): Command;
@@ -1,70 +1,43 @@
1
- import process from "node:process";
2
1
  import { Command } from "commander";
3
- import { readOptionalPositionalArg } from "#/core/cli/positional";
4
- import { consumeCliAppError } from "#/core/cli/result-handle";
2
+ import { applyCommandPipeline } from "#/core/cli/command-pipeline";
5
3
  import { nodeFilesystem } from "#/core/filesystem/node";
6
- import { logger } from "#/core/logger";
7
- import { parseWithSchema } from "#/core/schema-parse";
8
- import { exitCodeForTagSyncResult } from "#/tag/cli-result";
9
- import { tagSyncRunRequestSchema } from "#/tag/cli-schema";
10
- import { presentTagSyncResult, TagSyncProgressPresenter } from "#/tag/output";
11
- import { prepareTagSync } from "#/tag/prepare";
12
- import { runTagSync } from "#/tag/sync";
4
+ import { exitCodeForTagResult, formatTagJsonOutput } from "#/tag/cli-result";
5
+ import { tagRunRequestSchema } from "#/tag/cli-schema";
6
+ import { presentTagResult, TagProgressPresenter } from "#/tag/output";
7
+ import { prepareTag } from "#/tag/prepare";
8
+ import { runTag } from "#/tag/run";
9
+ const tagPipeline = {
10
+ positional: { name: "[target]", help: "Directory or file to tag (default: auto-discover workspace packages)" },
11
+ schema: tagRunRequestSchema,
12
+ configureArgv: (command) => {
13
+ command.option("--dry-run", "Show summary without writing files", false);
14
+ },
15
+ prepare: (fs, input) => prepareTag(fs, { currentWorkingDirectory: input.currentWorkingDirectory, rawTarget: input.rawArg }),
16
+ buildRequest: ({ prelude, opts }) => {
17
+ const tagConfig = prelude.config.tag ?? {};
18
+ return {
19
+ rootDir: prelude.rootDir,
20
+ write: !opts.dryRun,
21
+ targetPath: prelude.resolvedTargetPath,
22
+ skipPackages: tagConfig.skipPackages,
23
+ config: tagConfig,
24
+ };
25
+ },
26
+ createPresenter: () => new TagProgressPresenter(),
27
+ run: (fs, request, presenter) => runTag(fs, { ...request, listener: presenter }),
28
+ presentHuman: ({ result, prelude }) => {
29
+ presentTagResult(result, prelude.rootDir);
30
+ },
31
+ formatJson: ({ result, prelude }) => formatTagJsonOutput(result, prelude.rootDir),
32
+ exitCode: exitCodeForTagResult,
33
+ };
13
34
  /**
14
35
  * Creates the `tag` subcommand, which stamps `@since` tags on exported declarations.
15
36
  *
16
37
  * @since 0.3.16-canary.0
17
38
  */
18
39
  export function createTagCommand() {
19
- const cmd = new Command("tag")
20
- .description("Add @since <version> JSDoc tags to exported declarations")
21
- .argument("[target]", "Directory or file to tag (default: auto-discover workspace packages)")
22
- .option("--dry-run", "Show summary without writing files", false)
23
- .option("--json", "Print one JSON summary on stdout (suppresses human progress)", false)
24
- .action(async (target, opts) => {
25
- const prelude = await prepareTagSync(nodeFilesystem, {
26
- currentWorkingDirectory: process.cwd(),
27
- rawTarget: readOptionalPositionalArg(target),
28
- });
29
- if (!consumeCliAppError(prelude)) {
30
- return;
31
- }
32
- const { rootDir, config, resolvedTargetPath } = prelude.value;
33
- const tagConfig = config.tag ?? {};
34
- const parsed = parseWithSchema(tagSyncRunRequestSchema, {
35
- rootDir,
36
- write: !opts.dryRun,
37
- json: opts.json,
38
- targetPath: resolvedTargetPath,
39
- skipPackages: tagConfig.skipPackages,
40
- config: tagConfig,
41
- });
42
- if (!consumeCliAppError(parsed)) {
43
- return;
44
- }
45
- const progressPresenter = new TagSyncProgressPresenter();
46
- const tagOutcome = await runTagSync(nodeFilesystem, {
47
- ...parsed.value,
48
- listener: parsed.value.json ? undefined : progressPresenter,
49
- });
50
- if (!consumeCliAppError(tagOutcome)) {
51
- return;
52
- }
53
- if (parsed.value.json) {
54
- logger.out(formatTagSyncJsonOutput(tagOutcome.value, rootDir));
55
- process.exitCode = exitCodeForTagSyncResult(tagOutcome.value);
56
- }
57
- else {
58
- process.exitCode = presentTagSyncResult(tagOutcome.value, rootDir);
59
- }
60
- });
40
+ const cmd = new Command("tag").description("Add @since <version> JSDoc tags to exported declarations");
41
+ applyCommandPipeline(cmd, nodeFilesystem, tagPipeline);
61
42
  return cmd;
62
- }
63
- function formatTagSyncJsonOutput(result, rootDir) {
64
- return JSON.stringify({
65
- schemaVersion: 1,
66
- ok: result.hookError === null,
67
- cwd: rootDir,
68
- result,
69
- });
70
43
  }
@@ -0,0 +1,13 @@
1
+ import type { TagTargetCandidate } from "#/tag/domain/types";
2
+ /**
3
+ * Partitions tag target candidates into those to tag and those to skip, matching each candidate's
4
+ * package name against `skipPackages` as glob patterns.
5
+ *
6
+ * @remarks Candidates without a package name (e.g. an explicit-target path) are never skipped.
7
+ *
8
+ * @since 0.5.0-canary.0
9
+ */
10
+ export declare function filterSkippedCandidates(targetCandidates: Array<TagTargetCandidate>, skipPackages: ReadonlyArray<string> | undefined): {
11
+ includedCandidates: Array<TagTargetCandidate>;
12
+ skippedPackages: Array<string>;
13
+ };
@@ -0,0 +1,29 @@
1
+ import { createAnyGlobMatcher } from "#/core/glob";
2
+ /**
3
+ * Partitions tag target candidates into those to tag and those to skip, matching each candidate's
4
+ * package name against `skipPackages` as glob patterns.
5
+ *
6
+ * @remarks Candidates without a package name (e.g. an explicit-target path) are never skipped.
7
+ *
8
+ * @since 0.5.0-canary.0
9
+ */
10
+ export function filterSkippedCandidates(targetCandidates, skipPackages) {
11
+ if (!skipPackages || skipPackages.length === 0) {
12
+ return {
13
+ includedCandidates: targetCandidates,
14
+ skippedPackages: [],
15
+ };
16
+ }
17
+ const isSkipped = createAnyGlobMatcher(skipPackages);
18
+ const includedCandidates = [];
19
+ const skippedPackages = [];
20
+ for (const candidate of targetCandidates) {
21
+ const packageName = candidate.packageName;
22
+ if (packageName && isSkipped(packageName)) {
23
+ skippedPackages.push(packageName);
24
+ continue;
25
+ }
26
+ includedCandidates.push(candidate);
27
+ }
28
+ return { includedCandidates, skippedPackages };
29
+ }