clivly 0.9.2 → 0.9.4

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 (64) hide show
  1. package/README.md +60 -6
  2. package/core-entity-config.cjs +1 -1
  3. package/core-entity-config.mjs +1 -1
  4. package/core-mappings-config.cjs +1 -1
  5. package/core-mappings-config.mjs +1 -1
  6. package/core-sync-engine.cjs +1 -1
  7. package/core-sync-engine.mjs +1 -1
  8. package/core-view-compiler.cjs +1 -1
  9. package/core-view-compiler.mjs +1 -1
  10. package/core.cjs +11 -6
  11. package/core.d.cts +3 -2
  12. package/core.d.mts +3 -2
  13. package/core.mjs +8 -7
  14. package/drizzle.cjs +74 -9
  15. package/drizzle.d.cts +83 -7
  16. package/drizzle.d.mts +83 -7
  17. package/drizzle.mjs +74 -10
  18. package/{entity-config-DtBsl2MQ.cjs → entity-config-7sGCk_nw.cjs} +1 -1
  19. package/{entity-config-kUHri9yA.mjs → entity-config-B74SPOUZ.mjs} +1 -1
  20. package/index.cjs +141 -29
  21. package/index.d.cts +2 -1
  22. package/index.d.mts +2 -1
  23. package/index.mjs +141 -30
  24. package/integration-state-BK-riZnm.d.cts +130 -0
  25. package/integration-state-BK-riZnm.d.mts +130 -0
  26. package/{internal-Df-PtOH_.mjs → internal-CykXpEGk.mjs} +2 -2
  27. package/{internal-CwnEG6Wl.cjs → internal-DqduZU3l.cjs} +2 -2
  28. package/internal-entity-config.cjs +1 -1
  29. package/internal-entity-config.mjs +1 -1
  30. package/internal-entity-heuristics.cjs +1 -1
  31. package/internal-entity-heuristics.mjs +1 -1
  32. package/internal-mappings-config.cjs +1 -1
  33. package/internal-mappings-config.mjs +1 -1
  34. package/{internal-CDY8g9Ic.d.mts → internal-o2M7FGlR.d.mts} +29 -1
  35. package/internal-sync-engine.cjs +1 -1
  36. package/internal-sync-engine.mjs +1 -1
  37. package/internal-view-compiler.cjs +1 -1
  38. package/internal-view-compiler.mjs +1 -1
  39. package/{internal-Da_dlcQ_.d.cts → internal-wCXSELDN.d.cts} +29 -1
  40. package/internal.cjs +11 -6
  41. package/internal.d.cts +3 -2
  42. package/internal.d.mts +3 -2
  43. package/internal.mjs +8 -7
  44. package/{mappings-config-B0RqFLxu.cjs → mappings-config-CLyEg0sf.cjs} +1 -1
  45. package/{mappings-config-B1b1HVBg.mjs → mappings-config-DQS_s4dg.mjs} +1 -1
  46. package/{namespace-probe-C6aHjedO.d.cts → namespace-probe-BoGI18dQ.d.cts} +15 -0
  47. package/{namespace-probe-Dj-0Q3Hb.d.mts → namespace-probe-Cn7voAd0.d.mts} +15 -0
  48. package/package.json +1 -1
  49. package/{projection-D7xmQP4S.mjs → projection-CSGJbZlZ.mjs} +25 -4
  50. package/{projection-C5244vGa.cjs → projection-Dz6_i1-w.cjs} +25 -4
  51. package/projection-sql-BgnfiGqF.mjs +65 -0
  52. package/projection-sql-Cl1qIn8m.cjs +94 -0
  53. package/{sdk-D4Wp_uxb.cjs → sdk-CM1UO-I7.cjs} +59 -15
  54. package/{sdk-DXV8M_Io.mjs → sdk-DYBDR939.mjs} +54 -16
  55. package/sdk.cjs +3 -2
  56. package/sdk.d.cts +5 -2
  57. package/sdk.d.mts +5 -2
  58. package/sdk.mjs +3 -3
  59. package/{sync-engine-abE94g6X.cjs → sync-engine-C4A5jgA4.cjs} +1 -1
  60. package/{sync-engine-SuxSzbZ4.mjs → sync-engine-Dt5QQSKO.mjs} +1 -1
  61. package/{view-compiler-Blu4OXJ7.cjs → view-compiler-B5nDal14.cjs} +21 -74
  62. package/{view-compiler-CQx8TRrW.mjs → view-compiler-CSYwEWf5.mjs} +2 -55
  63. package/vite.d.cts +1 -1
  64. package/vite.d.mts +1 -1
package/README.md CHANGED
@@ -60,7 +60,7 @@ database tables and does not modify your ORM schema.
60
60
  | [`clivly login`](#clivly-login) | Pair this machine and write credentials to your env file |
61
61
  | [`clivly status`](#clivly-status) | Check your setup, step by step. Read-only |
62
62
  | [`clivly add widget`](#clivly-add-widget) | Scaffold the chat-session route |
63
- | [`clivly push-schema`](#clivly-push-schema) | Report your schema to Clivly without deploying |
63
+ | [`clivly push-schema`](#clivly-push-schema) | Push your schema, custom objects and mappings to Clivly without deploying |
64
64
  | [`clivly dev`](#clivly-dev) | Tunnel localhost so remote sync can reach you |
65
65
  | `clivly --version` | Print the installed `clivly` version |
66
66
  | [`clivly ping` / `connect` / `doctor`](#deprecated-aliases) | Deprecated aliases running parts of `status` |
@@ -257,8 +257,36 @@ Walks your setup one step at a time and stops at the first thing that isn't
257
257
  ready, telling you what to do about it. **This is the command to reach for when
258
258
  something isn't working.** It is read-only and writes nothing.
259
259
 
260
- The ladder: credential → Clivly reachable → `clivly.config` loads →
261
- `clivly.config` is edge-safe → setup checks → sync trigger URL.
260
+ It answers two questions under two headings:
261
+
262
+ - **Workspace** — how far setup has got *on Clivly's side*. The server computes
263
+ this ladder and the CLI prints its verdict, so the terminal and the dashboard
264
+ can never disagree about where you are. Shown whenever reachability is in
265
+ scope; `clivly doctor` is local by definition and omits it.
266
+ - **This project** — the local ladder, run here on your machine: credential →
267
+ Clivly reachable → `clivly.config` loads → `clivly.config` is edge-safe →
268
+ setup checks → sync trigger URL.
269
+
270
+ ```text
271
+ Clivly status
272
+
273
+ Workspace
274
+ ✅ Create a credential
275
+ ✅ Install Clivly in your app heartbeat 2m ago
276
+ ✅ Check what the SDK reported found 12 tables
277
+ ⏳ Choose the table holding your people
278
+ 🔒 Let Clivly start a sync
279
+
280
+ This project
281
+ ✅ Step 1 of 6 · API key present
282
+ ✅ Step 2 of 6 · Clivly reachable — Acme
283
+ ...
284
+ ```
285
+
286
+ If the Workspace section reads
287
+ `⚠️ This Clivly server does not report setup progress`, or names a rejected key
288
+ or an unreachable host, that means the question could not be asked — not that
289
+ your workspace is empty.
262
290
 
263
291
  | Flag | Effect |
264
292
  | --- | --- |
@@ -303,9 +331,35 @@ for the full flow.
303
331
  npx clivly push-schema [--config <path>]
304
332
  ```
305
333
 
306
- Sends your discovered tables and columns to Clivly so the dashboard can offer
307
- them for mapping — without deploying your app. Reads your config; writes nothing
308
- locally. **Table and column names only; never row data.**
334
+ Pushes everything your config declares to Clivly, without deploying your app:
335
+
336
+ 1. **Discovery** — your tables and columns, so the dashboard can offer them for
337
+ mapping. **Names only; never row data.**
338
+ 2. **Custom object types** — anything you declared with `objectType`, so you
339
+ never create one in the dashboard and paste its id back into config.
340
+ 3. **Mappings** — the rows that make those objects actually receive data. Until
341
+ a mapping exists, a sync is accepted and stores nothing.
342
+
343
+ Reads your config; writes nothing locally. Safe to re-run — it reports what it
344
+ created, updated, or left alone.
345
+
346
+ ```text
347
+ Clivly push-schema
348
+ ✅ Schema reported to Clivly.
349
+ ✅ Created 1 custom object: client_accounts.
350
+ ✅ Mapped 2 entities: clients, advisors.
351
+ Open Integrations → Mapping to review them.
352
+ ```
353
+
354
+ **Exits `1` if Clivly refuses your config** — most often because an entity would
355
+ overwrite a mapping someone edited in the dashboard. Config owns the mappings it
356
+ declares; a dashboard-edited mapping is never silently overwritten. That makes
357
+ this command safe to run in CI as a schema gate.
358
+
359
+ > Two older-version paths, both non-fatal. If the **SDK in your app** predates
360
+ > this feature, only steps 1 and 2 run. If **Clivly** does not have the route
361
+ > yet, the command warns that it could not declare them and still exits `0` —
362
+ > your schema did land, so re-running once Clivly is upgraded finishes the job.
309
363
 
310
364
  ---
311
365
 
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_entity_config = require("./entity-config-DtBsl2MQ.cjs");
2
+ const require_entity_config = require("./entity-config-7sGCk_nw.cjs");
3
3
  //#region src/core-entity-config.ts
4
4
  require("./deprecate-subpath-B9ngvizt.cjs").warnDeprecatedSubpath("clivly/core/entity-config", "clivly/internal/entity-config");
5
5
  //#endregion
@@ -1,4 +1,4 @@
1
- import { a as MATERIALIZING_CONCEPTS, c as entitiesConfigSchema, d as relationshipSchema, f as relationshipsSchema, i as ClivlyConfigError, l as filterSchema, n as CRM_CONCEPTS, o as customObjectDeclarations, p as validateEntitiesConfig, r as CUSTOM_CONCEPT, s as defineClivlyConfig, t as CANONICAL_FIELDS, u as projectionFields } from "./entity-config-kUHri9yA.mjs";
1
+ import { a as MATERIALIZING_CONCEPTS, c as entitiesConfigSchema, d as relationshipSchema, f as relationshipsSchema, i as ClivlyConfigError, l as filterSchema, n as CRM_CONCEPTS, o as customObjectDeclarations, p as validateEntitiesConfig, r as CUSTOM_CONCEPT, s as defineClivlyConfig, t as CANONICAL_FIELDS, u as projectionFields } from "./entity-config-B74SPOUZ.mjs";
2
2
  import { t as warnDeprecatedSubpath } from "./deprecate-subpath-CmvZtCpE.mjs";
3
3
  //#region src/core-entity-config.ts
4
4
  warnDeprecatedSubpath("clivly/core/entity-config", "clivly/internal/entity-config");
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_mappings_config = require("./mappings-config-B0RqFLxu.cjs");
2
+ const require_mappings_config = require("./mappings-config-CLyEg0sf.cjs");
3
3
  const require_deprecate_subpath = require("./deprecate-subpath-B9ngvizt.cjs");
4
4
  require("./internal-mappings-config.cjs");
5
5
  //#region src/core-mappings-config.ts
@@ -1,4 +1,4 @@
1
- import { n as mappingsToEntitiesConfig, t as entitiesToMappings } from "./mappings-config-B1b1HVBg.mjs";
1
+ import { n as mappingsToEntitiesConfig, t as entitiesToMappings } from "./mappings-config-DQS_s4dg.mjs";
2
2
  import { t as warnDeprecatedSubpath } from "./deprecate-subpath-CmvZtCpE.mjs";
3
3
  import "./internal-mappings-config.mjs";
4
4
  //#region src/core-mappings-config.ts
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_deprecate_subpath = require("./deprecate-subpath-B9ngvizt.cjs");
3
- const require_sync_engine = require("./sync-engine-abE94g6X.cjs");
3
+ const require_sync_engine = require("./sync-engine-C4A5jgA4.cjs");
4
4
  require("./internal-sync-engine.cjs");
5
5
  //#region src/core-sync-engine.ts
6
6
  require_deprecate_subpath.warnDeprecatedSubpath("clivly/core/sync-engine", "clivly/internal/sync-engine");
@@ -1,5 +1,5 @@
1
1
  import { t as warnDeprecatedSubpath } from "./deprecate-subpath-CmvZtCpE.mjs";
2
- import { i as runSync, n as previewSync, r as reconcile, t as computeSampleWarnings } from "./sync-engine-SuxSzbZ4.mjs";
2
+ import { i as runSync, n as previewSync, r as reconcile, t as computeSampleWarnings } from "./sync-engine-Dt5QQSKO.mjs";
3
3
  import "./internal-sync-engine.mjs";
4
4
  //#region src/core-sync-engine.ts
5
5
  warnDeprecatedSubpath("clivly/core/sync-engine", "clivly/internal/sync-engine");
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_deprecate_subpath = require("./deprecate-subpath-B9ngvizt.cjs");
3
- const require_view_compiler = require("./view-compiler-Blu4OXJ7.cjs");
3
+ const require_view_compiler = require("./view-compiler-B5nDal14.cjs");
4
4
  require("./internal-view-compiler.cjs");
5
5
  //#region src/core-view-compiler.ts
6
6
  require_deprecate_subpath.warnDeprecatedSubpath("clivly/core/view-compiler", "clivly/internal/view-compiler");
@@ -1,5 +1,5 @@
1
1
  import { t as warnDeprecatedSubpath } from "./deprecate-subpath-CmvZtCpE.mjs";
2
- import { a as explainViewExecutionError, i as explainEntitiesConfig, n as compileEntityView, r as compileEntityViews, t as DEFAULT_VIEW_PREFIX } from "./view-compiler-CQx8TRrW.mjs";
2
+ import { a as explainViewExecutionError, i as explainEntitiesConfig, n as compileEntityView, r as compileEntityViews, t as DEFAULT_VIEW_PREFIX } from "./view-compiler-CSYwEWf5.mjs";
3
3
  import "./internal-view-compiler.mjs";
4
4
  //#region src/core-view-compiler.ts
5
5
  warnDeprecatedSubpath("clivly/core/view-compiler", "clivly/internal/view-compiler");
package/core.cjs CHANGED
@@ -1,13 +1,14 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_projection = require("./projection-C5244vGa.cjs");
3
- const require_entity_config = require("./entity-config-DtBsl2MQ.cjs");
4
- const require_mappings_config = require("./mappings-config-B0RqFLxu.cjs");
2
+ const require_projection = require("./projection-Dz6_i1-w.cjs");
3
+ const require_entity_config = require("./entity-config-7sGCk_nw.cjs");
4
+ const require_mappings_config = require("./mappings-config-CLyEg0sf.cjs");
5
5
  const require_deprecate_subpath = require("./deprecate-subpath-B9ngvizt.cjs");
6
6
  const require_auth_adapter = require("./auth-adapter-CiEXcweZ.cjs");
7
7
  const require_mapping_form = require("./mapping-form-BpfON_ME.cjs");
8
- const require_internal = require("./internal-CwnEG6Wl.cjs");
9
- const require_view_compiler = require("./view-compiler-Blu4OXJ7.cjs");
10
- const require_sync_engine = require("./sync-engine-abE94g6X.cjs");
8
+ const require_internal = require("./internal-DqduZU3l.cjs");
9
+ const require_projection_sql = require("./projection-sql-Cl1qIn8m.cjs");
10
+ const require_view_compiler = require("./view-compiler-B5nDal14.cjs");
11
+ const require_sync_engine = require("./sync-engine-C4A5jgA4.cjs");
11
12
  //#region src/core.ts
12
13
  require_deprecate_subpath.warnDeprecatedSubpath("clivly/core", "clivly/sdk", "Import \"defineClivlyConfig\" and its config types from \"clivly/sdk\"; import everything else from \"clivly/internal\" (no stability guarantee — see STABILITY.md).");
13
14
  //#endregion
@@ -23,6 +24,9 @@ exports.buildRelationships = require_mapping_form.buildRelationships;
23
24
  exports.columnMetaFor = require_entity_config.columnMetaFor;
24
25
  exports.compileEntityView = require_view_compiler.compileEntityView;
25
26
  exports.compileEntityViews = require_view_compiler.compileEntityViews;
27
+ exports.compileProjectionFrom = require_projection_sql.compileProjectionFrom;
28
+ exports.compileProjectionIdentity = require_projection_sql.compileProjectionIdentity;
29
+ exports.compileProjectionJoins = require_projection_sql.compileProjectionJoins;
26
30
  exports.coversUniqueKey = require_entity_config.coversUniqueKey;
27
31
  exports.defineClivlyConfig = require_entity_config.defineClivlyConfig;
28
32
  exports.describeCardinality = require_internal.describeCardinality;
@@ -39,6 +43,7 @@ exports.joinFansOut = require_entity_config.joinFansOut;
39
43
  exports.mappingsToEntitiesConfig = require_mappings_config.mappingsToEntitiesConfig;
40
44
  exports.primaryKeyColumns = require_entity_config.primaryKeyColumns;
41
45
  exports.projectionSchema = require_projection.projectionSchema;
46
+ exports.quoteIdent = require_projection_sql.quoteIdent;
42
47
  exports.reconcile = require_sync_engine.reconcile;
43
48
  exports.relationshipSchema = require_entity_config.relationshipSchema;
44
49
  exports.relationshipViaSignature = require_mapping_form.relationshipViaSignature;
package/core.d.cts CHANGED
@@ -6,5 +6,6 @@ import { i as relationshipViaSignature, n as buildFilterFromDiscriminator, r as
6
6
  import { i as mappingsToEntitiesConfig, t as EntityMappingRow } from "./mappings-config-RQLGx8ub.cjs";
7
7
  import { a as compileEntityView, i as ExplainResult, n as CompiledView, o as compileEntityViews, r as DEFAULT_VIEW_PREFIX, s as explainEntitiesConfig, t as CompileOptions } from "./view-compiler-CmEdAMwj.cjs";
8
8
  import { c as SyncResult, f as reconcile, l as SyncStore, n as MirrorRecord, o as SourceRow, p as runSync, r as PersistAction, s as SyncAction, t as EntitySyncResult } from "./sync-engine-BG2O1an2.cjs";
9
- import { a as validateProjection, c as draftErrors, d as suggestJoinConditions, f as fanOutJoins, i as primaryKeyColumns, l as draftToProjection, n as coversUniqueKey, o as ProjectionDraft, p as joinFansOut, r as hasRichMeta, s as describeCardinality, t as columnMetaFor, u as emptyProjectionDraft } from "./internal-Da_dlcQ_.cjs";
10
- export { type Activity, type ActivityType, BASE_REF, CANONICAL_FIELDS, type CRMAdapter, CRM_CONCEPTS, type ClivlyAuthAdapter, ClivlyConfigError, type ClivlyEntitiesConfig, type ClivlyEntityConfig, type ClivlyUser, type Company, type CompileOptions, type CompiledView, type ConfigValidationError, type ConfigValidationResult, type Contact, type ContactFilters, type ContactStatus, type CreateActivityInput, type CreateCompanyInput, type CreateContactInput, type CreateDealInput, type CreateTaskInput, type CrmConcept, type CrmMembership, type CrmRole, DEFAULT_VIEW_PREFIX, type Deal, type DealStage, type DiscoveredColumnMeta, type DiscoveredSchemaTable, type EntityMappingRow, type EntitySyncResult, type ExplainResult, type FilterExpr, type FilterValue, MATERIALIZING_CONCEPTS, type MaterializingConcept, type MembershipResolver, type MirrorRecord, type Note, type PersistAction, type ProjectionDraft, type ProjectionFieldBinding, type ProjectionIdentity, type ProjectionJoin, type ProjectionMapping, type ProjectionRef, type RecordSource, type RelationshipCandidate, type RelationshipSpec, type RelationshipVia, type RelationshipsMap, type SourceRow, type SyncAction, type SyncResult, type SyncStore, type Task, type TaskEntityType, type TaskFilters, type TaskPriority, type TaskStatus, type UpdateContactInput, type UpdateDealInput, type UpdateTaskInput, authCustom, buildFilterFromDiscriminator, buildRelationships, columnMetaFor, compileEntityView, compileEntityViews, coversUniqueKey, defineClivlyConfig, describeCardinality, draftErrors, draftToProjection, emptyProjectionDraft, entitiesConfigSchema, explainEntitiesConfig, fanOutJoins, filterSchema, hasRichMeta, identityRefs, joinFansOut, mappingsToEntitiesConfig, primaryKeyColumns, projectionSchema, reconcile, relationshipSchema, relationshipViaSignature, relationshipsSchema, runSync, suggestJoinConditions, validateEntitiesConfig, validateProjection };
9
+ import { a as IntegrationStep, c as StepProblem, i as IntegrationStatus, l as StepState, n as IntegrationFacts, o as NextAction, r as IntegrationState, s as StepId, t as ConnectionLiveness } from "./integration-state-BK-riZnm.cjs";
10
+ import { _ as joinFansOut, a as validateProjection, c as compileProjectionJoins, d as describeCardinality, f as draftErrors, g as fanOutJoins, h as suggestJoinConditions, i as primaryKeyColumns, l as quoteIdent, m as emptyProjectionDraft, n as coversUniqueKey, o as compileProjectionFrom, p as draftToProjection, r as hasRichMeta, s as compileProjectionIdentity, t as columnMetaFor, u as ProjectionDraft } from "./internal-wCXSELDN.cjs";
11
+ export { type Activity, type ActivityType, BASE_REF, CANONICAL_FIELDS, type CRMAdapter, CRM_CONCEPTS, type ClivlyAuthAdapter, ClivlyConfigError, type ClivlyEntitiesConfig, type ClivlyEntityConfig, type ClivlyUser, type Company, type CompileOptions, type CompiledView, type ConfigValidationError, type ConfigValidationResult, type ConnectionLiveness, type Contact, type ContactFilters, type ContactStatus, type CreateActivityInput, type CreateCompanyInput, type CreateContactInput, type CreateDealInput, type CreateTaskInput, type CrmConcept, type CrmMembership, type CrmRole, DEFAULT_VIEW_PREFIX, type Deal, type DealStage, type DiscoveredColumnMeta, type DiscoveredSchemaTable, type EntityMappingRow, type EntitySyncResult, type ExplainResult, type FilterExpr, type FilterValue, type IntegrationFacts, type IntegrationState, type IntegrationStatus, type IntegrationStep, MATERIALIZING_CONCEPTS, type MaterializingConcept, type MembershipResolver, type MirrorRecord, type NextAction, type Note, type PersistAction, type ProjectionDraft, type ProjectionFieldBinding, type ProjectionIdentity, type ProjectionJoin, type ProjectionMapping, type ProjectionRef, type RecordSource, type RelationshipCandidate, type RelationshipSpec, type RelationshipVia, type RelationshipsMap, type SourceRow, type StepId, type StepProblem, type StepState, type SyncAction, type SyncResult, type SyncStore, type Task, type TaskEntityType, type TaskFilters, type TaskPriority, type TaskStatus, type UpdateContactInput, type UpdateDealInput, type UpdateTaskInput, authCustom, buildFilterFromDiscriminator, buildRelationships, columnMetaFor, compileEntityView, compileEntityViews, compileProjectionFrom, compileProjectionIdentity, compileProjectionJoins, coversUniqueKey, defineClivlyConfig, describeCardinality, draftErrors, draftToProjection, emptyProjectionDraft, entitiesConfigSchema, explainEntitiesConfig, fanOutJoins, filterSchema, hasRichMeta, identityRefs, joinFansOut, mappingsToEntitiesConfig, primaryKeyColumns, projectionSchema, quoteIdent, reconcile, relationshipSchema, relationshipViaSignature, relationshipsSchema, runSync, suggestJoinConditions, validateEntitiesConfig, validateProjection };
package/core.d.mts CHANGED
@@ -6,5 +6,6 @@ import { i as relationshipViaSignature, n as buildFilterFromDiscriminator, r as
6
6
  import { i as mappingsToEntitiesConfig, t as EntityMappingRow } from "./mappings-config-D9dsonoi.mjs";
7
7
  import { a as compileEntityView, i as ExplainResult, n as CompiledView, o as compileEntityViews, r as DEFAULT_VIEW_PREFIX, s as explainEntitiesConfig, t as CompileOptions } from "./view-compiler-Bo7pqXW3.mjs";
8
8
  import { c as SyncResult, f as reconcile, l as SyncStore, n as MirrorRecord, o as SourceRow, p as runSync, r as PersistAction, s as SyncAction, t as EntitySyncResult } from "./sync-engine-DgQbrJON.mjs";
9
- import { a as validateProjection, c as draftErrors, d as suggestJoinConditions, f as fanOutJoins, i as primaryKeyColumns, l as draftToProjection, n as coversUniqueKey, o as ProjectionDraft, p as joinFansOut, r as hasRichMeta, s as describeCardinality, t as columnMetaFor, u as emptyProjectionDraft } from "./internal-CDY8g9Ic.mjs";
10
- export { type Activity, type ActivityType, BASE_REF, CANONICAL_FIELDS, type CRMAdapter, CRM_CONCEPTS, type ClivlyAuthAdapter, ClivlyConfigError, type ClivlyEntitiesConfig, type ClivlyEntityConfig, type ClivlyUser, type Company, type CompileOptions, type CompiledView, type ConfigValidationError, type ConfigValidationResult, type Contact, type ContactFilters, type ContactStatus, type CreateActivityInput, type CreateCompanyInput, type CreateContactInput, type CreateDealInput, type CreateTaskInput, type CrmConcept, type CrmMembership, type CrmRole, DEFAULT_VIEW_PREFIX, type Deal, type DealStage, type DiscoveredColumnMeta, type DiscoveredSchemaTable, type EntityMappingRow, type EntitySyncResult, type ExplainResult, type FilterExpr, type FilterValue, MATERIALIZING_CONCEPTS, type MaterializingConcept, type MembershipResolver, type MirrorRecord, type Note, type PersistAction, type ProjectionDraft, type ProjectionFieldBinding, type ProjectionIdentity, type ProjectionJoin, type ProjectionMapping, type ProjectionRef, type RecordSource, type RelationshipCandidate, type RelationshipSpec, type RelationshipVia, type RelationshipsMap, type SourceRow, type SyncAction, type SyncResult, type SyncStore, type Task, type TaskEntityType, type TaskFilters, type TaskPriority, type TaskStatus, type UpdateContactInput, type UpdateDealInput, type UpdateTaskInput, authCustom, buildFilterFromDiscriminator, buildRelationships, columnMetaFor, compileEntityView, compileEntityViews, coversUniqueKey, defineClivlyConfig, describeCardinality, draftErrors, draftToProjection, emptyProjectionDraft, entitiesConfigSchema, explainEntitiesConfig, fanOutJoins, filterSchema, hasRichMeta, identityRefs, joinFansOut, mappingsToEntitiesConfig, primaryKeyColumns, projectionSchema, reconcile, relationshipSchema, relationshipViaSignature, relationshipsSchema, runSync, suggestJoinConditions, validateEntitiesConfig, validateProjection };
9
+ import { a as IntegrationStep, c as StepProblem, i as IntegrationStatus, l as StepState, n as IntegrationFacts, o as NextAction, r as IntegrationState, s as StepId, t as ConnectionLiveness } from "./integration-state-BK-riZnm.mjs";
10
+ import { _ as joinFansOut, a as validateProjection, c as compileProjectionJoins, d as describeCardinality, f as draftErrors, g as fanOutJoins, h as suggestJoinConditions, i as primaryKeyColumns, l as quoteIdent, m as emptyProjectionDraft, n as coversUniqueKey, o as compileProjectionFrom, p as draftToProjection, r as hasRichMeta, s as compileProjectionIdentity, t as columnMetaFor, u as ProjectionDraft } from "./internal-o2M7FGlR.mjs";
11
+ export { type Activity, type ActivityType, BASE_REF, CANONICAL_FIELDS, type CRMAdapter, CRM_CONCEPTS, type ClivlyAuthAdapter, ClivlyConfigError, type ClivlyEntitiesConfig, type ClivlyEntityConfig, type ClivlyUser, type Company, type CompileOptions, type CompiledView, type ConfigValidationError, type ConfigValidationResult, type ConnectionLiveness, type Contact, type ContactFilters, type ContactStatus, type CreateActivityInput, type CreateCompanyInput, type CreateContactInput, type CreateDealInput, type CreateTaskInput, type CrmConcept, type CrmMembership, type CrmRole, DEFAULT_VIEW_PREFIX, type Deal, type DealStage, type DiscoveredColumnMeta, type DiscoveredSchemaTable, type EntityMappingRow, type EntitySyncResult, type ExplainResult, type FilterExpr, type FilterValue, type IntegrationFacts, type IntegrationState, type IntegrationStatus, type IntegrationStep, MATERIALIZING_CONCEPTS, type MaterializingConcept, type MembershipResolver, type MirrorRecord, type NextAction, type Note, type PersistAction, type ProjectionDraft, type ProjectionFieldBinding, type ProjectionIdentity, type ProjectionJoin, type ProjectionMapping, type ProjectionRef, type RecordSource, type RelationshipCandidate, type RelationshipSpec, type RelationshipVia, type RelationshipsMap, type SourceRow, type StepId, type StepProblem, type StepState, type SyncAction, type SyncResult, type SyncStore, type Task, type TaskEntityType, type TaskFilters, type TaskPriority, type TaskStatus, type UpdateContactInput, type UpdateDealInput, type UpdateTaskInput, authCustom, buildFilterFromDiscriminator, buildRelationships, columnMetaFor, compileEntityView, compileEntityViews, compileProjectionFrom, compileProjectionIdentity, compileProjectionJoins, coversUniqueKey, defineClivlyConfig, describeCardinality, draftErrors, draftToProjection, emptyProjectionDraft, entitiesConfigSchema, explainEntitiesConfig, fanOutJoins, filterSchema, hasRichMeta, identityRefs, joinFansOut, mappingsToEntitiesConfig, primaryKeyColumns, projectionSchema, quoteIdent, reconcile, relationshipSchema, relationshipViaSignature, relationshipsSchema, runSync, suggestJoinConditions, validateEntitiesConfig, validateProjection };
package/core.mjs CHANGED
@@ -1,13 +1,14 @@
1
- import { i as projectionSchema, r as identityRefs, t as BASE_REF } from "./projection-D7xmQP4S.mjs";
2
- import { _ as columnMetaFor, a as MATERIALIZING_CONCEPTS, b as primaryKeyColumns, c as entitiesConfigSchema, d as relationshipSchema, f as relationshipsSchema, g as joinFansOut, h as fanOutJoins, i as ClivlyConfigError, l as filterSchema, m as validateProjection, n as CRM_CONCEPTS, p as validateEntitiesConfig, s as defineClivlyConfig, t as CANONICAL_FIELDS, v as coversUniqueKey, y as hasRichMeta } from "./entity-config-kUHri9yA.mjs";
3
- import { n as mappingsToEntitiesConfig } from "./mappings-config-B1b1HVBg.mjs";
1
+ import { i as projectionSchema, r as identityRefs, t as BASE_REF } from "./projection-CSGJbZlZ.mjs";
2
+ import { _ as columnMetaFor, a as MATERIALIZING_CONCEPTS, b as primaryKeyColumns, c as entitiesConfigSchema, d as relationshipSchema, f as relationshipsSchema, g as joinFansOut, h as fanOutJoins, i as ClivlyConfigError, l as filterSchema, m as validateProjection, n as CRM_CONCEPTS, p as validateEntitiesConfig, s as defineClivlyConfig, t as CANONICAL_FIELDS, v as coversUniqueKey, y as hasRichMeta } from "./entity-config-B74SPOUZ.mjs";
3
+ import { n as mappingsToEntitiesConfig } from "./mappings-config-DQS_s4dg.mjs";
4
4
  import { t as warnDeprecatedSubpath } from "./deprecate-subpath-CmvZtCpE.mjs";
5
5
  import { t as authCustom } from "./auth-adapter-gfVDxf3d.mjs";
6
6
  import { n as buildRelationships, r as relationshipViaSignature, t as buildFilterFromDiscriminator } from "./mapping-form-DigkuvFc.mjs";
7
- import { a as suggestJoinConditions, i as emptyProjectionDraft, n as draftErrors, r as draftToProjection, t as describeCardinality } from "./internal-Df-PtOH_.mjs";
8
- import { i as explainEntitiesConfig, n as compileEntityView, r as compileEntityViews, t as DEFAULT_VIEW_PREFIX } from "./view-compiler-CQx8TRrW.mjs";
9
- import { i as runSync, r as reconcile } from "./sync-engine-SuxSzbZ4.mjs";
7
+ import { a as suggestJoinConditions, i as emptyProjectionDraft, n as draftErrors, r as draftToProjection, t as describeCardinality } from "./internal-CykXpEGk.mjs";
8
+ import { a as quoteIdent, n as compileProjectionIdentity, r as compileProjectionJoins, t as compileProjectionFrom } from "./projection-sql-BgnfiGqF.mjs";
9
+ import { i as explainEntitiesConfig, n as compileEntityView, r as compileEntityViews, t as DEFAULT_VIEW_PREFIX } from "./view-compiler-CSYwEWf5.mjs";
10
+ import { i as runSync, r as reconcile } from "./sync-engine-Dt5QQSKO.mjs";
10
11
  //#region src/core.ts
11
12
  warnDeprecatedSubpath("clivly/core", "clivly/sdk", "Import \"defineClivlyConfig\" and its config types from \"clivly/sdk\"; import everything else from \"clivly/internal\" (no stability guarantee — see STABILITY.md).");
12
13
  //#endregion
13
- export { BASE_REF, CANONICAL_FIELDS, CRM_CONCEPTS, ClivlyConfigError, DEFAULT_VIEW_PREFIX, MATERIALIZING_CONCEPTS, authCustom, buildFilterFromDiscriminator, buildRelationships, columnMetaFor, compileEntityView, compileEntityViews, coversUniqueKey, defineClivlyConfig, describeCardinality, draftErrors, draftToProjection, emptyProjectionDraft, entitiesConfigSchema, explainEntitiesConfig, fanOutJoins, filterSchema, hasRichMeta, identityRefs, joinFansOut, mappingsToEntitiesConfig, primaryKeyColumns, projectionSchema, reconcile, relationshipSchema, relationshipViaSignature, relationshipsSchema, runSync, suggestJoinConditions, validateEntitiesConfig, validateProjection };
14
+ export { BASE_REF, CANONICAL_FIELDS, CRM_CONCEPTS, ClivlyConfigError, DEFAULT_VIEW_PREFIX, MATERIALIZING_CONCEPTS, authCustom, buildFilterFromDiscriminator, buildRelationships, columnMetaFor, compileEntityView, compileEntityViews, compileProjectionFrom, compileProjectionIdentity, compileProjectionJoins, coversUniqueKey, defineClivlyConfig, describeCardinality, draftErrors, draftToProjection, emptyProjectionDraft, entitiesConfigSchema, explainEntitiesConfig, fanOutJoins, filterSchema, hasRichMeta, identityRefs, joinFansOut, mappingsToEntitiesConfig, primaryKeyColumns, projectionSchema, quoteIdent, reconcile, relationshipSchema, relationshipViaSignature, relationshipsSchema, runSync, suggestJoinConditions, validateEntitiesConfig, validateProjection };
package/drizzle.cjs CHANGED
@@ -1,7 +1,78 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_projection = require("./projection-Dz6_i1-w.cjs");
2
3
  const require_drizzle_meta = require("./drizzle-meta-Bb1JWYqf.cjs");
4
+ const require_projection_sql = require("./projection-sql-Cl1qIn8m.cjs");
3
5
  const require_drizzle = require("./drizzle-bfjVzYR6.cjs");
4
6
  let drizzle_orm = require("drizzle-orm");
7
+ //#region ../sdk/src/drizzle-projection.ts
8
+ /** `<ref>.<column>` — the token `fields` carries and cloud-ingest reads. */
9
+ function refToken(ref) {
10
+ return `${ref.table}.${ref.column}`;
11
+ }
12
+ function refSql(ref) {
13
+ return `${require_projection_sql.quoteIdent(ref.table)}.${require_projection_sql.quoteIdent(ref.column)}`;
14
+ }
15
+ function parseRef(value) {
16
+ if (typeof value !== "string") return value;
17
+ const dot = value.indexOf(".");
18
+ if (dot <= 0 || dot === value.length - 1) throw new Error(`fromDrizzleProjection: cursorField "${value}" must be a ref token like "base.updated_at".`);
19
+ return {
20
+ table: value.slice(0, dot),
21
+ column: value.slice(dot + 1)
22
+ };
23
+ }
24
+ /**
25
+ * Refs address tables symbolically — `base` or a join key — never by table name,
26
+ * which is what stops a projection reaching a table it did not declare. An
27
+ * unresolvable ref would otherwise compile to SQL referencing a missing alias
28
+ * and fail at the database with a message that never mentions the config.
29
+ */
30
+ function assertKnownRef(ref, known, context) {
31
+ if (!known.has(ref.table)) throw new Error(`fromDrizzleProjection: ${context} names unknown ref "${ref.table}" — expected "${[...known].join("\", \"")}".`);
32
+ }
33
+ function normalizeRows(result) {
34
+ if (Array.isArray(result)) return result;
35
+ const rows = result.rows;
36
+ if (Array.isArray(rows)) return rows;
37
+ throw new Error("fromDrizzleProjection: db.execute() returned neither an array of rows nor { rows }.");
38
+ }
39
+ function fromDrizzleProjection(db, projection, opts) {
40
+ const client = db;
41
+ const known = /* @__PURE__ */ new Set([require_projection.BASE_REF, ...projection.joins.map((j) => j.key)]);
42
+ if (projection.identity.kind === "base_pk" && projection.identity.column === void 0 && opts.basePkColumn === void 0) throw new Error(`fromDrizzleProjection: projection "${projection.entityKey}" has a base_pk identity with no column — pass { basePkColumn }.`);
43
+ const cursorRef = parseRef(opts.cursorField);
44
+ assertKnownRef(cursorRef, known, "cursorField");
45
+ for (const [field, binding] of Object.entries(projection.fieldBindings)) assertKnownRef(binding.from, known, `field "${field}"`);
46
+ const identityExpr = require_projection_sql.compileProjectionIdentity(projection, opts.basePkColumn ?? "");
47
+ const cursorToken = refToken(cursorRef);
48
+ const cursorExpr = `CAST(${refSql(cursorRef)} AS timestamptz)`;
49
+ const cursorRead = `to_char(${cursorExpr} AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"')`;
50
+ const selectItems = [`${identityExpr} AS ${require_projection_sql.quoteIdent("id")}`, `${cursorRead} AS ${require_projection_sql.quoteIdent(cursorToken)}`];
51
+ const emitted = /* @__PURE__ */ new Set([cursorToken]);
52
+ for (const binding of Object.values(projection.fieldBindings)) {
53
+ const token = refToken(binding.from);
54
+ if (emitted.has(token)) continue;
55
+ emitted.add(token);
56
+ selectItems.push(`${refSql(binding.from)} AS ${require_projection_sql.quoteIdent(token)}`);
57
+ }
58
+ const head = [
59
+ `select ${selectItems.join(", ")}`,
60
+ require_projection_sql.compileProjectionFrom(projection),
61
+ ...require_projection_sql.compileProjectionJoins(projection)
62
+ ].join(" ");
63
+ return {
64
+ entity: opts.entity,
65
+ cursorField: cursorToken,
66
+ idField: "id",
67
+ ...opts.objectType === void 0 ? {} : { objectType: opts.objectType },
68
+ fetchPage: async ({ since, limit }) => {
69
+ const where = since ? drizzle_orm.sql` where (${drizzle_orm.sql.raw(cursorExpr)}, ${drizzle_orm.sql.raw(identityExpr)}) > (${since.time.toISOString()}::timestamptz, ${since.id})` : drizzle_orm.sql``;
70
+ const query = drizzle_orm.sql`${drizzle_orm.sql.raw(head)}${where} order by ${drizzle_orm.sql.raw(cursorExpr)} asc, ${drizzle_orm.sql.raw(identityExpr)} asc limit ${limit}`;
71
+ return normalizeRows(await client.execute(query));
72
+ }
73
+ };
74
+ }
75
+ //#endregion
5
76
  //#region ../sdk/src/drizzle.ts
6
77
  function inferIdField(table) {
7
78
  const columns = (0, drizzle_orm.getTableColumns)(table);
@@ -14,14 +85,6 @@ function inferIdField(table) {
14
85
  const kind = primaryKeys.length === 0 ? "no" : "a composite";
15
86
  throw new Error(`fromDrizzle: table "${(0, drizzle_orm.getTableName)(table)}" has ${kind} single-column primary key — pass { idField } explicitly.`);
16
87
  }
17
- /**
18
- * Build a `SyncSource` from a Drizzle table, generating the keyset-paginated
19
- * `fetchPage` the SDK needs. `cursorField`/`idField` are drizzle property keys;
20
- * `idField` defaults to the table's single-column primary key.
21
- *
22
- * `drizzle-orm` is an optional peer dependency — installed only when you import
23
- * `@clivly/sdk/drizzle`.
24
- */
25
88
  function fromDrizzle(db, table, opts) {
26
89
  const drizzleDb = db;
27
90
  const idField = opts.idField ?? inferIdField(table);
@@ -38,7 +101,8 @@ function fromDrizzle(db, table, opts) {
38
101
  entity: opts.entity,
39
102
  cursorField: cursorColumnName,
40
103
  idField: idColumnName,
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)
104
+ 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),
105
+ ...opts.objectType === void 0 ? {} : { objectType: opts.objectType }
42
106
  };
43
107
  const uniqueConstraints = require_drizzle.buildUniqueConstraints(table);
44
108
  const meta = {
@@ -79,3 +143,4 @@ exports.buildUniqueConstraints = require_drizzle.buildUniqueConstraints;
79
143
  exports.discoverFromDrizzle = require_drizzle.discoverFromDrizzle;
80
144
  exports.drizzleIntrospector = drizzleIntrospector;
81
145
  exports.fromDrizzle = fromDrizzle;
146
+ exports.fromDrizzleProjection = fromDrizzleProjection;
package/drizzle.d.cts CHANGED
@@ -1,23 +1,99 @@
1
+ import { F as ProjectionRef, P as ProjectionMapping } from "./entity-config-B2RA53nw.cjs";
1
2
  import { n as buildUniqueConstraints, r as discoverFromDrizzle } from "./drizzle-DEtRrqtc.cjs";
2
- import { _ as SyncSource, t as NamespaceIntrospector } from "./namespace-probe-C6aHjedO.cjs";
3
+ import { _ as SyncSource, t as NamespaceIntrospector } from "./namespace-probe-BoGI18dQ.cjs";
3
4
  import { Table } from "drizzle-orm";
5
+ //#region ../sdk/src/drizzle-projection.d.ts
6
+ /**
7
+ * Build a `SyncSource` that actually executes a projection's joins.
8
+ *
9
+ * `fromDrizzle` emits a single-table select, so a projection entity paired with
10
+ * it pushed raw base-table rows and every joined field mirrored empty — the
11
+ * declared joins were inert, and the only symptom was a dry run reporting a
12
+ * missing column whose name was correct.
13
+ *
14
+ * The row shape is the contract the cloud already relies on. A projection's
15
+ * `fields` are ref *tokens* (`client_name -> "cl.full_name"`, from
16
+ * `projectionFields`), and `cloud-ingest` reads `row[token]` verbatim plus
17
+ * `row.id` for `sourceRef`. So this aliases every binding by its token rather
18
+ * than by its field name.
19
+ *
20
+ * That is the one deliberate difference from the view compiler, which aliases
21
+ * by field name because the sync engine reads the compiled view directly. FROM,
22
+ * JOIN and the identity expression all come from `@clivly/core`, so both paths
23
+ * join identically and produce the same `id` for the same row.
24
+ *
25
+ * `drizzle-orm` is an optional peer dependency — installed only when you import
26
+ * `@clivly/sdk/drizzle`. The `db` only needs `.execute()`, the same surface
27
+ * `drizzleIntrospector` requires.
28
+ */
29
+ interface FromDrizzleProjectionOptions {
30
+ /**
31
+ * The base table's primary key, required only when `identity` is `base_pk`
32
+ * without an explicit column. Unlike `fromDrizzle` there is no `Table` object
33
+ * to infer it from — a projection names tables as strings.
34
+ */
35
+ basePkColumn?: string;
36
+ /**
37
+ * The column to keyset-paginate on, as a ref token (`"base.updated_at"`) or
38
+ * a `ProjectionRef`. A projection spans several tables, so there is no
39
+ * single table to infer a cursor from.
40
+ */
41
+ cursorField: string | ProjectionRef;
42
+ /** The source name rows are pushed under. */
43
+ entity: string;
44
+ /**
45
+ * The custom object slug. Accepted here so the result is directly assignable
46
+ * to `source.custom` — bolting it on with a spread afterwards drops the
47
+ * non-enumerable drizzle metadata.
48
+ */
49
+ objectType?: string;
50
+ }
51
+ declare function fromDrizzleProjection(db: unknown, projection: ProjectionMapping, opts: FromDrizzleProjectionOptions & {
52
+ objectType: string;
53
+ }): SyncSource & {
54
+ objectType: string;
55
+ };
56
+ declare function fromDrizzleProjection(db: unknown, projection: ProjectionMapping, opts: FromDrizzleProjectionOptions): SyncSource;
57
+ //#endregion
4
58
  //#region ../sdk/src/drizzle.d.ts
5
59
  interface DrizzleDb {
6
60
  select: (...args: any[]) => any;
7
61
  }
62
+ interface FromDrizzleOptions {
63
+ cursorField: string;
64
+ entity: string;
65
+ idField?: string;
66
+ /**
67
+ * Custom-object slug, for sources destined for `source.custom`.
68
+ *
69
+ * Pass it here rather than attaching it afterwards. `source.custom` is typed
70
+ * `Array<SyncSource & { objectType: string }>`, so before this option existed
71
+ * the only way to satisfy that type was to bolt the property on post-hoc —
72
+ * and the idiomatic spread (`{ ...fromDrizzle(...), objectType }`) copies only
73
+ * ENUMERABLE own properties, silently dropping the non-enumerable
74
+ * `DRIZZLE_META` below. `doctor` would then report a `fromDrizzle` source as
75
+ * "hand-written" and skip its cursor/id column checks, which is both a lost
76
+ * check and a false explanation.
77
+ */
78
+ objectType?: string;
79
+ }
8
80
  /**
9
81
  * Build a `SyncSource` from a Drizzle table, generating the keyset-paginated
10
82
  * `fetchPage` the SDK needs. `cursorField`/`idField` are drizzle property keys;
11
83
  * `idField` defaults to the table's single-column primary key.
12
84
  *
85
+ * Pass `objectType` for custom objects — the result is then directly assignable
86
+ * to `source.custom` with no spread or mutation.
87
+ *
13
88
  * `drizzle-orm` is an optional peer dependency — installed only when you import
14
89
  * `@clivly/sdk/drizzle`.
15
90
  */
16
- declare function fromDrizzle(db: DrizzleDb, table: Table, opts: {
17
- entity: string;
18
- cursorField: string;
19
- idField?: string;
20
- }): SyncSource;
91
+ declare function fromDrizzle(db: DrizzleDb, table: Table, opts: FromDrizzleOptions & {
92
+ objectType: string;
93
+ }): SyncSource & {
94
+ objectType: string;
95
+ };
96
+ declare function fromDrizzle(db: DrizzleDb, table: Table, opts: FromDrizzleOptions): SyncSource;
21
97
  /**
22
98
  * Build a `NamespaceIntrospector` from any Drizzle client that exposes
23
99
  * `.execute()`. Reads `information_schema` in the connection's default schema
@@ -25,4 +101,4 @@ declare function fromDrizzle(db: DrizzleDb, table: Table, opts: {
25
101
  */
26
102
  declare function drizzleIntrospector(db: unknown): NamespaceIntrospector;
27
103
  //#endregion
28
- export { buildUniqueConstraints, discoverFromDrizzle, drizzleIntrospector, fromDrizzle };
104
+ export { type FromDrizzleProjectionOptions, buildUniqueConstraints, discoverFromDrizzle, drizzleIntrospector, fromDrizzle, fromDrizzleProjection };
package/drizzle.d.mts CHANGED
@@ -1,23 +1,99 @@
1
+ import { F as ProjectionRef, P as ProjectionMapping } from "./entity-config-B2RA53nw.mjs";
1
2
  import { n as buildUniqueConstraints, r as discoverFromDrizzle } from "./drizzle-CiK8MMEZ.mjs";
2
- import { _ as SyncSource, t as NamespaceIntrospector } from "./namespace-probe-Dj-0Q3Hb.mjs";
3
+ import { _ as SyncSource, t as NamespaceIntrospector } from "./namespace-probe-Cn7voAd0.mjs";
3
4
  import { Table } from "drizzle-orm";
5
+ //#region ../sdk/src/drizzle-projection.d.ts
6
+ /**
7
+ * Build a `SyncSource` that actually executes a projection's joins.
8
+ *
9
+ * `fromDrizzle` emits a single-table select, so a projection entity paired with
10
+ * it pushed raw base-table rows and every joined field mirrored empty — the
11
+ * declared joins were inert, and the only symptom was a dry run reporting a
12
+ * missing column whose name was correct.
13
+ *
14
+ * The row shape is the contract the cloud already relies on. A projection's
15
+ * `fields` are ref *tokens* (`client_name -> "cl.full_name"`, from
16
+ * `projectionFields`), and `cloud-ingest` reads `row[token]` verbatim plus
17
+ * `row.id` for `sourceRef`. So this aliases every binding by its token rather
18
+ * than by its field name.
19
+ *
20
+ * That is the one deliberate difference from the view compiler, which aliases
21
+ * by field name because the sync engine reads the compiled view directly. FROM,
22
+ * JOIN and the identity expression all come from `@clivly/core`, so both paths
23
+ * join identically and produce the same `id` for the same row.
24
+ *
25
+ * `drizzle-orm` is an optional peer dependency — installed only when you import
26
+ * `@clivly/sdk/drizzle`. The `db` only needs `.execute()`, the same surface
27
+ * `drizzleIntrospector` requires.
28
+ */
29
+ interface FromDrizzleProjectionOptions {
30
+ /**
31
+ * The base table's primary key, required only when `identity` is `base_pk`
32
+ * without an explicit column. Unlike `fromDrizzle` there is no `Table` object
33
+ * to infer it from — a projection names tables as strings.
34
+ */
35
+ basePkColumn?: string;
36
+ /**
37
+ * The column to keyset-paginate on, as a ref token (`"base.updated_at"`) or
38
+ * a `ProjectionRef`. A projection spans several tables, so there is no
39
+ * single table to infer a cursor from.
40
+ */
41
+ cursorField: string | ProjectionRef;
42
+ /** The source name rows are pushed under. */
43
+ entity: string;
44
+ /**
45
+ * The custom object slug. Accepted here so the result is directly assignable
46
+ * to `source.custom` — bolting it on with a spread afterwards drops the
47
+ * non-enumerable drizzle metadata.
48
+ */
49
+ objectType?: string;
50
+ }
51
+ declare function fromDrizzleProjection(db: unknown, projection: ProjectionMapping, opts: FromDrizzleProjectionOptions & {
52
+ objectType: string;
53
+ }): SyncSource & {
54
+ objectType: string;
55
+ };
56
+ declare function fromDrizzleProjection(db: unknown, projection: ProjectionMapping, opts: FromDrizzleProjectionOptions): SyncSource;
57
+ //#endregion
4
58
  //#region ../sdk/src/drizzle.d.ts
5
59
  interface DrizzleDb {
6
60
  select: (...args: any[]) => any;
7
61
  }
62
+ interface FromDrizzleOptions {
63
+ cursorField: string;
64
+ entity: string;
65
+ idField?: string;
66
+ /**
67
+ * Custom-object slug, for sources destined for `source.custom`.
68
+ *
69
+ * Pass it here rather than attaching it afterwards. `source.custom` is typed
70
+ * `Array<SyncSource & { objectType: string }>`, so before this option existed
71
+ * the only way to satisfy that type was to bolt the property on post-hoc —
72
+ * and the idiomatic spread (`{ ...fromDrizzle(...), objectType }`) copies only
73
+ * ENUMERABLE own properties, silently dropping the non-enumerable
74
+ * `DRIZZLE_META` below. `doctor` would then report a `fromDrizzle` source as
75
+ * "hand-written" and skip its cursor/id column checks, which is both a lost
76
+ * check and a false explanation.
77
+ */
78
+ objectType?: string;
79
+ }
8
80
  /**
9
81
  * Build a `SyncSource` from a Drizzle table, generating the keyset-paginated
10
82
  * `fetchPage` the SDK needs. `cursorField`/`idField` are drizzle property keys;
11
83
  * `idField` defaults to the table's single-column primary key.
12
84
  *
85
+ * Pass `objectType` for custom objects — the result is then directly assignable
86
+ * to `source.custom` with no spread or mutation.
87
+ *
13
88
  * `drizzle-orm` is an optional peer dependency — installed only when you import
14
89
  * `@clivly/sdk/drizzle`.
15
90
  */
16
- declare function fromDrizzle(db: DrizzleDb, table: Table, opts: {
17
- entity: string;
18
- cursorField: string;
19
- idField?: string;
20
- }): SyncSource;
91
+ declare function fromDrizzle(db: DrizzleDb, table: Table, opts: FromDrizzleOptions & {
92
+ objectType: string;
93
+ }): SyncSource & {
94
+ objectType: string;
95
+ };
96
+ declare function fromDrizzle(db: DrizzleDb, table: Table, opts: FromDrizzleOptions): SyncSource;
21
97
  /**
22
98
  * Build a `NamespaceIntrospector` from any Drizzle client that exposes
23
99
  * `.execute()`. Reads `information_schema` in the connection's default schema
@@ -25,4 +101,4 @@ declare function fromDrizzle(db: DrizzleDb, table: Table, opts: {
25
101
  */
26
102
  declare function drizzleIntrospector(db: unknown): NamespaceIntrospector;
27
103
  //#endregion
28
- export { buildUniqueConstraints, discoverFromDrizzle, drizzleIntrospector, fromDrizzle };
104
+ export { type FromDrizzleProjectionOptions, buildUniqueConstraints, discoverFromDrizzle, drizzleIntrospector, fromDrizzle, fromDrizzleProjection };