@cosmicdrift/kumiko-framework 0.320.0 → 0.322.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 (54) hide show
  1. package/package.json +4 -4
  2. package/src/__tests__/schema-cli.integration.test.ts +11 -0
  3. package/src/__tests__/upgrade-cli.test.ts +50 -3
  4. package/src/api/__tests__/client-ip.test.ts +25 -0
  5. package/src/api/__tests__/extra-routes.integration.test.ts +42 -0
  6. package/src/api/client-ip.ts +27 -0
  7. package/src/api/extra-route.ts +3 -0
  8. package/src/api/index.ts +7 -1
  9. package/src/api/request-context.ts +23 -1
  10. package/src/api/server.ts +3 -1
  11. package/src/changes.json +60 -0
  12. package/src/db/event-store-executor-write.ts +8 -0
  13. package/src/db/queries/event-store-transfer.ts +73 -0
  14. package/src/engine/__tests__/entity-handlers.test.ts +28 -0
  15. package/src/engine/__tests__/steps-webhook-send.test.ts +2 -2
  16. package/src/engine/entity-handlers.ts +20 -1
  17. package/src/engine/feature-ast/__tests__/fixtures/resolve-import/alias-reexport.ts +1 -0
  18. package/src/engine/feature-ast/__tests__/fixtures/resolve-import/cycle-a.ts +1 -0
  19. package/src/engine/feature-ast/__tests__/fixtures/resolve-import/cycle-b.ts +1 -0
  20. package/src/engine/feature-ast/__tests__/fixtures/resolve-import/entry.ts +3 -0
  21. package/src/engine/feature-ast/__tests__/fixtures/resolve-import/local-rebind.ts +3 -0
  22. package/src/engine/feature-ast/__tests__/fixtures/resolve-import/origin.ts +1 -0
  23. package/src/engine/feature-ast/__tests__/fixtures/resolve-import/star-barrel.ts +1 -0
  24. package/src/engine/feature-ast/__tests__/parse.test.ts +4 -4
  25. package/src/engine/feature-ast/__tests__/resolve-import.test.ts +138 -0
  26. package/src/engine/feature-ast/extractors/index.ts +4 -0
  27. package/src/engine/feature-ast/extractors/resolve-import.ts +187 -0
  28. package/src/engine/feature-ast/extractors/shared.ts +26 -19
  29. package/src/engine/feature-ast/parse.ts +13 -20
  30. package/src/engine/index.ts +3 -0
  31. package/src/engine/registry-state.ts +2 -1
  32. package/src/engine/steps/webhook-send.ts +4 -2
  33. package/src/engine/types/index.ts +2 -0
  34. package/src/errors/i18n/de.yaml +14 -0
  35. package/src/errors/i18n/en.yaml +13 -0
  36. package/src/errors/reasons.ts +5 -0
  37. package/src/event-store/__tests__/transfer.integration.test.ts +236 -0
  38. package/src/event-store/index.ts +6 -0
  39. package/src/event-store/transfer.ts +84 -0
  40. package/src/i18n/__tests__/i18n.test.ts +35 -0
  41. package/src/i18n/__tests__/mail-registry.test.ts +19 -0
  42. package/src/i18n/index.ts +11 -4
  43. package/src/i18n/mail-registry.ts +13 -7
  44. package/src/pipeline/__tests__/archive-stream.integration.test.ts +3 -1
  45. package/src/pipeline/__tests__/irreversible-operation-gate.integration.test.ts +249 -0
  46. package/src/pipeline/dispatch-shared.ts +33 -4
  47. package/src/pipeline/index.ts +4 -0
  48. package/src/pipeline/irreversible-operation-gate.ts +33 -0
  49. package/src/pipeline/multi-stream-apply-context.ts +4 -0
  50. package/src/schema-cli.ts +5 -1
  51. package/src/ui-types/__tests__/plural.test.ts +108 -0
  52. package/src/ui-types/index.ts +6 -0
  53. package/src/ui-types/plural.ts +69 -0
  54. package/src/upgrade-cli.ts +58 -18
@@ -100,22 +100,49 @@ function collectChangelogs(featuresDir: string): ChangelogEntry[] {
100
100
  return entries;
101
101
  }
102
102
 
103
- // Framework core changes belong to no feature — they live in a single
104
- // changes.json next to the framework sources.
105
- export function findCoreChangelogFile(cwd: string): string | null {
106
- const repoPath = join(cwd, "packages/framework/src/changes.json");
107
- if (existsSync(repoPath)) return repoPath;
108
-
103
+ // bundled-features is excluded: findFeaturesDirs collects it per feature
104
+ // (src/<feature>/changes.json), every other package has one src/changes.json.
105
+ export function findPackageChangelogFiles(cwd: string): string[] {
106
+ const isFrameworkRepo = existsSync(join(cwd, "packages/framework"));
107
+ if (isFrameworkRepo) {
108
+ const packagesDir = join(cwd, "packages");
109
+ return readdirSync(packagesDir, { withFileTypes: true })
110
+ .filter((d) => d.isDirectory() && d.name !== "bundled-features")
111
+ .map((d) => join(packagesDir, d.name, "src", "changes.json"))
112
+ .filter((p) => existsSync(p));
113
+ }
114
+
115
+ // Consumer/app repo: walk up (same 10-level cap as the other node_modules
116
+ // walks) collecting every hoisted @cosmicdrift package's changes.json.
117
+ // Dedupe by package dir name — the nearest node_modules to cwd wins, same
118
+ // precedence as findCodemodScriptsRoot/readPackageVersion. realpath also
119
+ // dedupes a workspace symlink that resolves to an already-collected file.
120
+ const files: string[] = [];
121
+ const seenNames = new Set<string>();
122
+ const seenRealPaths = new Set<string>();
109
123
  let dir = cwd;
110
124
  for (let i = 0; i < 10; i++) {
111
- const nmPath = join(dir, "node_modules/@cosmicdrift/kumiko-framework/src/changes.json");
112
- if (existsSync(nmPath)) return nmPath;
125
+ const scopeDir = join(dir, "node_modules/@cosmicdrift");
126
+ if (existsSync(scopeDir)) {
127
+ const pkgNames = readdirSync(scopeDir, { withFileTypes: true })
128
+ .filter((d) => d.isDirectory() && d.name !== "kumiko-bundled-features")
129
+ .map((d) => d.name);
130
+ for (const name of pkgNames) {
131
+ if (seenNames.has(name)) continue;
132
+ const changelogPath = join(scopeDir, name, "src", "changes.json");
133
+ if (!existsSync(changelogPath)) continue;
134
+ seenNames.add(name);
135
+ const realPath = realpathSync(changelogPath);
136
+ if (seenRealPaths.has(realPath)) continue;
137
+ seenRealPaths.add(realPath);
138
+ files.push(changelogPath);
139
+ }
140
+ }
113
141
  const parent = join(dir, "..");
114
142
  if (parent === dir) break;
115
143
  dir = parent;
116
144
  }
117
-
118
- return null;
145
+ return files;
119
146
  }
120
147
 
121
148
  export function findFeaturesDirs(cwd: string): string[] {
@@ -129,10 +156,9 @@ export function findFeaturesDirs(cwd: string): string[] {
129
156
  // Detected by presence of changes.json, not a package-name prefix — a
130
157
  // prefix heuristic silently stops matching once packages are renamed or a
131
158
  // differently-named package is added (fw#1605). Skipped inside the
132
- // framework repo itself (packages/framework present): its own
133
- // packages/framework/src/changes.json is the core changelog (already
134
- // collected via findCoreChangelogFile), not a feature package, and would
135
- // otherwise get double-counted as one here.
159
+ // framework repo itself (packages/framework present): every package's own
160
+ // changes.json is already collected via findPackageChangelogFiles, and
161
+ // would otherwise get double-counted as one here.
136
162
  const isFrameworkRepo = existsSync(join(cwd, "packages/framework"));
137
163
  const entDir = join(cwd, "packages");
138
164
  if (!isFrameworkRepo && existsSync(entDir)) {
@@ -459,6 +485,16 @@ async function applyCodemods(
459
485
  return 0;
460
486
  }
461
487
 
488
+ const UPGRADE_USAGE = `kumiko-upgrade [--from <version>] [--dir <path>] [--json] [--verbose] [--apply [--dry-run]]
489
+
490
+ --from <version> filter baseline version (default: last applied marker, or the installed version)
491
+ --dir <path> target directory to check/apply against (default: cwd)
492
+ --json machine-readable output
493
+ --verbose include full migration details for each pending entry
494
+ --apply run codemods for pending breaking changes and write the upgrade marker
495
+ --dry-run with --apply, report what would run without writing anything
496
+ --help, -h print this usage and exit`;
497
+
462
498
  // kumiko-lint-ignore complexity-budget CLI orchestration moved from bin/commands/upgrade.ts — same branching surface, shared by kumiko upgrade + published kumiko-upgrade bin
463
499
  export async function runUpgradeCli(
464
500
  argv: readonly string[],
@@ -466,6 +502,10 @@ export async function runUpgradeCli(
466
502
  out: UpgradeCliOut,
467
503
  options?: { readonly repoRoot?: string },
468
504
  ): Promise<number> {
505
+ if (argv.includes("--help") || argv.includes("-h")) {
506
+ out.log(UPGRADE_USAGE);
507
+ return 0;
508
+ }
469
509
  // Standalone CLI entry, not booted via runProdApp/runDevApp — Temporal needs an explicit polyfill here.
470
510
  await ensureTemporalPolyfill();
471
511
  const repoRoot = options?.repoRoot ?? cwd;
@@ -513,8 +553,8 @@ export async function runUpgradeCli(
513
553
  }
514
554
 
515
555
  const featuresDirs = findFeaturesDirs(cwd);
516
- const coreChangelogFile = findCoreChangelogFile(cwd);
517
- if (featuresDirs.length === 0 && !coreChangelogFile) {
556
+ const packageChangelogFiles = findPackageChangelogFiles(cwd);
557
+ if (featuresDirs.length === 0 && packageChangelogFiles.length === 0) {
518
558
  out.err("");
519
559
  out.err(" Could not find bundled-features directory.");
520
560
  out.err(" Run from framework/enterprise repo or an app with node_modules.");
@@ -526,8 +566,8 @@ export async function runUpgradeCli(
526
566
  for (const dir of featuresDirs) {
527
567
  allEntries.push(...collectChangelogs(dir));
528
568
  }
529
- if (coreChangelogFile) {
530
- allEntries.push(...readChangelogFile(coreChangelogFile));
569
+ for (const changelogFile of packageChangelogFiles) {
570
+ allEntries.push(...readChangelogFile(changelogFile));
531
571
  }
532
572
  const pending = sortEntries(filterEntriesAfter(allEntries, currentVersion));
533
573