miniread 1.101.2 → 1.102.1

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 (178) hide show
  1. package/README.md +6 -95
  2. package/dist/cli/config.d.ts +1 -6
  3. package/dist/cli/config.js +24 -72
  4. package/dist/index.d.ts +1 -1
  5. package/dist/index.js +1 -1
  6. package/dist/scripts/evaluate/check-expected-evaluations.d.ts +0 -6
  7. package/dist/scripts/evaluate/check-expected-evaluations.js +4 -25
  8. package/dist/scripts/evaluate/check-snapshots.d.ts +0 -3
  9. package/dist/scripts/evaluate/check-snapshots.js +4 -6
  10. package/dist/scripts/evaluate/create-output-slug.d.ts +0 -2
  11. package/dist/scripts/evaluate/create-output-slug.js +2 -20
  12. package/dist/scripts/evaluate/parse-evaluate-cli-options.js +7 -40
  13. package/dist/scripts/evaluate/run-check-mode.d.ts +0 -1
  14. package/dist/scripts/evaluate/run-check-mode.js +7 -37
  15. package/dist/scripts/evaluate/run-evaluate-cli.js +0 -3
  16. package/dist/scripts/evaluate/transform-manifest.d.ts +0 -1
  17. package/dist/scripts/evaluate/transform-manifest.js +11 -21
  18. package/dist/scripts/snapshot/run-testcase-transform.js +9 -11
  19. package/dist/transforms/_generated/catalog.d.ts +7 -0
  20. package/dist/transforms/_generated/catalog.js +606 -0
  21. package/dist/transforms/manifest-schema.d.ts +27 -0
  22. package/dist/transforms/manifest-schema.js +25 -0
  23. package/dist/transforms/preset-stats.json +2 -2
  24. package/dist/transforms/transform-catalog.d.ts +35 -0
  25. package/dist/transforms/transform-catalog.js +86 -0
  26. package/dist/transforms/transform-selection.d.ts +19 -0
  27. package/dist/transforms/transform-selection.js +62 -0
  28. package/dist/transforms-by-id/expand-boolean-literals/expand-boolean-literals-transform.js +93 -7
  29. package/dist/transforms-by-id/expand-boolean-literals/manifest.json +6 -5
  30. package/dist/transforms-by-id/expand-sequence-expressions-v5/manifest.json +3 -2
  31. package/dist/transforms-by-id/expand-special-number-literals/manifest.json +3 -2
  32. package/dist/transforms-by-id/expand-typeof-undefined-comparisons/manifest.json +3 -2
  33. package/dist/transforms-by-id/expand-undefined-literals/manifest.json +3 -2
  34. package/dist/transforms-by-id/remove-redundant-else/manifest.json +3 -2
  35. package/dist/transforms-by-id/rename-add-event-listener-parameters/manifest.json +4 -3
  36. package/dist/transforms-by-id/rename-add-event-listener-parameters/rename-add-event-listener-parameters-transform.js +9 -6
  37. package/dist/transforms-by-id/rename-arguments-length-flags/has-shadowed-arguments-binding.d.ts +3 -0
  38. package/dist/transforms-by-id/rename-arguments-length-flags/has-shadowed-arguments-binding.js +13 -0
  39. package/dist/transforms-by-id/rename-arguments-length-flags/manifest.json +7 -6
  40. package/dist/transforms-by-id/rename-arguments-length-flags/rename-arguments-length-flags-transform.js +62 -35
  41. package/dist/transforms-by-id/rename-asap-wrappers/manifest.json +3 -2
  42. package/dist/transforms-by-id/rename-awaiter-helper-functions/manifest.json +1 -0
  43. package/dist/transforms-by-id/rename-awaiter-parameters/manifest.json +3 -2
  44. package/dist/transforms-by-id/rename-buffer-variables/manifest.json +3 -2
  45. package/dist/transforms-by-id/rename-catch-parameters/manifest.json +3 -2
  46. package/dist/transforms-by-id/rename-char-code-at/manifest.json +3 -2
  47. package/dist/transforms-by-id/rename-charcode-variables-v2/manifest.json +3 -2
  48. package/dist/transforms-by-id/rename-client-aliases/manifest.json +3 -2
  49. package/dist/transforms-by-id/rename-comparison-flags/manifest.json +2 -2
  50. package/dist/transforms-by-id/rename-comparison-flags-v2/manifest.json +3 -2
  51. package/dist/transforms-by-id/rename-date-now-start-times/manifest.json +3 -2
  52. package/dist/transforms-by-id/rename-default-options-parameters-v3/manifest.json +1 -0
  53. package/dist/transforms-by-id/rename-deferred-resolve-parameters/manifest.json +3 -2
  54. package/dist/transforms-by-id/rename-deferred-resolve-parameters-v2/manifest.json +3 -2
  55. package/dist/transforms-by-id/rename-destructured-aliases/manifest.json +3 -2
  56. package/dist/transforms-by-id/rename-document-fragment-variables/manifest.json +1 -0
  57. package/dist/transforms-by-id/rename-error-first-callback-parameters/manifest.json +3 -2
  58. package/dist/transforms-by-id/rename-error-first-callback-parameters-v2/manifest.json +3 -2
  59. package/dist/transforms-by-id/rename-error-variables/manifest.json +3 -2
  60. package/dist/transforms-by-id/rename-event-parameters/manifest.json +3 -2
  61. package/dist/transforms-by-id/rename-execfile-arguments/manifest.json +1 -0
  62. package/dist/transforms-by-id/rename-file-extension-variables/manifest.json +3 -2
  63. package/dist/transforms-by-id/rename-file-reader-variables/manifest.json +1 -0
  64. package/dist/transforms-by-id/rename-fs-sync-variables/manifest.json +3 -2
  65. package/dist/transforms-by-id/rename-http-method-parameters/manifest.json +1 -0
  66. package/dist/transforms-by-id/rename-http-server-parameters/get-member-expression-property-name.d.ts +2 -0
  67. package/dist/transforms-by-id/rename-http-server-parameters/get-member-expression-property-name.js +14 -0
  68. package/dist/transforms-by-id/rename-http-server-parameters/has-property-usage.d.ts +2 -0
  69. package/dist/transforms-by-id/rename-http-server-parameters/has-property-usage.js +17 -0
  70. package/dist/transforms-by-id/rename-http-server-parameters/manifest.json +4 -3
  71. package/dist/transforms-by-id/rename-http-server-parameters/rename-http-server-parameters-transform.js +16 -37
  72. package/dist/transforms-by-id/rename-indexeddb-request-variables/manifest.json +1 -0
  73. package/dist/transforms-by-id/rename-interval-ids/manifest.json +1 -0
  74. package/dist/transforms-by-id/rename-invalid-parameter-arguments/manifest.json +1 -0
  75. package/dist/transforms-by-id/rename-loop-index-variables-v3/manifest.json +3 -2
  76. package/dist/transforms-by-id/rename-loop-length-variables/manifest.json +3 -2
  77. package/dist/transforms-by-id/rename-map-by-id-variables/manifest.json +3 -2
  78. package/dist/transforms-by-id/rename-object-entries-parameters/manifest.json +1 -0
  79. package/dist/transforms-by-id/rename-object-keys-iterator-variables/manifest.json +1 -0
  80. package/dist/transforms-by-id/rename-object-keys-reducer-parameters/manifest.json +1 -0
  81. package/dist/transforms-by-id/rename-object-keys-variables/manifest.json +3 -2
  82. package/dist/transforms-by-id/rename-object-property-value-variables/manifest.json +3 -2
  83. package/dist/transforms-by-id/rename-parameters-to-match-properties-v2/manifest.json +3 -2
  84. package/dist/transforms-by-id/rename-platform-win32-flags/manifest.json +1 -0
  85. package/dist/transforms-by-id/rename-process-stdout-handlers/manifest.json +2 -2
  86. package/dist/transforms-by-id/rename-promise-catch-parameters/manifest.json +5 -4
  87. package/dist/transforms-by-id/rename-promise-catch-parameters/rename-promise-catch-parameters-transform.js +38 -21
  88. package/dist/transforms-by-id/rename-promise-executor-parameters-v2/manifest.json +1 -0
  89. package/dist/transforms-by-id/rename-queue-traversal-variables/manifest.json +1 -0
  90. package/dist/transforms-by-id/rename-range-parameters/get-explicit-start-count-method-usage.d.ts +10 -0
  91. package/dist/transforms-by-id/rename-range-parameters/get-explicit-start-count-method-usage.js +45 -0
  92. package/dist/transforms-by-id/rename-range-parameters/get-range-parameter-default-assignments.d.ts +1 -0
  93. package/dist/transforms-by-id/rename-range-parameters/get-range-parameter-default-assignments.js +8 -2
  94. package/dist/transforms-by-id/rename-range-parameters/get-range-parameter-names.js +101 -32
  95. package/dist/transforms-by-id/rename-range-parameters/has-explicit-start-count-range-usage.d.ts +3 -0
  96. package/dist/transforms-by-id/rename-range-parameters/has-explicit-start-count-range-usage.js +41 -0
  97. package/dist/transforms-by-id/rename-range-parameters/has-start-count-loop-boundary-usage.d.ts +5 -0
  98. package/dist/transforms-by-id/rename-range-parameters/has-start-count-loop-boundary-usage.js +62 -0
  99. package/dist/transforms-by-id/rename-range-parameters/has-start-count-sum.js +2 -23
  100. package/dist/transforms-by-id/rename-range-parameters/is-identifier-for-binding.d.ts +5 -0
  101. package/dist/transforms-by-id/rename-range-parameters/is-identifier-for-binding.js +4 -0
  102. package/dist/transforms-by-id/rename-range-parameters/is-start-count-sum-expression.d.ts +5 -0
  103. package/dist/transforms-by-id/rename-range-parameters/is-start-count-sum-expression.js +12 -0
  104. package/dist/transforms-by-id/rename-range-parameters/manifest.json +4 -3
  105. package/dist/transforms-by-id/rename-read-file-lines/manifest.json +3 -2
  106. package/dist/transforms-by-id/rename-regex-builders/manifest.json +3 -2
  107. package/dist/transforms-by-id/rename-regex-source-parameters/manifest.json +1 -0
  108. package/dist/transforms-by-id/rename-replace-child-parameters/manifest.json +2 -2
  109. package/dist/transforms-by-id/rename-rest-parameters/manifest.json +1 -0
  110. package/dist/transforms-by-id/rename-rest-pop-callbacks/manifest.json +1 -0
  111. package/dist/transforms-by-id/rename-search-parameters-variables/manifest.json +1 -0
  112. package/dist/transforms-by-id/rename-setstate-updater-parameters/manifest.json +3 -2
  113. package/dist/transforms-by-id/rename-string-split-variables-v2/manifest.json +3 -2
  114. package/dist/transforms-by-id/rename-this-aliases/manifest.json +3 -2
  115. package/dist/transforms-by-id/rename-timeout-ids/manifest.json +3 -2
  116. package/dist/transforms-by-id/rename-timeout-promises/manifest.json +1 -0
  117. package/dist/transforms-by-id/rename-to-buffer-results/manifest.json +1 -0
  118. package/dist/transforms-by-id/rename-typeof-variables/manifest.json +1 -0
  119. package/dist/transforms-by-id/rename-typescript-helper-aliases/manifest.json +1 -0
  120. package/dist/transforms-by-id/rename-uint8array-concat-variables/manifest.json +3 -2
  121. package/dist/transforms-by-id/rename-unix-timestamp-parameters/evaluate-timestamp-seconds-parameter.d.ts +4 -0
  122. package/dist/transforms-by-id/rename-unix-timestamp-parameters/evaluate-timestamp-seconds-parameter.js +36 -0
  123. package/dist/transforms-by-id/rename-unix-timestamp-parameters/manifest.json +6 -5
  124. package/dist/transforms-by-id/rename-unix-timestamp-parameters/rename-unix-timestamp-parameters-transform.js +1 -108
  125. package/dist/transforms-by-id/rename-unix-timestamp-parameters/timestamp-parameter-guards.d.ts +5 -0
  126. package/dist/transforms-by-id/rename-unix-timestamp-parameters/timestamp-parameter-guards.js +74 -0
  127. package/dist/transforms-by-id/rename-unix-timestamp-parameters/timestamp-seconds-reference.d.ts +3 -0
  128. package/dist/transforms-by-id/rename-unix-timestamp-parameters/timestamp-seconds-reference.js +55 -0
  129. package/dist/transforms-by-id/rename-unix-timestamp-parameters/unwrap-timestamp-nodes.d.ts +10 -0
  130. package/dist/transforms-by-id/rename-unix-timestamp-parameters/unwrap-timestamp-nodes.js +54 -0
  131. package/dist/transforms-by-id/rename-url-parameters/manifest.json +3 -2
  132. package/dist/transforms-by-id/rename-url-variables/manifest.json +3 -2
  133. package/dist/transforms-by-id/rename-use-reference-guards-v2/manifest.json +3 -2
  134. package/dist/transforms-by-id/rename-use-reference-sets/manifest.json +1 -0
  135. package/dist/transforms-by-id/rename-worker-handles/manifest.json +1 -0
  136. package/dist/transforms-by-id/rename-zod-check-parameters/manifest.json +6 -5
  137. package/dist/transforms-by-id/rename-zod-check-parameters/rename-zod-check-parameters-transform.js +0 -32
  138. package/dist/transforms-by-id/replace-dynamic-require-eval/manifest.json +1 -0
  139. package/dist/transforms-by-id/simplify-boolean-negations/manifest.json +3 -2
  140. package/dist/transforms-by-id/simplify-string-trim/manifest.json +4 -3
  141. package/dist/transforms-by-id/simplify-string-trim/simplify-string-trim-transform.js +10 -3
  142. package/dist/transforms-by-id/split-variable-declarations/is-safe-to-split-variable-declaration.js +8 -6
  143. package/dist/transforms-by-id/split-variable-declarations/manifest.json +6 -5
  144. package/dist/transforms-by-id/stabilize-deferred-stable-rhs/manifest.json +1 -0
  145. package/dist/transforms-by-id/stabilize-deferred-top-level-bindings/manifest.json +1 -0
  146. package/dist/transforms-by-id/stabilize-nested-bindings/manifest.json +3 -2
  147. package/dist/transforms-by-id/stabilize-top-level-bindings/manifest.json +1 -0
  148. package/dist/transforms-by-id/use-object-property-shorthand/manifest.json +3 -2
  149. package/dist/transforms-by-id/use-object-shorthand/manifest.json +3 -2
  150. package/dist/transforms-by-id/use-optional-chaining/manifest.json +1 -0
  151. package/package.json +3 -4
  152. package/bin/miniread-pick-random-transform +0 -17
  153. package/dist/scripts/pick-random-transform/create-pick-random-transform-command.d.ts +0 -9
  154. package/dist/scripts/pick-random-transform/create-pick-random-transform-command.js +0 -28
  155. package/dist/scripts/pick-random-transform/load-transform-selection-entries.d.ts +0 -4
  156. package/dist/scripts/pick-random-transform/load-transform-selection-entries.js +0 -42
  157. package/dist/scripts/pick-random-transform/parse-pick-random-transform-cli-options.d.ts +0 -10
  158. package/dist/scripts/pick-random-transform/parse-pick-random-transform-cli-options.js +0 -10
  159. package/dist/scripts/pick-random-transform/pick-random-transform-candidates.d.ts +0 -13
  160. package/dist/scripts/pick-random-transform/pick-random-transform-candidates.js +0 -37
  161. package/dist/scripts/pick-random-transform/run-pick-random-transform-cli.d.ts +0 -1
  162. package/dist/scripts/pick-random-transform/run-pick-random-transform-cli.js +0 -64
  163. package/dist/scripts/pick-random-transform.d.ts +0 -1
  164. package/dist/scripts/pick-random-transform.js +0 -12
  165. package/dist/transforms/_generated/manifest.d.ts +0 -22
  166. package/dist/transforms/_generated/manifest.js +0 -510
  167. package/dist/transforms/_generated/registry.d.ts +0 -3
  168. package/dist/transforms/_generated/registry.js +0 -177
  169. package/dist/transforms/recommended-transform-order.d.ts +0 -7
  170. package/dist/transforms/recommended-transform-order.js +0 -104
  171. package/dist/transforms/transform-presets.d.ts +0 -3
  172. package/dist/transforms/transform-presets.js +0 -4
  173. package/dist/transforms/transform-registry.d.ts +0 -1
  174. package/dist/transforms/transform-registry.js +0 -1
  175. package/dist/transforms-by-id/rename-range-parameters/get-first-non-directive-statement.d.ts +0 -2
  176. package/dist/transforms-by-id/rename-range-parameters/get-first-non-directive-statement.js +0 -16
  177. package/dist/transforms-by-id/rename-range-parameters/has-count-non-positive-guard.d.ts +0 -3
  178. package/dist/transforms-by-id/rename-range-parameters/has-count-non-positive-guard.js +0 -49
package/README.md CHANGED
@@ -97,103 +97,14 @@ Run `npx -y miniread --help` to learn available options.
97
97
  Use `miniread` when you need readable JavaScript/TypeScript from minified input for review, diffing, or grepping; it works as a stdin/stdout filter so it composes well with Unix pipelines.
98
98
  ```
99
99
 
100
- ## Development
100
+ ## Development Workflows
101
101
 
102
- ```bash
103
- pnpm install
104
- pnpm run download-sources # Downloads Claude Code versions for evaluation
105
- pnpm run build
106
- node bin/miniread --help
107
- ```
108
-
109
- ## Script layout
110
-
111
- Developer tooling is organized by responsibility:
112
-
113
- - `scripts/evaluation/` — core evaluation orchestration
114
- - `scripts/registry/` — transform registry + manifest code generation
115
- - `scripts/workflow/` — general workflow helpers (for example, source downloads)
116
- - `workflows/scripts/evaluation/` — workflow-specific baseline helpers
117
- - `src/scripts/evaluate/compute-directory-diff.ts` — diff generation core used by evaluation
118
-
119
- ## miniread-evaluate (developer tool)
120
-
121
- The `miniread-evaluate` CLI compares transform configurations by measuring diff reduction across version pairs under `./sources/`. It prints TSV to stdout by default (or JSON with `--format json`) and sends logs/errors to stderr.
122
- `miniread-evaluate` may emit no stdout for long periods while diffing/formatting; this is normal.
123
-
124
- Metric semantics:
125
-
126
- - `BASELINE_CHANGED_LINES` (TSV) = changed lines in `baselineOutputFrom` vs `baselineOutputTo`
127
- - `TEST_CHANGED_LINES` (TSV) = changed lines in `testOutputFrom` vs `testOutputTo`
128
- - `DIFF_SIZE_PERCENT` = `TEST_CHANGED_LINES / BASELINE_CHANGED_LINES * 100`
129
- - `manifest.evaluations[<pair>].changedLines` = changed lines in `baselineOutputFrom` vs `testOutputFrom` (transform reach for the `from` version), not `BASELINE_CHANGED_LINES - TEST_CHANGED_LINES`
130
-
131
- ### Requirements
132
-
133
- - `diff` (override with `MINIREAD_EVALUATE_DIFF_PATH`)
134
- - `pnpm` + `prettier` (used unless `--no-format-code`; overrides: `MINIREAD_EVALUATE_PNPM_PATH`, `MINIREAD_EVALUATE_PRETTIER_PATH`)
135
-
136
- ### Usage
137
-
138
- ```bash
139
- pnpm run miniread-evaluate -- --help
140
-
141
- # Compare baseline none vs a transform
142
- pnpm run miniread-evaluate -- --compare v1.0:v1.1 --baseline none --test rename-destructured-aliases
143
-
144
- # Pipeline example: sort by reduction ratio (best first)
145
- pnpm run miniread-evaluate -- --compare v1.0:v1.1 --compare v2.0:v2.1 --baseline none --test rename-destructured-aliases \
146
- | tail -n +2 | sort -k5,5nr | head -10
147
- ```
102
+ Development workflow/tooling documentation lives under `development-workflows/`:
148
103
 
149
- ### Update/verify `manifest.json` for a transform
150
-
151
- After any change to a transform, you must rerun its evaluation so `changedLines`
152
- in `manifest.json` stays up to date:
153
-
154
- ```bash
155
- ./scripts/evaluation/rerun-transform-evaluations.sh <transform_id>
156
- ```
157
-
158
- ```bash
159
- # Preferred: rerun evaluations for a specific transform and update its manifest entry
160
- # Uses pair: claude-code-2.1.10:claude-code-2.1.11
161
- ./scripts/evaluation/rerun-transform-evaluations.sh <transform-id>
162
-
163
- # Optional: override the version pair when needed
164
- PAIR=claude-code-2.1.10:claude-code-2.1.11 ./scripts/evaluation/rerun-transform-evaluations.sh <transform-id>
165
-
166
- # Alternative (direct CLI)
167
- pnpm run miniread-evaluate -- \
168
- --compare claude-code-2.1.10:claude-code-2.1.11 \
169
- --baseline none \
170
- --test <transform-id> \
171
- --update-manifest \
172
- --overwrite
173
-
174
- # Verify the manifest entry was updated
175
- jq '.evaluations["claude-code-2.1.10:claude-code-2.1.11"]' \
176
- src/transforms-by-id/<transform-id>/manifest.json
177
- ```
178
-
179
- ## miniread-pick-random-transform (developer tool)
180
-
181
- The `miniread-pick-random-transform` CLI picks random transform IDs from eligible recommended transforms and prints a JSON array.
182
-
183
- ### Usage
184
-
185
- ```bash
186
- pnpm run miniread-pick-random-transform -- --help
187
-
188
- # Pick 3 random candidates from eligible recommended transforms
189
- pnpm run miniread-pick-random-transform
190
-
191
- # Pick 5 random candidates
192
- pnpm run miniread-pick-random-transform -- --pick 5
193
-
194
- # Optional: read manifests from a custom transforms directory
195
- pnpm run miniread-pick-random-transform -- --transforms-directory src/transforms-by-id --pick 3
196
- ```
104
+ - `development-workflows/AGENTS.md` shared development tooling and workflow helper docs
105
+ - `development-workflows/new-transform.md` — transform iteration workflow
106
+ - `development-workflows/improve-transform-performance.md` runtime performance optimization workflow
107
+ - `development-workflows/improve-transform-coverage.md` coverage improvement workflow
197
108
 
198
109
  ## License
199
110
 
@@ -1,10 +1,5 @@
1
1
  import type { Transform } from "../core/types.js";
2
- type TransformSummary = {
3
- id: string;
4
- description: string;
5
- scope: Transform["scope"];
6
- parallelizable: boolean;
7
- };
2
+ import { type TransformSummary } from "../transforms/transform-catalog.js";
8
3
  export declare const getTransformSummaries: () => TransformSummary[];
9
4
  type GetTransformsResult = {
10
5
  ok: true;
@@ -1,85 +1,37 @@
1
- import { transformPresets } from "../transforms/transform-presets.js";
2
- import { allTransformIds, transformRegistry, } from "../transforms/transform-registry.js";
1
+ import { expandTransformSelectors, listTransformSummaries, resolveTransformsByIds, } from "../transforms/transform-catalog.js";
3
2
  export const getTransformSummaries = () => {
4
- const summaries = [];
5
- for (const id of allTransformIds) {
6
- const transform = transformRegistry[id];
7
- if (!transform)
8
- continue;
9
- summaries.push({
10
- id,
11
- description: transform.description,
12
- scope: transform.scope,
13
- parallelizable: transform.parallelizable,
14
- });
15
- }
16
- return summaries;
17
- };
18
- const getTransformsForPreset = (preset) => {
19
- if (preset === "recommended" || preset === "default") {
20
- return [...transformPresets.recommended];
21
- }
22
- if (preset === "all") {
23
- return [...allTransformIds];
24
- }
25
- return;
3
+ return listTransformSummaries();
26
4
  };
27
5
  export const getTransformsToRun = (transformList) => {
28
6
  // undefined = run recommended transforms (default behavior)
29
7
  if (transformList === undefined) {
30
- const requestedIds = getTransformsForPreset("recommended");
31
- if (!requestedIds || requestedIds.length === 0) {
8
+ const requestedIds = expandTransformSelectors({
9
+ value: transformList,
10
+ defaultPreset: "recommended",
11
+ });
12
+ if (requestedIds.length === 0) {
32
13
  return { ok: false, error: "No recommended transforms are configured." };
33
14
  }
34
- const transforms = [];
35
- for (const id of requestedIds) {
36
- const transform = transformRegistry[id];
37
- if (!transform)
38
- return { ok: false, error: `Unknown transform: ${id}` };
39
- transforms.push(transform);
15
+ const resolveResult = resolveTransformsByIds(requestedIds);
16
+ if (!resolveResult.ok) {
17
+ const unknownTransformId = resolveResult.unknownTransformIds[0];
18
+ if (!unknownTransformId) {
19
+ return { ok: false, error: "Unknown transform: <missing-id>" };
20
+ }
21
+ return { ok: false, error: `Unknown transform: ${unknownTransformId}` };
40
22
  }
41
- return { ok: true, transforms };
42
- }
43
- // Empty string = run no transforms (explicit empty list)
44
- if (transformList === "" || transformList === "none") {
45
- return { ok: true, transforms: [] };
46
- }
47
- // Parse comma-separated list
48
- const requestedIds = transformList.split(",").map((id) => id.trim());
49
- const expandedIds = [];
50
- const unknownIds = [];
51
- for (const id of requestedIds) {
52
- if (!id || id === "none")
53
- continue;
54
- const presetTransforms = getTransformsForPreset(id);
55
- if (presetTransforms) {
56
- expandedIds.push(...presetTransforms);
57
- continue;
58
- }
59
- expandedIds.push(id);
60
- }
61
- const uniqueIds = [];
62
- const seen = new Set();
63
- for (const id of expandedIds) {
64
- if (seen.has(id))
65
- continue;
66
- seen.add(id);
67
- uniqueIds.push(id);
68
- }
69
- const transforms = [];
70
- for (const id of uniqueIds) {
71
- const transform = transformRegistry[id];
72
- if (!transform) {
73
- unknownIds.push(id);
74
- continue;
75
- }
76
- transforms.push(transform);
77
- }
78
- if (unknownIds.length > 0) {
23
+ return { ok: true, transforms: resolveResult.transforms };
24
+ }
25
+ const requestedIds = expandTransformSelectors({
26
+ value: transformList,
27
+ defaultPreset: "none",
28
+ });
29
+ const resolveResult = resolveTransformsByIds(requestedIds);
30
+ if (!resolveResult.ok) {
79
31
  return {
80
32
  ok: false,
81
- error: `Unknown transform(s): ${unknownIds.join(", ")}. Use --list-transforms to see available transforms.`,
33
+ error: `Unknown transform(s): ${resolveResult.unknownTransformIds.join(", ")}. Use --list-transforms to see available transforms.`,
82
34
  };
83
35
  }
84
- return { ok: true, transforms };
36
+ return { ok: true, transforms: resolveResult.transforms };
85
37
  };
package/dist/index.d.ts CHANGED
@@ -2,6 +2,6 @@ export type { Transform, TransformContext, TransformScope, ProjectGraph, SourceF
2
2
  export { appPaths } from "./core/paths.js";
3
3
  export type { AppPaths } from "./core/paths.js";
4
4
  export { buildProjectGraph } from "./core/project-graph.js";
5
- export { allTransformIds, transformRegistry, } from "./transforms/transform-registry.js";
5
+ export { allTransformIds, transformRegistry, } from "./transforms/transform-catalog.js";
6
6
  export { runTransforms } from "./cli/runner.js";
7
7
  export type { RunnerOptions, RunnerResult } from "./cli/runner.js";
package/dist/index.js CHANGED
@@ -2,6 +2,6 @@
2
2
  export { appPaths } from "./core/paths.js";
3
3
  export { buildProjectGraph } from "./core/project-graph.js";
4
4
  // Transform registry
5
- export { allTransformIds, transformRegistry, } from "./transforms/transform-registry.js";
5
+ export { allTransformIds, transformRegistry, } from "./transforms/transform-catalog.js";
6
6
  // Runner (for programmatic use)
7
7
  export { runTransforms } from "./cli/runner.js";
@@ -1,16 +1,10 @@
1
1
  import type { SnapshotIssue } from "./check-snapshots.js";
2
- type MissingManifestEntry = {
3
- transformId: string;
4
- path: string;
5
- };
6
2
  type CheckExpectedEvaluationsResult = {
7
3
  transformIds: string[];
8
- missingManifestEntries: MissingManifestEntry[];
9
4
  snapshotIssues: SnapshotIssue[];
10
5
  allPresent: boolean;
11
6
  };
12
7
  type CheckExpectedEvaluationsOptions = {
13
- transformsDirectory: string;
14
8
  testCasesDirectory: string;
15
9
  };
16
10
  export declare const checkExpectedEvaluations: (options: CheckExpectedEvaluationsOptions) => Promise<CheckExpectedEvaluationsResult>;
@@ -1,37 +1,16 @@
1
- import * as fs from "node:fs/promises";
2
- import path from "node:path";
3
- import { allTransformIds } from "../../transforms/transform-registry.js";
4
- import { transformRegistry } from "../../transforms/transform-registry.js";
5
- import { transformPresets } from "../../transforms/transform-presets.js";
1
+ import { allTransformIds } from "../../transforms/transform-catalog.js";
6
2
  import { checkAllSnapshots } from "./check-snapshots.js";
7
3
  export const checkExpectedEvaluations = async (options) => {
8
- const { transformsDirectory, testCasesDirectory } = options;
9
- const transformIds = allTransformIds.toSorted();
10
- const missingManifestEntries = [];
11
- // Check that each transform has a manifest.json file
12
- for (const transformId of transformIds) {
13
- const manifestPath = path.join(transformsDirectory, transformId, "manifest.json");
14
- try {
15
- await fs.access(manifestPath);
16
- }
17
- catch {
18
- missingManifestEntries.push({
19
- transformId,
20
- path: manifestPath,
21
- });
22
- }
23
- }
4
+ const { testCasesDirectory } = options;
5
+ const transformIds = [...allTransformIds];
24
6
  // Check test-cases matrix with smart snapshot detection
25
7
  const snapshotIssues = await checkAllSnapshots({
26
8
  testCasesDirectory,
27
9
  transformIds,
28
- transformRegistry,
29
- recommendedTransformIds: transformPresets.recommended,
30
10
  });
31
- const allPresent = missingManifestEntries.length === 0 && snapshotIssues.length === 0;
11
+ const allPresent = snapshotIssues.length === 0;
32
12
  return {
33
13
  transformIds,
34
- missingManifestEntries,
35
14
  snapshotIssues,
36
15
  allPresent,
37
16
  };
@@ -1,4 +1,3 @@
1
- import type { Transform } from "../../core/types.js";
2
1
  export type SnapshotIssue = {
3
2
  transformId: string;
4
3
  testCase: string;
@@ -8,8 +7,6 @@ export type SnapshotIssue = {
8
7
  type CheckAllSnapshotsOptions = {
9
8
  testCasesDirectory: string;
10
9
  transformIds: string[];
11
- transformRegistry: Record<string, Transform>;
12
- recommendedTransformIds: string[];
13
10
  };
14
11
  export declare const checkAllSnapshots: (options: CheckAllSnapshotsOptions) => Promise<SnapshotIssue[]>;
15
12
  export {};
@@ -2,6 +2,7 @@ import * as fs from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import * as prettier from "prettier";
4
4
  import { normalizeCode } from "../../core/normalize-code.js";
5
+ import { getRecommendedTransforms, getTransformById, } from "../../transforms/transform-catalog.js";
5
6
  import { transformContent } from "./transform-content.js";
6
7
  import { checkRecommendedSnapshot } from "./check-recommended-snapshot.js";
7
8
  const formatCode = async (code) => {
@@ -86,13 +87,10 @@ const getTestCaseNames = async (testCasesDirectory) => {
86
87
  return testCaseNames.toSorted();
87
88
  };
88
89
  export const checkAllSnapshots = async (options) => {
89
- const { testCasesDirectory, transformIds, transformRegistry, recommendedTransformIds, } = options;
90
+ const { testCasesDirectory, transformIds } = options;
90
91
  const snapshotIssues = [];
91
92
  const testCaseNames = await getTestCaseNames(testCasesDirectory);
92
- // Get the recommended transforms in order
93
- const recommendedTransforms = recommendedTransformIds
94
- .map((id) => transformRegistry[id])
95
- .filter((t) => t !== undefined);
93
+ const recommendedTransforms = getRecommendedTransforms();
96
94
  for (const testCaseName of testCaseNames) {
97
95
  const basePath = path.join(testCasesDirectory, testCaseName, "base.js");
98
96
  const baseContent = await fs.readFile(basePath, "utf8");
@@ -107,7 +105,7 @@ export const checkAllSnapshots = async (options) => {
107
105
  snapshotPath,
108
106
  transformId,
109
107
  testCaseName,
110
- transform: transformRegistry[transformId],
108
+ transform: getTransformById(transformId),
111
109
  });
112
110
  if (issue) {
113
111
  snapshotIssues.push(issue);
@@ -1,7 +1,5 @@
1
1
  type CreateOutputSlugOptions = {
2
2
  transforms: string[];
3
- recommendedTransforms: readonly string[];
4
- allTransformIds: readonly string[];
5
3
  };
6
4
  export declare const createOutputSlug: (options: CreateOutputSlugOptions) => string;
7
5
  export {};
@@ -1,26 +1,8 @@
1
1
  import crypto from "node:crypto";
2
+ import { getTransformSelectionSlugSource } from "../../transforms/transform-catalog.js";
2
3
  import { sanitizeFileComponent } from "./sanitize.js";
3
- const isSameOrderedList = (a, b) => {
4
- if (a.length !== b.length)
5
- return false;
6
- for (const [index, value] of a.entries()) {
7
- const other = b[index];
8
- if (other === undefined)
9
- return false;
10
- if (value !== other)
11
- return false;
12
- }
13
- return true;
14
- };
15
4
  const createRawTransformSlug = (options) => {
16
- const { transforms, recommendedTransforms, allTransformIds } = options;
17
- if (transforms.length === 0)
18
- return "none";
19
- if (isSameOrderedList(transforms, recommendedTransforms))
20
- return "recommended";
21
- if (isSameOrderedList(transforms, allTransformIds))
22
- return "all";
23
- return transforms.join("-");
5
+ return getTransformSelectionSlugSource(options.transforms);
24
6
  };
25
7
  export const createOutputSlug = (options) => {
26
8
  const sanitized = sanitizeFileComponent(createRawTransformSlug(options));
@@ -1,36 +1,11 @@
1
1
  import path from "node:path";
2
- import { transformPresets } from "../../transforms/transform-presets.js";
3
- import { allTransformIds } from "../../transforms/transform-registry.js";
2
+ import { expandTransformSelectors } from "../../transforms/transform-catalog.js";
4
3
  import { createOutputSlug } from "./create-output-slug.js";
5
4
  const parseTransformList = (value) => {
6
- if (!value || value === "none")
7
- return [];
8
- const ids = value
9
- .split(",")
10
- .map((id) => id.trim())
11
- .filter(Boolean)
12
- .filter((id) => id !== "none");
13
- const expandedIds = [];
14
- for (const id of ids) {
15
- if (id === "recommended" || id === "default") {
16
- expandedIds.push(...transformPresets.recommended);
17
- continue;
18
- }
19
- if (id === "all") {
20
- expandedIds.push(...allTransformIds);
21
- continue;
22
- }
23
- expandedIds.push(id);
24
- }
25
- const uniqueIds = [];
26
- const seen = new Set();
27
- for (const id of expandedIds) {
28
- if (seen.has(id))
29
- continue;
30
- seen.add(id);
31
- uniqueIds.push(id);
32
- }
33
- return uniqueIds;
5
+ return expandTransformSelectors({
6
+ value,
7
+ defaultPreset: "none",
8
+ });
34
9
  };
35
10
  const containsPathSeparator = (value) => {
36
11
  return value.includes("/") || value.includes("\\");
@@ -65,16 +40,8 @@ export const parseEvaluateCliOptions = (options) => {
65
40
  const verbose = rawOptions.verbose ?? false;
66
41
  const overwrite = rawOptions.overwrite ?? false;
67
42
  const formatCode = rawOptions.formatCode;
68
- const baselineSlug = createOutputSlug({
69
- transforms: baselineTransforms,
70
- recommendedTransforms: transformPresets.recommended,
71
- allTransformIds,
72
- });
73
- const testSlug = createOutputSlug({
74
- transforms: testTransforms,
75
- recommendedTransforms: transformPresets.recommended,
76
- allTransformIds,
77
- });
43
+ const baselineSlug = createOutputSlug({ transforms: baselineTransforms });
44
+ const testSlug = createOutputSlug({ transforms: testTransforms });
78
45
  const sourcesDirectory = path.resolve(cwd, rawOptions.sources);
79
46
  const evaluationDirectory = path.resolve(cwd, rawOptions.evaluationDir);
80
47
  const transformsDirectory = path.resolve(cwd, "src/transforms-by-id");
@@ -1,6 +1,5 @@
1
1
  import type { OutputFormat } from "./create-evaluate-command.js";
2
2
  type RunCheckModeOptions = {
3
- transformsDirectory: string;
4
3
  rootDirectory: string;
5
4
  format: OutputFormat;
6
5
  };
@@ -1,29 +1,20 @@
1
1
  import path from "node:path";
2
2
  import { checkExpectedEvaluations } from "./check-expected-evaluations.js";
3
3
  export const runCheckMode = async (options) => {
4
- const { transformsDirectory, rootDirectory, format } = options;
4
+ const { rootDirectory, format } = options;
5
5
  const checkResult = await checkExpectedEvaluations({
6
- transformsDirectory,
7
6
  testCasesDirectory: path.join(rootDirectory, "test-cases"),
8
7
  });
9
8
  if (format === "json") {
10
9
  console.log(JSON.stringify(checkResult, undefined, 2));
11
10
  }
12
11
  else {
13
- const allIssues = [
14
- ...checkResult.missingManifestEntries.map((item) => ({
15
- type: "manifest",
16
- transformId: item.transformId,
17
- testCase: "",
18
- path: item.path,
19
- })),
20
- ...checkResult.snapshotIssues.map((item) => ({
21
- type: item.issue,
22
- transformId: item.transformId,
23
- testCase: item.testCase,
24
- path: item.snapshotPath,
25
- })),
26
- ];
12
+ const allIssues = checkResult.snapshotIssues.map((item) => ({
13
+ type: item.issue,
14
+ transformId: item.transformId,
15
+ testCase: item.testCase,
16
+ path: item.snapshotPath,
17
+ }));
27
18
  if (allIssues.length > 0) {
28
19
  console.log("type\ttransform_id\ttest_case\tpath");
29
20
  for (const item of allIssues) {
@@ -32,27 +23,6 @@ export const runCheckMode = async (options) => {
32
23
  }
33
24
  }
34
25
  let exitCode = 0;
35
- if (checkResult.missingManifestEntries.length > 0) {
36
- console.error(`\n[MISSING MANIFEST FILES] ${checkResult.missingManifestEntries.length} transform(s) missing manifest.json:`);
37
- for (const item of checkResult.missingManifestEntries) {
38
- console.error(` - ${item.transformId}`);
39
- }
40
- console.error(`\n To fix: Create a manifest.json file in each transform directory with the following structure:`);
41
- console.error(` {`);
42
- console.error(` "recommended": true,`);
43
- console.error(` "notes": "Description of the transform's impact",`);
44
- console.error(` "evaluations": {`);
45
- console.error(` "source-v1.0.0:source-v1.0.1": {`);
46
- console.error(` "diffSizePercent": 100,`);
47
- console.error(` "evaluatedAt": "2026-01-25T00:00:00.000Z",`);
48
- console.error(` "changedLines": 0,`);
49
- console.error(` "durationSeconds": 0,`);
50
- console.error(` "stableNames": 0`);
51
- console.error(` }`);
52
- console.error(` }`);
53
- console.error(` }`);
54
- exitCode = 1;
55
- }
56
26
  const missingSnapshots = checkResult.snapshotIssues.filter((issue) => issue.issue === "missing-required");
57
27
  const unnecessarySnapshots = checkResult.snapshotIssues.filter((issue) => issue.issue === "unnecessary");
58
28
  const outdatedSnapshots = checkResult.snapshotIssues.filter((issue) => issue.issue === "outdated");
@@ -1,6 +1,5 @@
1
1
  import * as fs from "node:fs/promises";
2
2
  import packageJson from "../../../package.json" with { type: "json" };
3
- import { transformPresets } from "../../transforms/transform-presets.js";
4
3
  import { createEvaluateCommand } from "./create-evaluate-command.js";
5
4
  import { parseEvaluateCliOptions, } from "./parse-evaluate-cli-options.js";
6
5
  import { resolveEvaluateDependencies } from "./resolve-evaluate-dependencies.js";
@@ -36,7 +35,6 @@ export const runEvaluateCli = async (argv) => {
36
35
  };
37
36
  if (parsedOptions.checkMode) {
38
37
  return runCheckMode({
39
- transformsDirectory: parsedOptions.transformsDirectory,
40
38
  rootDirectory: process.cwd(),
41
39
  format: parsedOptions.format,
42
40
  });
@@ -111,7 +109,6 @@ export const runEvaluateCli = async (argv) => {
111
109
  baselineTransforms: parsedOptions.baselineTransforms,
112
110
  testTransforms: parsedOptions.testTransforms,
113
111
  diffSizeRatios: results.map((r) => r.diffSizeRatio),
114
- recommendedTransformIds: transformPresets.recommended,
115
112
  transformChangedLines: results.map((r) => r.transformChangedLines),
116
113
  evaluatedPairs: results.map((r) => r.pair),
117
114
  durationSeconds: results.map((r) => r.durationSeconds),
@@ -9,7 +9,6 @@ type UpdateTransformManifestOptions = {
9
9
  testTransforms: string[];
10
10
  /** Diff size ratios (test/baseline) per evaluation pair. */
11
11
  diffSizeRatios: number[];
12
- recommendedTransformIds: string[];
13
12
  /** Changed lines per evaluation pair (added + removed). */
14
13
  transformChangedLines?: (number | undefined)[];
15
14
  /** Source pairs used in the evaluation. */
@@ -1,9 +1,9 @@
1
- import * as fs from "node:fs/promises";
2
1
  import path from "node:path";
3
2
  import { buildEvaluationStats } from "./build-evaluation-stats.js";
4
3
  import { haveSameIds, normalizeTransformIds, uniqueIds, } from "./transform-id-set.js";
5
4
  import { writeJsonFileAtomic } from "./write-text-file-atomic.js";
6
5
  import presetStats from "../../transforms/preset-stats.json" with { type: "json" };
6
+ import { getTransformCatalogEntry, recommendedTransformIds, } from "../../transforms/transform-catalog.js";
7
7
  const average = (values) => {
8
8
  if (values.length === 0)
9
9
  return 0;
@@ -13,20 +13,8 @@ const average = (values) => {
13
13
  }
14
14
  return total / values.length;
15
15
  };
16
- const loadManifest = async (manifestPath) => {
17
- try {
18
- const content = await fs.readFile(manifestPath, "utf8");
19
- return JSON.parse(content);
20
- }
21
- catch (error) {
22
- if (error instanceof Error && "code" in error && error.code === "ENOENT") {
23
- return undefined;
24
- }
25
- throw error;
26
- }
27
- };
28
16
  export const updateTransformManifestFromEvaluation = async (options) => {
29
- const { transformsDirectory, presetStatsPath, baselineTransforms, testTransforms, diffSizeRatios, recommendedTransformIds, transformChangedLines, evaluatedPairs, durationSeconds, stableNames, } = options;
17
+ const { transformsDirectory, presetStatsPath, baselineTransforms, testTransforms, diffSizeRatios, transformChangedLines, evaluatedPairs, durationSeconds, stableNames, } = options;
30
18
  const baselineIds = normalizeTransformIds(baselineTransforms);
31
19
  const testIds = normalizeTransformIds(testTransforms);
32
20
  const isBaselineNone = baselineIds.length === 0 ||
@@ -38,8 +26,8 @@ export const updateTransformManifestFromEvaluation = async (options) => {
38
26
  const transformId = testIds[0];
39
27
  if (transformId) {
40
28
  const manifestPath = path.join(transformsDirectory, transformId, "manifest.json");
41
- const manifest = await loadManifest(manifestPath);
42
- if (manifest) {
29
+ const catalogEntry = getTransformCatalogEntry(transformId);
30
+ if (catalogEntry) {
43
31
  const newEvaluations = buildEvaluationStats({
44
32
  evaluatedPairs,
45
33
  diffSizeRatios,
@@ -48,14 +36,16 @@ export const updateTransformManifestFromEvaluation = async (options) => {
48
36
  stableNames,
49
37
  });
50
38
  const mergedEvaluations = {
51
- ...manifest.evaluations,
39
+ ...catalogEntry.manifest.evaluations,
52
40
  ...newEvaluations,
53
41
  };
54
- const evaluationsChanged = JSON.stringify(manifest.evaluations) !==
42
+ const evaluationsChanged = JSON.stringify(catalogEntry.manifest.evaluations) !==
55
43
  JSON.stringify(mergedEvaluations);
56
44
  if (evaluationsChanged) {
57
- manifest.evaluations = mergedEvaluations;
58
- await writeJsonFileAtomic(manifestPath, manifest, {
45
+ await writeJsonFileAtomic(manifestPath, {
46
+ ...catalogEntry.manifest,
47
+ evaluations: mergedEvaluations,
48
+ }, {
59
49
  overwrite: true,
60
50
  });
61
51
  messages.push(`Updated ${transformId}/manifest.json`);
@@ -63,7 +53,7 @@ export const updateTransformManifestFromEvaluation = async (options) => {
63
53
  }
64
54
  }
65
55
  else {
66
- messages.push(`Skipping update for ${transformId}: manifest.json not found at ${manifestPath}`);
56
+ messages.push(`Skipping update for ${transformId}: transform ID is not in the registry.`);
67
57
  }
68
58
  }
69
59
  }