clivly 0.8.0 → 0.9.1

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 (112) hide show
  1. package/README.md +330 -134
  2. package/core-drizzle.cjs +3 -1
  3. package/core-drizzle.d.cts +3 -2
  4. package/core-drizzle.d.mts +3 -2
  5. package/core-drizzle.mjs +2 -2
  6. package/core-entity-config.cjs +2 -1
  7. package/core-entity-config.d.cts +2 -2
  8. package/core-entity-config.d.mts +2 -2
  9. package/core-entity-config.mjs +2 -2
  10. package/core-entity-heuristics.d.cts +3 -2
  11. package/core-entity-heuristics.d.mts +3 -2
  12. package/core-mapping-form.d.cts +1 -1
  13. package/core-mapping-form.d.mts +1 -1
  14. package/core-mappings-config.cjs +1 -1
  15. package/core-mappings-config.d.cts +1 -1
  16. package/core-mappings-config.d.mts +1 -1
  17. package/core-mappings-config.mjs +1 -1
  18. package/core-sync-engine.cjs +1 -1
  19. package/core-sync-engine.d.cts +1 -1
  20. package/core-sync-engine.d.mts +1 -1
  21. package/core-sync-engine.mjs +1 -1
  22. package/core-view-compiler.cjs +2 -1
  23. package/core-view-compiler.d.cts +2 -2
  24. package/core-view-compiler.d.mts +2 -2
  25. package/core-view-compiler.mjs +2 -2
  26. package/core.cjs +21 -5
  27. package/core.d.cts +7 -6
  28. package/core.d.mts +7 -6
  29. package/core.mjs +7 -6
  30. package/drizzle-3kvhkwO7.mjs +110 -0
  31. package/drizzle-DooDUGqO.d.mts +41 -0
  32. package/drizzle-bfjVzYR6.cjs +127 -0
  33. package/drizzle-jz0lrAgl.d.cts +41 -0
  34. package/drizzle.cjs +12 -40
  35. package/drizzle.d.cts +3 -11
  36. package/drizzle.d.mts +3 -11
  37. package/drizzle.mjs +12 -41
  38. package/entity-config-D08zAeFY.mjs +657 -0
  39. package/{entity-config-DoUCXtq5.d.cts → entity-config-fKQhimtD.d.cts} +263 -2
  40. package/{entity-config-DoUCXtq5.d.mts → entity-config-fKQhimtD.d.mts} +263 -2
  41. package/entity-config-nuXge6rY.cjs +778 -0
  42. package/index.cjs +768 -122
  43. package/index.d.cts +12 -0
  44. package/index.d.mts +12 -0
  45. package/index.mjs +769 -123
  46. package/internal-BGVUG312.mjs +68 -0
  47. package/internal-BLCK81kB.d.mts +72 -0
  48. package/internal-C-YBW2DB.d.cts +72 -0
  49. package/internal-D4HDi2GC.cjs +97 -0
  50. package/internal-drizzle.cjs +3 -1
  51. package/internal-drizzle.d.cts +2 -2
  52. package/internal-drizzle.d.mts +2 -2
  53. package/internal-drizzle.mjs +2 -2
  54. package/internal-entity-config.cjs +2 -1
  55. package/internal-entity-config.d.cts +2 -2
  56. package/internal-entity-config.d.mts +2 -2
  57. package/internal-entity-config.mjs +2 -2
  58. package/internal-entity-heuristics.cjs +28 -8
  59. package/internal-entity-heuristics.d.cts +2 -12
  60. package/internal-entity-heuristics.d.mts +2 -12
  61. package/internal-entity-heuristics.mjs +28 -8
  62. package/internal-mapping-form.d.cts +1 -1
  63. package/internal-mapping-form.d.mts +1 -1
  64. package/internal-mappings-config.cjs +1 -1
  65. package/internal-mappings-config.d.cts +1 -1
  66. package/internal-mappings-config.d.mts +1 -1
  67. package/internal-mappings-config.mjs +1 -1
  68. package/internal-sync-engine.cjs +1 -1
  69. package/internal-sync-engine.d.cts +1 -1
  70. package/internal-sync-engine.d.mts +1 -1
  71. package/internal-sync-engine.mjs +1 -1
  72. package/internal-view-compiler.cjs +2 -1
  73. package/internal-view-compiler.d.cts +2 -2
  74. package/internal-view-compiler.d.mts +2 -2
  75. package/internal-view-compiler.mjs +2 -2
  76. package/internal.cjs +21 -4
  77. package/internal.d.cts +7 -6
  78. package/internal.d.mts +7 -6
  79. package/internal.mjs +7 -5
  80. package/{mapping-form-D93lhHEc.d.mts → mapping-form-DhY0iFmN.d.cts} +1 -1
  81. package/{mapping-form-lfyEE7EJ.d.cts → mapping-form-Du36VZr1.d.mts} +1 -1
  82. package/{mappings-config-DsUa7-1w.d.mts → mappings-config-B1qNM8VL.d.cts} +7 -1
  83. package/{mappings-config-XmzB4dag.d.cts → mappings-config-BChZsany.d.mts} +7 -1
  84. package/{mappings-config-BsRADNRv.cjs → mappings-config-C8ynKmDK.cjs} +32 -6
  85. package/{mappings-config-Dbgxx3Nv.mjs → mappings-config-DNaYGyKN.mjs} +32 -6
  86. package/namespace-probe-BkUs8raG.d.mts +381 -0
  87. package/namespace-probe-aRFmpU85.d.cts +381 -0
  88. package/package.json +1 -1
  89. package/{entity-config-va2bkH5o.mjs → projection-C5244vGa.cjs} +130 -309
  90. package/{entity-config-D87rV-tE.cjs → projection-D7xmQP4S.mjs} +60 -381
  91. package/{sdk-iqOXeWIp.cjs → sdk-Bj-ZDf4u.cjs} +126 -28
  92. package/{sdk-C6WANW8M.mjs → sdk-BvRD2jAp.mjs} +126 -28
  93. package/sdk.cjs +2 -2
  94. package/sdk.d.cts +36 -1
  95. package/sdk.d.mts +36 -1
  96. package/sdk.mjs +2 -2
  97. package/{sync-engine-DGk_AeHJ.d.mts → sync-engine-DHQ7rXZe.d.mts} +2 -2
  98. package/{sync-engine-B7QIbXro.d.cts → sync-engine-DiPjH53O.d.cts} +2 -2
  99. package/{sync-engine-Do5ru3WF.mjs → sync-engine-SuxSzbZ4.mjs} +9 -2
  100. package/{sync-engine-CzEbpQGv.cjs → sync-engine-abE94g6X.cjs} +9 -2
  101. package/{view-compiler-BIwvm-o2.cjs → view-compiler-Blu4OXJ7.cjs} +103 -12
  102. package/{view-compiler-ChWr_Lml.mjs → view-compiler-CQx8TRrW.mjs} +98 -13
  103. package/{view-compiler-BWz0sGdm.d.cts → view-compiler-CcUwzZut.d.mts} +12 -2
  104. package/{view-compiler-Bn_EJJMO.d.mts → view-compiler-DqAdVxLq.d.cts} +12 -2
  105. package/vite.d.cts +1 -1
  106. package/vite.d.mts +1 -1
  107. package/drizzle-B89tLo4T.mjs +0 -31
  108. package/drizzle-CFOr9dU9.d.mts +0 -20
  109. package/drizzle-DiReZf6d.cjs +0 -36
  110. package/drizzle-DmeKSqeF.d.cts +0 -20
  111. package/types-CsL0rFYh.d.cts +0 -155
  112. package/types-CsL0rFYh.d.mts +0 -155
@@ -2120,6 +2120,126 @@ interface ZodReadonly<T extends SomeType = $ZodType> extends _ZodType<$ZodReadon
2120
2120
  }
2121
2121
  declare const ZodReadonly: $constructor<ZodReadonly>;
2122
2122
  //#endregion
2123
+ //#region ../core/src/projection.d.ts
2124
+ /**
2125
+ * Projection-backed custom mappings — one custom object derived from a base
2126
+ * table plus explicit joins.
2127
+ *
2128
+ * A projection is deliberately narrow: equality joins only, direct column
2129
+ * bindings only, no expressions and no aggregation. Everything a user can
2130
+ * express here compiles to a single read-only view whose `id` column is
2131
+ * provably unique per row, which is what lets the sync engine consume it
2132
+ * unchanged.
2133
+ *
2134
+ * Refs address tables symbolically: `"base"` for the base table, or a join's
2135
+ * `key`. Raw table names are never accepted in a ref, so a projection can
2136
+ * never reach a table it did not declare.
2137
+ */
2138
+ /** The reserved ref name for the projection's base table. */
2139
+ declare const BASE_REF = "base";
2140
+ declare const projectionRefSchema: ZodObject<{
2141
+ table: ZodString;
2142
+ column: ZodString;
2143
+ }, $strict>;
2144
+ type ProjectionRef = output<typeof projectionRefSchema>;
2145
+ declare const projectionJoinSchema: ZodObject<{
2146
+ key: ZodString;
2147
+ table: ZodString;
2148
+ type: ZodEnum<{
2149
+ inner: "inner";
2150
+ left: "left";
2151
+ }>;
2152
+ on: ZodArray<ZodObject<{
2153
+ left: ZodObject<{
2154
+ table: ZodString;
2155
+ column: ZodString;
2156
+ }, $strict>;
2157
+ op: ZodLiteral<"eq">;
2158
+ right: ZodObject<{
2159
+ table: ZodString;
2160
+ column: ZodString;
2161
+ }, $strict>;
2162
+ }, $strict>>;
2163
+ }, $strict>;
2164
+ type ProjectionJoin = output<typeof projectionJoinSchema>;
2165
+ declare const projectionFieldBindingSchema: ZodObject<{
2166
+ from: ZodObject<{
2167
+ table: ZodString;
2168
+ column: ZodString;
2169
+ }, $strict>;
2170
+ }, $strict>;
2171
+ type ProjectionFieldBinding = output<typeof projectionFieldBindingSchema>;
2172
+ declare const projectionIdentitySchema: ZodUnion<readonly [ZodObject<{
2173
+ kind: ZodLiteral<"base_pk">;
2174
+ column: ZodOptional<ZodString>;
2175
+ }, $strict>, ZodObject<{
2176
+ kind: ZodLiteral<"column">;
2177
+ from: ZodObject<{
2178
+ table: ZodString;
2179
+ column: ZodString;
2180
+ }, $strict>;
2181
+ }, $strict>, ZodObject<{
2182
+ kind: ZodLiteral<"composite">;
2183
+ parts: ZodArray<ZodObject<{
2184
+ table: ZodString;
2185
+ column: ZodString;
2186
+ }, $strict>>;
2187
+ }, $strict>]>;
2188
+ type ProjectionIdentity = output<typeof projectionIdentitySchema>;
2189
+ declare const projectionSchema: ZodObject<{
2190
+ version: ZodLiteral<1>;
2191
+ kind: ZodLiteral<"projection">;
2192
+ entityKey: ZodString;
2193
+ baseTable: ZodString;
2194
+ joins: ZodArray<ZodObject<{
2195
+ key: ZodString;
2196
+ table: ZodString;
2197
+ type: ZodEnum<{
2198
+ inner: "inner";
2199
+ left: "left";
2200
+ }>;
2201
+ on: ZodArray<ZodObject<{
2202
+ left: ZodObject<{
2203
+ table: ZodString;
2204
+ column: ZodString;
2205
+ }, $strict>;
2206
+ op: ZodLiteral<"eq">;
2207
+ right: ZodObject<{
2208
+ table: ZodString;
2209
+ column: ZodString;
2210
+ }, $strict>;
2211
+ }, $strict>>;
2212
+ }, $strict>>;
2213
+ fieldBindings: ZodRecord<ZodString, ZodObject<{
2214
+ from: ZodObject<{
2215
+ table: ZodString;
2216
+ column: ZodString;
2217
+ }, $strict>;
2218
+ }, $strict>>;
2219
+ identity: ZodUnion<readonly [ZodObject<{
2220
+ kind: ZodLiteral<"base_pk">;
2221
+ column: ZodOptional<ZodString>;
2222
+ }, $strict>, ZodObject<{
2223
+ kind: ZodLiteral<"column">;
2224
+ from: ZodObject<{
2225
+ table: ZodString;
2226
+ column: ZodString;
2227
+ }, $strict>;
2228
+ }, $strict>, ZodObject<{
2229
+ kind: ZodLiteral<"composite">;
2230
+ parts: ZodArray<ZodObject<{
2231
+ table: ZodString;
2232
+ column: ZodString;
2233
+ }, $strict>>;
2234
+ }, $strict>]>;
2235
+ }, $strict>;
2236
+ type ProjectionMapping = output<typeof projectionSchema>;
2237
+ /**
2238
+ * Every column ref an identity depends on. `basePkColumn` is the base table's
2239
+ * discovered PK, used only when a `base_pk` identity omits an explicit column.
2240
+ */
2241
+ declare function identityRefs(identity: ProjectionIdentity, basePkColumn: string): ProjectionRef[];
2242
+ //#endregion
2123
2243
  //#region ../core/src/entity-config.d.ts
2124
2244
  /**
2125
2245
  * Entity Config v2 — the declarative contract that turns Clivly's "schema-aware"
@@ -2312,6 +2432,53 @@ declare const entitySchema: ZodObject<{
2312
2432
  }, $strict>]>;
2313
2433
  }, $strict>>>;
2314
2434
  targetObjectTypeId: ZodOptional<ZodString>;
2435
+ projection: ZodOptional<ZodObject<{
2436
+ version: ZodLiteral<1>;
2437
+ kind: ZodLiteral<"projection">;
2438
+ entityKey: ZodString;
2439
+ baseTable: ZodString;
2440
+ joins: ZodArray<ZodObject<{
2441
+ key: ZodString;
2442
+ table: ZodString;
2443
+ type: ZodEnum<{
2444
+ inner: "inner";
2445
+ left: "left";
2446
+ }>;
2447
+ on: ZodArray<ZodObject<{
2448
+ left: ZodObject<{
2449
+ table: ZodString;
2450
+ column: ZodString;
2451
+ }, $strict>;
2452
+ op: ZodLiteral<"eq">;
2453
+ right: ZodObject<{
2454
+ table: ZodString;
2455
+ column: ZodString;
2456
+ }, $strict>;
2457
+ }, $strict>>;
2458
+ }, $strict>>;
2459
+ fieldBindings: ZodRecord<ZodString, ZodObject<{
2460
+ from: ZodObject<{
2461
+ table: ZodString;
2462
+ column: ZodString;
2463
+ }, $strict>;
2464
+ }, $strict>>;
2465
+ identity: ZodUnion<readonly [ZodObject<{
2466
+ kind: ZodLiteral<"base_pk">;
2467
+ column: ZodOptional<ZodString>;
2468
+ }, $strict>, ZodObject<{
2469
+ kind: ZodLiteral<"column">;
2470
+ from: ZodObject<{
2471
+ table: ZodString;
2472
+ column: ZodString;
2473
+ }, $strict>;
2474
+ }, $strict>, ZodObject<{
2475
+ kind: ZodLiteral<"composite">;
2476
+ parts: ZodArray<ZodObject<{
2477
+ table: ZodString;
2478
+ column: ZodString;
2479
+ }, $strict>>;
2480
+ }, $strict>]>;
2481
+ }, $strict>>;
2315
2482
  }, $strict>;
2316
2483
  type ClivlyEntityConfig = output<typeof entitySchema>;
2317
2484
  declare const entitiesConfigSchema: ZodObject<{
@@ -2360,9 +2527,71 @@ declare const entitiesConfigSchema: ZodObject<{
2360
2527
  }, $strict>]>;
2361
2528
  }, $strict>>>;
2362
2529
  targetObjectTypeId: ZodOptional<ZodString>;
2530
+ projection: ZodOptional<ZodObject<{
2531
+ version: ZodLiteral<1>;
2532
+ kind: ZodLiteral<"projection">;
2533
+ entityKey: ZodString;
2534
+ baseTable: ZodString;
2535
+ joins: ZodArray<ZodObject<{
2536
+ key: ZodString;
2537
+ table: ZodString;
2538
+ type: ZodEnum<{
2539
+ inner: "inner";
2540
+ left: "left";
2541
+ }>;
2542
+ on: ZodArray<ZodObject<{
2543
+ left: ZodObject<{
2544
+ table: ZodString;
2545
+ column: ZodString;
2546
+ }, $strict>;
2547
+ op: ZodLiteral<"eq">;
2548
+ right: ZodObject<{
2549
+ table: ZodString;
2550
+ column: ZodString;
2551
+ }, $strict>;
2552
+ }, $strict>>;
2553
+ }, $strict>>;
2554
+ fieldBindings: ZodRecord<ZodString, ZodObject<{
2555
+ from: ZodObject<{
2556
+ table: ZodString;
2557
+ column: ZodString;
2558
+ }, $strict>;
2559
+ }, $strict>>;
2560
+ identity: ZodUnion<readonly [ZodObject<{
2561
+ kind: ZodLiteral<"base_pk">;
2562
+ column: ZodOptional<ZodString>;
2563
+ }, $strict>, ZodObject<{
2564
+ kind: ZodLiteral<"column">;
2565
+ from: ZodObject<{
2566
+ table: ZodString;
2567
+ column: ZodString;
2568
+ }, $strict>;
2569
+ }, $strict>, ZodObject<{
2570
+ kind: ZodLiteral<"composite">;
2571
+ parts: ZodArray<ZodObject<{
2572
+ table: ZodString;
2573
+ column: ZodString;
2574
+ }, $strict>>;
2575
+ }, $strict>]>;
2576
+ }, $strict>>;
2363
2577
  }, $strict>>;
2364
2578
  }, $strict>;
2365
2579
  type ClivlyEntitiesConfig = output<typeof entitiesConfigSchema>;
2580
+ /**
2581
+ * What an author may hand to `defineClivlyConfig`. Identical to
2582
+ * `ClivlyEntityConfig` except that a projection entity may omit `fields` —
2583
+ * it is derived from `projection.fieldBindings`. Without a projection `fields`
2584
+ * stays required, so the looser input never weakens the ordinary case.
2585
+ */
2586
+ type ClivlyEntityConfigInput = (ClivlyEntityConfig & {
2587
+ projection?: undefined;
2588
+ }) | (Omit<ClivlyEntityConfig, "fields"> & {
2589
+ fields?: Record<string, string>;
2590
+ projection: ProjectionMapping;
2591
+ });
2592
+ type ClivlyEntitiesConfigInput = Omit<ClivlyEntitiesConfig, "entities"> & {
2593
+ entities: Record<string, ClivlyEntityConfigInput>;
2594
+ };
2366
2595
  /** Thrown by `defineClivlyConfig({ strict: true })` on non-canonical field keys. */
2367
2596
  declare class ClivlyConfigError extends Error {
2368
2597
  readonly issues: ConfigValidationError[];
@@ -2380,18 +2609,50 @@ declare class ClivlyConfigError extends Error {
2380
2609
  * a `ClivlyConfigError` instead. Does NOT validate against the host schema — that
2381
2610
  * needs the discovered schema; see `validateEntitiesConfig`.
2382
2611
  */
2383
- declare function defineClivlyConfig(config: ClivlyEntitiesConfig, options?: {
2612
+ /**
2613
+ * The `fields` entry a projection binding implies, qualified as `ref.column`.
2614
+ * Qualified rather than bare: two bindings can pull the same column name from
2615
+ * different tables (`cl.full_name` and `adv.full_name`), which a bare column
2616
+ * name cannot tell apart.
2617
+ */
2618
+ declare function projectionFields(projection: ProjectionMapping): Record<string, string>;
2619
+ declare function defineClivlyConfig(config: ClivlyEntitiesConfigInput, options?: {
2384
2620
  strict?: boolean;
2385
2621
  onWarn?: (message: string) => void;
2386
2622
  }): ClivlyEntitiesConfig;
2623
+ /**
2624
+ * Per-column metadata a host reports for a discovered table. Structurally
2625
+ * identical to the SDK's `DiscoveredColumn` and to `entity-heuristics.ts`'s
2626
+ * (currently separate) `DiscoveredColumnMeta` — a later task converges that
2627
+ * module onto this one. Every field is optional: a v1 host reports column
2628
+ * names only.
2629
+ */
2630
+ interface DiscoveredColumnMeta {
2631
+ isForeignKey?: boolean;
2632
+ isPrimaryKey?: boolean;
2633
+ name: string;
2634
+ nullable?: boolean;
2635
+ references?: {
2636
+ table: string;
2637
+ column: string;
2638
+ };
2639
+ type?: string;
2640
+ }
2387
2641
  /**
2388
2642
  * A host table the SDK reported for discovery. Structurally identical to the
2389
2643
  * SDK's `DiscoveredTable`; duplicated here to keep `@clivly/core` free of an
2390
2644
  * SDK dependency (core is the base contract SDK builds on).
2645
+ *
2646
+ * `columns` is the stable v1 contract. `columnsMeta` and `uniqueConstraints`
2647
+ * are the enrichment projection mappings require — absent on v1 hosts, which
2648
+ * is why projection validation fails closed rather than assuming "no keys".
2391
2649
  */
2392
2650
  interface DiscoveredSchemaTable {
2393
2651
  columns: string[];
2652
+ columnsMeta?: DiscoveredColumnMeta[];
2394
2653
  name: string;
2654
+ /** Every unique key as DB column names; PKs included. Absent = unknown. */
2655
+ uniqueConstraints?: string[][];
2395
2656
  }
2396
2657
  interface ConfigValidationError {
2397
2658
  message: string;
@@ -2413,4 +2674,4 @@ interface ConfigValidationResult {
2413
2674
  */
2414
2675
  declare function validateEntitiesConfig(config: ClivlyEntitiesConfig, schema: DiscoveredSchemaTable[]): ConfigValidationResult;
2415
2676
  //#endregion
2416
- export { validateEntitiesConfig as C, relationshipsSchema as S, RelationshipsMap as _, ClivlyEntitiesConfig as a, filterSchema as b, ConfigValidationResult as c, FilterExpr as d, FilterValue as f, RelationshipVia as g, RelationshipSpec as h, ClivlyConfigError as i, CrmConcept as l, MaterializingConcept as m, CRM_CONCEPTS as n, ClivlyEntityConfig as o, MATERIALIZING_CONCEPTS as p, CUSTOM_CONCEPT as r, ConfigValidationError as s, CANONICAL_FIELDS as t, DiscoveredSchemaTable as u, defineClivlyConfig as v, relationshipSchema as x, entitiesConfigSchema as y };
2677
+ export { ProjectionIdentity as A, filterSchema as C, validateEntitiesConfig as D, relationshipsSchema as E, projectionSchema as F, ProjectionMapping as M, ProjectionRef as N, BASE_REF as O, identityRefs as P, entitiesConfigSchema as S, relationshipSchema as T, MaterializingConcept as _, ClivlyEntitiesConfig as a, RelationshipsMap as b, ClivlyEntityConfigInput as c, CrmConcept as d, DiscoveredColumnMeta as f, MATERIALIZING_CONCEPTS as g, FilterValue as h, ClivlyConfigError as i, ProjectionJoin as j, ProjectionFieldBinding as k, ConfigValidationError as l, FilterExpr as m, CRM_CONCEPTS as n, ClivlyEntitiesConfigInput as o, DiscoveredSchemaTable as p, CUSTOM_CONCEPT as r, ClivlyEntityConfig as s, CANONICAL_FIELDS as t, ConfigValidationResult as u, RelationshipSpec as v, projectionFields as w, defineClivlyConfig as x, RelationshipVia as y };
@@ -2120,6 +2120,126 @@ interface ZodReadonly<T extends SomeType = $ZodType> extends _ZodType<$ZodReadon
2120
2120
  }
2121
2121
  declare const ZodReadonly: $constructor<ZodReadonly>;
2122
2122
  //#endregion
2123
+ //#region ../core/src/projection.d.ts
2124
+ /**
2125
+ * Projection-backed custom mappings — one custom object derived from a base
2126
+ * table plus explicit joins.
2127
+ *
2128
+ * A projection is deliberately narrow: equality joins only, direct column
2129
+ * bindings only, no expressions and no aggregation. Everything a user can
2130
+ * express here compiles to a single read-only view whose `id` column is
2131
+ * provably unique per row, which is what lets the sync engine consume it
2132
+ * unchanged.
2133
+ *
2134
+ * Refs address tables symbolically: `"base"` for the base table, or a join's
2135
+ * `key`. Raw table names are never accepted in a ref, so a projection can
2136
+ * never reach a table it did not declare.
2137
+ */
2138
+ /** The reserved ref name for the projection's base table. */
2139
+ declare const BASE_REF = "base";
2140
+ declare const projectionRefSchema: ZodObject<{
2141
+ table: ZodString;
2142
+ column: ZodString;
2143
+ }, $strict>;
2144
+ type ProjectionRef = output<typeof projectionRefSchema>;
2145
+ declare const projectionJoinSchema: ZodObject<{
2146
+ key: ZodString;
2147
+ table: ZodString;
2148
+ type: ZodEnum<{
2149
+ inner: "inner";
2150
+ left: "left";
2151
+ }>;
2152
+ on: ZodArray<ZodObject<{
2153
+ left: ZodObject<{
2154
+ table: ZodString;
2155
+ column: ZodString;
2156
+ }, $strict>;
2157
+ op: ZodLiteral<"eq">;
2158
+ right: ZodObject<{
2159
+ table: ZodString;
2160
+ column: ZodString;
2161
+ }, $strict>;
2162
+ }, $strict>>;
2163
+ }, $strict>;
2164
+ type ProjectionJoin = output<typeof projectionJoinSchema>;
2165
+ declare const projectionFieldBindingSchema: ZodObject<{
2166
+ from: ZodObject<{
2167
+ table: ZodString;
2168
+ column: ZodString;
2169
+ }, $strict>;
2170
+ }, $strict>;
2171
+ type ProjectionFieldBinding = output<typeof projectionFieldBindingSchema>;
2172
+ declare const projectionIdentitySchema: ZodUnion<readonly [ZodObject<{
2173
+ kind: ZodLiteral<"base_pk">;
2174
+ column: ZodOptional<ZodString>;
2175
+ }, $strict>, ZodObject<{
2176
+ kind: ZodLiteral<"column">;
2177
+ from: ZodObject<{
2178
+ table: ZodString;
2179
+ column: ZodString;
2180
+ }, $strict>;
2181
+ }, $strict>, ZodObject<{
2182
+ kind: ZodLiteral<"composite">;
2183
+ parts: ZodArray<ZodObject<{
2184
+ table: ZodString;
2185
+ column: ZodString;
2186
+ }, $strict>>;
2187
+ }, $strict>]>;
2188
+ type ProjectionIdentity = output<typeof projectionIdentitySchema>;
2189
+ declare const projectionSchema: ZodObject<{
2190
+ version: ZodLiteral<1>;
2191
+ kind: ZodLiteral<"projection">;
2192
+ entityKey: ZodString;
2193
+ baseTable: ZodString;
2194
+ joins: ZodArray<ZodObject<{
2195
+ key: ZodString;
2196
+ table: ZodString;
2197
+ type: ZodEnum<{
2198
+ inner: "inner";
2199
+ left: "left";
2200
+ }>;
2201
+ on: ZodArray<ZodObject<{
2202
+ left: ZodObject<{
2203
+ table: ZodString;
2204
+ column: ZodString;
2205
+ }, $strict>;
2206
+ op: ZodLiteral<"eq">;
2207
+ right: ZodObject<{
2208
+ table: ZodString;
2209
+ column: ZodString;
2210
+ }, $strict>;
2211
+ }, $strict>>;
2212
+ }, $strict>>;
2213
+ fieldBindings: ZodRecord<ZodString, ZodObject<{
2214
+ from: ZodObject<{
2215
+ table: ZodString;
2216
+ column: ZodString;
2217
+ }, $strict>;
2218
+ }, $strict>>;
2219
+ identity: ZodUnion<readonly [ZodObject<{
2220
+ kind: ZodLiteral<"base_pk">;
2221
+ column: ZodOptional<ZodString>;
2222
+ }, $strict>, ZodObject<{
2223
+ kind: ZodLiteral<"column">;
2224
+ from: ZodObject<{
2225
+ table: ZodString;
2226
+ column: ZodString;
2227
+ }, $strict>;
2228
+ }, $strict>, ZodObject<{
2229
+ kind: ZodLiteral<"composite">;
2230
+ parts: ZodArray<ZodObject<{
2231
+ table: ZodString;
2232
+ column: ZodString;
2233
+ }, $strict>>;
2234
+ }, $strict>]>;
2235
+ }, $strict>;
2236
+ type ProjectionMapping = output<typeof projectionSchema>;
2237
+ /**
2238
+ * Every column ref an identity depends on. `basePkColumn` is the base table's
2239
+ * discovered PK, used only when a `base_pk` identity omits an explicit column.
2240
+ */
2241
+ declare function identityRefs(identity: ProjectionIdentity, basePkColumn: string): ProjectionRef[];
2242
+ //#endregion
2123
2243
  //#region ../core/src/entity-config.d.ts
2124
2244
  /**
2125
2245
  * Entity Config v2 — the declarative contract that turns Clivly's "schema-aware"
@@ -2312,6 +2432,53 @@ declare const entitySchema: ZodObject<{
2312
2432
  }, $strict>]>;
2313
2433
  }, $strict>>>;
2314
2434
  targetObjectTypeId: ZodOptional<ZodString>;
2435
+ projection: ZodOptional<ZodObject<{
2436
+ version: ZodLiteral<1>;
2437
+ kind: ZodLiteral<"projection">;
2438
+ entityKey: ZodString;
2439
+ baseTable: ZodString;
2440
+ joins: ZodArray<ZodObject<{
2441
+ key: ZodString;
2442
+ table: ZodString;
2443
+ type: ZodEnum<{
2444
+ inner: "inner";
2445
+ left: "left";
2446
+ }>;
2447
+ on: ZodArray<ZodObject<{
2448
+ left: ZodObject<{
2449
+ table: ZodString;
2450
+ column: ZodString;
2451
+ }, $strict>;
2452
+ op: ZodLiteral<"eq">;
2453
+ right: ZodObject<{
2454
+ table: ZodString;
2455
+ column: ZodString;
2456
+ }, $strict>;
2457
+ }, $strict>>;
2458
+ }, $strict>>;
2459
+ fieldBindings: ZodRecord<ZodString, ZodObject<{
2460
+ from: ZodObject<{
2461
+ table: ZodString;
2462
+ column: ZodString;
2463
+ }, $strict>;
2464
+ }, $strict>>;
2465
+ identity: ZodUnion<readonly [ZodObject<{
2466
+ kind: ZodLiteral<"base_pk">;
2467
+ column: ZodOptional<ZodString>;
2468
+ }, $strict>, ZodObject<{
2469
+ kind: ZodLiteral<"column">;
2470
+ from: ZodObject<{
2471
+ table: ZodString;
2472
+ column: ZodString;
2473
+ }, $strict>;
2474
+ }, $strict>, ZodObject<{
2475
+ kind: ZodLiteral<"composite">;
2476
+ parts: ZodArray<ZodObject<{
2477
+ table: ZodString;
2478
+ column: ZodString;
2479
+ }, $strict>>;
2480
+ }, $strict>]>;
2481
+ }, $strict>>;
2315
2482
  }, $strict>;
2316
2483
  type ClivlyEntityConfig = output<typeof entitySchema>;
2317
2484
  declare const entitiesConfigSchema: ZodObject<{
@@ -2360,9 +2527,71 @@ declare const entitiesConfigSchema: ZodObject<{
2360
2527
  }, $strict>]>;
2361
2528
  }, $strict>>>;
2362
2529
  targetObjectTypeId: ZodOptional<ZodString>;
2530
+ projection: ZodOptional<ZodObject<{
2531
+ version: ZodLiteral<1>;
2532
+ kind: ZodLiteral<"projection">;
2533
+ entityKey: ZodString;
2534
+ baseTable: ZodString;
2535
+ joins: ZodArray<ZodObject<{
2536
+ key: ZodString;
2537
+ table: ZodString;
2538
+ type: ZodEnum<{
2539
+ inner: "inner";
2540
+ left: "left";
2541
+ }>;
2542
+ on: ZodArray<ZodObject<{
2543
+ left: ZodObject<{
2544
+ table: ZodString;
2545
+ column: ZodString;
2546
+ }, $strict>;
2547
+ op: ZodLiteral<"eq">;
2548
+ right: ZodObject<{
2549
+ table: ZodString;
2550
+ column: ZodString;
2551
+ }, $strict>;
2552
+ }, $strict>>;
2553
+ }, $strict>>;
2554
+ fieldBindings: ZodRecord<ZodString, ZodObject<{
2555
+ from: ZodObject<{
2556
+ table: ZodString;
2557
+ column: ZodString;
2558
+ }, $strict>;
2559
+ }, $strict>>;
2560
+ identity: ZodUnion<readonly [ZodObject<{
2561
+ kind: ZodLiteral<"base_pk">;
2562
+ column: ZodOptional<ZodString>;
2563
+ }, $strict>, ZodObject<{
2564
+ kind: ZodLiteral<"column">;
2565
+ from: ZodObject<{
2566
+ table: ZodString;
2567
+ column: ZodString;
2568
+ }, $strict>;
2569
+ }, $strict>, ZodObject<{
2570
+ kind: ZodLiteral<"composite">;
2571
+ parts: ZodArray<ZodObject<{
2572
+ table: ZodString;
2573
+ column: ZodString;
2574
+ }, $strict>>;
2575
+ }, $strict>]>;
2576
+ }, $strict>>;
2363
2577
  }, $strict>>;
2364
2578
  }, $strict>;
2365
2579
  type ClivlyEntitiesConfig = output<typeof entitiesConfigSchema>;
2580
+ /**
2581
+ * What an author may hand to `defineClivlyConfig`. Identical to
2582
+ * `ClivlyEntityConfig` except that a projection entity may omit `fields` —
2583
+ * it is derived from `projection.fieldBindings`. Without a projection `fields`
2584
+ * stays required, so the looser input never weakens the ordinary case.
2585
+ */
2586
+ type ClivlyEntityConfigInput = (ClivlyEntityConfig & {
2587
+ projection?: undefined;
2588
+ }) | (Omit<ClivlyEntityConfig, "fields"> & {
2589
+ fields?: Record<string, string>;
2590
+ projection: ProjectionMapping;
2591
+ });
2592
+ type ClivlyEntitiesConfigInput = Omit<ClivlyEntitiesConfig, "entities"> & {
2593
+ entities: Record<string, ClivlyEntityConfigInput>;
2594
+ };
2366
2595
  /** Thrown by `defineClivlyConfig({ strict: true })` on non-canonical field keys. */
2367
2596
  declare class ClivlyConfigError extends Error {
2368
2597
  readonly issues: ConfigValidationError[];
@@ -2380,18 +2609,50 @@ declare class ClivlyConfigError extends Error {
2380
2609
  * a `ClivlyConfigError` instead. Does NOT validate against the host schema — that
2381
2610
  * needs the discovered schema; see `validateEntitiesConfig`.
2382
2611
  */
2383
- declare function defineClivlyConfig(config: ClivlyEntitiesConfig, options?: {
2612
+ /**
2613
+ * The `fields` entry a projection binding implies, qualified as `ref.column`.
2614
+ * Qualified rather than bare: two bindings can pull the same column name from
2615
+ * different tables (`cl.full_name` and `adv.full_name`), which a bare column
2616
+ * name cannot tell apart.
2617
+ */
2618
+ declare function projectionFields(projection: ProjectionMapping): Record<string, string>;
2619
+ declare function defineClivlyConfig(config: ClivlyEntitiesConfigInput, options?: {
2384
2620
  strict?: boolean;
2385
2621
  onWarn?: (message: string) => void;
2386
2622
  }): ClivlyEntitiesConfig;
2623
+ /**
2624
+ * Per-column metadata a host reports for a discovered table. Structurally
2625
+ * identical to the SDK's `DiscoveredColumn` and to `entity-heuristics.ts`'s
2626
+ * (currently separate) `DiscoveredColumnMeta` — a later task converges that
2627
+ * module onto this one. Every field is optional: a v1 host reports column
2628
+ * names only.
2629
+ */
2630
+ interface DiscoveredColumnMeta {
2631
+ isForeignKey?: boolean;
2632
+ isPrimaryKey?: boolean;
2633
+ name: string;
2634
+ nullable?: boolean;
2635
+ references?: {
2636
+ table: string;
2637
+ column: string;
2638
+ };
2639
+ type?: string;
2640
+ }
2387
2641
  /**
2388
2642
  * A host table the SDK reported for discovery. Structurally identical to the
2389
2643
  * SDK's `DiscoveredTable`; duplicated here to keep `@clivly/core` free of an
2390
2644
  * SDK dependency (core is the base contract SDK builds on).
2645
+ *
2646
+ * `columns` is the stable v1 contract. `columnsMeta` and `uniqueConstraints`
2647
+ * are the enrichment projection mappings require — absent on v1 hosts, which
2648
+ * is why projection validation fails closed rather than assuming "no keys".
2391
2649
  */
2392
2650
  interface DiscoveredSchemaTable {
2393
2651
  columns: string[];
2652
+ columnsMeta?: DiscoveredColumnMeta[];
2394
2653
  name: string;
2654
+ /** Every unique key as DB column names; PKs included. Absent = unknown. */
2655
+ uniqueConstraints?: string[][];
2395
2656
  }
2396
2657
  interface ConfigValidationError {
2397
2658
  message: string;
@@ -2413,4 +2674,4 @@ interface ConfigValidationResult {
2413
2674
  */
2414
2675
  declare function validateEntitiesConfig(config: ClivlyEntitiesConfig, schema: DiscoveredSchemaTable[]): ConfigValidationResult;
2415
2676
  //#endregion
2416
- export { validateEntitiesConfig as C, relationshipsSchema as S, RelationshipsMap as _, ClivlyEntitiesConfig as a, filterSchema as b, ConfigValidationResult as c, FilterExpr as d, FilterValue as f, RelationshipVia as g, RelationshipSpec as h, ClivlyConfigError as i, CrmConcept as l, MaterializingConcept as m, CRM_CONCEPTS as n, ClivlyEntityConfig as o, MATERIALIZING_CONCEPTS as p, CUSTOM_CONCEPT as r, ConfigValidationError as s, CANONICAL_FIELDS as t, DiscoveredSchemaTable as u, defineClivlyConfig as v, relationshipSchema as x, entitiesConfigSchema as y };
2677
+ export { ProjectionIdentity as A, filterSchema as C, validateEntitiesConfig as D, relationshipsSchema as E, projectionSchema as F, ProjectionMapping as M, ProjectionRef as N, BASE_REF as O, identityRefs as P, entitiesConfigSchema as S, relationshipSchema as T, MaterializingConcept as _, ClivlyEntitiesConfig as a, RelationshipsMap as b, ClivlyEntityConfigInput as c, CrmConcept as d, DiscoveredColumnMeta as f, MATERIALIZING_CONCEPTS as g, FilterValue as h, ClivlyConfigError as i, ProjectionJoin as j, ProjectionFieldBinding as k, ConfigValidationError as l, FilterExpr as m, CRM_CONCEPTS as n, ClivlyEntitiesConfigInput as o, DiscoveredSchemaTable as p, CUSTOM_CONCEPT as r, ClivlyEntityConfig as s, CANONICAL_FIELDS as t, ConfigValidationResult as u, RelationshipSpec as v, projectionFields as w, defineClivlyConfig as x, RelationshipVia as y };