@pattern-stack/codegen 0.2.0 → 0.3.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 (52) hide show
  1. package/README.md +9 -4
  2. package/dist/src/cli/index.js +136 -128
  3. package/dist/src/cli/index.js.map +1 -1
  4. package/dist/src/index.d.ts +16 -0
  5. package/dist/src/index.js +25 -0
  6. package/dist/src/index.js.map +1 -1
  7. package/package.json +10 -1
  8. package/templates/entity/new/backend/application/commands/create.ejs.t +38 -1
  9. package/templates/entity/new/backend/application/commands/delete.ejs.t +41 -1
  10. package/templates/entity/new/backend/application/commands/update.ejs.t +42 -1
  11. package/templates/entity/new/backend/database/repository.ejs.t +33 -3
  12. package/templates/entity/new/backend/domain/repository-interface.ejs.t +6 -3
  13. package/templates/entity/new/backend/modules/core/module.ejs.t +6 -0
  14. package/templates/entity/new/backend/presentation/controller.ejs.t +32 -10
  15. package/templates/entity/new/clean-lite-ps/controller.ejs.t +72 -11
  16. package/templates/entity/new/clean-lite-ps/entity.ejs.t +16 -2
  17. package/templates/entity/new/clean-lite-ps/index.ejs.t +1 -1
  18. package/templates/entity/new/clean-lite-ps/module.ejs.t +45 -2
  19. package/templates/entity/new/clean-lite-ps/prompt-extension.js +459 -98
  20. package/templates/entity/new/clean-lite-ps/repository.ejs.t +57 -4
  21. package/templates/entity/new/clean-lite-ps/search-controller.ejs.t +50 -0
  22. package/templates/entity/new/clean-lite-ps/service.ejs.t +98 -1
  23. package/templates/entity/new/clean-lite-ps/use-cases/create.ejs.t +150 -0
  24. package/templates/entity/new/clean-lite-ps/use-cases/delete.ejs.t +70 -0
  25. package/templates/entity/new/clean-lite-ps/use-cases/find-by-id-with-fields.ejs.t +19 -0
  26. package/templates/entity/new/clean-lite-ps/use-cases/find-by-id.ejs.t +7 -3
  27. package/templates/entity/new/clean-lite-ps/use-cases/list-with-fields.ejs.t +17 -0
  28. package/templates/entity/new/clean-lite-ps/use-cases/search.ejs.t +63 -0
  29. package/templates/entity/new/clean-lite-ps/use-cases/update.ejs.t +153 -0
  30. package/templates/entity/new/prompt.js +284 -41
  31. package/templates/relationship/new/entity.ejs.t +2 -2
  32. package/templates/relationship/new/prompt.js +3 -7
  33. package/templates/relationship/new/service.ejs.t +1 -1
  34. package/templates/subsystem/bridge/generated-keep.ejs.t +4 -0
  35. package/templates/subsystem/bridge/prompt.js +36 -0
  36. package/templates/subsystem/bridge-config/codegen-config-bridge-block.ejs.t +20 -0
  37. package/templates/subsystem/bridge-config/prompt.js +20 -0
  38. package/templates/subsystem/events/domain-events.schema.ejs.t +81 -0
  39. package/templates/subsystem/events/generated-keep.ejs.t +4 -0
  40. package/templates/subsystem/events/prompt.js +39 -0
  41. package/templates/subsystem/events-config/codegen-config-events-block.ejs.t +26 -0
  42. package/templates/subsystem/events-config/prompt.js +20 -0
  43. package/templates/subsystem/jobs/job-orchestration.schema.ejs.t +221 -0
  44. package/templates/subsystem/jobs/main-hook.ejs.t +11 -0
  45. package/templates/subsystem/jobs/prompt.js +40 -0
  46. package/templates/subsystem/jobs/worker.ejs.t +82 -0
  47. package/templates/subsystem/jobs-config/codegen-config-jobs-block.ejs.t +55 -0
  48. package/templates/subsystem/jobs-config/prompt.js +20 -0
  49. package/templates/subsystem/sync/prompt.js +43 -0
  50. package/templates/subsystem/sync/sync-audit.schema.ejs.t +195 -0
  51. package/templates/subsystem/sync-config/codegen-config-sync-block.ejs.t +29 -0
  52. package/templates/subsystem/sync-config/prompt.js +22 -0
package/README.md CHANGED
@@ -23,7 +23,7 @@ entity:
23
23
  name: contact
24
24
  plural: contacts
25
25
  table: contacts
26
- family: synced # synced | activity | metadata | knowledge
26
+ pattern: Synced # Synced | Activity | Metadata | Knowledge | Base (or app-defined)
27
27
 
28
28
  fields:
29
29
  email:
@@ -94,7 +94,11 @@ codegen subsystem install events # domain event bus (transactional outbox)
94
94
  codegen subsystem install jobs # background job queue (pg-boss pattern)
95
95
  codegen subsystem install cache # key-value cache with TTL
96
96
  codegen subsystem install storage # file storage (local filesystem)
97
+ codegen subsystem install sync # external-system sync engine (IChangeSource + orchestrator + audit log)
98
+ codegen subsystem install bridge # event-to-job bridge (durable async fanout via @JobHandler.triggers)
97
99
  codegen subsystem list # show installed + available
100
+
101
+ codegen events consumers <type> # list all Tier 1/2/3 consumers of an event type
98
102
  ```
99
103
 
100
104
  Each subsystem generates a protocol (interface), Drizzle backend (Postgres), memory backend (tests), and a NestJS module with `forRoot({ backend })` factory.
@@ -123,8 +127,8 @@ modules/ NestJS module wiring
123
127
  ```
124
128
  modules/{plural}/
125
129
  {entity}.entity.ts Drizzle table + types
126
- {entity}.repository.ts Extends family base class
127
- {entity}.service.ts Extends family base service
130
+ {entity}.repository.ts Extends pattern base class
131
+ {entity}.service.ts Extends pattern base service
128
132
  {entity}.controller.ts REST endpoints
129
133
  {plural}.module.ts NestJS module
130
134
  dto/ Create, Update, Output DTOs
@@ -164,6 +168,7 @@ queries:
164
168
  paths:
165
169
  backend_src: src
166
170
  entities_dir: entities
171
+ events_dir: events
167
172
  generated: src/generated
168
173
 
169
174
  generate:
@@ -202,7 +207,7 @@ src/ Generator source code
202
207
  formatters/ Console, JSON, markdown output
203
208
  __tests__/ Unit tests (mirrors src/ structure)
204
209
  runtime/ Code shipped into consumer projects
205
- base-classes/ BaseRepository, BaseService, family bases
210
+ base-classes/ BaseRepository, BaseService, pattern bases
206
211
  subsystems/ Events, Jobs, Cache, Storage
207
212
  templates/ Hygen EJS templates
208
213
  test/ Baseline snapshots, scaffold integration, smoke test
@@ -1087,7 +1087,7 @@ var init_icons = __esm({
1087
1087
 
1088
1088
  // src/schema/entity-definition.schema.ts
1089
1089
  import { z } from "zod";
1090
- var FieldTypeSchema, UiTypeSchema, UiImportanceSchema, AnalyticsAggregationSchema, AnalyticsDimensionTypeSchema, AnalyticsEntityTypeSchema, AnalyticsTimeGranularitySchema, AnalyticsVisibilitySchema, NonAdditiveDimensionSchema, SemanticMetadataSchema, UiMetadataSchema, BaseFieldSchema, FieldDefinitionSchema, RelationshipTypeSchema, RelationshipSchema, BehaviorConfigSchema, BehaviorStrategySchema, FolderStructureSchema, FileGroupingSchema, ExposeLayerSchema, EntityConfigSchema, QueryDeclarationSchema, SyncDirectionSchema, ProviderSyncSchema, SyncConfigSchema, EventDeclarationSchema, SimpleMetricSchema, DerivedMetricSchema, RatioMetricSchema, CumulativeMetricSchema, MetricDefinitionSchema, AnalyticsBlockSchema, EntityDefinitionSchema;
1090
+ var FieldTypeSchema, UiTypeSchema, UiImportanceSchema, AnalyticsAggregationSchema, AnalyticsDimensionTypeSchema, AnalyticsEntityTypeSchema, AnalyticsTimeGranularitySchema, AnalyticsVisibilitySchema, NonAdditiveDimensionSchema, SemanticMetadataSchema, UiMetadataSchema, BaseFieldSchema, FieldDefinitionSchema, RelationshipTypeSchema, RelationshipSchema, BehaviorConfigSchema, BehaviorStrategySchema, FolderStructureSchema, FileGroupingSchema, ExposeLayerSchema, EntityConfigSchema, QueryDeclarationSchema, SyncDirectionSchema, ProviderSyncSchema, SyncConfigSchema, EventDeclarationSchema, SimpleMetricSchema, DerivedMetricSchema, RatioMetricSchema, CumulativeMetricSchema, MetricDefinitionSchema, AnalyticsBlockSchema, GenerateConfigSchema, EntityDefinitionSchema;
1091
1091
  var init_entity_definition_schema = __esm({
1092
1092
  "src/schema/entity-definition.schema.ts"() {
1093
1093
  "use strict";
@@ -1420,12 +1420,37 @@ var init_entity_definition_schema = __esm({
1420
1420
  cube_name: z.string().optional(),
1421
1421
  metrics: z.record(z.string(), MetricDefinitionSchema).optional()
1422
1422
  });
1423
+ GenerateConfigSchema = z.object({
1424
+ writes: z.boolean().optional().default(true)
1425
+ }).strict();
1423
1426
  EntityDefinitionSchema = z.object({
1424
1427
  entity: EntityConfigSchema,
1425
1428
  fields: z.record(z.string(), FieldDefinitionSchema),
1426
1429
  relationships: z.record(z.string(), RelationshipSchema).optional(),
1427
1430
  // Behaviors add cross-cutting concerns (timestamps, soft_delete, user_tracking, etc.)
1428
1431
  behaviors: z.array(BehaviorConfigSchema).optional().default([]),
1432
+ // Per-entity generation toggles (e.g. disable write-side emission)
1433
+ generate: GenerateConfigSchema.optional(),
1434
+ // EAV (entity-attribute-value) dual-write + paired reads (ADR-13).
1435
+ // When `true`, codegen emits:
1436
+ // - FindXWithFieldsUseCase + ListXWithFieldsUseCase (paired reads)
1437
+ // - CreateX / UpdateX use cases in transactional compound-write shape
1438
+ // (composes entity service + FieldValueService in one db.transaction,
1439
+ // splits `{ fields, ...core }` from the DTO)
1440
+ // - GET /:id/with-fields + GET /with-fields controller routes
1441
+ // - Service with injected FieldValueRepository + findByIdWithFields /
1442
+ // listWithFields paired read methods
1443
+ //
1444
+ // Consumer contract (must be in place before regen):
1445
+ // - BaseService.create/update/delete accept optional `tx` parameter
1446
+ // - `@shared/eav-helpers` exports `toEavRows(entityId, entityType, fields)`
1447
+ // and `mergeEavRows(rows)`
1448
+ // - FieldValueService exposes `upsertMany(rows, tx?)` (inherited from
1449
+ // MetadataEntityService)
1450
+ // - DRIZZLE_DB injection token available via `@shared/constants/tokens`
1451
+ //
1452
+ // Defaults to `false` — opt in per entity that needs dynamic/custom fields.
1453
+ eav: z.boolean().optional().default(false),
1429
1454
  // v2: Declarative query generation (ADR-005)
1430
1455
  // Generates repository + service + use case methods from declarations
1431
1456
  queries: z.array(QueryDeclarationSchema).optional(),
@@ -3983,6 +4008,7 @@ var init_git_safety = __esm({
3983
4008
  // src/cli/shared/barrel-generator.ts
3984
4009
  import fs2 from "fs";
3985
4010
  import path3 from "path";
4011
+ import pluralize from "pluralize";
3986
4012
  function toPascalCase(input) {
3987
4013
  return input.split(/[-_\s]+/).filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("");
3988
4014
  }
@@ -4008,17 +4034,36 @@ function collectEntities(entitiesDir) {
4008
4034
  entities.sort((a, b) => a.name.localeCompare(b.name));
4009
4035
  return entities;
4010
4036
  }
4037
+ function listRelationshipYamls(relationshipsDir) {
4038
+ if (!fs2.existsSync(relationshipsDir)) return [];
4039
+ return fs2.readdirSync(relationshipsDir).filter((f) => f.endsWith(".yaml") || f.endsWith(".yml")).map((f) => path3.join(relationshipsDir, f)).filter((full) => detectYamlType(full) === "relationship").sort();
4040
+ }
4041
+ function collectRelationships(relationshipsDir) {
4042
+ const files = listRelationshipYamls(relationshipsDir);
4043
+ const junctions = [];
4044
+ for (const file of files) {
4045
+ const result = loadRelationshipFromYaml(file);
4046
+ if (!result.success) continue;
4047
+ const rel = result.definition.relationship;
4048
+ const name = rel.name;
4049
+ const plural = rel.table ?? pluralize(name);
4050
+ junctions.push({ name, plural });
4051
+ }
4052
+ junctions.sort((a, b) => a.name.localeCompare(b.name));
4053
+ return junctions;
4054
+ }
4011
4055
  function entityFilePaths(info, architecture, backendSrc) {
4012
4056
  const name = info.name;
4013
4057
  const plural = info.plural;
4014
4058
  const nameKebab = toKebabCase(name);
4015
4059
  const pluralKebab = toKebabCase(plural);
4016
4060
  if (architecture === "clean-lite-ps") {
4061
+ const prefix = backendSrc && backendSrc !== "." ? `${backendSrc}/` : "";
4017
4062
  return {
4018
- moduleFile: `modules/${plural}/${plural}.module.ts`,
4063
+ moduleFile: `${prefix}modules/${plural}/${plural}.module.ts`,
4019
4064
  moduleClass: `${toPascalCase(plural)}Module`,
4020
4065
  // Drizzle entity schema lives alongside the entity file in clean-lite-ps.
4021
- schemaFile: `modules/${plural}/${name}.entity.ts`
4066
+ schemaFile: `${prefix}modules/${plural}/${name}.entity.ts`
4022
4067
  };
4023
4068
  }
4024
4069
  return {
@@ -4069,13 +4114,17 @@ async function regenerateBarrels(opts) {
4069
4114
  const {
4070
4115
  ctx,
4071
4116
  entitiesDir,
4117
+ relationshipsDir = path3.resolve(ctx.cwd, "relationships"),
4072
4118
  generatedDir,
4073
4119
  architecture,
4074
4120
  backendSrc = resolveBackendSrc(ctx),
4075
4121
  dryRun = false
4076
4122
  } = opts;
4077
4123
  const cwd = ctx.cwd;
4078
- const entities = collectEntities(entitiesDir);
4124
+ const entities = [
4125
+ ...collectEntities(entitiesDir),
4126
+ ...collectRelationships(relationshipsDir)
4127
+ ].sort((a, b) => a.name.localeCompare(b.name));
4079
4128
  const generatedRel = path3.relative(cwd, generatedDir) || path3.basename(generatedDir);
4080
4129
  const modulesRel = path3.posix.join(
4081
4130
  generatedRel.split(path3.sep).join("/"),
@@ -4328,12 +4377,14 @@ var init_entity = __esm({
4328
4377
  }
4329
4378
  }
4330
4379
  const entitiesDir = ctx.entitiesDir ?? path4.resolve(ctx.cwd, "entities");
4380
+ const relationshipsDir = path4.resolve(ctx.cwd, "relationships");
4331
4381
  const generatedDir = resolveGeneratedDir(ctx);
4332
4382
  const architecture = resolveArchitecture(ctx);
4333
4383
  if (this.dryRun) {
4334
4384
  const barrelPlan = await regenerateBarrels({
4335
4385
  ctx,
4336
4386
  entitiesDir,
4387
+ relationshipsDir,
4337
4388
  generatedDir,
4338
4389
  architecture,
4339
4390
  dryRun: true
@@ -4396,6 +4447,7 @@ var init_entity = __esm({
4396
4447
  barrelResult = await regenerateBarrels({
4397
4448
  ctx,
4398
4449
  entitiesDir,
4450
+ relationshipsDir,
4399
4451
  generatedDir,
4400
4452
  architecture
4401
4453
  });
@@ -4610,7 +4662,7 @@ async function copyRuntime(opts) {
4610
4662
  if (!fs4.existsSync(sourceDir) || !fs4.statSync(sourceDir).isDirectory()) {
4611
4663
  throw new Error(`runtime source directory not found: ${sourceDir}`);
4612
4664
  }
4613
- const runtimeRoot2 = opts.runtimeRoot ? path5.resolve(opts.runtimeRoot) : path5.resolve(sourceDir, "..", "..");
4665
+ const runtimeRoot3 = opts.runtimeRoot ? path5.resolve(opts.runtimeRoot) : path5.resolve(sourceDir, "..", "..");
4614
4666
  const depsTargetRoot = opts.depsTargetRoot ?? path5.resolve(targetDir, "..");
4615
4667
  const result = {
4616
4668
  written: [],
@@ -4647,7 +4699,7 @@ async function copyRuntime(opts) {
4647
4699
  for (const spec of extractRelativeImports(content)) {
4648
4700
  const resolvedSrc = resolveSourceImport(next.src, spec);
4649
4701
  if (!resolvedSrc) continue;
4650
- const relToRuntime = path5.relative(runtimeRoot2, resolvedSrc);
4702
+ const relToRuntime = path5.relative(runtimeRoot3, resolvedSrc);
4651
4703
  if (relToRuntime.startsWith("..") || path5.isAbsolute(relToRuntime)) continue;
4652
4704
  const relToSource = path5.relative(sourceDir, resolvedSrc);
4653
4705
  if (!relToSource.startsWith("..") && !path5.isAbsolute(relToSource)) continue;
@@ -5081,15 +5133,15 @@ var init_subsystem = __esm({
5081
5133
  import fs7 from "fs";
5082
5134
  import path8 from "path";
5083
5135
  import { stringify as stringifyYaml } from "yaml";
5136
+ function runtimeRoot2() {
5137
+ return path8.resolve(import.meta.dirname, "..", "..", "..", "runtime");
5138
+ }
5084
5139
  function resolveRuntimePath(cwd) {
5085
- const runtimeAbs = path8.resolve(import.meta.dirname, "..", "..", "..", "runtime");
5086
- const shimDir = path8.join(cwd, "shared", "base-classes");
5087
- return path8.relative(shimDir, runtimeAbs);
5140
+ const shimDir = path8.join(cwd, "src", "shared", "base-classes");
5141
+ return path8.relative(shimDir, runtimeRoot2());
5088
5142
  }
5089
- function resolveRuntimePathFor(cwd, shimRelDir) {
5090
- const runtimeAbs = path8.resolve(import.meta.dirname, "..", "..", "..", "runtime");
5091
- const shimDir = path8.join(cwd, shimRelDir);
5092
- return path8.relative(shimDir, runtimeAbs);
5143
+ function loadRuntimeFile(relPath) {
5144
+ return fs7.readFileSync(path8.join(runtimeRoot2(), relPath), "utf-8");
5093
5145
  }
5094
5146
  function databaseModuleContent() {
5095
5147
  return `import { Module, Global } from '@nestjs/common';
@@ -5123,27 +5175,9 @@ export type DrizzleDB = ReturnType<typeof drizzle<typeof schema>>;
5123
5175
  export class DatabaseModule {}
5124
5176
  `;
5125
5177
  }
5126
- function tokensShim(cwd) {
5127
- const rt = resolveRuntimePathFor(cwd, "shared/constants");
5128
- return `/**
5129
- * Re-export DRIZZLE injection token from the codegen runtime.
5130
- * Generated code imports from '@shared/constants/tokens'.
5131
- */
5132
- export { DRIZZLE } from '${rt}/constants/tokens';
5133
- `;
5134
- }
5135
- function drizzleTypeShim(cwd) {
5136
- const rt = resolveRuntimePathFor(cwd, "shared/types");
5137
- return `/**
5138
- * Re-export the DrizzleClient type from the codegen runtime.
5139
- * Generated code imports from '@shared/types/drizzle'.
5140
- */
5141
- export type { DrizzleClient } from '${rt}/types/drizzle';
5142
- `;
5143
- }
5144
5178
  function appModuleContent() {
5145
5179
  return `import { Module } from '@nestjs/common';
5146
- import { DatabaseModule } from '../shared/database/database.module';
5180
+ import { DatabaseModule } from './shared/database/database.module';
5147
5181
  import { GENERATED_MODULES } from './generated/modules';
5148
5182
 
5149
5183
  /**
@@ -5164,7 +5198,7 @@ function rootSchemaContent() {
5164
5198
  * Re-exports the generated schema barrel. Codegen owns src/generated/schema.ts
5165
5199
  * \u2014 add or remove entity YAML to change the table set.
5166
5200
  */
5167
- export * from './src/generated/schema';
5201
+ export * from './generated/schema';
5168
5202
  `;
5169
5203
  }
5170
5204
  function emptyModulesBarrel() {
@@ -5216,17 +5250,14 @@ function tsconfigTemplate() {
5216
5250
  "resolveJsonModule": true,
5217
5251
  "baseUrl": ".",
5218
5252
  "paths": {
5219
- "@shared/*": ["./shared/*"],
5220
- "@modules/*": ["./modules/*"],
5253
+ "@shared/*": ["./src/shared/*"],
5254
+ "@modules/*": ["./src/modules/*"],
5221
5255
  "@generated/*": ["./src/generated/*"]
5222
5256
  },
5223
5257
  "types": ["node"]
5224
5258
  },
5225
5259
  "include": [
5226
5260
  "src/**/*",
5227
- "shared/**/*",
5228
- "modules/**/*",
5229
- "schema.ts",
5230
5261
  "drizzle.config.ts"
5231
5262
  ]
5232
5263
  }
@@ -5370,7 +5401,7 @@ async function buildInitPlan(ctx, options) {
5370
5401
  const configPath = path8.join(cwd, "codegen.config.yaml");
5371
5402
  const config = {
5372
5403
  paths: {
5373
- backend_src: ".",
5404
+ backend_src: "src",
5374
5405
  entities_dir: "entities",
5375
5406
  generated: "src/generated"
5376
5407
  },
@@ -5443,33 +5474,15 @@ async function buildInitPlan(ctx, options) {
5443
5474
  entries.push(
5444
5475
  fileEntry(
5445
5476
  cwd,
5446
- path8.join(cwd, "shared", "database", "database.module.ts"),
5477
+ path8.join(cwd, "src", "shared", "database", "database.module.ts"),
5447
5478
  databaseModuleContent(),
5448
5479
  { force }
5449
5480
  )
5450
5481
  );
5451
- entries.push(
5452
- fileEntry(cwd, path8.join(cwd, "shared", "constants", "tokens.ts"), tokensShim(cwd), {
5453
- force
5454
- })
5455
- );
5456
- entries.push(
5457
- fileEntry(cwd, path8.join(cwd, "shared", "types", "drizzle.ts"), drizzleTypeShim(cwd), {
5458
- force
5459
- })
5460
- );
5461
- {
5462
- const rt = resolveRuntimePathFor(cwd, "shared/base-classes");
5463
- for (const shim of BASE_CLASS_SHIMS) {
5464
- entries.push(
5465
- fileEntry(
5466
- cwd,
5467
- path8.join(cwd, "shared", "base-classes", shim.file),
5468
- shim.exportLine(rt),
5469
- { force }
5470
- )
5471
- );
5472
- }
5482
+ for (const v of VENDORED_RUNTIME_FILES) {
5483
+ entries.push(
5484
+ fileEntry(cwd, path8.join(cwd, v.target), loadRuntimeFile(v.runtime), { force })
5485
+ );
5473
5486
  }
5474
5487
  entries.push(
5475
5488
  fileEntry(
@@ -5506,7 +5519,7 @@ async function buildInitPlan(ctx, options) {
5506
5519
  }
5507
5520
  }
5508
5521
  {
5509
- const schemaPath = path8.join(cwd, "schema.ts");
5522
+ const schemaPath = path8.join(cwd, "src", "schema.ts");
5510
5523
  if (!fs7.existsSync(schemaPath)) {
5511
5524
  entries.push({
5512
5525
  path: schemaPath,
@@ -5519,7 +5532,7 @@ async function buildInitPlan(ctx, options) {
5519
5532
  path: schemaPath,
5520
5533
  relPath: relOf(cwd, schemaPath),
5521
5534
  action: "skip",
5522
- reason: "exists \u2014 ensure it re-exports './src/generated/schema'"
5535
+ reason: "exists \u2014 ensure it re-exports './generated/schema'"
5523
5536
  });
5524
5537
  }
5525
5538
  }
@@ -5581,71 +5594,36 @@ function writePlan(plan) {
5581
5594
  }
5582
5595
  return { created, merged, overwritten, skipped };
5583
5596
  }
5584
- var BASE_CLASS_SHIMS, REQUIRED_ALIASES, REQUIRED_COMPILER_OPTIONS;
5597
+ var VENDORED_RUNTIME_FILES, REQUIRED_ALIASES, REQUIRED_COMPILER_OPTIONS;
5585
5598
  var init_init_scaffold = __esm({
5586
5599
  "src/cli/shared/init-scaffold.ts"() {
5587
5600
  "use strict";
5588
5601
  init_scanner();
5589
- BASE_CLASS_SHIMS = [
5590
- {
5591
- file: "base-repository.ts",
5592
- exportLine: (rt) => `export * from '${rt}/base-classes/base-repository';
5593
- `
5594
- },
5595
- {
5596
- file: "base-service.ts",
5597
- exportLine: (rt) => `export * from '${rt}/base-classes/base-service';
5598
- `
5599
- },
5600
- {
5601
- file: "synced-entity-repository.ts",
5602
- exportLine: (rt) => `export * from '${rt}/base-classes/synced-entity-repository';
5603
- `
5604
- },
5605
- {
5606
- file: "synced-entity-service.ts",
5607
- exportLine: (rt) => `export * from '${rt}/base-classes/synced-entity-service';
5608
- `
5609
- },
5610
- {
5611
- file: "activity-entity-repository.ts",
5612
- exportLine: (rt) => `export * from '${rt}/base-classes/activity-entity-repository';
5613
- `
5614
- },
5615
- {
5616
- file: "activity-entity-service.ts",
5617
- exportLine: (rt) => `export * from '${rt}/base-classes/activity-entity-service';
5618
- `
5619
- },
5620
- {
5621
- file: "metadata-entity-repository.ts",
5622
- exportLine: (rt) => `export * from '${rt}/base-classes/metadata-entity-repository';
5623
- `
5624
- },
5625
- {
5626
- file: "metadata-entity-service.ts",
5627
- exportLine: (rt) => `export * from '${rt}/base-classes/metadata-entity-service';
5628
- `
5629
- },
5630
- {
5631
- file: "knowledge-entity-repository.ts",
5632
- exportLine: (rt) => `export * from '${rt}/base-classes/knowledge-entity-repository';
5633
- `
5634
- },
5635
- {
5636
- file: "knowledge-entity-service.ts",
5637
- exportLine: (rt) => `export * from '${rt}/base-classes/knowledge-entity-service';
5638
- `
5639
- },
5640
- {
5641
- file: "with-analytics.ts",
5642
- exportLine: (rt) => `export { WithAnalytics } from '${rt}/base-classes/with-analytics';
5643
- `
5644
- }
5602
+ VENDORED_RUNTIME_FILES = [
5603
+ // base-classes — consumer-facing inheritance targets
5604
+ { runtime: "base-classes/base-repository.ts", target: "src/shared/base-classes/base-repository.ts" },
5605
+ { runtime: "base-classes/base-service.ts", target: "src/shared/base-classes/base-service.ts" },
5606
+ { runtime: "base-classes/synced-entity-repository.ts", target: "src/shared/base-classes/synced-entity-repository.ts" },
5607
+ { runtime: "base-classes/synced-entity-service.ts", target: "src/shared/base-classes/synced-entity-service.ts" },
5608
+ { runtime: "base-classes/activity-entity-repository.ts", target: "src/shared/base-classes/activity-entity-repository.ts" },
5609
+ { runtime: "base-classes/activity-entity-service.ts", target: "src/shared/base-classes/activity-entity-service.ts" },
5610
+ { runtime: "base-classes/metadata-entity-repository.ts", target: "src/shared/base-classes/metadata-entity-repository.ts" },
5611
+ { runtime: "base-classes/metadata-entity-service.ts", target: "src/shared/base-classes/metadata-entity-service.ts" },
5612
+ { runtime: "base-classes/knowledge-entity-repository.ts", target: "src/shared/base-classes/knowledge-entity-repository.ts" },
5613
+ { runtime: "base-classes/knowledge-entity-service.ts", target: "src/shared/base-classes/knowledge-entity-service.ts" },
5614
+ { runtime: "base-classes/with-analytics.ts", target: "src/shared/base-classes/with-analytics.ts" },
5615
+ // base-classes transitive deps of base-service
5616
+ { runtime: "base-classes/lifecycle-events.ts", target: "src/shared/base-classes/lifecycle-events.ts" },
5617
+ { runtime: "base-classes/base-read-use-cases.ts", target: "src/shared/base-classes/base-read-use-cases.ts" },
5618
+ // Types + constants reached via `@shared/types/*` and `@shared/constants/*`
5619
+ { runtime: "types/drizzle.ts", target: "src/shared/types/drizzle.ts" },
5620
+ { runtime: "constants/tokens.ts", target: "src/shared/constants/tokens.ts" },
5621
+ // Events protocol — imported transitively by base-service + lifecycle-events
5622
+ { runtime: "subsystems/events/event-bus.protocol.ts", target: "src/shared/subsystems/events/event-bus.protocol.ts" }
5645
5623
  ];
5646
5624
  REQUIRED_ALIASES = {
5647
- "@shared/*": ["./shared/*"],
5648
- "@modules/*": ["./modules/*"],
5625
+ "@shared/*": ["./src/shared/*"],
5626
+ "@modules/*": ["./src/modules/*"],
5649
5627
  "@generated/*": ["./src/generated/*"]
5650
5628
  };
5651
5629
  REQUIRED_COMPILER_OPTIONS = {
@@ -6918,7 +6896,7 @@ __export(relationship_exports, {
6918
6896
  import fs10 from "fs";
6919
6897
  import path11 from "path";
6920
6898
  import { Command as Command6, Option as Option6 } from "clipanion";
6921
- function listRelationshipYamls(dir) {
6899
+ function listRelationshipYamls2(dir) {
6922
6900
  if (!fs10.existsSync(dir)) return [];
6923
6901
  return fs10.readdirSync(dir).filter((f) => f.endsWith(".yaml") || f.endsWith(".yml")).filter((f) => {
6924
6902
  const fullPath = path11.join(dir, f);
@@ -6945,7 +6923,7 @@ function padRight2(s, n) {
6945
6923
  }
6946
6924
  async function summary5(ctx) {
6947
6925
  const relDir = path11.resolve(ctx.cwd, "relationships");
6948
- const files = listRelationshipYamls(relDir);
6926
+ const files = listRelationshipYamls2(relDir);
6949
6927
  if (files.length === 0) {
6950
6928
  return {
6951
6929
  title: "relationships",
@@ -6991,6 +6969,7 @@ var init_relationship = __esm({
6991
6969
  init_context();
6992
6970
  init_hygen();
6993
6971
  init_git_safety();
6972
+ init_barrel_generator();
6994
6973
  init_theme();
6995
6974
  init_icons();
6996
6975
  init_output();
@@ -7027,7 +7006,7 @@ var init_relationship = __esm({
7027
7006
  let targets = [];
7028
7007
  if (this.all) {
7029
7008
  const dir = path11.resolve(ctx.cwd, "relationships");
7030
- targets = listRelationshipYamls(dir);
7009
+ targets = listRelationshipYamls2(dir);
7031
7010
  if (targets.length === 0) {
7032
7011
  printError(`No relationship YAML files found in ${dir}`);
7033
7012
  return 1;
@@ -7100,6 +7079,25 @@ var init_relationship = __esm({
7100
7079
  if (!isJsonMode()) printError(`${v.name} \u2014 ${res.stderr ?? "failed"}`);
7101
7080
  }
7102
7081
  }
7082
+ const entitiesDir = ctx.entitiesDir ?? path11.resolve(ctx.cwd, "entities");
7083
+ const relationshipsDir = path11.resolve(ctx.cwd, "relationships");
7084
+ const generatedDir = resolveGeneratedDir(ctx);
7085
+ const architecture = resolveArchitecture(ctx);
7086
+ let barrelResult = null;
7087
+ try {
7088
+ barrelResult = await regenerateBarrels({
7089
+ ctx,
7090
+ entitiesDir,
7091
+ relationshipsDir,
7092
+ generatedDir,
7093
+ architecture
7094
+ });
7095
+ } catch (err) {
7096
+ const msg = err instanceof Error ? err.message : String(err);
7097
+ if (!isJsonMode()) {
7098
+ printWarning(`barrel regeneration failed \u2014 ${msg}`);
7099
+ }
7100
+ }
7103
7101
  if (isJsonMode()) {
7104
7102
  printJson({
7105
7103
  command: "relationship new",
@@ -7108,7 +7106,12 @@ var init_relationship = __esm({
7108
7106
  failed: failed.length
7109
7107
  },
7110
7108
  succeeded,
7111
- failed
7109
+ failed,
7110
+ barrels: barrelResult ? {
7111
+ modules: barrelResult.modulesBarrel,
7112
+ schema: barrelResult.schemaBarrel,
7113
+ entityCount: barrelResult.entityCount
7114
+ } : null
7112
7115
  });
7113
7116
  } else {
7114
7117
  const total = validated.length + invalid.length;
@@ -7120,6 +7123,11 @@ var init_relationship = __esm({
7120
7123
  `${total} relationships \xB7 ${succeeded.length} succeeded \xB7 ${failed.length} failed`
7121
7124
  );
7122
7125
  }
7126
+ if (barrelResult) {
7127
+ printInfo(
7128
+ `barrels regenerated (${barrelResult.entityCount} modules) \u2192 ${path11.relative(ctx.cwd, barrelResult.modulesBarrel)}, ${path11.relative(ctx.cwd, barrelResult.schemaBarrel)}`
7129
+ );
7130
+ }
7123
7131
  }
7124
7132
  return failed.length === 0 ? 0 : 1;
7125
7133
  }
@@ -7141,7 +7149,7 @@ var init_relationship = __esm({
7141
7149
  skipDetection: true
7142
7150
  });
7143
7151
  const relDir = path11.resolve(ctx.cwd, "relationships");
7144
- const files = listRelationshipYamls(relDir);
7152
+ const files = listRelationshipYamls2(relDir);
7145
7153
  if (files.length === 0) {
7146
7154
  printInfo("No relationship definitions found.");
7147
7155
  return 0;