@codefast/cli 0.3.15 → 0.3.16-canary.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 (209) hide show
  1. package/README.md +1 -1
  2. package/dist/arrange/analyze.mjs +24 -0
  3. package/dist/{domains/arrange/presentation/presenters/arrange-cli.schema.mjs → arrange/cli-schema.mjs} +10 -1
  4. package/dist/arrange/command.mjs +106 -0
  5. package/dist/{domains/arrange/domain/arrange-analyze.domain-service.mjs → arrange/domain/analyze-service.mjs} +17 -10
  6. package/dist/{domains/arrange/domain/ast/ast-node.model.mjs → arrange/domain/ast/ast-node.mjs} +57 -3
  7. package/dist/{domains/arrange/domain/ast/collectors-cn.collector.mjs → arrange/domain/ast/collectors-cn.mjs} +21 -9
  8. package/dist/{domains/arrange/domain/ast/collectors-jsx.collector.mjs → arrange/domain/ast/collectors-jsx.mjs} +5 -2
  9. package/dist/{domains/arrange/domain/ast/collectors-tv.collector.mjs → arrange/domain/ast/collectors-tv.mjs} +21 -6
  10. package/dist/{domains/arrange/domain/ast/ast-helpers.helper.mjs → arrange/domain/ast/helpers.mjs} +26 -9
  11. package/dist/{domains/arrange/domain/ast/targets.model.mjs → arrange/domain/ast/targets.mjs} +19 -10
  12. package/dist/{domains/arrange/domain/constants.domain.mjs → arrange/domain/constants.mjs} +63 -18
  13. package/dist/{domains/arrange/domain/arrange-grouping.domain-service.mjs → arrange/domain/grouping-service.mjs} +31 -10
  14. package/dist/{domains/arrange/domain/grouping.domain.mjs → arrange/domain/grouping.mjs} +39 -18
  15. package/dist/{domains/arrange/domain/imports.domain.mjs → arrange/domain/imports.mjs} +7 -3
  16. package/dist/{domains/arrange/domain/source-text-formatters.formatter.mjs → arrange/domain/source-text-formatters.mjs} +22 -5
  17. package/dist/{domains/arrange/domain/tailwind-token.value-object.mjs → arrange/domain/tailwind-token.mjs} +12 -3
  18. package/dist/{domains/arrange/domain/tailwind-token-classifier.domain-service.mjs → arrange/domain/token-classifier.mjs} +40 -15
  19. package/dist/arrange/output.mjs +79 -0
  20. package/dist/arrange/process-file.mjs +42 -0
  21. package/dist/arrange/resolve-target.mjs +24 -0
  22. package/dist/arrange/scan-target.mjs +20 -0
  23. package/dist/arrange/source-parse.mjs +18 -0
  24. package/dist/arrange/suggest.mjs +15 -0
  25. package/dist/arrange/sync.mjs +51 -0
  26. package/dist/arrange/typescript-ast-translator.mjs +354 -0
  27. package/dist/arrange/workspace.mjs +31 -0
  28. package/dist/bin.mjs +1 -1
  29. package/dist/{program.mjs → cli.mjs} +14 -20
  30. package/dist/core/cli/format-error.mjs +15 -0
  31. package/dist/core/cli/global-options.mjs +10 -0
  32. package/dist/core/cli/positional.mjs +11 -0
  33. package/dist/core/cli/result-handle.mjs +51 -0
  34. package/dist/core/config/loader.mjs +79 -0
  35. package/dist/{domains/config/domain/codefast-config.schema.mjs → core/config/schema.mjs} +16 -2
  36. package/dist/core/config/warnings.mjs +12 -0
  37. package/dist/core/config.mjs +19 -0
  38. package/dist/{shell/domain/caught-unknown-message.value-object.mjs → core/errors.mjs} +20 -4
  39. package/dist/core/exit-codes.mjs +17 -0
  40. package/dist/core/filesystem/node.mjs +32 -0
  41. package/dist/core/logger.mjs +15 -0
  42. package/dist/{shell/domain/result.model.mjs → core/result.mjs} +7 -3
  43. package/dist/core/schema-parse.mjs +18 -0
  44. package/dist/{shell/domain/source-text-edit.support.mjs → core/source-text-edit.mjs} +14 -13
  45. package/dist/core/verbose-diagnostics.mjs +11 -0
  46. package/dist/core/workspace/resolver.mjs +177 -0
  47. package/dist/core/workspace/typescript-walk.mjs +36 -0
  48. package/dist/{domains/mirror/application/mirror-sync-cli-result.mjs → mirror/cli-result.mjs} +8 -2
  49. package/dist/{domains/mirror/presentation/presenters/mirror-cli.schema.mjs → mirror/cli-schema.mjs} +4 -1
  50. package/dist/mirror/command.mjs +57 -0
  51. package/dist/mirror/dist-filesystem-impl.mjs +42 -0
  52. package/dist/{domains/mirror/domain/constants.domain.mjs → mirror/domain/constants.mjs} +16 -1
  53. package/dist/{domains/mirror/infrastructure/guards/dirent-list.guard.mjs → mirror/domain/dirent-guard.mjs} +5 -2
  54. package/dist/{domains/mirror/domain/errors.domain.mjs → mirror/domain/errors.mjs} +7 -1
  55. package/dist/{domains/mirror/domain/generate-mirror-exports.domain-service.mjs → mirror/domain/exports.mjs} +17 -10
  56. package/dist/{domains/mirror/domain/package-display-name.policy.mjs → mirror/domain/package-display-name.mjs} +5 -2
  57. package/dist/{domains/mirror/domain/path-normalizer.value-object.mjs → mirror/domain/path-normalizer.mjs} +4 -1
  58. package/dist/mirror/output.mjs +45 -0
  59. package/dist/mirror/package-path.mjs +32 -0
  60. package/dist/mirror/prepare.mjs +33 -0
  61. package/dist/mirror/sync-reporter.mjs +104 -0
  62. package/dist/mirror/sync-workspace-package.mjs +103 -0
  63. package/dist/mirror/sync.mjs +87 -0
  64. package/dist/{domains/mirror/infrastructure/package-json-exports.repository.mjs → mirror/write-exports.mjs} +11 -7
  65. package/dist/tag/cli-result.mjs +11 -0
  66. package/dist/{domains/tag/presentation/presenters/tag-cli.schema.mjs → tag/cli-schema.mjs} +4 -1
  67. package/dist/tag/command.mjs +56 -0
  68. package/dist/tag/output.mjs +87 -0
  69. package/dist/tag/prepare.mjs +29 -0
  70. package/dist/tag/resolve-target-path.mjs +12 -0
  71. package/dist/tag/since-writer.mjs +130 -0
  72. package/dist/tag/sync.mjs +141 -0
  73. package/dist/tag/target-candidates.mjs +68 -0
  74. package/dist/tag/target-runner.mjs +26 -0
  75. package/dist/tag/version-resolver.mjs +25 -0
  76. package/package.json +4 -7
  77. package/dist/bootstrap/cli-application.module.mjs +0 -18
  78. package/dist/bootstrap/composition-root.mjs +0 -14
  79. package/dist/bootstrap/register-cli-command-trees.mjs +0 -7
  80. package/dist/domains/arrange/application/ports/outbound/arrange-target-scanner.port.mjs +0 -1
  81. package/dist/domains/arrange/application/ports/outbound/domain-source-parser.port.mjs +0 -1
  82. package/dist/domains/arrange/application/ports/outbound/file-walker.port.mjs +0 -1
  83. package/dist/domains/arrange/application/ports/presenting/present-analyze-report.presenter.mjs +0 -1
  84. package/dist/domains/arrange/application/ports/presenting/present-arrange-sync-result.presenter.mjs +0 -1
  85. package/dist/domains/arrange/application/ports/presenting/present-group-file-preview.presenter.mjs +0 -1
  86. package/dist/domains/arrange/application/requests/analyze-directory.request.mjs +0 -1
  87. package/dist/domains/arrange/application/requests/arrange-sync.request.mjs +0 -1
  88. package/dist/domains/arrange/application/requests/suggest-groups.request.mjs +0 -1
  89. package/dist/domains/arrange/application/use-cases/analyze-directory.use-case.mjs +0 -255
  90. package/dist/domains/arrange/application/use-cases/prepare-arrange-workspace.use-case.mjs +0 -264
  91. package/dist/domains/arrange/application/use-cases/run-arrange-sync.use-case.mjs +0 -274
  92. package/dist/domains/arrange/application/use-cases/suggest-cn-groups.use-case.mjs +0 -237
  93. package/dist/domains/arrange/arrange.module.mjs +0 -38
  94. package/dist/domains/arrange/composition/tokens.mjs +0 -17
  95. package/dist/domains/arrange/contracts/models.mjs +0 -1
  96. package/dist/domains/arrange/domain/tailwind-grouping.domain-service.mjs +0 -231
  97. package/dist/domains/arrange/domain/types.domain.mjs +0 -1
  98. package/dist/domains/arrange/infrastructure/adapters/arrange-file-processor.adapter.mjs +0 -267
  99. package/dist/domains/arrange/infrastructure/adapters/arrange-target-path-resolver.adapter.mjs +0 -247
  100. package/dist/domains/arrange/infrastructure/adapters/arrange-target-scanner.adapter.mjs +0 -243
  101. package/dist/domains/arrange/infrastructure/adapters/domain-source-parser.adapter.mjs +0 -241
  102. package/dist/domains/arrange/infrastructure/adapters/file-walker.adapter.mjs +0 -240
  103. package/dist/domains/arrange/infrastructure/typescript-ast-translator.mjs +0 -580
  104. package/dist/domains/arrange/presentation/cli/arrange.command.mjs +0 -465
  105. package/dist/domains/arrange/presentation/presenters/arrange-analyze.presenter.mjs +0 -252
  106. package/dist/domains/arrange/presentation/presenters/arrange-sync.presenter.mjs +0 -236
  107. package/dist/domains/arrange/presentation/presenters/group-file-preview.presenter.mjs +0 -271
  108. package/dist/domains/config/application/ports/outbound/codefast-config-schema.port.mjs +0 -1
  109. package/dist/domains/config/application/ports/outbound/config-loader.port.mjs +0 -1
  110. package/dist/domains/config/application/ports/outbound/config-warning-reporter.port.mjs +0 -1
  111. package/dist/domains/config/composition/tokens.mjs +0 -7
  112. package/dist/domains/config/domain/schema.domain.mjs +0 -1
  113. package/dist/domains/config/infrastructure/adapters/config-loader.adapter.mjs +0 -305
  114. package/dist/domains/config/infrastructure/adapters/config-warning-reporter.adapter.mjs +0 -234
  115. package/dist/domains/config/infrastructure/adapters/zod-codefast-config-schema.adapter.mjs +0 -236
  116. package/dist/domains/mirror/application/ports/inbound/prepare-mirror-sync.port.mjs +0 -1
  117. package/dist/domains/mirror/application/ports/inbound/run-mirror-sync.port.mjs +0 -1
  118. package/dist/domains/mirror/application/ports/outbound/file-system-service.port.mjs +0 -1
  119. package/dist/domains/mirror/application/ports/outbound/mirror-package-path.port.mjs +0 -1
  120. package/dist/domains/mirror/application/ports/outbound/mirror-sync-reporter.port.mjs +0 -1
  121. package/dist/domains/mirror/application/ports/outbound/package-repository.port.mjs +0 -1
  122. package/dist/domains/mirror/application/ports/outbound/sync-workspace-package.port.mjs +0 -1
  123. package/dist/domains/mirror/application/ports/presenting/present-mirror-sync-progress.presenter.mjs +0 -1
  124. package/dist/domains/mirror/application/requests/mirror-sync-execution-input.mjs +0 -1
  125. package/dist/domains/mirror/application/requests/mirror-sync.request.mjs +0 -1
  126. package/dist/domains/mirror/application/use-cases/prepare-mirror-sync.use-case.mjs +0 -263
  127. package/dist/domains/mirror/application/use-cases/run-mirror-sync.use-case.mjs +0 -317
  128. package/dist/domains/mirror/composition/tokens.mjs +0 -12
  129. package/dist/domains/mirror/contracts/models.mjs +0 -1
  130. package/dist/domains/mirror/domain/types.domain.mjs +0 -1
  131. package/dist/domains/mirror/infrastructure/adapters/file-system-service.adapter.mjs +0 -261
  132. package/dist/domains/mirror/infrastructure/adapters/mirror-package-path-resolver.adapter.mjs +0 -252
  133. package/dist/domains/mirror/infrastructure/adapters/mirror-sync-reporter.adapter.mjs +0 -322
  134. package/dist/domains/mirror/infrastructure/adapters/package-repository.adapter.mjs +0 -241
  135. package/dist/domains/mirror/infrastructure/adapters/sync-workspace-package.adapter.mjs +0 -328
  136. package/dist/domains/mirror/mirror.module.mjs +0 -26
  137. package/dist/domains/mirror/presentation/cli/mirror.command.mjs +0 -328
  138. package/dist/domains/mirror/presentation/presenters/present-mirror-sync-progress.presenter.mjs +0 -265
  139. package/dist/domains/tag/application/ports/inbound/prepare-tag-sync.port.mjs +0 -1
  140. package/dist/domains/tag/application/ports/inbound/run-tag-sync.port.mjs +0 -1
  141. package/dist/domains/tag/application/ports/outbound/tag-eligible-workspace-paths.port.mjs +0 -1
  142. package/dist/domains/tag/application/ports/outbound/tag-since-writer.port.mjs +0 -1
  143. package/dist/domains/tag/application/ports/outbound/tag-target-path-resolver.port.mjs +0 -1
  144. package/dist/domains/tag/application/ports/outbound/tag-target-runner.port.mjs +0 -1
  145. package/dist/domains/tag/application/ports/outbound/tag-version-resolver.port.mjs +0 -1
  146. package/dist/domains/tag/application/ports/presenting/present-tag-sync-progress.presenter.mjs +0 -1
  147. package/dist/domains/tag/application/ports/presenting/present-tag-sync-result.presenter.mjs +0 -1
  148. package/dist/domains/tag/application/requests/tag-sync-execution-input.mjs +0 -1
  149. package/dist/domains/tag/application/requests/tag-sync.request.mjs +0 -1
  150. package/dist/domains/tag/application/tag-sync-cli-result.mjs +0 -11
  151. package/dist/domains/tag/application/use-cases/prepare-tag-sync.use-case.mjs +0 -260
  152. package/dist/domains/tag/application/use-cases/run-tag-sync.use-case.mjs +0 -375
  153. package/dist/domains/tag/composition/tokens.mjs +0 -13
  154. package/dist/domains/tag/contracts/models.mjs +0 -1
  155. package/dist/domains/tag/domain/types.domain.mjs +0 -1
  156. package/dist/domains/tag/infrastructure/adapters/tag-since-writer.adapter.mjs +0 -348
  157. package/dist/domains/tag/infrastructure/adapters/tag-target-path-resolver.adapter.mjs +0 -235
  158. package/dist/domains/tag/infrastructure/adapters/tag-target-resolver.adapter.mjs +0 -302
  159. package/dist/domains/tag/infrastructure/adapters/tag-target-runner.adapter.mjs +0 -259
  160. package/dist/domains/tag/infrastructure/adapters/tag-version-resolver.adapter.mjs +0 -249
  161. package/dist/domains/tag/presentation/cli/tag.command.mjs +0 -325
  162. package/dist/domains/tag/presentation/presenters/present-tag-sync-progress.presenter.mjs +0 -248
  163. package/dist/domains/tag/presentation/presenters/present-tag-sync-result.presenter.mjs +0 -290
  164. package/dist/domains/tag/tag.module.mjs +0 -28
  165. package/dist/shell/application/cli-runtime.tokens.mjs +0 -18
  166. package/dist/shell/application/coordination/cli-executor.coordination.mjs +0 -1
  167. package/dist/shell/application/coordination/cli-schema-parsing.coordination.mjs +0 -1
  168. package/dist/shell/application/global-cli-options.model.mjs +0 -5
  169. package/dist/shell/application/ports/inbound/load-codefast-config.port.mjs +0 -1
  170. package/dist/shell/application/ports/outbound/cli-fs.port.mjs +0 -1
  171. package/dist/shell/application/ports/outbound/cli-logger.port.mjs +0 -1
  172. package/dist/shell/application/ports/outbound/cli-path.port.mjs +0 -1
  173. package/dist/shell/application/ports/outbound/cli-runtime.port.mjs +0 -1
  174. package/dist/shell/application/ports/outbound/cli-telemetry.port.mjs +0 -1
  175. package/dist/shell/application/ports/outbound/cli-verbose-diagnostics.port.mjs +0 -1
  176. package/dist/shell/application/ports/outbound/format-app-error.port.mjs +0 -1
  177. package/dist/shell/application/ports/outbound/global-cli-options-parse.port.mjs +0 -1
  178. package/dist/shell/application/ports/outbound/repo-root-resolver.port.mjs +0 -1
  179. package/dist/shell/application/ports/outbound/typescript-source-file-walker.port.mjs +0 -1
  180. package/dist/shell/application/ports/outbound/workspace-package-layout.port.mjs +0 -1
  181. package/dist/shell/application/ports/primary/command.port.mjs +0 -1
  182. package/dist/shell/application/services/cli-executor.service.mjs +0 -267
  183. package/dist/shell/application/services/schema-validator.service.mjs +0 -236
  184. package/dist/shell/application/use-cases/load-codefast-config.use-case.mjs +0 -243
  185. package/dist/shell/composition/tokens.mjs +0 -5
  186. package/dist/shell/contracts/cli-command-slots.mjs +0 -11
  187. package/dist/shell/domain/cli-exit-codes.domain.mjs +0 -11
  188. package/dist/shell/domain/cli-positional-arg.value-object.mjs +0 -6
  189. package/dist/shell/domain/errors.domain.mjs +0 -17
  190. package/dist/shell/infrastructure/adapters/cli-verbose-diagnostics.adapter.mjs +0 -228
  191. package/dist/shell/infrastructure/adapters/format-app-error.adapter.mjs +0 -236
  192. package/dist/shell/infrastructure/adapters/global-cli-options-parser.adapter.mjs +0 -233
  193. package/dist/shell/infrastructure/adapters/repo-root-resolver.adapter.mjs +0 -244
  194. package/dist/shell/infrastructure/adapters/typescript-source-file-walker.adapter.mjs +0 -259
  195. package/dist/shell/infrastructure/commander/commander-cli-host.adapter.mjs +0 -69
  196. package/dist/shell/infrastructure/node/node-cli-fs.adapter.mjs +0 -249
  197. package/dist/shell/infrastructure/node/node-cli-logger.adapter.mjs +0 -231
  198. package/dist/shell/infrastructure/node/node-cli-path.adapter.mjs +0 -246
  199. package/dist/shell/infrastructure/node/node-cli-runtime.adapter.mjs +0 -234
  200. package/dist/shell/infrastructure/telemetry/cli-telemetry.adapter.mjs +0 -280
  201. package/dist/shell/infrastructure/workspace/node-pnpm-workspace-package-layout.adapter.mjs +0 -385
  202. package/dist/shell/shell.module.mjs +0 -43
  203. package/dist/shell/wiring/optional-cli-port-telemetry-activation.mjs +0 -13
  204. /package/dist/{domains/arrange/application/ports/inbound/analyze-directory.port.mjs → arrange/domain/types.mjs} +0 -0
  205. /package/dist/{domains/arrange/application/ports/inbound/prepare-arrange-workspace.port.mjs → core/filesystem/port.mjs} +0 -0
  206. /package/dist/{domains/arrange/application/ports/inbound/run-arrange-sync.port.mjs → mirror/domain/dist-filesystem.mjs} +0 -0
  207. /package/dist/{domains/arrange/application/ports/inbound/suggest-cn-groups.port.mjs → mirror/domain/types.mjs} +0 -0
  208. /package/dist/{domains/arrange/application/ports/outbound/arrange-file-processor.port.mjs → mirror/sync-types.mjs} +0 -0
  209. /package/dist/{domains/arrange/application/ports/outbound/arrange-target-path-resolver.port.mjs → tag/domain/types.mjs} +0 -0
@@ -0,0 +1,79 @@
1
+ import { logger } from "../core/logger.mjs";
2
+ import "./domain/constants.mjs";
3
+ import { lineOf } from "./domain/ast/helpers.mjs";
4
+ import path from "node:path";
5
+ //#region src/arrange/output.ts
6
+ /**
7
+ * @since 0.3.16-canary.0
8
+ */
9
+ function printAnalyzeReport(resolvedTargetPath, report) {
10
+ logger.out(`Path: ${path.resolve(resolvedTargetPath)}`);
11
+ logger.out(`.ts/.tsx files: ${report.files}`);
12
+ logger.out(`cn(...) call sites: ${report.cnCallExpressions}`);
13
+ logger.out(`tv(...) call sites: ${report.tvCallExpressions}`);
14
+ logger.out(`\nLong cn(...) string literals (≥18 tokens — consider splitting arguments): ${report.longCnStringLiterals.length}`);
15
+ for (const findingEntry of report.longCnStringLiterals.slice(0, 40)) logger.out(` ${findingEntry.file}:${findingEntry.line} (${findingEntry.tokenCount} tokens) ${findingEntry.preview}`);
16
+ if (report.longCnStringLiterals.length > 40) logger.out(` … and ${report.longCnStringLiterals.length - 40} more`);
17
+ logger.out(`\nLong tv({...}) string literals in base/variants/… (≥18 tokens): ${report.longTvStringLiterals.length}`);
18
+ for (const findingEntry of report.longTvStringLiterals.slice(0, 40)) logger.out(` ${findingEntry.file}:${findingEntry.line} (${findingEntry.tokenCount} tokens) ${findingEntry.preview}`);
19
+ if (report.longTvStringLiterals.length > 40) logger.out(` … and ${report.longTvStringLiterals.length - 40} more`);
20
+ logger.out(`\nJSX className="..." or className={'...'} (static strings, ≥18 tokens): ${report.longJsxClassNameLiterals.length}`);
21
+ for (const findingEntry of report.longJsxClassNameLiterals.slice(0, 40)) logger.out(` ${findingEntry.file}:${findingEntry.line} (${findingEntry.tokenCount} tokens) ${findingEntry.preview}`);
22
+ if (report.longJsxClassNameLiterals.length > 40) logger.out(` … and ${report.longJsxClassNameLiterals.length - 40} more`);
23
+ logger.out(`\ncn(...) nested inside tv({...}) (prefer a string or array — preview/apply can rewrite): ${report.cnInsideTvCalls.length}`);
24
+ for (const findingEntry of report.cnInsideTvCalls.slice(0, 40)) logger.out(` ${findingEntry.file}:${findingEntry.line} (${findingEntry.argCount} args) ${findingEntry.preview}`);
25
+ if (report.cnInsideTvCalls.length > 40) logger.out(` … and ${report.cnInsideTvCalls.length - 40} more`);
26
+ }
27
+ /**
28
+ * @since 0.3.16-canary.0
29
+ */
30
+ function printSyncResult(result, write) {
31
+ logger.out(`\nTotal: ${result.filePaths.length} file(s), ${result.totalFound} site(s) (cn/tv/JSX className) to review.`);
32
+ if (write) logger.out(`Applied: ${result.totalChanged} site(s) updated.`);
33
+ else logger.out(`(Run "apply" to write changes, or "pnpm cli:arrange-apply" / "pnpm exec codefast arrange apply")`);
34
+ if (write ? result.totalChanged > 0 : result.totalFound > 0) logger.out("Note: class order may change across concern groups — smoke-test the UI if you rely on cascade order.");
35
+ if (result.hookError !== null) logger.err(result.hookError);
36
+ }
37
+ /**
38
+ * @since 0.3.16-canary.0
39
+ */
40
+ function printGroupFilePreviewFromWork(work) {
41
+ printGroupFilePreviewBody({
42
+ filePath: work.filePath,
43
+ reportTotal: work.reportTotal,
44
+ cnInTvNoReplacement: work.cnInTvNoReplacement,
45
+ cnInTvCalls: work.cnInTvCalls,
46
+ unwrapReplacementByCall: work.unwrapReplacementByCall,
47
+ sourceText: work.sourceText,
48
+ domainSf: work.domainSfForLineNumbers,
49
+ unwrapEdits: work.unwrapEdits,
50
+ plannedGroupEdits: work.plannedGroupEdits
51
+ });
52
+ }
53
+ function printGroupFilePreviewBody(args) {
54
+ const { filePath, reportTotal, cnInTvNoReplacement, cnInTvCalls, unwrapReplacementByCall, sourceText, domainSf, unwrapEdits, plannedGroupEdits } = args;
55
+ let header = `\n── ${filePath} (${reportTotal} site(s)`;
56
+ if (cnInTvNoReplacement > 0) header += `; plus ${cnInTvNoReplacement} cn() inside tv left unchanged (0 args)`;
57
+ header += `) ──`;
58
+ logger.out(header);
59
+ for (const call of cnInTvCalls) {
60
+ const replacement = unwrapReplacementByCall.get(call);
61
+ if (replacement === void 0) {
62
+ logger.out(` Line ${lineOf(domainSf, call)} [tv ⊃ cn]: cn(...) has no arguments — skipped`);
63
+ continue;
64
+ }
65
+ const start = call.pos;
66
+ const end = call.end;
67
+ if (sourceText.slice(start, end) === replacement) continue;
68
+ logger.out(` Line ${lineOf(domainSf, call)} [tv ⊃ cn → string/array]:`);
69
+ logger.out(` ${replacement.split("\n").join("\n ")}`);
70
+ }
71
+ if (unwrapEdits.length > 0 && plannedGroupEdits.length > 0) logger.out(" ([cn] / [tv] / [JSX className] lines below reflect content after unwrap of cn inside tv.)");
72
+ for (const plan of plannedGroupEdits) {
73
+ logger.out(` Line ${lineOf(plan.lineSf, plan.reportNode)} [${plan.label}]:`);
74
+ logger.out(` ${plan.replacement.split("\n").join("\n ")}`);
75
+ logger.out(` // Buckets: ${JSON.stringify(plan.bucketSummary)}`);
76
+ }
77
+ }
78
+ //#endregion
79
+ export { printAnalyzeReport, printGroupFilePreviewFromWork, printSyncResult };
@@ -0,0 +1,42 @@
1
+ import { parseDomainSourceFile } from "./source-parse.mjs";
2
+ import { buildGroupFileUnwrapState, countPersistedGroupFileEdits, groupFileDryRunNoEdits, groupFileEditsTouchJsxCn, groupFilePreviewTotals, groupFileWorkHasNothingToReport, mergeGroupFileBodyText, tryBuildGroupFileWorkPlan } from "./domain/grouping-service.mjs";
3
+ import { ensureCnImport } from "./domain/imports.mjs";
4
+ //#region src/arrange/process-file.ts
5
+ /**
6
+ * @since 0.3.16-canary.0
7
+ */
8
+ function processArrangeGroupFile(fs, args) {
9
+ const { filePath, options } = args;
10
+ const sourceText = fs.readFileSync(filePath, "utf8");
11
+ const domainSfInitial = parseDomainSourceFile(filePath, sourceText);
12
+ const unwrap = buildGroupFileUnwrapState(domainSfInitial, sourceText);
13
+ const work = tryBuildGroupFileWorkPlan({
14
+ filePath,
15
+ sourceText,
16
+ domainSfInitial,
17
+ domainSfGrouped: parseDomainSourceFile(filePath, unwrap.textAfterUnwrap),
18
+ withClassName: options.withClassName,
19
+ unwrap
20
+ });
21
+ if (work === null) return groupFileDryRunNoEdits(filePath);
22
+ if (!options.write) {
23
+ if (groupFileWorkHasNothingToReport(work)) return groupFileDryRunNoEdits(filePath);
24
+ return {
25
+ ...groupFilePreviewTotals(work),
26
+ workPlan: work
27
+ };
28
+ }
29
+ const persistedEditCount = countPersistedGroupFileEdits(work);
30
+ let newText = mergeGroupFileBodyText(work);
31
+ if (persistedEditCount > 0) {
32
+ if (groupFileEditsTouchJsxCn(work)) newText = ensureCnImport(parseDomainSourceFile(filePath, newText), options.cnImport);
33
+ fs.writeFileSync(filePath, newText, "utf8");
34
+ }
35
+ return {
36
+ filePath,
37
+ totalFound: persistedEditCount + work.cnInTvNoReplacement,
38
+ changed: persistedEditCount
39
+ };
40
+ }
41
+ //#endregion
42
+ export { processArrangeGroupFile };
@@ -0,0 +1,24 @@
1
+ import path from "node:path";
2
+ //#region src/arrange/resolve-target.ts
3
+ const packageJsonFileName = "package.json";
4
+ /**
5
+ * @since 0.3.16-canary.0
6
+ */
7
+ function resolveArrangeTargetPath(fs, args) {
8
+ const explicitTargetPath = args.rawTarget ? path.isAbsolute(args.rawTarget) ? path.resolve(args.rawTarget) : path.resolve(args.currentWorkingDirectory, args.rawTarget) : void 0;
9
+ if (explicitTargetPath) return fs.canonicalPathSync(explicitTargetPath);
10
+ const resolvedDefaultTarget = findNearestPackageDirectory(fs, args.currentWorkingDirectory) ?? args.currentWorkingDirectory;
11
+ return fs.canonicalPathSync(resolvedDefaultTarget);
12
+ }
13
+ function findNearestPackageDirectory(fs, currentWorkingDirectory) {
14
+ let currentDir = path.resolve(currentWorkingDirectory);
15
+ while (true) {
16
+ const packageJsonPath = path.join(currentDir, packageJsonFileName);
17
+ if (fs.existsSync(packageJsonPath)) return currentDir;
18
+ const parentDirectory = path.dirname(currentDir);
19
+ if (parentDirectory === currentDir) return;
20
+ currentDir = parentDirectory;
21
+ }
22
+ }
23
+ //#endregion
24
+ export { resolveArrangeTargetPath };
@@ -0,0 +1,20 @@
1
+ import { messageFrom } from "../core/errors.mjs";
2
+ import { logger } from "../core/logger.mjs";
3
+ import { walkTsxFiles } from "../core/workspace/typescript-walk.mjs";
4
+ import path from "node:path";
5
+ //#region src/arrange/scan-target.ts
6
+ /**
7
+ * @since 0.3.16-canary.0
8
+ */
9
+ function scanArrangeTargets(fs, targetPath) {
10
+ const resolvedTargetPath = path.resolve(targetPath);
11
+ if (fs.statSync(resolvedTargetPath).isDirectory()) try {
12
+ return walkTsxFiles(resolvedTargetPath, fs);
13
+ } catch (caughtError) {
14
+ logger.err(`[file-walker] ${messageFrom(caughtError)}`);
15
+ throw caughtError;
16
+ }
17
+ return [resolvedTargetPath];
18
+ }
19
+ //#endregion
20
+ export { scanArrangeTargets };
@@ -0,0 +1,18 @@
1
+ import { messageFrom } from "../core/errors.mjs";
2
+ import { logger } from "../core/logger.mjs";
3
+ import { TypeScriptAstTranslator } from "./typescript-ast-translator.mjs";
4
+ //#region src/arrange/source-parse.ts
5
+ const translator = new TypeScriptAstTranslator();
6
+ /**
7
+ * @since 0.3.16-canary.0
8
+ */
9
+ function parseDomainSourceFile(filePath, sourceText) {
10
+ try {
11
+ return translator.translateSourceFile(filePath, sourceText);
12
+ } catch (caughtError) {
13
+ logger.err(`[domain-source-parser] ${messageFrom(caughtError)}`);
14
+ throw caughtError;
15
+ }
16
+ }
17
+ //#endregion
18
+ export { parseDomainSourceFile };
@@ -0,0 +1,15 @@
1
+ import { suggestCnGroups, summarizeGroupBucketLabels } from "./domain/grouping.mjs";
2
+ import { formatArray, formatCnCall } from "./domain/source-text-formatters.mjs";
3
+ //#region src/arrange/suggest.ts
4
+ /**
5
+ * @since 0.3.16-canary.0
6
+ */
7
+ function suggestCnGroupsFromCli(request) {
8
+ const groups = suggestCnGroups(request.inlineClasses);
9
+ return {
10
+ primaryLine: request.emitTvStyleArray ? formatArray(groups) : formatCnCall(groups, { trailingClassName: request.trailingClassName }),
11
+ bucketsCommentLine: `// Buckets: ${JSON.stringify(summarizeGroupBucketLabels(groups))}`
12
+ };
13
+ }
14
+ //#endregion
15
+ export { suggestCnGroupsFromCli };
@@ -0,0 +1,51 @@
1
+ import { messageFrom } from "../core/errors.mjs";
2
+ import { ok } from "../core/result.mjs";
3
+ import { scanArrangeTargets } from "./scan-target.mjs";
4
+ import { processArrangeGroupFile } from "./process-file.mjs";
5
+ //#region src/arrange/sync.ts
6
+ async function runOnAfterWriteHook(hook, modifiedFiles) {
7
+ if (!hook || modifiedFiles.length === 0) return null;
8
+ try {
9
+ await hook({ files: modifiedFiles });
10
+ return null;
11
+ } catch (caughtHookError) {
12
+ return `[arrange] onAfterWrite hook failed: ${messageFrom(caughtHookError)}`;
13
+ }
14
+ }
15
+ /**
16
+ * @since 0.3.16-canary.0
17
+ */
18
+ async function runArrangeSync(fs, request) {
19
+ const filePaths = scanArrangeTargets(fs, request.targetPath);
20
+ const modifiedFiles = [];
21
+ const previewPlans = [];
22
+ let totalFound = 0;
23
+ let totalChanged = 0;
24
+ const groupOptions = {
25
+ write: request.write,
26
+ withClassName: !!request.withClassName,
27
+ cnImport: request.cnImport
28
+ };
29
+ for (const filePath of filePaths) {
30
+ const fileProcessResult = processArrangeGroupFile(fs, {
31
+ filePath,
32
+ options: groupOptions
33
+ });
34
+ totalFound += fileProcessResult.totalFound;
35
+ totalChanged += fileProcessResult.changed;
36
+ if (fileProcessResult.changed > 0) modifiedFiles.push(fileProcessResult.filePath);
37
+ if (fileProcessResult.workPlan) previewPlans.push(fileProcessResult.workPlan);
38
+ }
39
+ const arrangeConfig = request.config;
40
+ const hookError = request.write && modifiedFiles.length > 0 ? await runOnAfterWriteHook(arrangeConfig?.onAfterWrite, modifiedFiles) : null;
41
+ return ok({
42
+ filePaths,
43
+ modifiedFiles,
44
+ totalFound,
45
+ totalChanged,
46
+ hookError,
47
+ previewPlans
48
+ });
49
+ }
50
+ //#endregion
51
+ export { runArrangeSync };
@@ -0,0 +1,354 @@
1
+ import "./domain/ast/ast-node.mjs";
2
+ import ts from "typescript";
3
+ //#region src/arrange/typescript-ast-translator.ts
4
+ /**
5
+ * Anti-corruption layer: maps TypeScript compiler AST to arrange domain AST.
6
+ * This module is the only place that imports `typescript` for arrange AST translation.
7
+ */
8
+ /**
9
+ * @since 0.3.16-canary.0
10
+ */
11
+ var TypeScriptAstTranslator = class {
12
+ translateSourceFile(filePath, sourceText) {
13
+ return this.parseDomainSourceFile(filePath, sourceText);
14
+ }
15
+ translateUnknown(n, parent, sf) {
16
+ const self = {
17
+ kind: 1,
18
+ pos: n.getStart(sf),
19
+ end: n.getEnd(),
20
+ parent,
21
+ children: []
22
+ };
23
+ const childList = [];
24
+ ts.forEachChild(n, (child) => {
25
+ childList.push(this.translateNode(child, self, sf));
26
+ });
27
+ return {
28
+ ...self,
29
+ children: childList
30
+ };
31
+ }
32
+ mapBinaryOperator(operatorToken) {
33
+ if (operatorToken.kind === ts.SyntaxKind.PlusToken) return 0;
34
+ return 1;
35
+ }
36
+ translateNode(n, parent, sf) {
37
+ const pos = n.getStart(sf);
38
+ const end = n.getEnd();
39
+ switch (n.kind) {
40
+ case ts.SyntaxKind.Identifier: return {
41
+ kind: 2,
42
+ pos,
43
+ end,
44
+ parent,
45
+ text: n.text
46
+ };
47
+ case ts.SyntaxKind.StringLiteral: return {
48
+ kind: 3,
49
+ pos,
50
+ end,
51
+ parent,
52
+ text: n.text
53
+ };
54
+ case ts.SyntaxKind.NoSubstitutionTemplateLiteral: return {
55
+ kind: 4,
56
+ pos,
57
+ end,
58
+ parent,
59
+ text: n.text
60
+ };
61
+ case ts.SyntaxKind.ImportDeclaration: {
62
+ const decl = n;
63
+ const self = {
64
+ kind: 5,
65
+ pos,
66
+ end,
67
+ parent,
68
+ importClause: void 0,
69
+ moduleSpecifier: void 0
70
+ };
71
+ if (decl.importClause) self.importClause = this.translateNode(decl.importClause, self, sf);
72
+ self.moduleSpecifier = this.translateNode(decl.moduleSpecifier, self, sf);
73
+ return self;
74
+ }
75
+ case ts.SyntaxKind.ImportClause: {
76
+ const clause = n;
77
+ const self = {
78
+ kind: 6,
79
+ pos,
80
+ end,
81
+ parent,
82
+ isTypeOnly: clause.isTypeOnly,
83
+ name: void 0,
84
+ namedBindings: void 0
85
+ };
86
+ if (clause.name) self.name = this.translateNode(clause.name, self, sf);
87
+ if (clause.namedBindings) self.namedBindings = this.translateNode(clause.namedBindings, self, sf);
88
+ return self;
89
+ }
90
+ case ts.SyntaxKind.NamedImports: {
91
+ const named = n;
92
+ const self = {
93
+ kind: 7,
94
+ pos,
95
+ end,
96
+ parent,
97
+ elements: []
98
+ };
99
+ const elements = [];
100
+ for (const element of named.elements) elements.push(this.translateNode(element, self, sf));
101
+ return {
102
+ ...self,
103
+ elements
104
+ };
105
+ }
106
+ case ts.SyntaxKind.NamespaceImport: {
107
+ const ns = n;
108
+ const self = {
109
+ kind: 8,
110
+ pos,
111
+ end,
112
+ parent,
113
+ name: void 0
114
+ };
115
+ self.name = this.translateNode(ns.name, self, sf);
116
+ return self;
117
+ }
118
+ case ts.SyntaxKind.ImportSpecifier: {
119
+ const spec = n;
120
+ const self = {
121
+ kind: 9,
122
+ pos,
123
+ end,
124
+ parent,
125
+ propertyName: void 0,
126
+ name: void 0
127
+ };
128
+ if (spec.propertyName) self.propertyName = this.translateNode(spec.propertyName, self, sf);
129
+ self.name = this.translateNode(spec.name, self, sf);
130
+ return self;
131
+ }
132
+ case ts.SyntaxKind.CallExpression: {
133
+ const call = n;
134
+ const self = {
135
+ kind: 10,
136
+ pos,
137
+ end,
138
+ parent,
139
+ expression: void 0,
140
+ arguments: []
141
+ };
142
+ self.expression = this.translateNode(call.expression, self, sf);
143
+ self.arguments = call.arguments.map((arg) => this.translateNode(arg, self, sf));
144
+ return self;
145
+ }
146
+ case ts.SyntaxKind.PropertyAccessExpression: {
147
+ const pa = n;
148
+ const self = {
149
+ kind: 11,
150
+ pos,
151
+ end,
152
+ parent,
153
+ expression: void 0,
154
+ name: void 0
155
+ };
156
+ self.expression = this.translateNode(pa.expression, self, sf);
157
+ self.name = this.translateNode(pa.name, self, sf);
158
+ return self;
159
+ }
160
+ case ts.SyntaxKind.ObjectLiteralExpression: {
161
+ const obj = n;
162
+ const self = {
163
+ kind: 12,
164
+ pos,
165
+ end,
166
+ parent,
167
+ properties: []
168
+ };
169
+ const properties = [];
170
+ for (const prop of obj.properties) properties.push(this.translateNode(prop, self, sf));
171
+ return {
172
+ ...self,
173
+ properties
174
+ };
175
+ }
176
+ case ts.SyntaxKind.PropertyAssignment: {
177
+ const prop = n;
178
+ const self = {
179
+ kind: 13,
180
+ pos,
181
+ end,
182
+ parent,
183
+ name: void 0,
184
+ initializer: void 0
185
+ };
186
+ self.name = this.translateNode(prop.name, self, sf);
187
+ self.initializer = this.translateNode(prop.initializer, self, sf);
188
+ return self;
189
+ }
190
+ case ts.SyntaxKind.ArrayLiteralExpression: {
191
+ const arr = n;
192
+ const self = {
193
+ kind: 14,
194
+ pos,
195
+ end,
196
+ parent,
197
+ elements: []
198
+ };
199
+ const elements = [];
200
+ for (const element of arr.elements) elements.push(this.translateNode(element, self, sf));
201
+ return {
202
+ ...self,
203
+ elements
204
+ };
205
+ }
206
+ case ts.SyntaxKind.SpreadElement: {
207
+ const sp = n;
208
+ const self = {
209
+ kind: 15,
210
+ pos,
211
+ end,
212
+ parent,
213
+ expression: void 0
214
+ };
215
+ self.expression = this.translateNode(sp.expression, self, sf);
216
+ return self;
217
+ }
218
+ case ts.SyntaxKind.ParenthesizedExpression: {
219
+ const pe = n;
220
+ const self = {
221
+ kind: 16,
222
+ pos,
223
+ end,
224
+ parent,
225
+ expression: void 0
226
+ };
227
+ self.expression = this.translateNode(pe.expression, self, sf);
228
+ return self;
229
+ }
230
+ case ts.SyntaxKind.AsExpression: {
231
+ const ae = n;
232
+ const self = {
233
+ kind: 17,
234
+ pos,
235
+ end,
236
+ parent,
237
+ expression: void 0
238
+ };
239
+ self.expression = this.translateNode(ae.expression, self, sf);
240
+ return self;
241
+ }
242
+ case ts.SyntaxKind.SatisfiesExpression: {
243
+ const se = n;
244
+ const self = {
245
+ kind: 18,
246
+ pos,
247
+ end,
248
+ parent,
249
+ expression: void 0
250
+ };
251
+ self.expression = this.translateNode(se.expression, self, sf);
252
+ return self;
253
+ }
254
+ case ts.SyntaxKind.NonNullExpression: {
255
+ const nn = n;
256
+ const self = {
257
+ kind: 19,
258
+ pos,
259
+ end,
260
+ parent,
261
+ expression: void 0
262
+ };
263
+ self.expression = this.translateNode(nn.expression, self, sf);
264
+ return self;
265
+ }
266
+ case ts.SyntaxKind.ConditionalExpression: {
267
+ const ce = n;
268
+ const self = {
269
+ kind: 20,
270
+ pos,
271
+ end,
272
+ parent,
273
+ condition: void 0,
274
+ whenTrue: void 0,
275
+ whenFalse: void 0
276
+ };
277
+ self.condition = this.translateNode(ce.condition, self, sf);
278
+ self.whenTrue = this.translateNode(ce.whenTrue, self, sf);
279
+ self.whenFalse = this.translateNode(ce.whenFalse, self, sf);
280
+ return self;
281
+ }
282
+ case ts.SyntaxKind.BinaryExpression: {
283
+ const be = n;
284
+ const self = {
285
+ kind: 21,
286
+ pos,
287
+ end,
288
+ parent,
289
+ left: void 0,
290
+ operator: this.mapBinaryOperator(be.operatorToken),
291
+ right: void 0
292
+ };
293
+ self.left = this.translateNode(be.left, self, sf);
294
+ self.right = this.translateNode(be.right, self, sf);
295
+ return self;
296
+ }
297
+ case ts.SyntaxKind.ExpressionStatement: {
298
+ const es = n;
299
+ const self = {
300
+ kind: 22,
301
+ pos,
302
+ end,
303
+ parent,
304
+ expression: void 0
305
+ };
306
+ self.expression = this.translateNode(es.expression, self, sf);
307
+ return self;
308
+ }
309
+ case ts.SyntaxKind.JsxAttribute: {
310
+ const ja = n;
311
+ const self = {
312
+ kind: 23,
313
+ pos,
314
+ end,
315
+ parent,
316
+ name: void 0,
317
+ initializer: void 0
318
+ };
319
+ self.name = this.translateNode(ja.name, self, sf);
320
+ if (ja.initializer) self.initializer = this.translateNode(ja.initializer, self, sf);
321
+ return self;
322
+ }
323
+ case ts.SyntaxKind.JsxExpression: {
324
+ const je = n;
325
+ const self = {
326
+ kind: 24,
327
+ pos,
328
+ end,
329
+ parent,
330
+ expression: void 0
331
+ };
332
+ if (je.expression) self.expression = this.translateNode(je.expression, self, sf);
333
+ return self;
334
+ }
335
+ default: return this.translateUnknown(n, parent, sf);
336
+ }
337
+ }
338
+ translateTypeScriptSourceFile(tsSf) {
339
+ const text = tsSf.getFullText();
340
+ const statements = tsSf.statements.map((statement) => this.translateNode(statement, null, tsSf));
341
+ return {
342
+ fileName: tsSf.fileName,
343
+ text,
344
+ statements
345
+ };
346
+ }
347
+ parseDomainSourceFile(filePath, sourceText) {
348
+ const scriptKind = filePath.endsWith(".tsx") ? ts.ScriptKind.TSX : ts.ScriptKind.TS;
349
+ const tsSf = ts.createSourceFile(filePath, sourceText, ts.ScriptTarget.Latest, true, scriptKind);
350
+ return this.translateTypeScriptSourceFile(tsSf);
351
+ }
352
+ };
353
+ //#endregion
354
+ export { TypeScriptAstTranslator };
@@ -0,0 +1,31 @@
1
+ import { AppError, messageFrom } from "../core/errors.mjs";
2
+ import { err, ok } from "../core/result.mjs";
3
+ import { loadCodefastConfig } from "../core/config.mjs";
4
+ import { findRepoRoot } from "../core/workspace/resolver.mjs";
5
+ import { resolveArrangeTargetPath } from "./resolve-target.mjs";
6
+ //#region src/arrange/workspace.ts
7
+ /**
8
+ * @since 0.3.16-canary.0
9
+ */
10
+ async function prepareArrangeWorkspace(fs, args) {
11
+ const resolvedTarget = resolveArrangeTargetPath(fs, {
12
+ currentWorkingDirectory: args.currentWorkingDirectory,
13
+ rawTarget: args.rawTarget
14
+ });
15
+ if (!fs.existsSync(resolvedTarget)) return err(new AppError("NOT_FOUND", `Not found: ${resolvedTarget}`));
16
+ let rootDir;
17
+ try {
18
+ rootDir = findRepoRoot(args.currentWorkingDirectory, fs);
19
+ } catch (caughtError) {
20
+ return err(new AppError("INFRA_FAILURE", messageFrom(caughtError), caughtError));
21
+ }
22
+ const loadedOutcome = await loadCodefastConfig(rootDir, fs);
23
+ if (!loadedOutcome.ok) return loadedOutcome;
24
+ return ok({
25
+ resolvedTarget,
26
+ rootDir,
27
+ config: loadedOutcome.value.config
28
+ });
29
+ }
30
+ //#endregion
31
+ export { prepareArrangeWorkspace };
package/dist/bin.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { runCli } from "./program.mjs";
2
+ import { runCli } from "./cli.mjs";
3
3
  import process from "node:process";
4
4
  //#region src/bin.ts
5
5
  const code = await runCli(process.argv);