@pattern-stack/codegen 0.20.1 → 0.21.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 (100) hide show
  1. package/CHANGELOG.md +95 -0
  2. package/dist/{chunk-VNBC3VXM.js → chunk-3A34R6CI.js} +7 -7
  3. package/dist/{chunk-I6UXRJ3Q.js → chunk-43SBT72G.js} +4 -4
  4. package/dist/{chunk-BK5ICA2F.js → chunk-4MVGAMUA.js} +4 -4
  5. package/dist/{chunk-KK5A7B2T.js → chunk-524YKITE.js} +134 -20
  6. package/dist/chunk-524YKITE.js.map +1 -0
  7. package/dist/{chunk-P7EZCTIN.js → chunk-6CJRZHV4.js} +11 -11
  8. package/dist/{chunk-COGHTKXY.js → chunk-7625PLY7.js} +4 -4
  9. package/dist/{chunk-5RT7JGKT.js → chunk-7OVCARTQ.js} +4 -4
  10. package/dist/{chunk-BHZP6LOV.js → chunk-CDLWYZVQ.js} +7 -7
  11. package/dist/{chunk-W2UIDI3R.js → chunk-CLWBNXKF.js} +4 -4
  12. package/dist/{chunk-AODME4YK.js → chunk-EEJC66ZF.js} +6 -6
  13. package/dist/{chunk-YK5JEVLX.js → chunk-FFUDEIFF.js} +6 -6
  14. package/dist/{chunk-VOYFPR3S.js → chunk-G3IKPDTP.js} +4 -4
  15. package/dist/chunk-G3IKPDTP.js.map +1 -0
  16. package/dist/{chunk-AJILKWGO.js → chunk-GMRTI7AK.js} +13 -13
  17. package/dist/{chunk-4OC5MSHO.js → chunk-GOO5ZMYO.js} +4 -4
  18. package/dist/{chunk-M3TIZGIB.js → chunk-GV337QP3.js} +9 -9
  19. package/dist/{chunk-CZQUOIDY.js → chunk-J7JMVS2B.js} +4 -4
  20. package/dist/{chunk-SZYZ4SHF.js → chunk-MBFSG4KQ.js} +10 -10
  21. package/dist/{chunk-T6SCOJF4.js → chunk-NXHL5YII.js} +4 -4
  22. package/dist/{chunk-XWBK3XJK.js → chunk-O2A6XHGD.js} +4 -4
  23. package/dist/{chunk-ATVGYF3D.js → chunk-QFUIE37H.js} +3 -3
  24. package/dist/{chunk-SGSWVNNB.js → chunk-R6F6KFIL.js} +7 -7
  25. package/dist/{chunk-MB5VVG4Z.js → chunk-TKU6VYG3.js} +11 -11
  26. package/dist/{chunk-DUMI2J5M.js → chunk-VQOAATIG.js} +4 -4
  27. package/dist/{chunk-E45CSC33.js → chunk-XKWOJZZ4.js} +2 -2
  28. package/dist/{chunk-MVKW2BCR.js → chunk-YULGWXCY.js} +4 -4
  29. package/dist/{chunk-HCAKMT64.js → chunk-YXI7K4MJ.js} +8 -8
  30. package/dist/runtime/base-classes/index.js +17 -17
  31. package/dist/runtime/subsystems/analytics/analytics.module.js +2 -2
  32. package/dist/runtime/subsystems/analytics/index.js +4 -4
  33. package/dist/runtime/subsystems/auth/auth.module.js +3 -3
  34. package/dist/runtime/subsystems/auth/index.js +7 -7
  35. package/dist/runtime/subsystems/bridge/bridge-delivery-handler.js +3 -3
  36. package/dist/runtime/subsystems/bridge/bridge-delivery.drizzle-backend.js +3 -3
  37. package/dist/runtime/subsystems/bridge/bridge-outbox-drain-hook.js +7 -7
  38. package/dist/runtime/subsystems/bridge/bridge.module.js +19 -19
  39. package/dist/runtime/subsystems/bridge/event-flow.service.js +2 -2
  40. package/dist/runtime/subsystems/bridge/index.js +23 -23
  41. package/dist/runtime/subsystems/cache/cache.module.js +2 -2
  42. package/dist/runtime/subsystems/cache/index.js +4 -4
  43. package/dist/runtime/subsystems/events/event-bus.drizzle-backend.js +3 -3
  44. package/dist/runtime/subsystems/events/event-bus.memory-backend.js +2 -2
  45. package/dist/runtime/subsystems/events/events.module.d.ts +24 -7
  46. package/dist/runtime/subsystems/events/events.module.js +5 -5
  47. package/dist/runtime/subsystems/events/index.js +7 -7
  48. package/dist/runtime/subsystems/index.js +75 -75
  49. package/dist/runtime/subsystems/integration/build-change-source.js +2 -2
  50. package/dist/runtime/subsystems/integration/index.js +22 -22
  51. package/dist/runtime/subsystems/integration/integration-cursor-store.drizzle-backend.js +2 -2
  52. package/dist/runtime/subsystems/integration/integration-run-recorder.drizzle-backend.js +2 -2
  53. package/dist/runtime/subsystems/integration/integration.module.js +4 -4
  54. package/dist/runtime/subsystems/jobs/index.js +43 -43
  55. package/dist/runtime/subsystems/jobs/job-orchestrator.bullmq-backend.js +8 -8
  56. package/dist/runtime/subsystems/jobs/job-orchestrator.drizzle-backend.js +4 -4
  57. package/dist/runtime/subsystems/jobs/job-orchestrator.memory-backend.js +2 -2
  58. package/dist/runtime/subsystems/jobs/job-run-service.drizzle-backend.js +3 -3
  59. package/dist/runtime/subsystems/jobs/job-run-service.memory-backend.js +2 -2
  60. package/dist/runtime/subsystems/jobs/job-worker.bullmq-backend.js +3 -3
  61. package/dist/runtime/subsystems/jobs/job-worker.js +4 -4
  62. package/dist/runtime/subsystems/jobs/job-worker.module.js +12 -12
  63. package/dist/runtime/subsystems/jobs/jobs-domain.module.js +10 -10
  64. package/dist/runtime/subsystems/observability/index.js +3 -3
  65. package/dist/runtime/subsystems/observability/observability.module.js +3 -3
  66. package/dist/runtime/subsystems/observability/observability.service.js +2 -2
  67. package/dist/runtime/subsystems/storage/index.js +4 -4
  68. package/dist/runtime/subsystems/storage/storage.module.js +2 -2
  69. package/dist/src/cli/index.js +123 -84
  70. package/dist/src/cli/index.js.map +1 -1
  71. package/dist/src/index.d.ts +111 -1
  72. package/dist/src/index.js +10 -8
  73. package/package.json +1 -1
  74. package/runtime/subsystems/events/events.module.ts +24 -7
  75. package/dist/chunk-KK5A7B2T.js.map +0 -1
  76. package/dist/chunk-VOYFPR3S.js.map +0 -1
  77. /package/dist/{chunk-VNBC3VXM.js.map → chunk-3A34R6CI.js.map} +0 -0
  78. /package/dist/{chunk-I6UXRJ3Q.js.map → chunk-43SBT72G.js.map} +0 -0
  79. /package/dist/{chunk-BK5ICA2F.js.map → chunk-4MVGAMUA.js.map} +0 -0
  80. /package/dist/{chunk-P7EZCTIN.js.map → chunk-6CJRZHV4.js.map} +0 -0
  81. /package/dist/{chunk-COGHTKXY.js.map → chunk-7625PLY7.js.map} +0 -0
  82. /package/dist/{chunk-5RT7JGKT.js.map → chunk-7OVCARTQ.js.map} +0 -0
  83. /package/dist/{chunk-BHZP6LOV.js.map → chunk-CDLWYZVQ.js.map} +0 -0
  84. /package/dist/{chunk-W2UIDI3R.js.map → chunk-CLWBNXKF.js.map} +0 -0
  85. /package/dist/{chunk-AODME4YK.js.map → chunk-EEJC66ZF.js.map} +0 -0
  86. /package/dist/{chunk-YK5JEVLX.js.map → chunk-FFUDEIFF.js.map} +0 -0
  87. /package/dist/{chunk-AJILKWGO.js.map → chunk-GMRTI7AK.js.map} +0 -0
  88. /package/dist/{chunk-4OC5MSHO.js.map → chunk-GOO5ZMYO.js.map} +0 -0
  89. /package/dist/{chunk-M3TIZGIB.js.map → chunk-GV337QP3.js.map} +0 -0
  90. /package/dist/{chunk-CZQUOIDY.js.map → chunk-J7JMVS2B.js.map} +0 -0
  91. /package/dist/{chunk-SZYZ4SHF.js.map → chunk-MBFSG4KQ.js.map} +0 -0
  92. /package/dist/{chunk-T6SCOJF4.js.map → chunk-NXHL5YII.js.map} +0 -0
  93. /package/dist/{chunk-XWBK3XJK.js.map → chunk-O2A6XHGD.js.map} +0 -0
  94. /package/dist/{chunk-ATVGYF3D.js.map → chunk-QFUIE37H.js.map} +0 -0
  95. /package/dist/{chunk-SGSWVNNB.js.map → chunk-R6F6KFIL.js.map} +0 -0
  96. /package/dist/{chunk-MB5VVG4Z.js.map → chunk-TKU6VYG3.js.map} +0 -0
  97. /package/dist/{chunk-DUMI2J5M.js.map → chunk-VQOAATIG.js.map} +0 -0
  98. /package/dist/{chunk-E45CSC33.js.map → chunk-XKWOJZZ4.js.map} +0 -0
  99. /package/dist/{chunk-MVKW2BCR.js.map → chunk-YULGWXCY.js.map} +0 -0
  100. /package/dist/{chunk-HCAKMT64.js.map → chunk-YXI7K4MJ.js.map} +0 -0
package/CHANGELOG.md CHANGED
@@ -4,6 +4,101 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.21.0] — 2026-06-06
8
+
9
+ **FieldMeta enrichment (ADR-040, Phase A of type-aware rendering).** The
10
+ frontend emitter's per-entity field metadata now carries enough vocabulary for
11
+ consumers to build metadata-driven rendering (the swe-brain renderer kit
12
+ consumes this in its Phase B). All additive.
13
+
14
+ ### Added
15
+
16
+ - **Full `ui_*` hint passthrough.** `ui_group`, `ui_visible`, `ui_placeholder`,
17
+ `ui_help`, and `ui_format` were accepted by the schema but dropped before
18
+ emission. They now survive parser → derivation → emitted `FieldMeta`
19
+ (`group` / `visible` / `placeholder` / `help` / `format`). `format` was
20
+ previously only ever the hardcoded timestamp `{ dateFormat: 'relative' }`;
21
+ authored `ui_format` now passes through.
22
+ - **Key-field curation (qField parity).** New YAML keys `ui_key_field` +
23
+ `ui_key_field_order` surface as `isKeyField` / `keyFieldOrder` on the row
24
+ (the qField / EAV `field_definitions` names — one vocabulary, multiple
25
+ homes), and `<camel>Metadata` gains `keyFields`: the ordered curated
26
+ field-name list (sorted by `keyFieldOrder`, declaration order for ties) that
27
+ drives card/preview field selection.
28
+ - **Family/behavior common-field bundles** (timestamps precedent): the
29
+ `soft_delete` behavior now contributes a `deletedAt` row
30
+ (datetime / tertiary / relative); entities whose declared fields carry the
31
+ synced/integrated shape (both `external_id` AND `provider`) get
32
+ `group: 'external_sync'` defaulted onto those fields (plus
33
+ `provider_metadata` when present) — a derivation default only, authored
34
+ `ui_group` always wins. Behavior-contributed columns (not in the parsed
35
+ field map) still get no rows: the emitter never emits a row for a column it
36
+ cannot see.
37
+ - **EAV `data_type` → `FieldType` contract.** `EAV_DATA_TYPE_TO_FIELD_TYPE`
38
+ (`string→text, integer/decimal→number, boolean→boolean, date→date,
39
+ datetime→datetime, json→json, reference→reference, picklist→enum,
40
+ multipicklist→enum`; multi-select rendering is consumer-side) is exported
41
+ from the package root AND emitted into every generated
42
+ `fields/field-meta.ts`, rendered from the same source object so the copies
43
+ cannot drift. See ADR-040 for the convergence story
44
+ (qField/CatalogField ↔ codegen FieldMeta ↔ EAV `field_definitions`).
45
+
46
+ ### Tests
47
+
48
+ - emit-fields suite: hint passthrough (incl. author-override-beats-default and
49
+ string escaping), key-field curation + `keyFields` ordering, soft_delete /
50
+ external-sync bundles, EAV contract completeness vs the emitted copy.
51
+ - Frontend golden fixtures now exercise the new surface; the snapshot locks
52
+ curation ordering (`first_name` before `email` despite declaration order),
53
+ the `deletedAt` bundle, and the `external_sync` group default.
54
+
55
+ ## [0.20.2] — 2026-06-06
56
+
57
+ Two consumer-found fixes (dogfooding swe-brain on 0.20.1).
58
+
59
+ ### Fixed
60
+
61
+ - **ADR-039 boot tick was lost to a module-init race.** `EventSchedulerLifecycle`
62
+ ran `materializeBoot()` from `onModuleInit`, which fires during the EVENTS
63
+ module's own init — BEFORE later modules (notably `BridgeModule`, whose
64
+ outbox-drain hook turns a scheduled event into `bridge_delivery` rows) finish
65
+ wiring. With `listenNotify` the boot row drained within ~3ms and was marked
66
+ `processed` with ZERO deliveries and no error (verified live: slot
67
+ `@schedule/reconcile_due/1780707600000` processed 3ms after materialisation,
68
+ zero `bridge_delivery` rows for `reconcile-poll#0`; the in-loop tick at the
69
+ next slot boundary delivered correctly — boot-only loss). **Fix:** the
70
+ lifecycle now defers to `onApplicationBootstrap` (fires after all modules'
71
+ `onModuleInit` + every hook is attached), so the boot tick drains against the
72
+ fully-wired pipeline. The tick interval start moved with it (both passes live
73
+ in `EventScheduler.start()`). Regression tests assert the hook surface is
74
+ `onApplicationBootstrap` (not `onModuleInit`) and that a boot-materialised
75
+ scheduled event reaches a subscriber attached after init.
76
+ - **#473 — `subsystem install observability` never wired `ObservabilityModule`.**
77
+ The install added `observability` to `subsystems.install` but the barrel
78
+ emitter had no composer, so `ObservabilityModule.forRoot` was never emitted
79
+ into `SUBSYSTEM_MODULES` — consumers hand-wired it in `app.module.ts` (like
80
+ Auth). **Fix:** added an `observability` composer. It emits
81
+ `ObservabilityModule.forRoot()` (no `backend`/`multiTenant` — a combiner per
82
+ ADR-025 owns no durable state), imported package- or vendored-aware, and is
83
+ ordered LAST in `COMPOSABLE_ORDER` so its `forRoot` registers AFTER the
84
+ events/jobs/bridge/integration read ports it composes via `@Optional()` DI.
85
+ The `observability.reporters` block (OBS-6) is threaded into `forRoot` only
86
+ when a reporter is `enabled: true` (off-by-default, mirroring the
87
+ `listen_notify` / `differ` clauses); the default install stays a bare
88
+ `ObservabilityModule.forRoot()`. Closes #473.
89
+
90
+ ### Tests
91
+
92
+ - `subsystem-barrel-generator` tests: observability composer coverage (both
93
+ modes, combiner ordering after the composed siblings, reporters threaded only
94
+ when enabled).
95
+ - **Subsystems smoke now asserts forRoot presence per installed subsystem** (not
96
+ just events' `eventRegistry`) — it installs observability too and fails if the
97
+ real generated barrel is missing any installed subsystem's `forRoot` or if
98
+ observability isn't ordered after the read ports. Both gap classes (the
99
+ scheduler threading and the missing observability wiring) survived because
100
+ nothing end-to-end checked per-subsystem wiring.
101
+
7
102
  ## [0.20.1] — 2026-06-06
8
103
 
9
104
  **Fix: the subsystems barrel never threaded `eventRegistry` into
@@ -1,6 +1,3 @@
1
- import {
2
- MissingTenantIdError
3
- } from "./chunk-T4BIIU5E.js";
4
1
  import {
5
2
  clampLimit,
6
3
  decodeKeysetCursor,
@@ -8,12 +5,15 @@ import {
8
5
  toJobRunSummary
9
6
  } from "./chunk-L3LZWWSX.js";
10
7
  import {
11
- JOBS_MULTI_TENANT,
12
- JOB_ORCHESTRATOR
13
- } from "./chunk-ZPL74UQN.js";
8
+ MissingTenantIdError
9
+ } from "./chunk-T4BIIU5E.js";
14
10
  import {
15
11
  jobRuns
16
12
  } from "./chunk-OKXZ63IA.js";
13
+ import {
14
+ JOBS_MULTI_TENANT,
15
+ JOB_ORCHESTRATOR
16
+ } from "./chunk-ZPL74UQN.js";
17
17
  import {
18
18
  DRIZZLE
19
19
  } from "./chunk-U64T4YZE.js";
@@ -198,4 +198,4 @@ DrizzleJobRunService = __decorateClass([
198
198
  export {
199
199
  DrizzleJobRunService
200
200
  };
201
- //# sourceMappingURL=chunk-VNBC3VXM.js.map
201
+ //# sourceMappingURL=chunk-3A34R6CI.js.map
@@ -1,9 +1,9 @@
1
- import {
2
- WebhookChangeSource
3
- } from "./chunk-TIZXQU26.js";
4
1
  import {
5
2
  PollChangeSource
6
3
  } from "./chunk-4MF3HKJA.js";
4
+ import {
5
+ WebhookChangeSource
6
+ } from "./chunk-TIZXQU26.js";
7
7
 
8
8
  // runtime/subsystems/integration/build-change-source.ts
9
9
  function buildChangeSource(cfg, fetch, middlewares = []) {
@@ -26,4 +26,4 @@ function buildChangeSource(cfg, fetch, middlewares = []) {
26
26
  export {
27
27
  buildChangeSource
28
28
  };
29
- //# sourceMappingURL=chunk-I6UXRJ3Q.js.map
29
+ //# sourceMappingURL=chunk-43SBT72G.js.map
@@ -1,12 +1,12 @@
1
- import {
2
- STORAGE
3
- } from "./chunk-NYBCQZC7.js";
4
1
  import {
5
2
  LocalStorageBackend
6
3
  } from "./chunk-JWNHNUYL.js";
7
4
  import {
8
5
  MemoryStorageBackend
9
6
  } from "./chunk-3SZFUTXE.js";
7
+ import {
8
+ STORAGE
9
+ } from "./chunk-NYBCQZC7.js";
10
10
  import {
11
11
  __decorateClass
12
12
  } from "./chunk-2E224ZSN.js";
@@ -37,4 +37,4 @@ StorageModule = __decorateClass([
37
37
  export {
38
38
  StorageModule
39
39
  };
40
- //# sourceMappingURL=chunk-BK5ICA2F.js.map
40
+ //# sourceMappingURL=chunk-4MVGAMUA.js.map
@@ -120,7 +120,12 @@ var UiMetadataSchema = z.object({
120
120
  ui_visible: z.boolean().optional(),
121
121
  ui_placeholder: z.string().optional(),
122
122
  ui_help: z.string().optional(),
123
- ui_format: z.record(z.unknown()).optional()
123
+ ui_format: z.record(z.unknown()).optional(),
124
+ // Key-field curation (ADR-040): curated/displayed fields that drive card &
125
+ // preview surfaces. Names mirror qField / EAV `field_definitions`
126
+ // (`isKeyField` / `keyFieldOrder`) — one metadata vocabulary, multiple homes.
127
+ ui_key_field: z.boolean().optional(),
128
+ ui_key_field_order: z.number().optional()
124
129
  });
125
130
  var BaseFieldSchema = z.object({
126
131
  type: FieldTypeSchema,
@@ -1371,6 +1376,22 @@ function detectYamlType(filePath) {
1371
1376
  }
1372
1377
 
1373
1378
  // src/parser/load-entities.ts
1379
+ function parseUiMetadata(fieldDef) {
1380
+ return {
1381
+ label: fieldDef.ui_label,
1382
+ type: fieldDef.ui_type,
1383
+ importance: fieldDef.ui_importance,
1384
+ group: fieldDef.ui_group,
1385
+ sortable: fieldDef.ui_sortable,
1386
+ filterable: fieldDef.ui_filterable,
1387
+ visible: fieldDef.ui_visible,
1388
+ placeholder: fieldDef.ui_placeholder,
1389
+ help: fieldDef.ui_help,
1390
+ format: fieldDef.ui_format,
1391
+ keyField: fieldDef.ui_key_field,
1392
+ keyFieldOrder: fieldDef.ui_key_field_order
1393
+ };
1394
+ }
1374
1395
  function transformToEntity(result) {
1375
1396
  const { definition, filePath } = result;
1376
1397
  const queries = definition.queries?.filter((q) => "by" in q).map((q) => ({
@@ -1413,15 +1434,7 @@ function transformToEntity(result) {
1413
1434
  min: fieldDef.min,
1414
1435
  max: fieldDef.max
1415
1436
  },
1416
- ui: {
1417
- label: fieldDef.ui_label,
1418
- type: fieldDef.ui_type,
1419
- importance: fieldDef.ui_importance,
1420
- group: fieldDef.ui_group,
1421
- sortable: fieldDef.ui_sortable,
1422
- filterable: fieldDef.ui_filterable,
1423
- visible: fieldDef.ui_visible
1424
- }
1437
+ ui: parseUiMetadata(fieldDef)
1425
1438
  };
1426
1439
  entity.fields.set(name, field);
1427
1440
  }
@@ -1614,15 +1627,7 @@ function transformToRelationshipDefinition(result) {
1614
1627
  min: fieldDef.min,
1615
1628
  max: fieldDef.max
1616
1629
  },
1617
- ui: {
1618
- label: fieldDef.ui_label,
1619
- type: fieldDef.ui_type,
1620
- importance: fieldDef.ui_importance,
1621
- group: fieldDef.ui_group,
1622
- sortable: fieldDef.ui_sortable,
1623
- filterable: fieldDef.ui_filterable,
1624
- visible: fieldDef.ui_visible
1625
- }
1630
+ ui: parseUiMetadata(fieldDef)
1626
1631
  };
1627
1632
  fields.set(name, field);
1628
1633
  }
@@ -4066,6 +4071,109 @@ registerLibraryPattern(KnowledgePattern);
4066
4071
  registerLibraryPattern(MetadataPattern);
4067
4072
  registerLibraryPattern(JunctionPattern);
4068
4073
 
4074
+ // src/emitters/frontend/field-meta.ts
4075
+ var CAMEL = (s) => s.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
4076
+ function formatLabel(fieldName) {
4077
+ return fieldName.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
4078
+ }
4079
+ function inferUiType(field) {
4080
+ if (field.ui.type) return field.ui.type;
4081
+ if (Array.isArray(field.choices) && field.choices.length > 0) return "enum";
4082
+ if (field.foreignKey) return "reference";
4083
+ const nameLower = field.name.toLowerCase();
4084
+ if (nameLower.includes("email")) return "email";
4085
+ if (nameLower.includes("url") || nameLower.includes("website")) return "url";
4086
+ if (nameLower.includes("password")) return "password";
4087
+ if (nameLower.includes("price") || nameLower.includes("amount") || nameLower.includes("cost") || nameLower.includes("value") || nameLower.includes("revenue")) {
4088
+ return "money";
4089
+ }
4090
+ if (nameLower.includes("percent") || nameLower.includes("rate")) {
4091
+ return "percentage";
4092
+ }
4093
+ switch (field.type) {
4094
+ case "string":
4095
+ return field.constraints.maxLength && field.constraints.maxLength > 500 ? "textarea" : "text";
4096
+ case "integer":
4097
+ case "decimal":
4098
+ return "number";
4099
+ case "boolean":
4100
+ return "boolean";
4101
+ case "uuid":
4102
+ return "text";
4103
+ case "date":
4104
+ return "date";
4105
+ case "datetime":
4106
+ return "datetime";
4107
+ case "json":
4108
+ return "json";
4109
+ default:
4110
+ return "text";
4111
+ }
4112
+ }
4113
+ function inferUiImportance(field) {
4114
+ if (field.ui.importance) return field.ui.importance;
4115
+ const nameLower = field.name.toLowerCase();
4116
+ if (["id", "created_at", "updated_at", "deleted_at"].includes(nameLower)) {
4117
+ return "tertiary";
4118
+ }
4119
+ if (field.foreignKey && nameLower.endsWith("_id")) return "secondary";
4120
+ if (field.required) return "primary";
4121
+ if (nameLower.includes("name") || nameLower.includes("title")) return "primary";
4122
+ return "secondary";
4123
+ }
4124
+ function isEntityRefField(field) {
4125
+ if (field.type === "entity_ref") return true;
4126
+ return field.name.endsWith("_entity_type") || field.name.endsWith("_entity_id");
4127
+ }
4128
+ function deriveFieldMeta(field, defaults = {}) {
4129
+ const hasChoices = Array.isArray(field.choices) && field.choices.length > 0;
4130
+ const meta = {
4131
+ field: CAMEL(field.name),
4132
+ label: field.ui.label ?? formatLabel(field.name),
4133
+ type: inferUiType(field),
4134
+ importance: inferUiImportance(field),
4135
+ sortable: field.ui.sortable ?? false,
4136
+ filterable: field.ui.filterable ?? false
4137
+ };
4138
+ const group = field.ui.group ?? defaults.group;
4139
+ if (group !== void 0) meta.group = group;
4140
+ if (field.ui.visible !== void 0) meta.visible = field.ui.visible;
4141
+ if (field.ui.placeholder !== void 0) meta.placeholder = field.ui.placeholder;
4142
+ if (field.ui.help !== void 0) meta.help = field.ui.help;
4143
+ if (field.ui.format !== void 0) meta.format = field.ui.format;
4144
+ if (hasChoices) meta.choices = field.choices;
4145
+ if (field.foreignKey) meta.reference = field.foreignKey.table;
4146
+ if (field.ui.keyField) {
4147
+ meta.isKeyField = true;
4148
+ if (field.ui.keyFieldOrder !== void 0) {
4149
+ meta.keyFieldOrder = field.ui.keyFieldOrder;
4150
+ }
4151
+ }
4152
+ return meta;
4153
+ }
4154
+ var EXTERNAL_SYNC_GROUP = "external_sync";
4155
+ var EXTERNAL_SYNC_FIELDS = /* @__PURE__ */ new Set([
4156
+ "external_id",
4157
+ "provider",
4158
+ "provider_metadata"
4159
+ ]);
4160
+ function hasExternalSyncShape(fieldNames) {
4161
+ const names = new Set(fieldNames);
4162
+ return names.has("external_id") && names.has("provider");
4163
+ }
4164
+ var EAV_DATA_TYPE_TO_FIELD_TYPE = {
4165
+ string: "text",
4166
+ integer: "number",
4167
+ decimal: "number",
4168
+ boolean: "boolean",
4169
+ date: "date",
4170
+ datetime: "datetime",
4171
+ json: "json",
4172
+ reference: "reference",
4173
+ picklist: "enum",
4174
+ multipicklist: "enum"
4175
+ };
4176
+
4069
4177
  // src/index.ts
4070
4178
  async function analyzeDomain(entitiesDir, relationshipsOrOptions) {
4071
4179
  const opts = typeof relationshipsOrOptions === "string" ? { relationshipsDir: relationshipsOrOptions } : relationshipsOrOptions ?? {};
@@ -4186,7 +4294,13 @@ export {
4186
4294
  KnowledgePattern,
4187
4295
  MetadataPattern,
4188
4296
  IntegratedPattern,
4297
+ isEntityRefField,
4298
+ deriveFieldMeta,
4299
+ EXTERNAL_SYNC_GROUP,
4300
+ EXTERNAL_SYNC_FIELDS,
4301
+ hasExternalSyncShape,
4302
+ EAV_DATA_TYPE_TO_FIELD_TYPE,
4189
4303
  analyzeDomain,
4190
4304
  validateEntities
4191
4305
  };
4192
- //# sourceMappingURL=chunk-KK5A7B2T.js.map
4306
+ //# sourceMappingURL=chunk-524YKITE.js.map