clivly 0.7.4 → 0.9.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 (109) hide show
  1. package/core-drizzle.cjs +3 -1
  2. package/core-drizzle.d.cts +3 -2
  3. package/core-drizzle.d.mts +3 -2
  4. package/core-drizzle.mjs +2 -2
  5. package/core-entity-config.cjs +1 -1
  6. package/core-entity-config.d.cts +2 -2
  7. package/core-entity-config.d.mts +2 -2
  8. package/core-entity-config.mjs +1 -1
  9. package/core-entity-heuristics.d.cts +3 -2
  10. package/core-entity-heuristics.d.mts +3 -2
  11. package/core-mapping-form.d.cts +1 -1
  12. package/core-mapping-form.d.mts +1 -1
  13. package/core-mappings-config.cjs +1 -1
  14. package/core-mappings-config.d.cts +1 -1
  15. package/core-mappings-config.d.mts +1 -1
  16. package/core-mappings-config.mjs +1 -1
  17. package/core-sync-engine.cjs +1 -1
  18. package/core-sync-engine.d.cts +1 -1
  19. package/core-sync-engine.d.mts +1 -1
  20. package/core-sync-engine.mjs +1 -1
  21. package/core-view-compiler.cjs +1 -1
  22. package/core-view-compiler.d.cts +1 -1
  23. package/core-view-compiler.d.mts +1 -1
  24. package/core-view-compiler.mjs +1 -1
  25. package/core.cjs +21 -5
  26. package/core.d.cts +7 -6
  27. package/core.d.mts +7 -6
  28. package/core.mjs +7 -6
  29. package/drizzle-3kvhkwO7.mjs +110 -0
  30. package/drizzle-BhN5M9zt.d.cts +41 -0
  31. package/drizzle-bfjVzYR6.cjs +127 -0
  32. package/drizzle-kBULBAOa.d.mts +41 -0
  33. package/drizzle.cjs +5 -37
  34. package/drizzle.d.cts +3 -3
  35. package/drizzle.d.mts +3 -3
  36. package/drizzle.mjs +5 -38
  37. package/{entity-config-DoUCXtq5.d.cts → entity-config-C4Yf_fPj.d.cts} +120 -1
  38. package/{entity-config-DoUCXtq5.d.mts → entity-config-C4Yf_fPj.d.mts} +120 -1
  39. package/entity-config-CsLl-ftC.cjs +727 -0
  40. package/entity-config-D3LmzgLb.mjs +612 -0
  41. package/index.cjs +28 -2
  42. package/index.d.cts +6 -0
  43. package/index.d.mts +6 -0
  44. package/index.mjs +28 -2
  45. package/internal-B8ydhsKd.d.cts +73 -0
  46. package/internal-BARjyN4n.cjs +97 -0
  47. package/internal-DMySVbM0.mjs +68 -0
  48. package/internal-MBkNo3bw.d.mts +73 -0
  49. package/internal-drizzle.cjs +3 -1
  50. package/internal-drizzle.d.cts +2 -2
  51. package/internal-drizzle.d.mts +2 -2
  52. package/internal-drizzle.mjs +2 -2
  53. package/internal-entity-config.cjs +1 -1
  54. package/internal-entity-config.d.cts +2 -2
  55. package/internal-entity-config.d.mts +2 -2
  56. package/internal-entity-config.mjs +1 -1
  57. package/internal-entity-heuristics.cjs +1 -1
  58. package/internal-entity-heuristics.d.cts +2 -12
  59. package/internal-entity-heuristics.d.mts +2 -12
  60. package/internal-entity-heuristics.mjs +1 -1
  61. package/internal-mapping-form.d.cts +1 -1
  62. package/internal-mapping-form.d.mts +1 -1
  63. package/internal-mappings-config.cjs +1 -1
  64. package/internal-mappings-config.d.cts +1 -1
  65. package/internal-mappings-config.d.mts +1 -1
  66. package/internal-mappings-config.mjs +1 -1
  67. package/internal-sync-engine.cjs +1 -1
  68. package/internal-sync-engine.d.cts +1 -1
  69. package/internal-sync-engine.d.mts +1 -1
  70. package/internal-sync-engine.mjs +1 -1
  71. package/internal-view-compiler.cjs +1 -1
  72. package/internal-view-compiler.d.cts +1 -1
  73. package/internal-view-compiler.d.mts +1 -1
  74. package/internal-view-compiler.mjs +1 -1
  75. package/internal.cjs +21 -4
  76. package/internal.d.cts +7 -6
  77. package/internal.d.mts +7 -6
  78. package/internal.mjs +7 -5
  79. package/{mapping-form-D93lhHEc.d.mts → mapping-form-43bwOTat.d.cts} +1 -1
  80. package/{mapping-form-lfyEE7EJ.d.cts → mapping-form-DUvWUYCo.d.mts} +1 -1
  81. package/{mappings-config-BsRADNRv.cjs → mappings-config-BSSwdHiq.cjs} +32 -6
  82. package/mappings-config-BpcR8bBo.d.mts +167 -0
  83. package/{mappings-config-Dbgxx3Nv.mjs → mappings-config-bJQT_gSa.mjs} +32 -6
  84. package/mappings-config-xsLMn3I-.d.cts +167 -0
  85. package/{namespace-probe-B4WE45TH.d.mts → namespace-probe-BSH_p9TK.d.cts} +10 -1
  86. package/{namespace-probe-DRzOtaRT.d.cts → namespace-probe-Dsp5uNkS.d.mts} +10 -1
  87. package/package.json +1 -1
  88. package/{entity-config-va2bkH5o.mjs → projection-C5244vGa.cjs} +130 -309
  89. package/{entity-config-D87rV-tE.cjs → projection-D7xmQP4S.mjs} +60 -381
  90. package/sdk.cjs +1 -1
  91. package/sdk.d.cts +2 -2
  92. package/sdk.d.mts +2 -2
  93. package/sdk.mjs +1 -1
  94. package/{sync-engine-Do5ru3WF.mjs → sync-engine-Bg6-SznL.mjs} +9 -2
  95. package/{sync-engine-CzEbpQGv.cjs → sync-engine-DEJvKw6E.cjs} +9 -2
  96. package/{sync-engine-DGk_AeHJ.d.mts → sync-engine-GNqRB8eS.d.cts} +2 -2
  97. package/{sync-engine-B7QIbXro.d.cts → sync-engine-ZsusW-q_.d.mts} +2 -2
  98. package/{view-compiler-BWz0sGdm.d.cts → view-compiler-Cin0neDO.d.mts} +1 -1
  99. package/{view-compiler-ChWr_Lml.mjs → view-compiler-DlTpOfZi.mjs} +81 -12
  100. package/{view-compiler-BIwvm-o2.cjs → view-compiler-DplczSjF.cjs} +81 -12
  101. package/{view-compiler-Bn_EJJMO.d.mts → view-compiler-Ll9cbIJz.d.cts} +1 -1
  102. package/vite.d.cts +1 -1
  103. package/vite.d.mts +1 -1
  104. package/drizzle-B89tLo4T.mjs +0 -31
  105. package/drizzle-CFOr9dU9.d.mts +0 -20
  106. package/drizzle-DiReZf6d.cjs +0 -36
  107. package/drizzle-DmeKSqeF.d.cts +0 -20
  108. package/mappings-config-DsUa7-1w.d.mts +0 -41
  109. package/mappings-config-XmzB4dag.d.cts +0 -41
@@ -0,0 +1,41 @@
1
+ import { d as DiscoveredSchemaTable, u as DiscoveredColumnMeta } from "./entity-config-C4Yf_fPj.mjs";
2
+ import { Table } from "drizzle-orm";
3
+ //#region ../core/src/drizzle.d.ts
4
+ /**
5
+ * Every unique key on a table, as DB column-name tuples. Primary keys count —
6
+ * fan-out detection asks "do these join columns cover a unique key?", and a PK
7
+ * answers that as well as any explicit unique constraint.
8
+ *
9
+ * Returns `undefined` if reflection fails (non-pg table, or a drizzle version
10
+ * without config access), meaning "unknown, cannot determine". Returns `[]`
11
+ * when reflection succeeds and the table genuinely has none. That distinction
12
+ * is load-bearing: `hasRichMeta` uses it to tell "metadata unavailable" from
13
+ * "confirmed no constraints", and projection validation fails closed on the
14
+ * former.
15
+ */
16
+ declare function buildUniqueConstraints(table: unknown): string[][] | undefined;
17
+ /**
18
+ * Per-column metadata (type, PK, nullability, FK edges) for a Drizzle table.
19
+ * Structural only — no DB round-trip, so it is safe to recompute on every
20
+ * heartbeat. FK reflection is best-effort; a non-Postgres table still gets
21
+ * name/type/PK/nullable.
22
+ */
23
+ declare function buildColumnsMeta(table: Table): DiscoveredColumnMeta[];
24
+ /**
25
+ * Derive Clivly's discovery shape (table + column names) from a Drizzle schema
26
+ * object — the `* as schema` you pass to `drizzle(client, { schema })`. This
27
+ * delivers the "reads your schema" promise for Drizzle hosts: no hand-authored
28
+ * `DiscoveredTable[]`. Feed the result to the SDK's `schema` option, or diff it
29
+ * against your entity config.
30
+ *
31
+ * Column names are the real database column names (e.g. `full_name`), not the
32
+ * Drizzle property keys (`fullName`). Non-table values in the schema object
33
+ * (relations, enums, helpers) are ignored.
34
+ *
35
+ * `drizzle-orm` is an **optional peer dependency** — you only need it installed
36
+ * when you import this entry (`@clivly/core/drizzle`); the rest of `@clivly/core`
37
+ * stays dependency-free.
38
+ */
39
+ declare function discoverFromDrizzle(schema: Record<string, unknown>): DiscoveredSchemaTable[];
40
+ //#endregion
41
+ export { buildUniqueConstraints as n, discoverFromDrizzle as r, buildColumnsMeta as t };
package/drizzle.cjs CHANGED
@@ -1,43 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_drizzle_meta = require("./drizzle-meta-Bb1JWYqf.cjs");
3
- const require_drizzle = require("./drizzle-DiReZf6d.cjs");
3
+ const require_drizzle = require("./drizzle-bfjVzYR6.cjs");
4
4
  let drizzle_orm = require("drizzle-orm");
5
- let drizzle_orm_pg_core = require("drizzle-orm/pg-core");
6
5
  //#region ../sdk/src/drizzle.ts
7
- function buildColumnsMeta(table) {
8
- const columns = (0, drizzle_orm.getTableColumns)(table);
9
- const fkByColumn = /* @__PURE__ */ new Map();
10
- try {
11
- for (const fk of (0, drizzle_orm_pg_core.getTableConfig)(table).foreignKeys) {
12
- const ref = fk.reference();
13
- const foreignTable = (0, drizzle_orm.getTableName)(ref.foreignTable);
14
- ref.columns.forEach((col, i) => {
15
- const foreignCol = ref.foreignColumns[i];
16
- if (foreignCol) fkByColumn.set(col.name, {
17
- table: foreignTable,
18
- column: foreignCol.name
19
- });
20
- });
21
- }
22
- } catch {}
23
- return Object.values(columns).map((col) => {
24
- const references = fkByColumn.get(col.name);
25
- let type;
26
- try {
27
- type = col.getSQLType();
28
- } catch {
29
- type = void 0;
30
- }
31
- return {
32
- name: col.name,
33
- type,
34
- nullable: !col.notNull,
35
- isPrimaryKey: Boolean(col.primary),
36
- isForeignKey: references !== void 0,
37
- ...references ? { references } : {}
38
- };
39
- });
40
- }
41
6
  function inferIdField(table) {
42
7
  const columns = (0, drizzle_orm.getTableColumns)(table);
43
8
  const primaryKeys = Object.entries(columns).filter(([, column]) => column.primary);
@@ -75,12 +40,14 @@ function fromDrizzle(db, table, opts) {
75
40
  idField: idColumnName,
76
41
  fetchPage: ({ since, limit }) => drizzleDb.select(projection).from(table).where(since ? drizzle_orm.sql`(${cursorColumn}, ${idColumn}) > (${since.time}, ${since.id})` : void 0).orderBy((0, drizzle_orm.asc)(cursorColumn), (0, drizzle_orm.asc)(idColumn)).limit(limit)
77
42
  };
43
+ const uniqueConstraints = require_drizzle.buildUniqueConstraints(table);
78
44
  const meta = {
79
45
  columnKeys: Object.keys(columns),
80
46
  cursorField: opts.cursorField,
81
47
  idField,
82
48
  tableName: (0, drizzle_orm.getTableName)(table),
83
- columnsMeta: buildColumnsMeta(table)
49
+ columnsMeta: require_drizzle.buildColumnsMeta(table),
50
+ ...uniqueConstraints === void 0 ? {} : { uniqueConstraints }
84
51
  };
85
52
  Object.defineProperty(source, require_drizzle_meta.DRIZZLE_META, {
86
53
  value: meta,
@@ -108,6 +75,7 @@ function drizzleIntrospector(db) {
108
75
  };
109
76
  }
110
77
  //#endregion
78
+ exports.buildUniqueConstraints = require_drizzle.buildUniqueConstraints;
111
79
  exports.discoverFromDrizzle = require_drizzle.discoverFromDrizzle;
112
80
  exports.drizzleIntrospector = drizzleIntrospector;
113
81
  exports.fromDrizzle = fromDrizzle;
package/drizzle.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { t as discoverFromDrizzle } from "./drizzle-DmeKSqeF.cjs";
2
- import { m as SyncSource, t as NamespaceIntrospector } from "./namespace-probe-DRzOtaRT.cjs";
1
+ import { n as buildUniqueConstraints, r as discoverFromDrizzle } from "./drizzle-BhN5M9zt.cjs";
2
+ import { m as SyncSource, t as NamespaceIntrospector } from "./namespace-probe-BSH_p9TK.cjs";
3
3
  import { Table } from "drizzle-orm";
4
4
  //#region ../sdk/src/drizzle.d.ts
5
5
  interface DrizzleDb {
@@ -25,4 +25,4 @@ declare function fromDrizzle(db: DrizzleDb, table: Table, opts: {
25
25
  */
26
26
  declare function drizzleIntrospector(db: unknown): NamespaceIntrospector;
27
27
  //#endregion
28
- export { discoverFromDrizzle, drizzleIntrospector, fromDrizzle };
28
+ export { buildUniqueConstraints, discoverFromDrizzle, drizzleIntrospector, fromDrizzle };
package/drizzle.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { t as discoverFromDrizzle } from "./drizzle-CFOr9dU9.mjs";
2
- import { m as SyncSource, t as NamespaceIntrospector } from "./namespace-probe-B4WE45TH.mjs";
1
+ import { n as buildUniqueConstraints, r as discoverFromDrizzle } from "./drizzle-kBULBAOa.mjs";
2
+ import { m as SyncSource, t as NamespaceIntrospector } from "./namespace-probe-Dsp5uNkS.mjs";
3
3
  import { Table } from "drizzle-orm";
4
4
  //#region ../sdk/src/drizzle.d.ts
5
5
  interface DrizzleDb {
@@ -25,4 +25,4 @@ declare function fromDrizzle(db: DrizzleDb, table: Table, opts: {
25
25
  */
26
26
  declare function drizzleIntrospector(db: unknown): NamespaceIntrospector;
27
27
  //#endregion
28
- export { discoverFromDrizzle, drizzleIntrospector, fromDrizzle };
28
+ export { buildUniqueConstraints, discoverFromDrizzle, drizzleIntrospector, fromDrizzle };
package/drizzle.mjs CHANGED
@@ -1,42 +1,7 @@
1
1
  import { t as DRIZZLE_META } from "./drizzle-meta-D-5k3n0i.mjs";
2
- import { t as discoverFromDrizzle } from "./drizzle-B89tLo4T.mjs";
2
+ import { n as buildUniqueConstraints, r as discoverFromDrizzle, t as buildColumnsMeta } from "./drizzle-3kvhkwO7.mjs";
3
3
  import { asc, getTableColumns, getTableName, sql } from "drizzle-orm";
4
- import { getTableConfig } from "drizzle-orm/pg-core";
5
4
  //#region ../sdk/src/drizzle.ts
6
- function buildColumnsMeta(table) {
7
- const columns = getTableColumns(table);
8
- const fkByColumn = /* @__PURE__ */ new Map();
9
- try {
10
- for (const fk of getTableConfig(table).foreignKeys) {
11
- const ref = fk.reference();
12
- const foreignTable = getTableName(ref.foreignTable);
13
- ref.columns.forEach((col, i) => {
14
- const foreignCol = ref.foreignColumns[i];
15
- if (foreignCol) fkByColumn.set(col.name, {
16
- table: foreignTable,
17
- column: foreignCol.name
18
- });
19
- });
20
- }
21
- } catch {}
22
- return Object.values(columns).map((col) => {
23
- const references = fkByColumn.get(col.name);
24
- let type;
25
- try {
26
- type = col.getSQLType();
27
- } catch {
28
- type = void 0;
29
- }
30
- return {
31
- name: col.name,
32
- type,
33
- nullable: !col.notNull,
34
- isPrimaryKey: Boolean(col.primary),
35
- isForeignKey: references !== void 0,
36
- ...references ? { references } : {}
37
- };
38
- });
39
- }
40
5
  function inferIdField(table) {
41
6
  const columns = getTableColumns(table);
42
7
  const primaryKeys = Object.entries(columns).filter(([, column]) => column.primary);
@@ -74,12 +39,14 @@ function fromDrizzle(db, table, opts) {
74
39
  idField: idColumnName,
75
40
  fetchPage: ({ since, limit }) => drizzleDb.select(projection).from(table).where(since ? sql`(${cursorColumn}, ${idColumn}) > (${since.time}, ${since.id})` : void 0).orderBy(asc(cursorColumn), asc(idColumn)).limit(limit)
76
41
  };
42
+ const uniqueConstraints = buildUniqueConstraints(table);
77
43
  const meta = {
78
44
  columnKeys: Object.keys(columns),
79
45
  cursorField: opts.cursorField,
80
46
  idField,
81
47
  tableName: getTableName(table),
82
- columnsMeta: buildColumnsMeta(table)
48
+ columnsMeta: buildColumnsMeta(table),
49
+ ...uniqueConstraints === void 0 ? {} : { uniqueConstraints }
83
50
  };
84
51
  Object.defineProperty(source, DRIZZLE_META, {
85
52
  value: meta,
@@ -107,4 +74,4 @@ function drizzleIntrospector(db) {
107
74
  };
108
75
  }
109
76
  //#endregion
110
- export { discoverFromDrizzle, drizzleIntrospector, fromDrizzle };
77
+ export { buildUniqueConstraints, discoverFromDrizzle, drizzleIntrospector, fromDrizzle };
@@ -2312,6 +2312,53 @@ declare const entitySchema: ZodObject<{
2312
2312
  }, $strict>]>;
2313
2313
  }, $strict>>>;
2314
2314
  targetObjectTypeId: ZodOptional<ZodString>;
2315
+ projection: ZodOptional<ZodObject<{
2316
+ version: ZodLiteral<1>;
2317
+ kind: ZodLiteral<"projection">;
2318
+ entityKey: ZodString;
2319
+ baseTable: ZodString;
2320
+ joins: ZodArray<ZodObject<{
2321
+ key: ZodString;
2322
+ table: ZodString;
2323
+ type: ZodEnum<{
2324
+ inner: "inner";
2325
+ left: "left";
2326
+ }>;
2327
+ on: ZodArray<ZodObject<{
2328
+ left: ZodObject<{
2329
+ table: ZodString;
2330
+ column: ZodString;
2331
+ }, $strict>;
2332
+ op: ZodLiteral<"eq">;
2333
+ right: ZodObject<{
2334
+ table: ZodString;
2335
+ column: ZodString;
2336
+ }, $strict>;
2337
+ }, $strict>>;
2338
+ }, $strict>>;
2339
+ fieldBindings: ZodRecord<ZodString, ZodObject<{
2340
+ from: ZodObject<{
2341
+ table: ZodString;
2342
+ column: ZodString;
2343
+ }, $strict>;
2344
+ }, $strict>>;
2345
+ identity: ZodUnion<readonly [ZodObject<{
2346
+ kind: ZodLiteral<"base_pk">;
2347
+ column: ZodOptional<ZodString>;
2348
+ }, $strict>, ZodObject<{
2349
+ kind: ZodLiteral<"column">;
2350
+ from: ZodObject<{
2351
+ table: ZodString;
2352
+ column: ZodString;
2353
+ }, $strict>;
2354
+ }, $strict>, ZodObject<{
2355
+ kind: ZodLiteral<"composite">;
2356
+ parts: ZodArray<ZodObject<{
2357
+ table: ZodString;
2358
+ column: ZodString;
2359
+ }, $strict>>;
2360
+ }, $strict>]>;
2361
+ }, $strict>>;
2315
2362
  }, $strict>;
2316
2363
  type ClivlyEntityConfig = output<typeof entitySchema>;
2317
2364
  declare const entitiesConfigSchema: ZodObject<{
@@ -2360,6 +2407,53 @@ declare const entitiesConfigSchema: ZodObject<{
2360
2407
  }, $strict>]>;
2361
2408
  }, $strict>>>;
2362
2409
  targetObjectTypeId: ZodOptional<ZodString>;
2410
+ projection: ZodOptional<ZodObject<{
2411
+ version: ZodLiteral<1>;
2412
+ kind: ZodLiteral<"projection">;
2413
+ entityKey: ZodString;
2414
+ baseTable: ZodString;
2415
+ joins: ZodArray<ZodObject<{
2416
+ key: ZodString;
2417
+ table: ZodString;
2418
+ type: ZodEnum<{
2419
+ inner: "inner";
2420
+ left: "left";
2421
+ }>;
2422
+ on: ZodArray<ZodObject<{
2423
+ left: ZodObject<{
2424
+ table: ZodString;
2425
+ column: ZodString;
2426
+ }, $strict>;
2427
+ op: ZodLiteral<"eq">;
2428
+ right: ZodObject<{
2429
+ table: ZodString;
2430
+ column: ZodString;
2431
+ }, $strict>;
2432
+ }, $strict>>;
2433
+ }, $strict>>;
2434
+ fieldBindings: ZodRecord<ZodString, ZodObject<{
2435
+ from: ZodObject<{
2436
+ table: ZodString;
2437
+ column: ZodString;
2438
+ }, $strict>;
2439
+ }, $strict>>;
2440
+ identity: ZodUnion<readonly [ZodObject<{
2441
+ kind: ZodLiteral<"base_pk">;
2442
+ column: ZodOptional<ZodString>;
2443
+ }, $strict>, ZodObject<{
2444
+ kind: ZodLiteral<"column">;
2445
+ from: ZodObject<{
2446
+ table: ZodString;
2447
+ column: ZodString;
2448
+ }, $strict>;
2449
+ }, $strict>, ZodObject<{
2450
+ kind: ZodLiteral<"composite">;
2451
+ parts: ZodArray<ZodObject<{
2452
+ table: ZodString;
2453
+ column: ZodString;
2454
+ }, $strict>>;
2455
+ }, $strict>]>;
2456
+ }, $strict>>;
2363
2457
  }, $strict>>;
2364
2458
  }, $strict>;
2365
2459
  type ClivlyEntitiesConfig = output<typeof entitiesConfigSchema>;
@@ -2384,14 +2478,39 @@ declare function defineClivlyConfig(config: ClivlyEntitiesConfig, options?: {
2384
2478
  strict?: boolean;
2385
2479
  onWarn?: (message: string) => void;
2386
2480
  }): ClivlyEntitiesConfig;
2481
+ /**
2482
+ * Per-column metadata a host reports for a discovered table. Structurally
2483
+ * identical to the SDK's `DiscoveredColumn` and to `entity-heuristics.ts`'s
2484
+ * (currently separate) `DiscoveredColumnMeta` — a later task converges that
2485
+ * module onto this one. Every field is optional: a v1 host reports column
2486
+ * names only.
2487
+ */
2488
+ interface DiscoveredColumnMeta {
2489
+ isForeignKey?: boolean;
2490
+ isPrimaryKey?: boolean;
2491
+ name: string;
2492
+ nullable?: boolean;
2493
+ references?: {
2494
+ table: string;
2495
+ column: string;
2496
+ };
2497
+ type?: string;
2498
+ }
2387
2499
  /**
2388
2500
  * A host table the SDK reported for discovery. Structurally identical to the
2389
2501
  * SDK's `DiscoveredTable`; duplicated here to keep `@clivly/core` free of an
2390
2502
  * SDK dependency (core is the base contract SDK builds on).
2503
+ *
2504
+ * `columns` is the stable v1 contract. `columnsMeta` and `uniqueConstraints`
2505
+ * are the enrichment projection mappings require — absent on v1 hosts, which
2506
+ * is why projection validation fails closed rather than assuming "no keys".
2391
2507
  */
2392
2508
  interface DiscoveredSchemaTable {
2393
2509
  columns: string[];
2510
+ columnsMeta?: DiscoveredColumnMeta[];
2394
2511
  name: string;
2512
+ /** Every unique key as DB column names; PKs included. Absent = unknown. */
2513
+ uniqueConstraints?: string[][];
2395
2514
  }
2396
2515
  interface ConfigValidationError {
2397
2516
  message: string;
@@ -2413,4 +2532,4 @@ interface ConfigValidationResult {
2413
2532
  */
2414
2533
  declare function validateEntitiesConfig(config: ClivlyEntitiesConfig, schema: DiscoveredSchemaTable[]): ConfigValidationResult;
2415
2534
  //#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 };
2535
+ export { ZodRecord as A, relationshipsSchema as C, ZodLiteral as D, ZodEnum as E, ZodUnion as M, output as N, ZodObject as O, $strict as P, relationshipSchema as S, ZodArray as T, RelationshipVia as _, ClivlyEntitiesConfig as a, entitiesConfigSchema as b, ConfigValidationResult as c, DiscoveredSchemaTable as d, FilterExpr as f, RelationshipSpec as g, MaterializingConcept as h, ClivlyConfigError as i, ZodString as j, ZodOptional as k, CrmConcept as l, MATERIALIZING_CONCEPTS as m, CRM_CONCEPTS as n, ClivlyEntityConfig as o, FilterValue as p, CUSTOM_CONCEPT as r, ConfigValidationError as s, CANONICAL_FIELDS as t, DiscoveredColumnMeta as u, RelationshipsMap as v, validateEntitiesConfig as w, filterSchema as x, defineClivlyConfig as y };
@@ -2312,6 +2312,53 @@ declare const entitySchema: ZodObject<{
2312
2312
  }, $strict>]>;
2313
2313
  }, $strict>>>;
2314
2314
  targetObjectTypeId: ZodOptional<ZodString>;
2315
+ projection: ZodOptional<ZodObject<{
2316
+ version: ZodLiteral<1>;
2317
+ kind: ZodLiteral<"projection">;
2318
+ entityKey: ZodString;
2319
+ baseTable: ZodString;
2320
+ joins: ZodArray<ZodObject<{
2321
+ key: ZodString;
2322
+ table: ZodString;
2323
+ type: ZodEnum<{
2324
+ inner: "inner";
2325
+ left: "left";
2326
+ }>;
2327
+ on: ZodArray<ZodObject<{
2328
+ left: ZodObject<{
2329
+ table: ZodString;
2330
+ column: ZodString;
2331
+ }, $strict>;
2332
+ op: ZodLiteral<"eq">;
2333
+ right: ZodObject<{
2334
+ table: ZodString;
2335
+ column: ZodString;
2336
+ }, $strict>;
2337
+ }, $strict>>;
2338
+ }, $strict>>;
2339
+ fieldBindings: ZodRecord<ZodString, ZodObject<{
2340
+ from: ZodObject<{
2341
+ table: ZodString;
2342
+ column: ZodString;
2343
+ }, $strict>;
2344
+ }, $strict>>;
2345
+ identity: ZodUnion<readonly [ZodObject<{
2346
+ kind: ZodLiteral<"base_pk">;
2347
+ column: ZodOptional<ZodString>;
2348
+ }, $strict>, ZodObject<{
2349
+ kind: ZodLiteral<"column">;
2350
+ from: ZodObject<{
2351
+ table: ZodString;
2352
+ column: ZodString;
2353
+ }, $strict>;
2354
+ }, $strict>, ZodObject<{
2355
+ kind: ZodLiteral<"composite">;
2356
+ parts: ZodArray<ZodObject<{
2357
+ table: ZodString;
2358
+ column: ZodString;
2359
+ }, $strict>>;
2360
+ }, $strict>]>;
2361
+ }, $strict>>;
2315
2362
  }, $strict>;
2316
2363
  type ClivlyEntityConfig = output<typeof entitySchema>;
2317
2364
  declare const entitiesConfigSchema: ZodObject<{
@@ -2360,6 +2407,53 @@ declare const entitiesConfigSchema: ZodObject<{
2360
2407
  }, $strict>]>;
2361
2408
  }, $strict>>>;
2362
2409
  targetObjectTypeId: ZodOptional<ZodString>;
2410
+ projection: ZodOptional<ZodObject<{
2411
+ version: ZodLiteral<1>;
2412
+ kind: ZodLiteral<"projection">;
2413
+ entityKey: ZodString;
2414
+ baseTable: ZodString;
2415
+ joins: ZodArray<ZodObject<{
2416
+ key: ZodString;
2417
+ table: ZodString;
2418
+ type: ZodEnum<{
2419
+ inner: "inner";
2420
+ left: "left";
2421
+ }>;
2422
+ on: ZodArray<ZodObject<{
2423
+ left: ZodObject<{
2424
+ table: ZodString;
2425
+ column: ZodString;
2426
+ }, $strict>;
2427
+ op: ZodLiteral<"eq">;
2428
+ right: ZodObject<{
2429
+ table: ZodString;
2430
+ column: ZodString;
2431
+ }, $strict>;
2432
+ }, $strict>>;
2433
+ }, $strict>>;
2434
+ fieldBindings: ZodRecord<ZodString, ZodObject<{
2435
+ from: ZodObject<{
2436
+ table: ZodString;
2437
+ column: ZodString;
2438
+ }, $strict>;
2439
+ }, $strict>>;
2440
+ identity: ZodUnion<readonly [ZodObject<{
2441
+ kind: ZodLiteral<"base_pk">;
2442
+ column: ZodOptional<ZodString>;
2443
+ }, $strict>, ZodObject<{
2444
+ kind: ZodLiteral<"column">;
2445
+ from: ZodObject<{
2446
+ table: ZodString;
2447
+ column: ZodString;
2448
+ }, $strict>;
2449
+ }, $strict>, ZodObject<{
2450
+ kind: ZodLiteral<"composite">;
2451
+ parts: ZodArray<ZodObject<{
2452
+ table: ZodString;
2453
+ column: ZodString;
2454
+ }, $strict>>;
2455
+ }, $strict>]>;
2456
+ }, $strict>>;
2363
2457
  }, $strict>>;
2364
2458
  }, $strict>;
2365
2459
  type ClivlyEntitiesConfig = output<typeof entitiesConfigSchema>;
@@ -2384,14 +2478,39 @@ declare function defineClivlyConfig(config: ClivlyEntitiesConfig, options?: {
2384
2478
  strict?: boolean;
2385
2479
  onWarn?: (message: string) => void;
2386
2480
  }): ClivlyEntitiesConfig;
2481
+ /**
2482
+ * Per-column metadata a host reports for a discovered table. Structurally
2483
+ * identical to the SDK's `DiscoveredColumn` and to `entity-heuristics.ts`'s
2484
+ * (currently separate) `DiscoveredColumnMeta` — a later task converges that
2485
+ * module onto this one. Every field is optional: a v1 host reports column
2486
+ * names only.
2487
+ */
2488
+ interface DiscoveredColumnMeta {
2489
+ isForeignKey?: boolean;
2490
+ isPrimaryKey?: boolean;
2491
+ name: string;
2492
+ nullable?: boolean;
2493
+ references?: {
2494
+ table: string;
2495
+ column: string;
2496
+ };
2497
+ type?: string;
2498
+ }
2387
2499
  /**
2388
2500
  * A host table the SDK reported for discovery. Structurally identical to the
2389
2501
  * SDK's `DiscoveredTable`; duplicated here to keep `@clivly/core` free of an
2390
2502
  * SDK dependency (core is the base contract SDK builds on).
2503
+ *
2504
+ * `columns` is the stable v1 contract. `columnsMeta` and `uniqueConstraints`
2505
+ * are the enrichment projection mappings require — absent on v1 hosts, which
2506
+ * is why projection validation fails closed rather than assuming "no keys".
2391
2507
  */
2392
2508
  interface DiscoveredSchemaTable {
2393
2509
  columns: string[];
2510
+ columnsMeta?: DiscoveredColumnMeta[];
2394
2511
  name: string;
2512
+ /** Every unique key as DB column names; PKs included. Absent = unknown. */
2513
+ uniqueConstraints?: string[][];
2395
2514
  }
2396
2515
  interface ConfigValidationError {
2397
2516
  message: string;
@@ -2413,4 +2532,4 @@ interface ConfigValidationResult {
2413
2532
  */
2414
2533
  declare function validateEntitiesConfig(config: ClivlyEntitiesConfig, schema: DiscoveredSchemaTable[]): ConfigValidationResult;
2415
2534
  //#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 };
2535
+ export { ZodRecord as A, relationshipsSchema as C, ZodLiteral as D, ZodEnum as E, ZodUnion as M, output as N, ZodObject as O, $strict as P, relationshipSchema as S, ZodArray as T, RelationshipVia as _, ClivlyEntitiesConfig as a, entitiesConfigSchema as b, ConfigValidationResult as c, DiscoveredSchemaTable as d, FilterExpr as f, RelationshipSpec as g, MaterializingConcept as h, ClivlyConfigError as i, ZodString as j, ZodOptional as k, CrmConcept as l, MATERIALIZING_CONCEPTS as m, CRM_CONCEPTS as n, ClivlyEntityConfig as o, FilterValue as p, CUSTOM_CONCEPT as r, ConfigValidationError as s, CANONICAL_FIELDS as t, DiscoveredColumnMeta as u, RelationshipsMap as v, validateEntitiesConfig as w, filterSchema as x, defineClivlyConfig as y };