@codefast/cli 0.3.14-canary.1 → 0.3.14

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 (142) hide show
  1. package/dist/{commands/arrange.mjs → lib/arrange/adapters/primary/cli/arrange.command.mjs} +32 -33
  2. package/dist/lib/arrange/adapters/primary/cli/arrange.presentation.module.mjs +14 -0
  3. package/dist/lib/arrange/adapters/primary/cli/presentation.tokens.mjs +5 -0
  4. package/dist/lib/arrange/{infra → adapters/secondary}/domain-source-parser.adapter.mjs +5 -8
  5. package/dist/lib/arrange/{infra → adapters/secondary}/file-walker.adapter.mjs +11 -9
  6. package/dist/lib/arrange/adapters/secondary/workspace-resolver.adapter.mjs +233 -0
  7. package/dist/lib/arrange/application/services/arrange-file-processor.service.mjs +37 -12
  8. package/dist/lib/arrange/application/services/arrange-target-path-resolver.service.mjs +21 -0
  9. package/dist/lib/arrange/application/services/arrange-target-scanner.service.mjs +10 -4
  10. package/dist/lib/arrange/application/use-cases/analyze-directory.use-case.mjs +7 -10
  11. package/dist/lib/arrange/{presentation/prepare-arrange.orchestrator.mjs → application/use-cases/prepare-arrange-workspace.use-case.mjs} +25 -20
  12. package/dist/lib/arrange/application/use-cases/run-arrange-sync.use-case.mjs +10 -19
  13. package/dist/lib/arrange/application/use-cases/suggest-cn-groups.use-case.mjs +9 -5
  14. package/dist/lib/arrange/arrange.module.mjs +17 -13
  15. package/dist/lib/arrange/contracts/tokens.mjs +6 -5
  16. package/dist/lib/arrange/domain/arrange-analyze.service.mjs +1 -1
  17. package/dist/lib/arrange/domain/ast/ast-helpers.helper.mjs +1 -1
  18. package/dist/lib/arrange/domain/ast/ast-node.model.mjs +1 -21
  19. package/dist/lib/arrange/domain/ast/collectors-tv.collector.mjs +2 -2
  20. package/dist/lib/arrange/domain/ast/targets.model.mjs +6 -6
  21. package/dist/lib/arrange/domain/grouping.domain.mjs +3 -2
  22. package/dist/lib/arrange/domain/imports.domain.mjs +1 -1
  23. package/dist/lib/arrange/domain/source-text-formatters.formatter.mjs +19 -2
  24. package/dist/lib/{tag/presentation/create-tag-progress-listener.presenter.mjs → arrange/domain/tailwind-grouping.service.mjs} +10 -7
  25. package/dist/lib/arrange/domain/{tokenizer.util.mjs → tailwind-token-classifier.domain-service.mjs} +3 -29
  26. package/dist/lib/arrange/domain/tailwind-token.value-object.mjs +31 -0
  27. package/dist/lib/arrange/{infra/ts-ast-translator.adapter.mjs → infrastructure/typescript-ast-translator.adapter.mjs} +2 -2
  28. package/dist/lib/arrange/presentation/arrange-analyze.presenter.mjs +259 -0
  29. package/dist/lib/arrange/presentation/arrange-cli.schema.mjs +18 -0
  30. package/dist/lib/arrange/presentation/arrange-sync.presenter.mjs +23 -2
  31. package/dist/lib/arrange/presentation/group-file-preview.presenter.mjs +10 -14
  32. package/dist/lib/bootstrap/composition-root.mjs +33 -0
  33. package/dist/lib/config/application/services/load-config.service.mjs +17 -0
  34. package/dist/lib/config/contracts/tokens.mjs +2 -1
  35. package/dist/lib/config/infrastructure/config-loader.adapter.mjs +306 -0
  36. package/dist/lib/config/{infra → infrastructure}/config-schema.adapter.mjs +2 -2
  37. package/dist/lib/{arrange/presentation/present-analyze-report.presenter.mjs → config/infrastructure/config-warning-reporter.adapter.mjs} +9 -8
  38. package/dist/lib/core/{presentation/try-load-codefast-config.presenter.mjs → application/load-codefast-config.use-case.mjs} +22 -22
  39. package/dist/lib/core/{presentation/global-cli-options.presenter.mjs → application/services/global-cli-options-parser.service.mjs} +3 -3
  40. package/dist/lib/core/application/services/schema-validator.service.mjs +17 -0
  41. package/dist/lib/core/contracts/tokens.mjs +7 -2
  42. package/dist/lib/core/core.module.mjs +3 -3
  43. package/dist/lib/core/{application/utils/caught-unknown-message.util.mjs → domain/caught-unknown-message.value-object.mjs} +1 -1
  44. package/dist/lib/core/domain/errors.domain.mjs +13 -12
  45. package/dist/lib/core/domain/result.model.mjs +1 -7
  46. package/dist/lib/core/infrastructure/infrastructure.module.mjs +30 -0
  47. package/dist/lib/core/infrastructure/path.adapter.mjs +246 -0
  48. package/dist/lib/core/{infra/logging-decorator.adapter.mjs → infrastructure/port-telemetry.decorator.mjs} +1 -1
  49. package/dist/lib/core/infrastructure/repo-root-resolver.adapter.mjs +233 -0
  50. package/dist/lib/core/{application/utils/verbose-diagnostics.util.mjs → infrastructure/verbose-diagnostics.policy.mjs} +1 -1
  51. package/dist/lib/core/presentation/cli-executor.presenter.mjs +3 -18
  52. package/dist/lib/core/presentation/cli-schema.parser.mjs +7 -0
  53. package/dist/lib/core/presentation/presentation.module.mjs +1 -7
  54. package/dist/lib/{infra → infrastructure}/node-io.adapter.mjs +22 -3
  55. package/dist/lib/{infra/workspace/repo-root.adapter.mjs → infrastructure/workspace/repo-root-resolver.service.mjs} +1 -1
  56. package/dist/lib/kernel/contracts/tokens.mjs +5 -0
  57. package/dist/{commands/mirror.mjs → lib/mirror/adapters/primary/cli/mirror.command.mjs} +17 -12
  58. package/dist/lib/mirror/{infra → adapters/secondary}/file-system-service.adapter.mjs +14 -9
  59. package/dist/lib/mirror/{infra → adapters/secondary}/mirror-sync-reporter.adapter.mjs +12 -5
  60. package/dist/lib/mirror/{infra → adapters/secondary}/package-repository.adapter.mjs +12 -6
  61. package/dist/lib/mirror/{application/services/sync-workspace-package.service.mjs → adapters/secondary/sync-workspace-package.adapter.mjs} +29 -29
  62. package/dist/lib/mirror/{infra → adapters/secondary}/workspace-service.adapter.mjs +12 -7
  63. package/dist/lib/mirror/application/{use-cases/generate-mirror-exports.use-case.mjs → services/generate-mirror-exports.service.mjs} +7 -7
  64. package/dist/lib/mirror/{presentation/resolve-mirror-package-arg.presenter.mjs → application/services/mirror-package-arg-resolver.service.mjs} +4 -4
  65. package/dist/lib/mirror/{presentation/prepare-mirror.orchestrator.mjs → application/use-cases/prepare-mirror-sync.use-case.mjs} +23 -22
  66. package/dist/lib/mirror/application/use-cases/run-mirror-sync.use-case.mjs +12 -12
  67. package/dist/lib/mirror/contracts/tokens.mjs +3 -3
  68. package/dist/lib/mirror/domain/package-display-name.policy.mjs +9 -0
  69. package/dist/lib/mirror/{infra/path-normalizer.adapter.mjs → domain/path-normalizer.value-object.mjs} +1 -1
  70. package/dist/lib/mirror/{infra/dirent-list.adapter.mjs → infrastructure/dirent-list.guard.mjs} +1 -1
  71. package/dist/lib/mirror/infrastructure/mirror-console-reporter.presenter.mjs +99 -0
  72. package/dist/lib/mirror/{infra/package-filter.adapter.mjs → infrastructure/package-filter-resolver.service.mjs} +2 -2
  73. package/dist/lib/mirror/{infra/update-pkg.adapter.mjs → infrastructure/package-json-exports.repository.mjs} +4 -19
  74. package/dist/lib/mirror/{infra/workspace-packages.adapter.mjs → infrastructure/workspace-packages.service.mjs} +4 -4
  75. package/dist/lib/mirror/mirror.module.mjs +17 -15
  76. package/dist/lib/mirror/presentation/{mirror-cli-schema.presenter.mjs → mirror-cli.schema.mjs} +1 -1
  77. package/dist/lib/shared/source-code/domain/text-edit.model.mjs +32 -5
  78. package/dist/lib/shared/source-code/{infra/tsx-file-walk.adapter.mjs → infrastructure/typescript-source-file-walker.service.mjs} +2 -2
  79. package/dist/lib/tag/adapters/primary/cli/presentation.tokens.mjs +6 -0
  80. package/dist/{commands/tag.mjs → lib/tag/adapters/primary/cli/tag.command.mjs} +23 -21
  81. package/dist/lib/tag/adapters/primary/cli/tag.presentation.module.mjs +13 -0
  82. package/dist/lib/tag/{infra → adapters/secondary}/tag-since-writer.adapter.mjs +12 -7
  83. package/dist/lib/tag/{infra → adapters/secondary}/tag-target-resolver.adapter.mjs +12 -5
  84. package/dist/lib/tag/{infra → adapters/secondary}/tag-version-resolver.adapter.mjs +10 -8
  85. package/dist/lib/tag/{infra → adapters/secondary}/typescript-tree-walk.adapter.mjs +12 -5
  86. package/dist/lib/tag/{presentation/resolve-tag-cli-target.presenter.mjs → application/services/tag-cli-target-path-resolver.service.mjs} +1 -1
  87. package/dist/lib/tag/application/services/tag-target-runner.service.mjs +21 -0
  88. package/dist/lib/tag/{presentation/prepare-tag.orchestrator.mjs → application/use-cases/prepare-tag-sync.use-case.mjs} +23 -23
  89. package/dist/lib/tag/application/use-cases/run-tag-sync.use-case.mjs +14 -31
  90. package/dist/lib/tag/contracts/tokens.mjs +2 -4
  91. package/dist/lib/tag/{infra → infrastructure}/tag-target-candidates.adapter.mjs +4 -4
  92. package/dist/lib/tag/presentation/present-tag-sync-result.presenter.mjs +1 -1
  93. package/dist/lib/tag/presentation/{tag-cli-schema.presenter.mjs → tag-cli.schema.mjs} +1 -1
  94. package/dist/lib/tag/presentation/tag-sync-progress-listener.presenter.mjs +243 -0
  95. package/dist/lib/tag/presentation/tag-sync.presenter.mjs +6 -23
  96. package/dist/lib/tag/tag.module.mjs +15 -13
  97. package/dist/program.mjs +2 -2
  98. package/package.json +16 -9
  99. package/dist/lib/arrange/application/arrange-analyze-json.format.mjs +0 -10
  100. package/dist/lib/arrange/application/arrange-group-json.format.mjs +0 -11
  101. package/dist/lib/arrange/application/arrange-sync-cli-result.mjs +0 -7
  102. package/dist/lib/arrange/application/arrange-sync-json.format.mjs +0 -12
  103. package/dist/lib/arrange/application/use-cases/group-file.use-case.mjs +0 -35
  104. package/dist/lib/arrange/arrange.feature.module.mjs +0 -19
  105. package/dist/lib/arrange/arrange.presentation.module.mjs +0 -13
  106. package/dist/lib/arrange/domain/errors.domain.mjs +0 -18
  107. package/dist/lib/arrange/infra/ensure-cn-import.adapter.mjs +0 -10
  108. package/dist/lib/arrange/infra/merge-cn-literal-pool-for-test.test-helper.mjs +0 -18
  109. package/dist/lib/arrange/presentation/arrange-cli-schema.presenter.mjs +0 -29
  110. package/dist/lib/arrange/presentation/formatters.presenter.mjs +0 -2
  111. package/dist/lib/arrange/presentation/present-analyze-cli.presenter.mjs +0 -7
  112. package/dist/lib/arrange/presentation/report.presenter.mjs +0 -24
  113. package/dist/lib/arrange/presentation/resolve-arrange-cli-target.presenter.mjs +0 -21
  114. package/dist/lib/config/application/use-cases/load-config.use-case.mjs +0 -17
  115. package/dist/lib/config/infra/loader.adapter.mjs +0 -84
  116. package/dist/lib/core/application/schema-parse.util.mjs +0 -17
  117. package/dist/lib/core/infra/composition-root.mjs +0 -21
  118. package/dist/lib/core/infra/infra.module.mjs +0 -23
  119. package/dist/lib/core/infra/path.adapter.mjs +0 -13
  120. package/dist/lib/core/operational/contracts/tokens.mjs +0 -7
  121. package/dist/lib/core/presentation/load-codefast-config.presenter.mjs +0 -18
  122. package/dist/lib/core/presentation/parse-cli-schema.presenter.mjs +0 -7
  123. package/dist/lib/infra/config-reporter.adapter.mjs +0 -11
  124. package/dist/lib/kernel/di/command.token.mjs +0 -5
  125. package/dist/lib/mirror/contracts/use-cases.contract.mjs +0 -1
  126. package/dist/lib/mirror/infra/mirror-sync-cli-options.adapter.mjs +0 -1
  127. package/dist/lib/mirror/mirror.feature.module.mjs +0 -19
  128. package/dist/lib/mirror/mirror.presentation.module.mjs +0 -11
  129. package/dist/lib/mirror/presentation/reporter.presenter.mjs +0 -111
  130. package/dist/lib/tag/contracts/presentation.contract.mjs +0 -1
  131. package/dist/lib/tag/contracts/use-cases.contract.mjs +0 -1
  132. package/dist/lib/tag/infra/tag-sync-cli-options.adapter.mjs +0 -1
  133. package/dist/lib/tag/presentation/resolve-tag-workspace-root.presenter.mjs +0 -12
  134. package/dist/lib/tag/tag.feature.module.mjs +0 -19
  135. package/dist/lib/tag/tag.presentation.module.mjs +0 -15
  136. /package/dist/lib/arrange/{contracts/presentation.contract.mjs → application/ports/workspace-resolver.port.mjs} +0 -0
  137. /package/dist/lib/arrange/contracts/{use-cases.contract.mjs → analyze-report-presenter.contract.mjs} +0 -0
  138. /package/dist/lib/{arrange/infra/arrange-sync-cli-options.adapter.mjs → config/application/ports/config-warning-reporter.port.mjs} +0 -0
  139. /package/dist/lib/core/{contracts/presentation.contract.mjs → application/ports/repo-root-resolver.port.mjs} +0 -0
  140. /package/dist/lib/core/{presentation/command.interface.mjs → application/ports/runtime.port.mjs} +0 -0
  141. /package/dist/lib/{infra/fs-contract.port.mjs → kernel/contracts/cli-command.contract.mjs} +0 -0
  142. /package/dist/lib/{mirror/contracts/presentation.contract.mjs → tag/contracts/tag-sync-result-presenter.contract.mjs} +0 -0
@@ -1,12 +1,11 @@
1
- import { CliFsToken } from "../../core/operational/contracts/tokens.mjs";
2
- import { appError } from "../../core/domain/errors.domain.mjs";
3
- import { err, ok } from "../../core/domain/result.model.mjs";
4
- import { messageFromCaughtUnknown } from "../../core/application/utils/caught-unknown-message.util.mjs";
5
- import { findRepoRoot } from "../../infra/workspace/repo-root.adapter.mjs";
6
- import { resolveArrangeCliTargetPath } from "./resolve-arrange-cli-target.presenter.mjs";
7
- import { TryLoadCodefastConfigPresenterToken } from "../../core/contracts/tokens.mjs";
1
+ import { WorkspaceResolverPortToken } from "../../contracts/tokens.mjs";
2
+ import { CliFsToken, LoadCodefastConfigUseCaseToken } from "../../../core/contracts/tokens.mjs";
3
+ import { AppError } from "../../../core/domain/errors.domain.mjs";
4
+ import { err, ok } from "../../../core/domain/result.model.mjs";
5
+ import { messageFromCaughtUnknown } from "../../../core/domain/caught-unknown-message.value-object.mjs";
6
+ import { resolveArrangeTargetPath } from "../services/arrange-target-path-resolver.service.mjs";
8
7
  import { inject, injectable } from "@codefast/di";
9
- //#region src/lib/arrange/presentation/prepare-arrange.orchestrator.ts
8
+ //#region src/lib/arrange/application/use-cases/prepare-arrange-workspace.use-case.ts
10
9
  function toPrimitive(input, hint) {
11
10
  if (typeof input !== "object" || input === null) return input;
12
11
  var prim = input[Symbol.toPrimitive];
@@ -217,32 +216,38 @@ function _apply_decs_2311(targetClass, classDecs, memberDecs, classDecsHaveThis,
217
216
  };
218
217
  }
219
218
  let _dec, _initClass;
220
- _dec = injectable([inject(CliFsToken), inject(TryLoadCodefastConfigPresenterToken)]);
221
- let _PrepareArrangeOrchestrator;
219
+ _dec = injectable([
220
+ inject(CliFsToken),
221
+ inject(LoadCodefastConfigUseCaseToken),
222
+ inject(WorkspaceResolverPortToken)
223
+ ]);
224
+ let _PrepareArrangeWorkspaceUseCaseImpl;
222
225
  (class {
223
226
  fs;
224
- tryLoadCodefastConfig;
227
+ loadCodefastConfig;
228
+ workspaceResolver;
225
229
  static {
226
- ({c: [_PrepareArrangeOrchestrator, _initClass]} = _apply_decs_2311(this, [_dec], []));
230
+ ({c: [_PrepareArrangeWorkspaceUseCaseImpl, _initClass]} = _apply_decs_2311(this, [_dec], []));
227
231
  }
228
- constructor(fs, tryLoadCodefastConfig) {
232
+ constructor(fs, loadCodefastConfig, workspaceResolver) {
229
233
  this.fs = fs;
230
- this.tryLoadCodefastConfig = tryLoadCodefastConfig;
234
+ this.loadCodefastConfig = loadCodefastConfig;
235
+ this.workspaceResolver = workspaceResolver;
231
236
  }
232
237
  async execute(args) {
233
- const resolvedTarget = resolveArrangeCliTargetPath({
238
+ const resolvedTarget = resolveArrangeTargetPath({
234
239
  fs: this.fs,
235
240
  currentWorkingDirectory: args.currentWorkingDirectory,
236
241
  rawTarget: args.rawTarget
237
242
  });
238
- if (!this.fs.existsSync(resolvedTarget)) return err(appError("NOT_FOUND", `Not found: ${resolvedTarget}`));
243
+ if (!this.fs.existsSync(resolvedTarget)) return err(new AppError("NOT_FOUND", `Not found: ${resolvedTarget}`));
239
244
  let rootDir;
240
245
  try {
241
- rootDir = findRepoRoot(this.fs, args.currentWorkingDirectory);
246
+ rootDir = this.workspaceResolver.findRepoRoot(args.currentWorkingDirectory);
242
247
  } catch (caughtError) {
243
- return err(appError("INFRA_FAILURE", messageFromCaughtUnknown(caughtError), caughtError));
248
+ return err(new AppError("INFRA_FAILURE", messageFromCaughtUnknown(caughtError), caughtError));
244
249
  }
245
- const loadedOutcome = await this.tryLoadCodefastConfig.execute(rootDir);
250
+ const loadedOutcome = await this.loadCodefastConfig.execute(rootDir);
246
251
  if (!loadedOutcome.ok) return loadedOutcome;
247
252
  return ok({
248
253
  resolvedTarget,
@@ -255,4 +260,4 @@ let _PrepareArrangeOrchestrator;
255
260
  }
256
261
  });
257
262
  //#endregion
258
- export { _PrepareArrangeOrchestrator as PrepareArrangeOrchestrator };
263
+ export { _PrepareArrangeWorkspaceUseCaseImpl as PrepareArrangeWorkspaceUseCaseImpl };
@@ -1,8 +1,6 @@
1
- import { ArrangeFileProcessorToken, ArrangeTargetScannerToken } from "../../contracts/tokens.mjs";
2
- import { CliFsToken } from "../../../core/operational/contracts/tokens.mjs";
3
- import { appError } from "../../../core/domain/errors.domain.mjs";
4
- import { err, ok } from "../../../core/domain/result.model.mjs";
5
- import { messageFromCaughtUnknown } from "../../../core/application/utils/caught-unknown-message.util.mjs";
1
+ import { ArrangeFileProcessorServiceToken, ArrangeTargetScannerServiceToken } from "../../contracts/tokens.mjs";
2
+ import { ok } from "../../../core/domain/result.model.mjs";
3
+ import { messageFromCaughtUnknown } from "../../../core/domain/caught-unknown-message.value-object.mjs";
6
4
  import { inject, injectable } from "@codefast/di";
7
5
  //#region src/lib/arrange/application/use-cases/run-arrange-sync.use-case.ts
8
6
  function toPrimitive(input, hint) {
@@ -224,31 +222,22 @@ async function runOnAfterWriteHook(hook, modifiedFiles) {
224
222
  return `[arrange] onAfterWrite hook failed: ${messageFromCaughtUnknown(caughtHookError)}`;
225
223
  }
226
224
  }
227
- _dec = injectable([
228
- inject(CliFsToken),
229
- inject(ArrangeTargetScannerToken),
230
- inject(ArrangeFileProcessorToken)
231
- ]);
225
+ _dec = injectable([inject(ArrangeTargetScannerServiceToken), inject(ArrangeFileProcessorServiceToken)]);
232
226
  let _RunArrangeSyncUseCaseImpl;
233
227
  (class {
234
- fs;
235
228
  targetScanner;
236
229
  fileProcessor;
237
230
  static {
238
231
  ({c: [_RunArrangeSyncUseCaseImpl, _initClass]} = _apply_decs_2311(this, [_dec], []));
239
232
  }
240
- constructor(fs, targetScanner, fileProcessor) {
241
- this.fs = fs;
233
+ constructor(targetScanner, fileProcessor) {
242
234
  this.targetScanner = targetScanner;
243
235
  this.fileProcessor = fileProcessor;
244
236
  }
245
237
  async execute(request) {
246
- if (!this.fs.existsSync(request.targetPath)) return err(appError("NOT_FOUND", `Not found: ${request.targetPath}`));
247
- const filePaths = this.targetScanner.scanTarget({
248
- targetPath: request.targetPath,
249
- fs: this.fs
250
- });
238
+ const filePaths = this.targetScanner.scanTarget({ targetPath: request.targetPath });
251
239
  const modifiedFiles = [];
240
+ const previewPlans = [];
252
241
  let totalFound = 0;
253
242
  let totalChanged = 0;
254
243
  const groupOptions = {
@@ -264,6 +253,7 @@ let _RunArrangeSyncUseCaseImpl;
264
253
  totalFound += fileProcessResult.totalFound;
265
254
  totalChanged += fileProcessResult.changed;
266
255
  if (fileProcessResult.changed > 0) modifiedFiles.push(fileProcessResult.filePath);
256
+ if (fileProcessResult.workPlan) previewPlans.push(fileProcessResult.workPlan);
267
257
  }
268
258
  const arrangeConfig = request.config;
269
259
  const hookError = request.write && modifiedFiles.length > 0 ? await runOnAfterWriteHook(arrangeConfig?.onAfterWrite, modifiedFiles) : null;
@@ -272,7 +262,8 @@ let _RunArrangeSyncUseCaseImpl;
272
262
  modifiedFiles,
273
263
  totalFound,
274
264
  totalChanged,
275
- hookError
265
+ hookError,
266
+ previewPlans
276
267
  });
277
268
  }
278
269
  static {
@@ -1,6 +1,6 @@
1
- import { suggestCnGroups, summarizeGroupBucketLabels } from "../../domain/grouping.domain.mjs";
1
+ import { TailwindGroupingServiceToken } from "../../contracts/tokens.mjs";
2
2
  import { formatArray, formatCnCall } from "../../domain/source-text-formatters.formatter.mjs";
3
- import { injectable } from "@codefast/di";
3
+ import { inject, injectable } from "@codefast/di";
4
4
  //#region src/lib/arrange/application/use-cases/suggest-cn-groups.use-case.ts
5
5
  function toPrimitive(input, hint) {
6
6
  if (typeof input !== "object" || input === null) return input;
@@ -212,17 +212,21 @@ function _apply_decs_2311(targetClass, classDecs, memberDecs, classDecsHaveThis,
212
212
  };
213
213
  }
214
214
  let _dec, _initClass;
215
- _dec = injectable([]);
215
+ _dec = injectable([inject(TailwindGroupingServiceToken)]);
216
216
  let _SuggestCnGroupsUseCaseImpl;
217
217
  (class {
218
+ grouping;
218
219
  static {
219
220
  ({c: [_SuggestCnGroupsUseCaseImpl, _initClass]} = _apply_decs_2311(this, [_dec], []));
220
221
  }
222
+ constructor(grouping) {
223
+ this.grouping = grouping;
224
+ }
221
225
  execute(request) {
222
- const groups = suggestCnGroups(request.inlineClasses);
226
+ const groups = this.grouping.suggestGroups(request.inlineClasses);
223
227
  return {
224
228
  primaryLine: request.emitTvStyleArray ? formatArray(groups) : formatCnCall(groups, { trailingClassName: request.trailingClassName }),
225
- bucketsCommentLine: `// Buckets: ${JSON.stringify(summarizeGroupBucketLabels(groups))}`
229
+ bucketsCommentLine: `// Buckets: ${JSON.stringify(this.grouping.summarizeBucketLabels(groups))}`
226
230
  };
227
231
  }
228
232
  static {
@@ -1,27 +1,31 @@
1
- import { AnalyzeDirectoryUseCaseToken, ArrangeFileProcessorToken, ArrangeTargetScannerToken, DomainSourceParserPortToken, FileWalkerPortToken, GroupFilePreviewPortToken, RunArrangeSyncUseCaseToken, SuggestCnGroupsUseCaseToken } from "./contracts/tokens.mjs";
2
- import { CliLoggerToken } from "../core/operational/contracts/tokens.mjs";
1
+ import { AnalyzeDirectoryUseCaseToken, ArrangeFileProcessorServiceToken, ArrangeTargetScannerServiceToken, DomainSourceParserPortToken, FileWalkerPortToken, PrepareArrangeWorkspaceUseCaseToken, RunArrangeSyncUseCaseToken, SuggestCnGroupsUseCaseToken, TailwindGroupingServiceToken, WorkspaceResolverPortToken } from "./contracts/tokens.mjs";
2
+ import { CliLoggerToken } from "../core/contracts/tokens.mjs";
3
3
  import { ArrangeFileProcessorServiceImpl as _ArrangeFileProcessorServiceImpl } from "./application/services/arrange-file-processor.service.mjs";
4
4
  import { ArrangeTargetScannerServiceImpl as _ArrangeTargetScannerServiceImpl } from "./application/services/arrange-target-scanner.service.mjs";
5
5
  import { AnalyzeDirectoryUseCaseImpl as _AnalyzeDirectoryUseCaseImpl } from "./application/use-cases/analyze-directory.use-case.mjs";
6
6
  import { RunArrangeSyncUseCaseImpl as _RunArrangeSyncUseCaseImpl } from "./application/use-cases/run-arrange-sync.use-case.mjs";
7
7
  import { SuggestCnGroupsUseCaseImpl as _SuggestCnGroupsUseCaseImpl } from "./application/use-cases/suggest-cn-groups.use-case.mjs";
8
- import { DomainSourceParserAdapter as _DomainSourceParserAdapter } from "./infra/domain-source-parser.adapter.mjs";
9
- import { FileWalkerAdapter as _FileWalkerAdapter } from "./infra/file-walker.adapter.mjs";
10
- import { GroupFilePreviewPresenterAdapter as _GroupFilePreviewPresenterAdapter } from "./presentation/group-file-preview.presenter.mjs";
11
- import { withOptionalPortTelemetry } from "../core/infra/logging-decorator.adapter.mjs";
12
- import { InfraModule } from "../core/infra/infra.module.mjs";
8
+ import { DomainSourceParserAdapter as _DomainSourceParserAdapter } from "./adapters/secondary/domain-source-parser.adapter.mjs";
9
+ import { FileWalkerAdapter as _FileWalkerAdapter } from "./adapters/secondary/file-walker.adapter.mjs";
10
+ import { WorkspaceResolverAdapter as _WorkspaceResolverAdapter } from "./adapters/secondary/workspace-resolver.adapter.mjs";
11
+ import { TailwindGroupingServiceImpl as _TailwindGroupingServiceImpl } from "./domain/tailwind-grouping.service.mjs";
12
+ import { PrepareArrangeWorkspaceUseCaseImpl as _PrepareArrangeWorkspaceUseCaseImpl } from "./application/use-cases/prepare-arrange-workspace.use-case.mjs";
13
+ import { withOptionalPortTelemetry } from "../core/infrastructure/port-telemetry.decorator.mjs";
14
+ import { InfrastructureModule } from "../core/infrastructure/infrastructure.module.mjs";
13
15
  import { Module } from "@codefast/di";
14
16
  //#region src/lib/arrange/arrange.module.ts
15
17
  const ArrangeModule = Module.create("cli-arrange", (moduleBuilder) => {
16
- moduleBuilder.import(InfraModule);
17
- moduleBuilder.bind(FileWalkerPortToken).to(_FileWalkerAdapter).onActivation((ctx, implementation) => withOptionalPortTelemetry("FileWalkerPort", implementation, ctx.resolve(CliLoggerToken))).singleton();
18
- moduleBuilder.bind(DomainSourceParserPortToken).to(_DomainSourceParserAdapter).onActivation((ctx, implementation) => withOptionalPortTelemetry("DomainSourceParserPort", implementation, ctx.resolve(CliLoggerToken))).singleton();
19
- moduleBuilder.bind(GroupFilePreviewPortToken).to(_GroupFilePreviewPresenterAdapter).onActivation((ctx, implementation) => withOptionalPortTelemetry("GroupFilePreviewPort", implementation, ctx.resolve(CliLoggerToken))).singleton();
18
+ moduleBuilder.import(InfrastructureModule);
19
+ moduleBuilder.bind(FileWalkerPortToken).to(_FileWalkerAdapter).singleton().onActivation((ctx, implementation) => withOptionalPortTelemetry("FileWalkerPort", implementation, ctx.resolve(CliLoggerToken)));
20
+ moduleBuilder.bind(DomainSourceParserPortToken).to(_DomainSourceParserAdapter).singleton().onActivation((ctx, implementation) => withOptionalPortTelemetry("DomainSourceParserPort", implementation, ctx.resolve(CliLoggerToken)));
21
+ moduleBuilder.bind(WorkspaceResolverPortToken).to(_WorkspaceResolverAdapter).singleton();
22
+ moduleBuilder.bind(TailwindGroupingServiceToken).to(_TailwindGroupingServiceImpl).singleton();
20
23
  moduleBuilder.bind(AnalyzeDirectoryUseCaseToken).to(_AnalyzeDirectoryUseCaseImpl).singleton();
21
- moduleBuilder.bind(ArrangeTargetScannerToken).to(_ArrangeTargetScannerServiceImpl).singleton();
22
- moduleBuilder.bind(ArrangeFileProcessorToken).to(_ArrangeFileProcessorServiceImpl).singleton();
24
+ moduleBuilder.bind(ArrangeTargetScannerServiceToken).to(_ArrangeTargetScannerServiceImpl).singleton();
25
+ moduleBuilder.bind(ArrangeFileProcessorServiceToken).to(_ArrangeFileProcessorServiceImpl).singleton();
23
26
  moduleBuilder.bind(RunArrangeSyncUseCaseToken).to(_RunArrangeSyncUseCaseImpl).singleton();
24
27
  moduleBuilder.bind(SuggestCnGroupsUseCaseToken).to(_SuggestCnGroupsUseCaseImpl).singleton();
28
+ moduleBuilder.bind(PrepareArrangeWorkspaceUseCaseToken).to(_PrepareArrangeWorkspaceUseCaseImpl).singleton();
25
29
  });
26
30
  //#endregion
27
31
  export { ArrangeModule };
@@ -3,12 +3,13 @@ import { token } from "@codefast/di";
3
3
  const FileWalkerPortToken = token("FileWalkerPort");
4
4
  const DomainSourceParserPortToken = token("DomainSourceParserPort");
5
5
  const GroupFilePreviewPortToken = token("GroupFilePreviewPort");
6
- const ArrangeTargetScannerToken = token("ArrangeTargetScannerService");
7
- const ArrangeFileProcessorToken = token("ArrangeFileProcessorService");
6
+ const ArrangeTargetScannerServiceToken = token("ArrangeTargetScannerService");
7
+ const ArrangeFileProcessorServiceToken = token("ArrangeFileProcessorService");
8
8
  const AnalyzeDirectoryUseCaseToken = token("AnalyzeDirectoryUseCase");
9
9
  const RunArrangeSyncUseCaseToken = token("RunArrangeSyncUseCase");
10
10
  const SuggestCnGroupsUseCaseToken = token("SuggestCnGroupsUseCase");
11
- const PrepareArrangeOrchestratorToken = token("PrepareArrangeOrchestrator");
12
- const PresentAnalyzeReportPresenterToken = token("PresentAnalyzeReportPresenter");
11
+ const PrepareArrangeWorkspaceUseCaseToken = token("PrepareArrangeWorkspaceUseCase");
12
+ const WorkspaceResolverPortToken = token("WorkspaceResolverPort");
13
+ const TailwindGroupingServiceToken = token("TailwindGroupingService");
13
14
  //#endregion
14
- export { AnalyzeDirectoryUseCaseToken, ArrangeFileProcessorToken, ArrangeTargetScannerToken, DomainSourceParserPortToken, FileWalkerPortToken, GroupFilePreviewPortToken, PrepareArrangeOrchestratorToken, PresentAnalyzeReportPresenterToken, RunArrangeSyncUseCaseToken, SuggestCnGroupsUseCaseToken };
15
+ export { AnalyzeDirectoryUseCaseToken, ArrangeFileProcessorServiceToken, ArrangeTargetScannerServiceToken, DomainSourceParserPortToken, FileWalkerPortToken, GroupFilePreviewPortToken, PrepareArrangeWorkspaceUseCaseToken, RunArrangeSyncUseCaseToken, SuggestCnGroupsUseCaseToken, TailwindGroupingServiceToken, WorkspaceResolverPortToken };
@@ -2,7 +2,7 @@ import "./constants.domain.mjs";
2
2
  import { forEachDomainChild, isDomainCallExpression, isDomainJsxAttribute, isDomainObjectLiteralExpression } from "./ast/ast-node.model.mjs";
3
3
  import { buildKnownCnTvBindings, isCnOrTvIdentifier, lineOf } from "./ast/ast-helpers.helper.mjs";
4
4
  import { forEachStringLiteralInClassExpression } from "./ast/collectors-cn.collector.mjs";
5
- import { tokenizeClassString } from "./tokenizer.util.mjs";
5
+ import { tokenizeClassString } from "./tailwind-token.value-object.mjs";
6
6
  import { collectCnCallsInsideTv, traverseTvObject } from "./ast/collectors-tv.collector.mjs";
7
7
  import { jsxClassNameStaticLiteral } from "./ast/collectors-jsx.collector.mjs";
8
8
  //#region src/lib/arrange/domain/arrange-analyze.service.ts
@@ -88,4 +88,4 @@ function lineOf(sourceFile, node) {
88
88
  return lines.join("\n");
89
89
  }
90
90
  //#endregion
91
- export { KNOWN_CN_TV_MODULES, applyEditsDescending, buildKnownCnTvBindings, indentOfLineContaining, isCnOrTvIdentifier, lineOf, moduleLooksLikeCnTvReexport, propertyAssignmentNameText, unwrapCnInsideTvCallReplacement };
91
+ export { applyEditsDescending, buildKnownCnTvBindings, isCnOrTvIdentifier, lineOf, propertyAssignmentNameText, unwrapCnInsideTvCallReplacement };
@@ -49,9 +49,6 @@ function isDomainTailwindClassLiteral(node) {
49
49
  function isDomainImportDeclaration(node) {
50
50
  return node.kind === 5;
51
51
  }
52
- function isDomainImportClause(node) {
53
- return node !== void 0 && node.kind === 6;
54
- }
55
52
  function isDomainNamedImports(node) {
56
53
  return node.kind === 7;
57
54
  }
@@ -82,9 +79,6 @@ function isDomainJsxAttribute(node) {
82
79
  function isDomainJsxExpression(node) {
83
80
  return node.kind === 24;
84
81
  }
85
- function isDomainExpressionStatement(node) {
86
- return node.kind === 22;
87
- }
88
82
  function forEachDomainChild(node, visit) {
89
83
  switch (node.kind) {
90
84
  case 1:
@@ -157,20 +151,6 @@ function forEachDomainChild(node, visit) {
157
151
  default: return;
158
152
  }
159
153
  }
160
- function forEachDomainDescendant(node, visit) {
161
- visit(node);
162
- forEachDomainChild(node, (child) => forEachDomainDescendant(child, visit));
163
- }
164
- function forEachDomainDescendantFromSourceFile(sourceFile, visit) {
165
- for (const statement of sourceFile.statements) forEachDomainDescendant(statement, visit);
166
- }
167
- function findFirstDomainDescendantWhere(sourceFile, predicate) {
168
- let found;
169
- forEachDomainDescendantFromSourceFile(sourceFile, (n) => {
170
- if (found === void 0 && predicate(n)) found = n;
171
- });
172
- return found;
173
- }
174
154
  function lineOfSourcePosition(sourceText, pos) {
175
155
  const boundedPos = Math.max(0, Math.min(pos, sourceText.length));
176
156
  let line = 1;
@@ -178,4 +158,4 @@ function lineOfSourcePosition(sourceText, pos) {
178
158
  return line;
179
159
  }
180
160
  //#endregion
181
- export { DomainBinaryOperator, DomainSyntaxKind, findFirstDomainDescendantWhere, forEachDomainChild, forEachDomainDescendant, forEachDomainDescendantFromSourceFile, isDomainArrayLiteralExpression, isDomainCallExpression, isDomainExpressionStatement, isDomainIdentifier, isDomainImportClause, isDomainImportDeclaration, isDomainJsxAttribute, isDomainJsxExpression, isDomainNamedImports, isDomainNamespaceImport, isDomainNoSubstitutionTemplateLiteral, isDomainObjectLiteralExpression, isDomainPropertyAccessExpression, isDomainPropertyAssignment, isDomainSpreadElement, isDomainStringLiteral, isDomainTailwindClassLiteral, lineOfSourcePosition };
161
+ export { DomainBinaryOperator, DomainSyntaxKind, forEachDomainChild, isDomainArrayLiteralExpression, isDomainCallExpression, isDomainIdentifier, isDomainImportDeclaration, isDomainJsxAttribute, isDomainJsxExpression, isDomainNamedImports, isDomainNamespaceImport, isDomainObjectLiteralExpression, isDomainPropertyAccessExpression, isDomainPropertyAssignment, isDomainSpreadElement, isDomainStringLiteral, isDomainTailwindClassLiteral, lineOfSourcePosition };
@@ -2,7 +2,7 @@ import "../constants.domain.mjs";
2
2
  import { forEachDomainChild, isDomainArrayLiteralExpression, isDomainCallExpression, isDomainObjectLiteralExpression, isDomainPropertyAssignment, isDomainSpreadElement, isDomainTailwindClassLiteral } from "./ast-node.model.mjs";
3
3
  import { buildKnownCnTvBindings, isCnOrTvIdentifier, propertyAssignmentNameText } from "./ast-helpers.helper.mjs";
4
4
  import { CN_APPLY_LITERAL_WALK_OPTS, collectUnconditionalTailwindLiteralsFromCnArguments, forEachStringLiteralInClassExpression, isUnsafeLiteralForCnStyleApplySplit } from "./collectors-cn.collector.mjs";
5
- import { tokenizeClassString } from "../tokenizer.util.mjs";
5
+ import { tokenizeClassString } from "../tailwind-token.value-object.mjs";
6
6
  //#region src/lib/arrange/domain/ast/collectors-tv.collector.ts
7
7
  function traverseTvObject(sourceFile, obj, visitor, depth = 0, knownBindings) {
8
8
  if (depth > 12) return;
@@ -171,4 +171,4 @@ function collectGroupableStringNodes(sourceFile) {
171
171
  return results;
172
172
  }
173
173
  //#endregion
174
- export { collectCnCallsInsideTv, collectGroupableStringNodes, collectTvSlots, emitTvSlot, listAllCnCallsInsideTvInSourceFile, makeStringNode, slotClassString, traverseTvObject };
174
+ export { collectCnCallsInsideTv, collectGroupableStringNodes, listAllCnCallsInsideTvInSourceFile, slotClassString, traverseTvObject };
@@ -1,11 +1,11 @@
1
1
  import "../constants.domain.mjs";
2
- import { indentOfLineContaining } from "../../../shared/source-code/domain/text-edit.model.mjs";
2
+ import { endAfterOptionalCommaFollowingInSource, indentOfLineContaining, textPrefixFromLineStartToPosition } from "../../../shared/source-code/domain/text-edit.model.mjs";
3
3
  import { forEachDomainChild, isDomainArrayLiteralExpression, isDomainJsxAttribute, isDomainTailwindClassLiteral } from "./ast-node.model.mjs";
4
4
  import { isUnsafeLiteralForCnStyleApplySplit } from "./collectors-cn.collector.mjs";
5
- import { tokenizeClassString } from "../tokenizer.util.mjs";
5
+ import { tokenizeClassString } from "../tailwind-token.value-object.mjs";
6
6
  import { collectGroupableStringNodes, slotClassString } from "./collectors-tv.collector.mjs";
7
7
  import { areCnTailwindPartitionsEquivalent, suggestCnGroups, summarizeGroupBucketLabels } from "../grouping.domain.mjs";
8
- import { escapeTsStringLiteralContent, formatArray, formatJsxCnAttributeValue } from "../source-text-formatters.formatter.mjs";
8
+ import { escapeTsStringLiteralContent, formatArray, formatArrayElementsAsSiblingLines, formatJsxCnAttributeValue } from "../source-text-formatters.formatter.mjs";
9
9
  import { jsxClassNameStaticLiteral } from "./collectors-jsx.collector.mjs";
10
10
  //#region src/lib/arrange/domain/ast/targets.model.ts
11
11
  function targetReplaceStart(target) {
@@ -81,12 +81,12 @@ function planGroupEditForTarget(target, textAfterUnwrap, withClassName) {
81
81
  const anchorClassLiteral = target.item.primaryClassLiteral;
82
82
  const parentArray = target.item.nodes.length > 1 && anchorClassLiteral.parent !== null && isDomainArrayLiteralExpression(anchorClassLiteral.parent) ? anchorClassLiteral.parent : null;
83
83
  const start = parentArray ? parentArray.pos : anchorClassLiteral.pos;
84
- const end = parentArray ? parentArray.end : anchorClassLiteral.end;
84
+ const end = parentArray ? parentArray.end : endAfterOptionalCommaFollowingInSource(textAfterUnwrap, anchorClassLiteral.end);
85
85
  const baseIndent = indentOfLineContaining(textAfterUnwrap, start);
86
86
  return {
87
87
  start,
88
88
  end,
89
- replacement: formatArray(groups).split("\n").map((line, lineIndex) => lineIndex === 0 ? line : `${baseIndent}${line}`).join("\n"),
89
+ replacement: parentArray ? formatArray(groups).split("\n").map((line, lineIndex) => lineIndex === 0 ? line : `${baseIndent}${line}`).join("\n") : formatArrayElementsAsSiblingLines(groups, textPrefixFromLineStartToPosition(textAfterUnwrap, start)),
90
90
  bucketSummary: summarizeGroupBucketLabels(groups),
91
91
  jsxCn: false,
92
92
  lineSf: target.item.sf,
@@ -107,4 +107,4 @@ function planGroupEditForTarget(target, textAfterUnwrap, withClassName) {
107
107
  };
108
108
  }
109
109
  //#endregion
110
- export { collectGroupTargets, collectLongJsxClassNameTargets, formatCnCallReplacement, planGroupEditForTarget, targetReplaceStart };
110
+ export { collectGroupTargets, planGroupEditForTarget, targetReplaceStart };
@@ -1,5 +1,6 @@
1
1
  import { BUCKET_ORDER } from "./constants.domain.mjs";
2
- import { bucketsCompatible, bucketsMergeCompatible, classifyToken, compositeSecondaryOrder, selectorKey, stateKey, stripVariants, tokenizeClassString } from "./tokenizer.util.mjs";
2
+ import { stripVariants, tokenizeClassString } from "./tailwind-token.value-object.mjs";
3
+ import { bucketsCompatible, bucketsMergeCompatible, classifyToken, compositeSecondaryOrder, selectorKey, stateKey } from "./tailwind-token-classifier.domain-service.mjs";
3
4
  //#region src/lib/arrange/domain/grouping.domain.ts
4
5
  /**
5
6
  * `cn()` grouping: bucket sequence is {@link BUCKET_ORDER} only; tokens are classified with
@@ -313,4 +314,4 @@ function suggestCnGroups(classString) {
313
314
  });
314
315
  }
315
316
  //#endregion
316
- export { areCnTailwindPartitionsEquivalent, capGroups, mergeEaseTimingIntoFollowingAnimatedState, mergeSingletons, suggestCnGroups, summarizeGroupBucketLabels };
317
+ export { areCnTailwindPartitionsEquivalent, suggestCnGroups, summarizeGroupBucketLabels };
@@ -52,4 +52,4 @@ function ensureCnImport(sourceFile, cnImportOverride) {
52
52
  return `${sourceText.slice(0, insertAt)}${importLine}\n${sourceText.slice(insertAt)}`;
53
53
  }
54
54
  //#endregion
55
- export { cnModuleSpecifierForFile, ensureCnImport };
55
+ export { ensureCnImport };
@@ -3,6 +3,9 @@ import { indentOfLineContaining } from "../../shared/source-code/domain/text-edi
3
3
  function escapeTsStringLiteralContent(group) {
4
4
  return group.replaceAll("\\", "\\\\").replaceAll("\"", "\\\"");
5
5
  }
6
+ /** Trailing comma on multiline Tailwind group lists (matches prior `cn` / `tv` array style). */ function commaAfterTailwindGroupLine(groupIndex, groupCount) {
7
+ return groupIndex < groupCount - 1 || groupCount > 1 ? "," : "";
8
+ }
6
9
  /**
7
10
  * Multiline fragment for use *inside* an existing `cn(...)` — replaces one
8
11
  * string argument with several, without producing `cn(cn(...))`.
@@ -37,12 +40,26 @@ function formatArray(groups) {
37
40
  for (let i = 0; i < groups.length; i++) {
38
41
  const group = groups[i];
39
42
  if (group === void 0) throw new Error("invariant: formatArray group missing");
40
- const comma = i < groups.length - 1 || groups.length > 1 ? "," : "";
43
+ const comma = commaAfterTailwindGroupLine(i, groups.length);
41
44
  lines.push(` "${escapeTsStringLiteralContent(group)}"${comma}`);
42
45
  }
43
46
  lines.push("]");
44
47
  return lines.join("\n");
45
48
  }
49
+ /**
50
+ * Multiple string literals as sequential lines for insertion **inside** an existing array
51
+ * (e.g. `tv({ base: [ … ] })` — avoids `[[ "a", "b" ]]` when replacing one long string).
52
+ */ function formatArrayElementsAsSiblingLines(groups, continuationPrefix) {
53
+ const segments = [];
54
+ for (let i = 0; i < groups.length; i++) {
55
+ const group = groups[i];
56
+ if (group === void 0) throw new Error("invariant: formatArrayElementsAsSiblingLines group missing");
57
+ const comma = commaAfterTailwindGroupLine(i, groups.length);
58
+ const segment = `"${escapeTsStringLiteralContent(group)}"${comma}`;
59
+ segments.push(i === 0 ? segment : `\n${continuationPrefix}${segment}`);
60
+ }
61
+ return segments.join("");
62
+ }
46
63
  function formatJsxCnAttributeValue(groups, source, valueNodeStart) {
47
64
  const baseIndent = indentOfLineContaining(source, valueNodeStart);
48
65
  return `{cn(\n${formatCnArguments(groups, {
@@ -51,4 +68,4 @@ function formatJsxCnAttributeValue(groups, source, valueNodeStart) {
51
68
  })}\n${baseIndent})}`;
52
69
  }
53
70
  //#endregion
54
- export { escapeTsStringLiteralContent, formatArray, formatCnArguments, formatCnCall, formatJsxCnAttributeValue };
71
+ export { escapeTsStringLiteralContent, formatArray, formatArrayElementsAsSiblingLines, formatCnCall, formatJsxCnAttributeValue };
@@ -1,6 +1,6 @@
1
- import { createTagProgressListener } from "./tag-sync.presenter.mjs";
1
+ import { suggestCnGroups, summarizeGroupBucketLabels } from "./grouping.domain.mjs";
2
2
  import { injectable } from "@codefast/di";
3
- //#region src/lib/tag/presentation/create-tag-progress-listener.presenter.ts
3
+ //#region src/lib/arrange/domain/tailwind-grouping.service.ts
4
4
  function toPrimitive(input, hint) {
5
5
  if (typeof input !== "object" || input === null) return input;
6
6
  var prim = input[Symbol.toPrimitive];
@@ -212,17 +212,20 @@ function _apply_decs_2311(targetClass, classDecs, memberDecs, classDecsHaveThis,
212
212
  }
213
213
  let _dec, _initClass;
214
214
  _dec = injectable([]);
215
- let _CreateTagProgressListenerPresenterImpl;
215
+ let _TailwindGroupingServiceImpl;
216
216
  (class {
217
217
  static {
218
- ({c: [_CreateTagProgressListenerPresenterImpl, _initClass]} = _apply_decs_2311(this, [_dec], []));
218
+ ({c: [_TailwindGroupingServiceImpl, _initClass]} = _apply_decs_2311(this, [_dec], []));
219
219
  }
220
- create(emitLine) {
221
- return createTagProgressListener(emitLine);
220
+ suggestGroups(classString) {
221
+ return suggestCnGroups(classString);
222
+ }
223
+ summarizeBucketLabels(groups) {
224
+ return summarizeGroupBucketLabels(groups);
222
225
  }
223
226
  static {
224
227
  _initClass();
225
228
  }
226
229
  });
227
230
  //#endregion
228
- export { _CreateTagProgressListenerPresenterImpl as CreateTagProgressListenerPresenterImpl };
231
+ export { _TailwindGroupingServiceImpl as TailwindGroupingServiceImpl };
@@ -1,5 +1,6 @@
1
1
  import { COMPATIBLE_BUCKET_SETS, RESPONSIVE_PREFIX, STATE_PREFIXES } from "./constants.domain.mjs";
2
- //#region src/lib/arrange/domain/tokenizer.util.ts
2
+ import { indexOfFirstVariantColon, stripVariants } from "./tailwind-token.value-object.mjs";
3
+ //#region src/lib/arrange/domain/tailwind-token-classifier.domain-service.ts
3
4
  /**
4
5
  * Bare-token classification is **total** (always returns a {@link Bucket}). The `Result` pattern
5
6
  * (`isOk` / `isErr`) belongs at arrange use-case / I/O boundaries, not on this hot path.
@@ -19,33 +20,6 @@ import { COMPATIBLE_BUCKET_SETS, RESPONSIVE_PREFIX, STATE_PREFIXES } from "./con
19
20
  if (/^(?:portrait|landscape|noscript)$/.test(prefix)) return true;
20
21
  return false;
21
22
  }
22
- function tokenizeClassString(classString) {
23
- return classString.trim().split(/\s+/).filter(Boolean);
24
- }
25
- /**
26
- * Index of the first `:` that separates a Tailwind variant segment from the rest.
27
- * Colons inside `[...]` (at positive bracket depth) are ignored so selectors like
28
- * `[&_a:hover]:text-red-500` split as `[&_a:hover]:` + `text-red-500`.
29
- */ function indexOfFirstVariantColon(text) {
30
- let depth = 0;
31
- for (let i = 0; i < text.length; i++) {
32
- const ch = text[i];
33
- if (ch === "[") depth++;
34
- else if (ch === "]") depth = Math.max(0, depth - 1);
35
- else if (ch === ":" && depth === 0) return i;
36
- }
37
- return -1;
38
- }
39
- function stripVariants(token) {
40
- let withoutVariants = token;
41
- const MAX_PASSES = 12;
42
- for (let i = 0; i < MAX_PASSES; i++) {
43
- const colonIdx = indexOfFirstVariantColon(withoutVariants);
44
- if (colonIdx === -1) break;
45
- withoutVariants = withoutVariants.slice(colonIdx + 1);
46
- }
47
- return withoutVariants;
48
- }
49
23
  /**
50
24
  * Outermost variant segment: first `:` at bracket depth 0 → text before it.
51
25
  */ function firstLeadingVariantPrefix(token) {
@@ -216,4 +190,4 @@ function bucketsCompatible(a, b) {
216
190
  return bucketsCompatible(a, b);
217
191
  }
218
192
  //#endregion
219
- export { bucketsCompatible, bucketsMergeCompatible, classifyBareUtility, classifyToken, compositeSecondaryOrder, indexOfFirstVariantColon, isArbitraryParentSelectorStateToken, selectorKey, stateKey, stripVariants, tokenizeClassString };
193
+ export { bucketsCompatible, bucketsMergeCompatible, classifyToken, compositeSecondaryOrder, selectorKey, stateKey };
@@ -0,0 +1,31 @@
1
+ import "./constants.domain.mjs";
2
+ //#region src/lib/arrange/domain/tailwind-token.value-object.ts
3
+ function tokenizeClassString(classString) {
4
+ return classString.trim().split(/\s+/).filter(Boolean);
5
+ }
6
+ /**
7
+ * Index of the first `:` that separates a Tailwind variant segment from the rest.
8
+ * Colons inside `[...]` (at positive bracket depth) are ignored so selectors like
9
+ * `[&_a:hover]:text-red-500` split as `[&_a:hover]:` + `text-red-500`.
10
+ */ function indexOfFirstVariantColon(text) {
11
+ let depth = 0;
12
+ for (let i = 0; i < text.length; i++) {
13
+ const ch = text[i];
14
+ if (ch === "[") depth++;
15
+ else if (ch === "]") depth = Math.max(0, depth - 1);
16
+ else if (ch === ":" && depth === 0) return i;
17
+ }
18
+ return -1;
19
+ }
20
+ function stripVariants(token) {
21
+ let withoutVariants = token;
22
+ const maxStripVariantPasses = 12;
23
+ for (let i = 0; i < maxStripVariantPasses; i++) {
24
+ const colonIdx = indexOfFirstVariantColon(withoutVariants);
25
+ if (colonIdx === -1) break;
26
+ withoutVariants = withoutVariants.slice(colonIdx + 1);
27
+ }
28
+ return withoutVariants;
29
+ }
30
+ //#endregion
31
+ export { indexOfFirstVariantColon, stripVariants, tokenizeClassString };
@@ -1,6 +1,6 @@
1
1
  import { DomainBinaryOperator, DomainSyntaxKind } from "../domain/ast/ast-node.model.mjs";
2
2
  import ts from "typescript";
3
- //#region src/lib/arrange/infra/ts-ast-translator.adapter.ts
3
+ //#region src/lib/arrange/infrastructure/typescript-ast-translator.adapter.ts
4
4
  /**
5
5
  * Anti-corruption layer: maps TypeScript compiler AST to arrange domain AST.
6
6
  * This module is the only place that imports `typescript` for arrange AST translation.
@@ -352,4 +352,4 @@ function parseDomainSourceFile(filePath, sourceText) {
352
352
  return translateTypeScriptSourceFile(ts.createSourceFile(filePath, sourceText, ts.ScriptTarget.Latest, true, scriptKind));
353
353
  }
354
354
  //#endregion
355
- export { parseDomainSourceFile, translateNode, translateTypeScriptSourceFile };
355
+ export { parseDomainSourceFile };