@pattern-stack/codegen 0.27.2 → 0.28.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 (50) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/dist/{chunk-YQA5PMOD.js → chunk-3GMQKHJD.js} +2 -2
  3. package/dist/{chunk-5TK7MEN4.js → chunk-CPUSJPAP.js} +1 -1
  4. package/dist/{chunk-5TK7MEN4.js.map → chunk-CPUSJPAP.js.map} +1 -1
  5. package/dist/{chunk-PBENHIN2.js → chunk-IB733A6R.js} +2 -2
  6. package/dist/{chunk-YHVZAL6U.js → chunk-K6LH4PXZ.js} +2 -2
  7. package/dist/{chunk-XW4XKN3F.js → chunk-KS4BZHIA.js} +7 -7
  8. package/dist/{chunk-BK5ICA2F.js → chunk-RUSUZZAF.js} +4 -4
  9. package/dist/{chunk-7LKAMLV4.js → chunk-T6SCOJF4.js} +4 -4
  10. package/dist/{chunk-LQZESSM3.js → chunk-WE6DIDMM.js} +1 -1
  11. package/dist/chunk-WE6DIDMM.js.map +1 -0
  12. package/dist/{chunk-K4BQQ2NN.js → chunk-YUVEJNRE.js} +133 -10
  13. package/dist/chunk-YUVEJNRE.js.map +1 -0
  14. package/dist/{chunk-EGXFEZ2N.js → chunk-Z7YFYK6H.js} +4 -4
  15. package/dist/runtime/subsystems/auth/auth.module.js +2 -2
  16. package/dist/runtime/subsystems/auth/index.js +11 -11
  17. package/dist/runtime/subsystems/bridge/bridge.module.js +6 -6
  18. package/dist/runtime/subsystems/bridge/index.js +6 -6
  19. package/dist/runtime/subsystems/events/events.module.js +3 -3
  20. package/dist/runtime/subsystems/events/generated/bus.js +2 -2
  21. package/dist/runtime/subsystems/events/generated/index.js +2 -2
  22. package/dist/runtime/subsystems/events/generated/registry.d.ts +6 -0
  23. package/dist/runtime/subsystems/events/generated/registry.js +1 -1
  24. package/dist/runtime/subsystems/events/index.js +3 -3
  25. package/dist/runtime/subsystems/index.js +34 -34
  26. package/dist/runtime/subsystems/integration/detection-config.schema.d.ts +6 -4
  27. package/dist/runtime/subsystems/integration/detection-config.schema.js +1 -1
  28. package/dist/runtime/subsystems/integration/index.js +1 -1
  29. package/dist/runtime/subsystems/jobs/index.js +13 -13
  30. package/dist/runtime/subsystems/jobs/job-worker.module.js +5 -5
  31. package/dist/runtime/subsystems/jobs/jobs-domain.module.js +3 -3
  32. package/dist/runtime/subsystems/observability/index.js +3 -3
  33. package/dist/runtime/subsystems/storage/index.js +4 -4
  34. package/dist/runtime/subsystems/storage/storage.module.js +2 -2
  35. package/dist/src/cli/index.js +81 -25
  36. package/dist/src/cli/index.js.map +1 -1
  37. package/dist/src/index.js +2 -2
  38. package/package.json +1 -1
  39. package/runtime/subsystems/events/generated/registry.ts +1 -0
  40. package/runtime/subsystems/integration/detection-config.schema.ts +7 -5
  41. package/templates/entity/new/clean-lite-ps/dto/output.ejs.t +6 -0
  42. package/dist/chunk-K4BQQ2NN.js.map +0 -1
  43. package/dist/chunk-LQZESSM3.js.map +0 -1
  44. /package/dist/{chunk-YQA5PMOD.js.map → chunk-3GMQKHJD.js.map} +0 -0
  45. /package/dist/{chunk-PBENHIN2.js.map → chunk-IB733A6R.js.map} +0 -0
  46. /package/dist/{chunk-YHVZAL6U.js.map → chunk-K6LH4PXZ.js.map} +0 -0
  47. /package/dist/{chunk-XW4XKN3F.js.map → chunk-KS4BZHIA.js.map} +0 -0
  48. /package/dist/{chunk-BK5ICA2F.js.map → chunk-RUSUZZAF.js.map} +0 -0
  49. /package/dist/{chunk-7LKAMLV4.js.map → chunk-T6SCOJF4.js.map} +0 -0
  50. /package/dist/{chunk-EGXFEZ2N.js.map → chunk-Z7YFYK6H.js.map} +0 -0
@@ -44,7 +44,7 @@ import {
44
44
  validateOrchestrationProject,
45
45
  validateProviders,
46
46
  writeManifest
47
- } from "../../chunk-K4BQQ2NN.js";
47
+ } from "../../chunk-YUVEJNRE.js";
48
48
  import "../../chunk-KVOWSC5S.js";
49
49
  import "../../chunk-VCXOPBYY.js";
50
50
  import "../../chunk-PRWIX6UW.js";
@@ -64,7 +64,7 @@ import "../../chunk-TIZXQU26.js";
64
64
  import "../../chunk-JEINYUJH.js";
65
65
  import {
66
66
  isDivisibleCursor
67
- } from "../../chunk-5TK7MEN4.js";
67
+ } from "../../chunk-CPUSJPAP.js";
68
68
  import "../../chunk-4KNXX6TI.js";
69
69
  import "../../chunk-3CJFPU6Q.js";
70
70
  import "../../chunk-U64T4YZE.js";
@@ -2017,7 +2017,10 @@ async function generateBridgeRegistry(opts) {
2017
2017
  skipped: true
2018
2018
  };
2019
2019
  }
2020
- const triggers = scanHandlerFiles(handlersDir);
2020
+ const triggers = [
2021
+ ...scanHandlerFiles(handlersDir),
2022
+ ...opts.extraTriggers ?? []
2023
+ ];
2021
2024
  validateNoDuplicateTriggers(triggers);
2022
2025
  const knownEventTypes = readKnownEventTypes(eventsGeneratedDir);
2023
2026
  validateAgainstEventRegistry(triggers, knownEventTypes);
@@ -2375,7 +2378,7 @@ function collectMergedEvents(opts) {
2375
2378
  const { events: entitySugar, issues: sugarIssues } = collectEntityEvents(entitiesDir);
2376
2379
  const { events: merged, issues: mergeIssues } = mergeEvents(
2377
2380
  topLevelResult.events,
2378
- entitySugar
2381
+ [...entitySugar, ...opts.extraSugarEvents ?? []]
2379
2382
  );
2380
2383
  const issues = [
2381
2384
  ...topLevelResult.issues,
@@ -2505,6 +2508,10 @@ var REGISTRY_INTERFACE = [
2505
2508
  // materialise ticks. `every` is ms-or-duration-string; the rest carry the
2506
2509
  // schema defaults.
2507
2510
  " schedule?: { every: string | number; align: boolean; catchUp: boolean; maxCatchUpSlots: number };",
2511
+ // Trigger-catalog projection — present only on events that opted in via the
2512
+ // `trigger:` block (selectable workflow triggers). Consumers build their
2513
+ // authoring catalog from this instead of a hand-maintained parallel list.
2514
+ " trigger?: { surface: string; label?: string; description?: string; fields: string[] };",
2508
2515
  "}"
2509
2516
  ].join("\n");
2510
2517
  var REGISTRY_GETTER = [
@@ -2566,6 +2573,9 @@ function buildRegistryContent(events) {
2566
2573
  ` schedule: { every: ${every}, align: ${ev.schedule.align}, catchUp: ${ev.schedule.catchUp}, maxCatchUpSlots: ${ev.schedule.maxCatchUpSlots} },`
2567
2574
  );
2568
2575
  }
2576
+ if (ev.trigger !== void 0) {
2577
+ chunks.push(` trigger: ${JSON.stringify(ev.trigger)},`);
2578
+ }
2569
2579
  chunks.push(` },`);
2570
2580
  }
2571
2581
  chunks.push(
@@ -2729,10 +2739,11 @@ function buildEventCodegenContents(events, mode = "vendored") {
2729
2739
  ];
2730
2740
  }
2731
2741
  async function generateEventCodegen(opts) {
2732
- const { entitiesDir, eventsDir, outputDir, mode = "vendored", dryRun = false } = opts;
2742
+ const { entitiesDir, eventsDir, outputDir, mode = "vendored", dryRun = false, extraSugarEvents } = opts;
2733
2743
  const { events: merged, issues } = collectMergedEvents({
2734
2744
  entitiesDir,
2735
- eventsDir
2745
+ eventsDir,
2746
+ extraSugarEvents
2736
2747
  });
2737
2748
  const files = buildEventCodegenContents(merged, mode).map(
2738
2749
  ({ name, content }) => ({
@@ -5729,6 +5740,21 @@ function resolvableRels(entity, ctx) {
5729
5740
  function fkField(rel2) {
5730
5741
  return rel2.foreignKey && rel2.foreignKey.length > 0 ? rel2.foreignKey : `${rel2.target}_id`;
5731
5742
  }
5743
+ function lookupFullFetchNames(ctx) {
5744
+ const referenceTargets = /* @__PURE__ */ new Set();
5745
+ for (const e of ctx.entities) {
5746
+ for (const r of resolvableRels(e, ctx)) referenceTargets.add(r.target.name);
5747
+ }
5748
+ const out = /* @__PURE__ */ new Set();
5749
+ for (const e of ctx.entities) {
5750
+ const parsed = ctx.parsed.get(e.name);
5751
+ const hasUnboundedText = parsed ? Array.from(parsed.fields.values()).some(
5752
+ (f) => f.type === "text" || f.type === "string" && f.constraints.maxLength === void 0
5753
+ ) : false;
5754
+ if (referenceTargets.has(e.name) || !hasUnboundedText) out.add(e.name);
5755
+ }
5756
+ return out;
5757
+ }
5732
5758
  function buildStoreIndexFile(ctx) {
5733
5759
  const entities = sortEntities(ctx.entities);
5734
5760
  const hookImports = entities.map((e) => `import { ${e.camelName}Hooks } from '../entities/${e.name}';`).join("\n");
@@ -5781,8 +5807,10 @@ export type AppStore = typeof store;
5781
5807
  }
5782
5808
  function buildResolversFile(ctx) {
5783
5809
  const entities = sortEntities(ctx.entities);
5810
+ const fullFetch = lookupFullFetchNames(ctx);
5811
+ const fetched = entities.filter((e) => fullFetch.has(e.name));
5784
5812
  const collectionImports = entities.map((e) => `import { ${e.camelName}Collection } from '../collections/${e.name}';`).join("\n");
5785
- const apiImports = entities.map((e) => `import { ${e.camelName}Api } from '../api/${e.name}';`).join("\n");
5813
+ const apiImports = fetched.map((e) => `import { ${e.camelName}Api } from '../api/${e.name}';`).join("\n");
5786
5814
  const typeImports = entities.map((e) => `import type { ${e.className} } from '${ctx.config.dbEntitiesImport}/${e.name}';`).join("\n");
5787
5815
  const resolverIface = entities.map(
5788
5816
  (e) => ` ${e.camelName}: (id: string | null | undefined) => ${e.className} | undefined;`
@@ -5795,7 +5823,7 @@ function buildResolversFile(ctx) {
5795
5823
  },`
5796
5824
  ).join("\n");
5797
5825
  const hydrationCacheFields = entities.map((e) => ` ${e.camelName}: new Map<string, ${e.className}>(),`).join("\n");
5798
- const hydrationCalls = entities.map(
5826
+ const hydrationCalls = fetched.map(
5799
5827
  (e) => ` ${e.camelName}Api.listAll().then((rows) => {
5800
5828
  hydrationCache.${e.camelName} = new Map(rows.map((r) => [r.id as string, r]));
5801
5829
  }),`
@@ -5884,22 +5912,34 @@ ${refsSection}`;
5884
5912
  }
5885
5913
  function buildLookupsFile(ctx) {
5886
5914
  const entities = sortEntities(ctx.entities);
5915
+ const fullFetch = lookupFullFetchNames(ctx);
5916
+ const fetched = entities.filter((e) => fullFetch.has(e.name));
5887
5917
  const collectionImports = entities.map((e) => `import { ${e.camelName}Collection } from '../collections/${e.name}';`).join("\n");
5888
- const apiImports = entities.map((e) => `import { ${e.camelName}Api } from '../api/${e.name}';`).join("\n");
5918
+ const apiImports = fetched.map((e) => `import { ${e.camelName}Api } from '../api/${e.name}';`).join("\n");
5889
5919
  const typeImports = entities.map((e) => `import type { ${e.className} } from '${ctx.config.dbEntitiesImport}/${e.name}';`).join("\n");
5890
5920
  const lookupIface = entities.map((e) => ` ${e.plural}: Map<string, ${e.className}>;`).join("\n");
5891
- const lookupBuild = entities.map(
5892
- (e) => ` ${e.plural}: new Map(
5921
+ const collectionStateMap = (e) => ` ${e.plural}: new Map(
5893
5922
  Array.from(${e.camelName}Collection.state.values()).map((item) => [
5894
5923
  (item as ${e.className}).id as string,
5895
5924
  item as ${e.className},
5896
5925
  ]),
5897
- ),`
5898
- ).join("\n");
5899
- const lookupBuildAsyncDecls = entities.map((e) => ` ${e.camelName}Api.listAll(),`).join("\n");
5900
- const lookupBuildAsyncFields = entities.map(
5901
- (e, i) => ` ${e.plural}: new Map(rows[${i}].map((r) => [r.id as string, r as ${e.className}])),`
5902
- ).join("\n");
5926
+ ),`;
5927
+ const lookupBuild = entities.map(collectionStateMap).join("\n");
5928
+ const lookupBuildAsyncDecls = fetched.map((e) => ` ${e.camelName}Api.listAll(),`).join("\n");
5929
+ const fetchedIndex = new Map(fetched.map((e, i) => [e.name, i]));
5930
+ const lookupBuildAsyncFields = entities.map((e) => {
5931
+ const i = fetchedIndex.get(e.name);
5932
+ return i === void 0 ? collectionStateMap(e) : ` ${e.plural}: new Map(rows[${i}].map((r) => [r.id as string, r as ${e.className}])),`;
5933
+ }).join("\n");
5934
+ const lookupBuildAsyncBody = fetched.length > 0 ? ` const rows = await Promise.all([
5935
+ ${lookupBuildAsyncDecls}
5936
+ ]);
5937
+ return {
5938
+ ${lookupBuildAsyncFields}
5939
+ };` : ` await Promise.resolve();
5940
+ return {
5941
+ ${lookupBuildAsyncFields}
5942
+ };`;
5903
5943
  const body = `${collectionImports}
5904
5944
  ${apiImports}
5905
5945
  ${typeImports}
@@ -5923,12 +5963,7 @@ ${lookupBuild}
5923
5963
  * may not be on the current page.
5924
5964
  */
5925
5965
  export async function buildLookupsAsync(): Promise<EntityLookups> {
5926
- const rows = await Promise.all([
5927
- ${lookupBuildAsyncDecls}
5928
- ]);
5929
- return {
5930
- ${lookupBuildAsyncFields}
5931
- };
5966
+ ${lookupBuildAsyncBody}
5932
5967
  }
5933
5968
 
5934
5969
  /**
@@ -5938,20 +5973,40 @@ ${lookupBuildAsyncFields}
5938
5973
  */
5939
5974
  export function createLookups() {
5940
5975
  let cache: EntityLookups | null = null;
5976
+ // Run-once guard for \`hydrate()\`. The store runtime calls hydrate from a
5977
+ // per-mount useEffect with NO dedup, so without this every EntityList/useData
5978
+ // mount (x2 under React StrictMode) kicks off another full buildLookupsAsync()
5979
+ // \u2014 a listAll() of every entity. On a large table (tens of thousands of rows)
5980
+ // that slurps the whole table N times concurrently and can OOM the renderer.
5981
+ // The guard collapses all callers onto a single hydration: cache the resolved
5982
+ // set, and dedupe concurrent callers onto one in-flight promise. \`clear()\`
5983
+ // forces a refresh. NOTE: this caps the damage but does not make full-fetching
5984
+ // a huge table cheap \u2014 lazy/on-demand FK resolution is the deeper fix.
5985
+ let inFlight: Promise<EntityLookups> | null = null;
5941
5986
  return {
5942
5987
  build: (): EntityLookups => {
5943
5988
  cache = buildLookups();
5944
5989
  return cache;
5945
5990
  },
5946
5991
  hydrate: async (): Promise<EntityLookups> => {
5947
- cache = await buildLookupsAsync();
5948
- return cache;
5992
+ if (cache) return cache;
5993
+ if (inFlight) return inFlight;
5994
+ inFlight = buildLookupsAsync()
5995
+ .then((result) => {
5996
+ cache = result;
5997
+ return result;
5998
+ })
5999
+ .finally(() => {
6000
+ inFlight = null;
6001
+ });
6002
+ return inFlight;
5949
6003
  },
5950
6004
  get current(): EntityLookups | null {
5951
6005
  return cache;
5952
6006
  },
5953
6007
  clear: (): void => {
5954
6008
  cache = null;
6009
+ inFlight = null;
5955
6010
  },
5956
6011
  };
5957
6012
  }
@@ -6422,6 +6477,7 @@ var GenerateConfigSchema = z.object({
6422
6477
  }).passthrough();
6423
6478
  var PathsConfigSchema = z.object({
6424
6479
  events_dir: z.string().optional(),
6480
+ jobs_dir: z.string().optional(),
6425
6481
  generated: z.string().default("src/generated")
6426
6482
  }).passthrough();
6427
6483
  var PatternsConfigSchema = z.array(z.string()).optional().default(["src/patterns/*.pattern.ts"]);