clivly 0.9.6 → 0.10.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 (146) hide show
  1. package/README.md +24 -12
  2. package/{adapter-C2eRbBfo.d.cts → adapter-1TN0zohk.d.cts} +1 -1
  3. package/{adapter-D5LRa-NA.d.mts → adapter-uxirB88i.d.mts} +1 -1
  4. package/{auth-adapter-Bjgo8LhN.d.mts → auth-adapter-CXTiW3Mb.d.cts} +1 -1
  5. package/{auth-adapter-DWzgl5Yq.d.cts → auth-adapter-DSuYwv1c.d.mts} +1 -1
  6. package/auth-better-auth.d.cts +1 -1
  7. package/auth-better-auth.d.mts +1 -1
  8. package/auth-clerk.d.cts +1 -1
  9. package/auth-clerk.d.mts +1 -1
  10. package/auth-workos.d.cts +1 -1
  11. package/auth-workos.d.mts +1 -1
  12. package/core-adapter.d.cts +1 -1
  13. package/core-adapter.d.mts +1 -1
  14. package/core-auth-adapter.cjs +1 -1
  15. package/core-auth-adapter.d.cts +1 -1
  16. package/core-auth-adapter.d.mts +1 -1
  17. package/core-auth-adapter.mjs +1 -1
  18. package/core-drizzle.cjs +1 -1
  19. package/core-drizzle.d.cts +1 -1
  20. package/core-drizzle.d.mts +1 -1
  21. package/core-drizzle.mjs +1 -1
  22. package/core-entity-config.cjs +1 -1
  23. package/core-entity-config.d.cts +1 -1
  24. package/core-entity-config.d.mts +1 -1
  25. package/core-entity-config.mjs +1 -1
  26. package/core-entity-heuristics.cjs +1 -0
  27. package/core-entity-heuristics.d.cts +3 -3
  28. package/core-entity-heuristics.d.mts +3 -3
  29. package/core-entity-heuristics.mjs +2 -2
  30. package/core-mapping-form.cjs +1 -1
  31. package/core-mapping-form.d.cts +1 -1
  32. package/core-mapping-form.d.mts +1 -1
  33. package/core-mapping-form.mjs +1 -1
  34. package/core-mappings-config.cjs +1 -1
  35. package/core-mappings-config.d.cts +1 -1
  36. package/core-mappings-config.d.mts +1 -1
  37. package/core-mappings-config.mjs +1 -1
  38. package/core-sync-engine.cjs +1 -1
  39. package/core-sync-engine.d.cts +1 -1
  40. package/core-sync-engine.d.mts +1 -1
  41. package/core-sync-engine.mjs +1 -1
  42. package/core-types.cjs +4 -0
  43. package/core-types.d.cts +2 -2
  44. package/core-types.d.mts +2 -2
  45. package/core-types.mjs +2 -1
  46. package/core-view-compiler.cjs +1 -1
  47. package/core-view-compiler.d.cts +1 -1
  48. package/core-view-compiler.d.mts +1 -1
  49. package/core-view-compiler.mjs +1 -1
  50. package/core.cjs +18 -17
  51. package/core.d.cts +10 -10
  52. package/core.d.mts +10 -10
  53. package/core.mjs +10 -9
  54. package/{drizzle-DEtRrqtc.d.cts → drizzle-DTOuGXEn.d.cts} +4 -2
  55. package/{drizzle-bfjVzYR6.cjs → drizzle-DcB7OfBp.cjs} +9 -1
  56. package/{drizzle-CiK8MMEZ.d.mts → drizzle-SGapoly2.d.mts} +4 -2
  57. package/{drizzle-3kvhkwO7.mjs → drizzle-wbcuG-cy.mjs} +9 -1
  58. package/drizzle.cjs +58 -24
  59. package/drizzle.d.cts +10 -4
  60. package/drizzle.d.mts +10 -4
  61. package/drizzle.mjs +58 -24
  62. package/{entity-config-CusbTOJ1.mjs → entity-config-C4d3K9CP.mjs} +114 -8
  63. package/{entity-config-B2RA53nw.d.cts → entity-config-DNQAMbMS.d.cts} +27 -1
  64. package/{entity-config-B2RA53nw.d.mts → entity-config-DNQAMbMS.d.mts} +27 -1
  65. package/{entity-config-DE30_RpU.cjs → entity-config-DgAe0_YD.cjs} +119 -7
  66. package/index.cjs +56 -15
  67. package/index.mjs +56 -15
  68. package/internal-BAOG5eE4.d.mts +226 -0
  69. package/internal-BHJ0X3fC.d.cts +226 -0
  70. package/internal-Bgiimp5D.mjs +144 -0
  71. package/internal-Cz59xMj8.cjs +167 -0
  72. package/internal-adapter.d.cts +1 -1
  73. package/internal-adapter.d.mts +1 -1
  74. package/internal-auth-adapter.d.cts +1 -1
  75. package/internal-auth-adapter.d.mts +1 -1
  76. package/internal-drizzle.cjs +1 -1
  77. package/internal-drizzle.d.cts +1 -1
  78. package/internal-drizzle.d.mts +1 -1
  79. package/internal-drizzle.mjs +1 -1
  80. package/internal-entity-config.cjs +1 -1
  81. package/internal-entity-config.d.cts +1 -1
  82. package/internal-entity-config.d.mts +1 -1
  83. package/internal-entity-config.mjs +1 -1
  84. package/internal-entity-heuristics.cjs +34 -1
  85. package/internal-entity-heuristics.d.cts +8 -2
  86. package/internal-entity-heuristics.d.mts +8 -2
  87. package/internal-entity-heuristics.mjs +34 -2
  88. package/internal-mapping-form.d.cts +1 -1
  89. package/internal-mapping-form.d.mts +1 -1
  90. package/internal-mappings-config.cjs +1 -1
  91. package/internal-mappings-config.d.cts +1 -1
  92. package/internal-mappings-config.d.mts +1 -1
  93. package/internal-mappings-config.mjs +1 -1
  94. package/internal-sync-engine.cjs +1 -1
  95. package/internal-sync-engine.d.cts +1 -1
  96. package/internal-sync-engine.d.mts +1 -1
  97. package/internal-sync-engine.mjs +1 -1
  98. package/internal-types.cjs +4 -0
  99. package/internal-types.d.cts +2 -2
  100. package/internal-types.d.mts +2 -2
  101. package/internal-types.mjs +2 -1
  102. package/internal-view-compiler.cjs +1 -1
  103. package/internal-view-compiler.d.cts +1 -1
  104. package/internal-view-compiler.d.mts +1 -1
  105. package/internal-view-compiler.mjs +1 -1
  106. package/internal.cjs +17 -15
  107. package/internal.d.cts +10 -10
  108. package/internal.d.mts +10 -10
  109. package/internal.mjs +9 -8
  110. package/{mapping-form-DH77BXLv.d.mts → mapping-form-Cc7Ewv8c.d.mts} +1 -1
  111. package/{mapping-form-J0aU6O7l.d.cts → mapping-form-DwdbYAfR.d.cts} +1 -1
  112. package/{mappings-config-D9dsonoi.d.mts → mappings-config-Be9D43Np.d.mts} +1 -1
  113. package/{mappings-config-RQLGx8ub.d.cts → mappings-config-DUt4-9iO.d.cts} +1 -1
  114. package/{mappings-config-CjCmT-aU.cjs → mappings-config-Dx9ldgdf.cjs} +2 -16
  115. package/{mappings-config-7qQ47p9K.mjs → mappings-config-MoXBeI8p.mjs} +1 -15
  116. package/{namespace-probe-Ckn9yJ6F.d.mts → namespace-probe-9ScMDR0t.d.mts} +42 -2
  117. package/{namespace-probe-DaTJINS-.d.cts → namespace-probe-DC4tbmLj.d.cts} +42 -2
  118. package/package.json +1 -1
  119. package/{projection-hnPSgH6G.mjs → projection-CSGJbZlZ.mjs} +1 -1
  120. package/{projection-DEwL-D8R.cjs → projection-Dz6_i1-w.cjs} +0 -6
  121. package/{projection-sql-iHy-Cx6V.cjs → projection-sql-CbXCKt3s.cjs} +1 -1
  122. package/{projection-sql-9zzTVGvf.mjs → projection-sql-iHoiYr1R.mjs} +1 -1
  123. package/{sdk-w8Kv_XnW.cjs → sdk-B1vX4kUJ.cjs} +347 -17
  124. package/{sdk-Dkq6ELkf.mjs → sdk-D6gX0TXS.mjs} +347 -17
  125. package/sdk.cjs +2 -2
  126. package/sdk.d.cts +3 -3
  127. package/sdk.d.mts +3 -3
  128. package/sdk.mjs +2 -2
  129. package/{sync-engine-BLgwLpR6.cjs → sync-engine-B0FT1ax6.cjs} +1 -1
  130. package/{sync-engine-B_IzoUSx.mjs → sync-engine-CTSIcLlZ.mjs} +1 -1
  131. package/{sync-engine-BG2O1an2.d.cts → sync-engine-Df0kHAoJ.d.cts} +2 -2
  132. package/{sync-engine-DgQbrJON.d.mts → sync-engine-ugFacJ6G.d.mts} +2 -2
  133. package/{types-B1oRXdNP.d.cts → types-Cq1uHUKp.d.cts} +28 -2
  134. package/{types-B1oRXdNP.d.mts → types-Cq1uHUKp.d.mts} +28 -2
  135. package/types-Cq5gHCTq.cjs +20 -0
  136. package/types-YJTkXKzU.mjs +9 -0
  137. package/{view-compiler-D_6gfXFr.mjs → view-compiler-BzKk8nY3.mjs} +2 -2
  138. package/{view-compiler-CmEdAMwj.d.cts → view-compiler-D3zp9S3K.d.cts} +1 -1
  139. package/{view-compiler-Bo7pqXW3.d.mts → view-compiler-TpzDTu7z.d.mts} +1 -1
  140. package/{view-compiler-BHI5E4QI.cjs → view-compiler-ZKZbd3SK.cjs} +2 -2
  141. package/vite.d.cts +1 -1
  142. package/vite.d.mts +1 -1
  143. package/internal-BQ47iN6f.cjs +0 -259
  144. package/internal-ChufvXE6.mjs +0 -212
  145. package/internal-CvlFk3KC.d.mts +0 -180
  146. package/internal-DGUOLQAq.d.cts +0 -180
package/core.d.mts CHANGED
@@ -1,11 +1,11 @@
1
- import { C as UpdateDealInput, S as UpdateContactInput, _ as Task, a as ContactFilters, b as TaskPriority, c as CreateCompanyInput, d as CreateTaskInput, f as CrmRole, g as RecordSource, h as Note, i as Contact, l as CreateContactInput, m as DealStage, n as ActivityType, o as ContactStatus, p as Deal, r as Company, s as CreateActivityInput, t as Activity, u as CreateDealInput, v as TaskEntityType, w as UpdateTaskInput, x as TaskStatus, y as TaskFilters } from "./types-B1oRXdNP.mjs";
2
- import { a as authCustom, i as MembershipResolver, n as ClivlyUser, r as CrmMembership, t as ClivlyAuthAdapter } from "./auth-adapter-Bjgo8LhN.mjs";
3
- import { t as CRMAdapter } from "./adapter-D5LRa-NA.mjs";
4
- import { A as BASE_REF, C as defineClivlyConfig, D as relationshipSchema, F as ProjectionRef, I as identityRefs, L as projectionSchema, M as ProjectionIdentity, N as ProjectionJoin, O as relationshipsSchema, P as ProjectionMapping, T as filterSchema, _ as MATERIALIZING_CONCEPTS, a as ClivlyEntitiesConfig, b as RelationshipVia, d as CrmConcept, g as FilterValue, h as FilterExpr, i as ClivlyConfigError, j as ProjectionFieldBinding, k as validateEntitiesConfig, l as ConfigValidationError, m as DiscoveredSchemaTable, n as CRM_CONCEPTS, p as DiscoveredColumnMeta, s as ClivlyEntityConfig, t as CANONICAL_FIELDS, u as ConfigValidationResult, v as MaterializingConcept, w as entitiesConfigSchema, x as RelationshipsMap, y as RelationshipSpec } from "./entity-config-B2RA53nw.mjs";
5
- import { i as relationshipViaSignature, n as buildFilterFromDiscriminator, r as buildRelationships, t as RelationshipCandidate } from "./mapping-form-DH77BXLv.mjs";
6
- import { i as mappingsToEntitiesConfig, t as EntityMappingRow } from "./mappings-config-D9dsonoi.mjs";
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
- 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";
1
+ import { A as ValueInterval, C as TaskEntityType, D as UpdateContactInput, E as TaskStatus, O as UpdateDealInput, S as Task, T as TaskPriority, _ as PipelineConfig, a as ContactFilters, b as RecordSource, c as CreateCompanyInput, d as CreateTaskInput, f as CrmRole, g as OPEN_STAGE_TYPE, h as Note, i as Contact, j as isClosedStageType, k as UpdateTaskInput, l as CreateContactInput, m as DealStage, n as ActivityType, o as ContactStatus, p as Deal, r as Company, s as CreateActivityInput, t as Activity, u as CreateDealInput, v as PipelineKind, w as TaskFilters, x as StageType, y as PipelineStageConfig } from "./types-Cq1uHUKp.mjs";
2
+ import { a as authCustom, i as MembershipResolver, n as ClivlyUser, r as CrmMembership, t as ClivlyAuthAdapter } from "./auth-adapter-DSuYwv1c.mjs";
3
+ import { t as CRMAdapter } from "./adapter-uxirB88i.mjs";
4
+ import { A as BASE_REF, C as defineClivlyConfig, D as relationshipSchema, E as projectionFields, F as ProjectionMapping, I as ProjectionRef, L as identityRefs, M as ProjectionFieldBinding, N as ProjectionIdentity, O as relationshipsSchema, P as ProjectionJoin, R as projectionSchema, T as filterSchema, _ as MATERIALIZING_CONCEPTS, a as ClivlyEntitiesConfig, b as RelationshipVia, d as CrmConcept, g as FilterValue, h as FilterExpr, i as ClivlyConfigError, j as PROJECTION_KEY_PATTERN, k as validateEntitiesConfig, l as ConfigValidationError, m as DiscoveredSchemaTable, n as CRM_CONCEPTS, p as DiscoveredColumnMeta, s as ClivlyEntityConfig, t as CANONICAL_FIELDS, u as ConfigValidationResult, v as MaterializingConcept, w as entitiesConfigSchema, x as RelationshipsMap, y as RelationshipSpec } from "./entity-config-DNQAMbMS.mjs";
5
+ import { i as relationshipViaSignature, n as buildFilterFromDiscriminator, r as buildRelationships, t as RelationshipCandidate } from "./mapping-form-Cc7Ewv8c.mjs";
6
+ import { i as mappingsToEntitiesConfig, t as EntityMappingRow } from "./mappings-config-Be9D43Np.mjs";
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-TpzDTu7z.mjs";
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-ugFacJ6G.mjs";
9
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 { C as fanOutJoins, S as suggestJoinConditions, _ as draftErrors, a as validateProjection, b as emptyProjectionDraft, c as compileProjectionIdentity, d as compileProjectionSelect, f as quoteIdent, g as describeCardinality, h as addDraftJoin, i as primaryKeyColumns, l as compileProjectionJoins, m as ProjectionDraft, n as coversUniqueKey, o as PREVIEW_MAX_ROWS, p as DraftRefOption, r as hasRichMeta, s as compileProjectionFrom, t as columnMetaFor, u as compileProjectionPreview, v as draftRefOptions, w as joinFansOut, x as removeDraftJoin, y as draftToProjection } from "./internal-CvlFk3KC.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 DraftRefOption, 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, PREVIEW_MAX_ROWS, 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, addDraftJoin, authCustom, buildFilterFromDiscriminator, buildRelationships, columnMetaFor, compileEntityView, compileEntityViews, compileProjectionFrom, compileProjectionIdentity, compileProjectionJoins, compileProjectionPreview, compileProjectionSelect, coversUniqueKey, defineClivlyConfig, describeCardinality, draftErrors, draftRefOptions, draftToProjection, emptyProjectionDraft, entitiesConfigSchema, explainEntitiesConfig, fanOutJoins, filterSchema, hasRichMeta, identityRefs, joinFansOut, mappingsToEntitiesConfig, primaryKeyColumns, projectionSchema, quoteIdent, reconcile, relationshipSchema, relationshipViaSignature, relationshipsSchema, removeDraftJoin, runSync, suggestJoinConditions, validateEntitiesConfig, validateProjection };
10
+ import { S as joinFansOut, _ as compileProjectionJoins, a as matchesCondition, b as quoteIdent, c as columnMetaFor, d as primaryKeyColumns, f as validateProjection, g as compileProjectionIdentity, h as compileProjectionFrom, i as evaluateStage, l as coversUniqueKey, m as PREVIEW_MAX_ROWS, n as ConditionOp, o as slugify, p as validateProjectionFilter, r as EvaluableRule, s as toObjectTypeSlug, t as Condition, u as hasRichMeta, v as compileProjectionPreview, x as fanOutJoins, y as compileProjectionSelect } from "./internal-BAOG5eE4.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 Condition, type ConditionOp, 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 EvaluableRule, 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, OPEN_STAGE_TYPE, PREVIEW_MAX_ROWS, PROJECTION_KEY_PATTERN, type PersistAction, type PipelineConfig, type PipelineKind, type PipelineStageConfig, type ProjectionFieldBinding, type ProjectionIdentity, type ProjectionJoin, type ProjectionMapping, type ProjectionRef, type RecordSource, type RelationshipCandidate, type RelationshipSpec, type RelationshipVia, type RelationshipsMap, type SourceRow, type StageType, 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, type ValueInterval, authCustom, buildFilterFromDiscriminator, buildRelationships, columnMetaFor, compileEntityView, compileEntityViews, compileProjectionFrom, compileProjectionIdentity, compileProjectionJoins, compileProjectionPreview, compileProjectionSelect, coversUniqueKey, defineClivlyConfig, entitiesConfigSchema, evaluateStage, explainEntitiesConfig, fanOutJoins, filterSchema, hasRichMeta, identityRefs, isClosedStageType, joinFansOut, mappingsToEntitiesConfig, matchesCondition, primaryKeyColumns, projectionFields, projectionSchema, quoteIdent, reconcile, relationshipSchema, relationshipViaSignature, relationshipsSchema, runSync, slugify, toObjectTypeSlug, validateEntitiesConfig, validateProjection, validateProjectionFilter };
package/core.mjs CHANGED
@@ -1,14 +1,15 @@
1
- import { a as projectionSchema, i as identityRefs, t as BASE_REF } from "./projection-hnPSgH6G.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-CusbTOJ1.mjs";
3
- import { n as mappingsToEntitiesConfig } from "./mappings-config-7qQ47p9K.mjs";
4
- import { t as warnDeprecatedSubpath } from "./deprecate-subpath-CmvZtCpE.mjs";
1
+ import { i as projectionSchema, n as PROJECTION_KEY_PATTERN, r as identityRefs, t as BASE_REF } from "./projection-CSGJbZlZ.mjs";
2
+ import { _ as joinFansOut, a as MATERIALIZING_CONCEPTS, b as hasRichMeta, c as entitiesConfigSchema, d as relationshipSchema, f as relationshipsSchema, g as fanOutJoins, h as validateProjectionFilter, i as ClivlyConfigError, l as filterSchema, m as validateProjection, n as CRM_CONCEPTS, p as validateEntitiesConfig, s as defineClivlyConfig, t as CANONICAL_FIELDS, u as projectionFields, v as columnMetaFor, x as primaryKeyColumns, y as coversUniqueKey } from "./entity-config-C4d3K9CP.mjs";
3
+ import { n as mappingsToEntitiesConfig } from "./mappings-config-MoXBeI8p.mjs";
5
4
  import { t as authCustom } from "./auth-adapter-gfVDxf3d.mjs";
6
5
  import { n as buildRelationships, r as relationshipViaSignature, t as buildFilterFromDiscriminator } from "./mapping-form-DigkuvFc.mjs";
7
- import { a as draftToProjection, c as suggestJoinConditions, i as draftRefOptions, n as describeCardinality, o as emptyProjectionDraft, r as draftErrors, s as removeDraftJoin, t as addDraftJoin } from "./internal-ChufvXE6.mjs";
8
- import { a as compileProjectionPreview, i as compileProjectionJoins, n as compileProjectionFrom, o as compileProjectionSelect, r as compileProjectionIdentity, s as quoteIdent, t as PREVIEW_MAX_ROWS } from "./projection-sql-9zzTVGvf.mjs";
9
- import { i as explainEntitiesConfig, n as compileEntityView, r as compileEntityViews, t as DEFAULT_VIEW_PREFIX } from "./view-compiler-D_6gfXFr.mjs";
10
- import { i as runSync, r as reconcile } from "./sync-engine-B_IzoUSx.mjs";
6
+ import { a as compileProjectionPreview, i as compileProjectionJoins, n as compileProjectionFrom, o as compileProjectionSelect, r as compileProjectionIdentity, s as quoteIdent, t as PREVIEW_MAX_ROWS } from "./projection-sql-iHoiYr1R.mjs";
7
+ import { i as toObjectTypeSlug, n as matchesCondition, r as slugify, t as evaluateStage } from "./internal-Bgiimp5D.mjs";
8
+ import { i as explainEntitiesConfig, n as compileEntityView, r as compileEntityViews, t as DEFAULT_VIEW_PREFIX } from "./view-compiler-BzKk8nY3.mjs";
9
+ import { i as runSync, r as reconcile } from "./sync-engine-CTSIcLlZ.mjs";
10
+ import { n as isClosedStageType, t as OPEN_STAGE_TYPE } from "./types-YJTkXKzU.mjs";
11
+ import { t as warnDeprecatedSubpath } from "./deprecate-subpath-CmvZtCpE.mjs";
11
12
  //#region src/core.ts
12
13
  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
14
- export { BASE_REF, CANONICAL_FIELDS, CRM_CONCEPTS, ClivlyConfigError, DEFAULT_VIEW_PREFIX, MATERIALIZING_CONCEPTS, PREVIEW_MAX_ROWS, addDraftJoin, authCustom, buildFilterFromDiscriminator, buildRelationships, columnMetaFor, compileEntityView, compileEntityViews, compileProjectionFrom, compileProjectionIdentity, compileProjectionJoins, compileProjectionPreview, compileProjectionSelect, coversUniqueKey, defineClivlyConfig, describeCardinality, draftErrors, draftRefOptions, draftToProjection, emptyProjectionDraft, entitiesConfigSchema, explainEntitiesConfig, fanOutJoins, filterSchema, hasRichMeta, identityRefs, joinFansOut, mappingsToEntitiesConfig, primaryKeyColumns, projectionSchema, quoteIdent, reconcile, relationshipSchema, relationshipViaSignature, relationshipsSchema, removeDraftJoin, runSync, suggestJoinConditions, validateEntitiesConfig, validateProjection };
15
+ export { BASE_REF, CANONICAL_FIELDS, CRM_CONCEPTS, ClivlyConfigError, DEFAULT_VIEW_PREFIX, MATERIALIZING_CONCEPTS, OPEN_STAGE_TYPE, PREVIEW_MAX_ROWS, PROJECTION_KEY_PATTERN, authCustom, buildFilterFromDiscriminator, buildRelationships, columnMetaFor, compileEntityView, compileEntityViews, compileProjectionFrom, compileProjectionIdentity, compileProjectionJoins, compileProjectionPreview, compileProjectionSelect, coversUniqueKey, defineClivlyConfig, entitiesConfigSchema, evaluateStage, explainEntitiesConfig, fanOutJoins, filterSchema, hasRichMeta, identityRefs, isClosedStageType, joinFansOut, mappingsToEntitiesConfig, matchesCondition, primaryKeyColumns, projectionFields, projectionSchema, quoteIdent, reconcile, relationshipSchema, relationshipViaSignature, relationshipsSchema, runSync, slugify, toObjectTypeSlug, validateEntitiesConfig, validateProjection, validateProjectionFilter };
@@ -1,4 +1,4 @@
1
- import { m as DiscoveredSchemaTable, p as DiscoveredColumnMeta } from "./entity-config-B2RA53nw.cjs";
1
+ import { m as DiscoveredSchemaTable, p as DiscoveredColumnMeta } from "./entity-config-DNQAMbMS.cjs";
2
2
  import { Table } from "drizzle-orm";
3
3
  //#region ../core/src/drizzle.d.ts
4
4
  /**
@@ -36,6 +36,8 @@ declare function buildColumnsMeta(table: Table): DiscoveredColumnMeta[];
36
36
  * when you import this entry (`@clivly/core/drizzle`); the rest of `@clivly/core`
37
37
  * stays dependency-free.
38
38
  */
39
- declare function discoverFromDrizzle(schema: Record<string, unknown>): DiscoveredSchemaTable[];
39
+ declare function discoverFromDrizzle(schema: Record<string, unknown>, options?: {
40
+ allowEmpty?: boolean;
41
+ }): DiscoveredSchemaTable[];
40
42
  //#endregion
41
43
  export { buildUniqueConstraints as n, discoverFromDrizzle as r, buildColumnsMeta as t };
@@ -91,7 +91,7 @@ function buildColumnsMeta(table) {
91
91
  * when you import this entry (`@clivly/core/drizzle`); the rest of `@clivly/core`
92
92
  * stays dependency-free.
93
93
  */
94
- function discoverFromDrizzle(schema) {
94
+ function discoverFromDrizzle(schema, options = {}) {
95
95
  const tables = [];
96
96
  for (const value of Object.values(schema)) {
97
97
  if (!(0, drizzle_orm.is)(value, drizzle_orm.Table)) continue;
@@ -104,8 +104,16 @@ function discoverFromDrizzle(schema) {
104
104
  ...uniqueConstraints === void 0 ? {} : { uniqueConstraints }
105
105
  });
106
106
  }
107
+ if (tables.length === 0 && !options.allowEmpty) throw new Error(`discoverFromDrizzle: found no Drizzle tables in the object it was given (${describeKeys(schema)}). Import the schema module's tables directly — \`import * as schema from "./db/schema"\` — rather than a barrel or a default export, which can collapse to \`{ default }\` under ESM/CJS interop. Pass { allowEmpty: true } if an empty schema is genuinely intended.`);
107
108
  return tables;
108
109
  }
110
+ /** The keys actually present, so the message names what was handed over. */
111
+ function describeKeys(schema) {
112
+ const keys = Object.keys(schema);
113
+ if (keys.length === 0) return "it was empty";
114
+ const shown = keys.slice(0, 5).join(", ");
115
+ return keys.length > 5 ? `keys: ${shown}, +${keys.length - 5} more` : `keys: ${shown}`;
116
+ }
109
117
  //#endregion
110
118
  Object.defineProperty(exports, "buildColumnsMeta", {
111
119
  enumerable: true,
@@ -1,4 +1,4 @@
1
- import { m as DiscoveredSchemaTable, p as DiscoveredColumnMeta } from "./entity-config-B2RA53nw.mjs";
1
+ import { m as DiscoveredSchemaTable, p as DiscoveredColumnMeta } from "./entity-config-DNQAMbMS.mjs";
2
2
  import { Table } from "drizzle-orm";
3
3
  //#region ../core/src/drizzle.d.ts
4
4
  /**
@@ -36,6 +36,8 @@ declare function buildColumnsMeta(table: Table): DiscoveredColumnMeta[];
36
36
  * when you import this entry (`@clivly/core/drizzle`); the rest of `@clivly/core`
37
37
  * stays dependency-free.
38
38
  */
39
- declare function discoverFromDrizzle(schema: Record<string, unknown>): DiscoveredSchemaTable[];
39
+ declare function discoverFromDrizzle(schema: Record<string, unknown>, options?: {
40
+ allowEmpty?: boolean;
41
+ }): DiscoveredSchemaTable[];
40
42
  //#endregion
41
43
  export { buildUniqueConstraints as n, discoverFromDrizzle as r, buildColumnsMeta as t };
@@ -91,7 +91,7 @@ function buildColumnsMeta(table) {
91
91
  * when you import this entry (`@clivly/core/drizzle`); the rest of `@clivly/core`
92
92
  * stays dependency-free.
93
93
  */
94
- function discoverFromDrizzle(schema) {
94
+ function discoverFromDrizzle(schema, options = {}) {
95
95
  const tables = [];
96
96
  for (const value of Object.values(schema)) {
97
97
  if (!is(value, Table)) continue;
@@ -104,7 +104,15 @@ function discoverFromDrizzle(schema) {
104
104
  ...uniqueConstraints === void 0 ? {} : { uniqueConstraints }
105
105
  });
106
106
  }
107
+ if (tables.length === 0 && !options.allowEmpty) throw new Error(`discoverFromDrizzle: found no Drizzle tables in the object it was given (${describeKeys(schema)}). Import the schema module's tables directly — \`import * as schema from "./db/schema"\` — rather than a barrel or a default export, which can collapse to \`{ default }\` under ESM/CJS interop. Pass { allowEmpty: true } if an empty schema is genuinely intended.`);
107
108
  return tables;
108
109
  }
110
+ /** The keys actually present, so the message names what was handed over. */
111
+ function describeKeys(schema) {
112
+ const keys = Object.keys(schema);
113
+ if (keys.length === 0) return "it was empty";
114
+ const shown = keys.slice(0, 5).join(", ");
115
+ return keys.length > 5 ? `keys: ${shown}, +${keys.length - 5} more` : `keys: ${shown}`;
116
+ }
109
117
  //#endregion
110
118
  export { buildUniqueConstraints as n, discoverFromDrizzle as r, buildColumnsMeta as t };
package/drizzle.cjs CHANGED
@@ -1,23 +1,9 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_projection = require("./projection-DEwL-D8R.cjs");
2
+ const require_projection = require("./projection-Dz6_i1-w.cjs");
3
3
  const require_drizzle_meta = require("./drizzle-meta-Bb1JWYqf.cjs");
4
- const require_projection_sql = require("./projection-sql-iHy-Cx6V.cjs");
5
- const require_drizzle = require("./drizzle-bfjVzYR6.cjs");
4
+ const require_projection_sql = require("./projection-sql-CbXCKt3s.cjs");
5
+ const require_drizzle = require("./drizzle-DcB7OfBp.cjs");
6
6
  let drizzle_orm = require("drizzle-orm");
7
- //#region ../sdk/src/projection-preview.ts
8
- /** `db.execute` returns either an array or `{ rows }`, depending on driver. */
9
- function rowsOf(result) {
10
- if (Array.isArray(result)) return result;
11
- const rows = result.rows;
12
- if (Array.isArray(rows)) return rows;
13
- throw new Error("previewProjection: db.execute() returned neither an array of rows nor { rows }.");
14
- }
15
- async function previewProjection(db, projection, opts) {
16
- const client = db;
17
- const { sql } = await import("drizzle-orm");
18
- return rowsOf(await client.execute(sql.raw(require_projection_sql.compileProjectionPreview(projection, opts.limit))));
19
- }
20
- //#endregion
21
7
  //#region ../sdk/src/drizzle-projection.ts
22
8
  /** `<ref>.<column>` — the token `fields` carries and cloud-ingest reads. */
23
9
  function refToken(ref) {
@@ -54,10 +40,12 @@ function fromDrizzleProjection(db, projection, opts) {
54
40
  const client = db;
55
41
  const known = /* @__PURE__ */ new Set([require_projection.BASE_REF, ...projection.joins.map((j) => j.key)]);
56
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 }.`);
57
- const cursorRef = parseRef(opts.cursorField);
58
- assertKnownRef(cursorRef, known, "cursorField");
59
43
  for (const [field, binding] of Object.entries(projection.fieldBindings)) assertKnownRef(binding.from, known, `field "${field}"`);
60
44
  const identityExpr = require_projection_sql.compileProjectionIdentity(projection, opts.basePkColumn ?? "");
45
+ const fromClause = [require_projection_sql.compileProjectionFrom(projection), ...require_projection_sql.compileProjectionJoins(projection)].join(" ");
46
+ if (opts.cursorField === void 0) return fromDrizzleProjectionByIdentity(client, projection, identityExpr, fromClause, opts);
47
+ const cursorRef = parseRef(opts.cursorField);
48
+ assertKnownRef(cursorRef, known, "cursorField");
61
49
  const cursorToken = refToken(cursorRef);
62
50
  const cursorExpr = `CAST(${refSql(cursorRef)} AS timestamptz)`;
63
51
  const cursorRead = `to_char(${cursorExpr} AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"')`;
@@ -69,11 +57,7 @@ function fromDrizzleProjection(db, projection, opts) {
69
57
  emitted.add(token);
70
58
  selectItems.push(`${refSql(binding.from)} AS ${require_projection_sql.quoteIdent(token)}`);
71
59
  }
72
- const head = [
73
- `select ${selectItems.join(", ")}`,
74
- require_projection_sql.compileProjectionFrom(projection),
75
- ...require_projection_sql.compileProjectionJoins(projection)
76
- ].join(" ");
60
+ const head = [`select ${selectItems.join(", ")}`, fromClause].join(" ");
77
61
  return {
78
62
  entity: opts.entity,
79
63
  cursorField: cursorToken,
@@ -86,6 +70,49 @@ function fromDrizzleProjection(db, projection, opts) {
86
70
  }
87
71
  };
88
72
  }
73
+ /**
74
+ * The identity-only paging path `fromDrizzleProjection` takes when
75
+ * `cursorField` is omitted. Deliberately not a generalisation of the
76
+ * timestamp path above — it selects no timestamp cursor, pages on the
77
+ * identity expression alone, and always reports `cursorField`/`idField` as
78
+ * `"id"`, the alias every row carries either way.
79
+ */
80
+ function fromDrizzleProjectionByIdentity(client, projection, identityExpr, fromClause, opts) {
81
+ const selectItems = [`${identityExpr} AS ${require_projection_sql.quoteIdent("id")}`];
82
+ const emitted = /* @__PURE__ */ new Set();
83
+ for (const binding of Object.values(projection.fieldBindings)) {
84
+ const token = refToken(binding.from);
85
+ if (emitted.has(token)) continue;
86
+ emitted.add(token);
87
+ selectItems.push(`${refSql(binding.from)} AS ${require_projection_sql.quoteIdent(token)}`);
88
+ }
89
+ const head = [`select ${selectItems.join(", ")}`, fromClause].join(" ");
90
+ return {
91
+ entity: opts.entity,
92
+ cursorField: "id",
93
+ idField: "id",
94
+ ...opts.objectType === void 0 ? {} : { objectType: opts.objectType },
95
+ fetchPage: async ({ since, limit }) => {
96
+ const where = since ? drizzle_orm.sql` where ${drizzle_orm.sql.raw(identityExpr)} > ${since.id}` : drizzle_orm.sql``;
97
+ const query = drizzle_orm.sql`${drizzle_orm.sql.raw(head)}${where} order by ${drizzle_orm.sql.raw(identityExpr)} asc limit ${limit}`;
98
+ return normalizeRows(await client.execute(query));
99
+ }
100
+ };
101
+ }
102
+ //#endregion
103
+ //#region ../sdk/src/projection-preview.ts
104
+ /** `db.execute` returns either an array or `{ rows }`, depending on driver. */
105
+ function rowsOf(result) {
106
+ if (Array.isArray(result)) return result;
107
+ const rows = result.rows;
108
+ if (Array.isArray(rows)) return rows;
109
+ throw new Error("previewProjection: db.execute() returned neither an array of rows nor { rows }.");
110
+ }
111
+ async function previewProjection(db, projection, opts) {
112
+ const client = db;
113
+ const { sql } = await import("drizzle-orm");
114
+ return rowsOf(await client.execute(sql.raw(require_projection_sql.compileProjectionPreview(projection, opts.limit))));
115
+ }
89
116
  //#endregion
90
117
  //#region ../sdk/src/drizzle.ts
91
118
  function inferIdField(table) {
@@ -152,6 +179,13 @@ function drizzleIntrospector(db) {
152
179
  },
153
180
  runProjection(projection, opts) {
154
181
  return previewProjection(db, projection, opts);
182
+ },
183
+ projectionSource(projection, opts) {
184
+ return fromDrizzleProjection(db, projection, {
185
+ entity: opts.objectType,
186
+ objectType: opts.objectType,
187
+ ...opts.basePkColumn ? { basePkColumn: opts.basePkColumn } : {}
188
+ });
155
189
  }
156
190
  };
157
191
  }
package/drizzle.d.cts CHANGED
@@ -1,6 +1,6 @@
1
- import { F as ProjectionRef, P as ProjectionMapping } from "./entity-config-B2RA53nw.cjs";
2
- import { n as buildUniqueConstraints, r as discoverFromDrizzle } from "./drizzle-DEtRrqtc.cjs";
3
- import { _ as SyncSource, t as NamespaceIntrospector } from "./namespace-probe-DaTJINS-.cjs";
1
+ import { F as ProjectionMapping, I as ProjectionRef } from "./entity-config-DNQAMbMS.cjs";
2
+ import { n as buildUniqueConstraints, r as discoverFromDrizzle } from "./drizzle-DTOuGXEn.cjs";
3
+ import { t as NamespaceIntrospector, v as SyncSource } from "./namespace-probe-DC4tbmLj.cjs";
4
4
  import { Table } from "drizzle-orm";
5
5
  //#region ../sdk/src/drizzle-projection.d.ts
6
6
  /**
@@ -37,8 +37,14 @@ interface FromDrizzleProjectionOptions {
37
37
  * The column to keyset-paginate on, as a ref token (`"base.updated_at"`) or
38
38
  * a `ProjectionRef`. A projection spans several tables, so there is no
39
39
  * single table to infer a cursor from.
40
+ *
41
+ * Omit it to page by identity alone — the mode a dashboard-authored
42
+ * projection uses, since it has no timestamp column and no UI to nominate
43
+ * one. `checkIdentitySafety` (`@clivly/core`) already proves the identity
44
+ * uniquely identifies a row, which makes it a sound keyset cursor with no
45
+ * timestamp involved.
40
46
  */
41
- cursorField: string | ProjectionRef;
47
+ cursorField?: string | ProjectionRef;
42
48
  /** The source name rows are pushed under. */
43
49
  entity: string;
44
50
  /**
package/drizzle.d.mts CHANGED
@@ -1,6 +1,6 @@
1
- import { F as ProjectionRef, P as ProjectionMapping } from "./entity-config-B2RA53nw.mjs";
2
- import { n as buildUniqueConstraints, r as discoverFromDrizzle } from "./drizzle-CiK8MMEZ.mjs";
3
- import { _ as SyncSource, t as NamespaceIntrospector } from "./namespace-probe-Ckn9yJ6F.mjs";
1
+ import { F as ProjectionMapping, I as ProjectionRef } from "./entity-config-DNQAMbMS.mjs";
2
+ import { n as buildUniqueConstraints, r as discoverFromDrizzle } from "./drizzle-SGapoly2.mjs";
3
+ import { t as NamespaceIntrospector, v as SyncSource } from "./namespace-probe-9ScMDR0t.mjs";
4
4
  import { Table } from "drizzle-orm";
5
5
  //#region ../sdk/src/drizzle-projection.d.ts
6
6
  /**
@@ -37,8 +37,14 @@ interface FromDrizzleProjectionOptions {
37
37
  * The column to keyset-paginate on, as a ref token (`"base.updated_at"`) or
38
38
  * a `ProjectionRef`. A projection spans several tables, so there is no
39
39
  * single table to infer a cursor from.
40
+ *
41
+ * Omit it to page by identity alone — the mode a dashboard-authored
42
+ * projection uses, since it has no timestamp column and no UI to nominate
43
+ * one. `checkIdentitySafety` (`@clivly/core`) already proves the identity
44
+ * uniquely identifies a row, which makes it a sound keyset cursor with no
45
+ * timestamp involved.
40
46
  */
41
- cursorField: string | ProjectionRef;
47
+ cursorField?: string | ProjectionRef;
42
48
  /** The source name rows are pushed under. */
43
49
  entity: string;
44
50
  /**
package/drizzle.mjs CHANGED
@@ -1,22 +1,8 @@
1
- import { t as BASE_REF } from "./projection-hnPSgH6G.mjs";
1
+ import { t as BASE_REF } from "./projection-CSGJbZlZ.mjs";
2
2
  import { t as DRIZZLE_META } from "./drizzle-meta-D-5k3n0i.mjs";
3
- import { a as compileProjectionPreview, i as compileProjectionJoins, n as compileProjectionFrom, r as compileProjectionIdentity, s as quoteIdent } from "./projection-sql-9zzTVGvf.mjs";
4
- import { n as buildUniqueConstraints, r as discoverFromDrizzle, t as buildColumnsMeta } from "./drizzle-3kvhkwO7.mjs";
3
+ import { a as compileProjectionPreview, i as compileProjectionJoins, n as compileProjectionFrom, r as compileProjectionIdentity, s as quoteIdent } from "./projection-sql-iHoiYr1R.mjs";
4
+ import { n as buildUniqueConstraints, r as discoverFromDrizzle, t as buildColumnsMeta } from "./drizzle-wbcuG-cy.mjs";
5
5
  import { asc, getTableColumns, getTableName, sql } from "drizzle-orm";
6
- //#region ../sdk/src/projection-preview.ts
7
- /** `db.execute` returns either an array or `{ rows }`, depending on driver. */
8
- function rowsOf(result) {
9
- if (Array.isArray(result)) return result;
10
- const rows = result.rows;
11
- if (Array.isArray(rows)) return rows;
12
- throw new Error("previewProjection: db.execute() returned neither an array of rows nor { rows }.");
13
- }
14
- async function previewProjection(db, projection, opts) {
15
- const client = db;
16
- const { sql } = await import("drizzle-orm");
17
- return rowsOf(await client.execute(sql.raw(compileProjectionPreview(projection, opts.limit))));
18
- }
19
- //#endregion
20
6
  //#region ../sdk/src/drizzle-projection.ts
21
7
  /** `<ref>.<column>` — the token `fields` carries and cloud-ingest reads. */
22
8
  function refToken(ref) {
@@ -53,10 +39,12 @@ function fromDrizzleProjection(db, projection, opts) {
53
39
  const client = db;
54
40
  const known = /* @__PURE__ */ new Set([BASE_REF, ...projection.joins.map((j) => j.key)]);
55
41
  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 }.`);
56
- const cursorRef = parseRef(opts.cursorField);
57
- assertKnownRef(cursorRef, known, "cursorField");
58
42
  for (const [field, binding] of Object.entries(projection.fieldBindings)) assertKnownRef(binding.from, known, `field "${field}"`);
59
43
  const identityExpr = compileProjectionIdentity(projection, opts.basePkColumn ?? "");
44
+ const fromClause = [compileProjectionFrom(projection), ...compileProjectionJoins(projection)].join(" ");
45
+ if (opts.cursorField === void 0) return fromDrizzleProjectionByIdentity(client, projection, identityExpr, fromClause, opts);
46
+ const cursorRef = parseRef(opts.cursorField);
47
+ assertKnownRef(cursorRef, known, "cursorField");
60
48
  const cursorToken = refToken(cursorRef);
61
49
  const cursorExpr = `CAST(${refSql(cursorRef)} AS timestamptz)`;
62
50
  const cursorRead = `to_char(${cursorExpr} AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"')`;
@@ -68,11 +56,7 @@ function fromDrizzleProjection(db, projection, opts) {
68
56
  emitted.add(token);
69
57
  selectItems.push(`${refSql(binding.from)} AS ${quoteIdent(token)}`);
70
58
  }
71
- const head = [
72
- `select ${selectItems.join(", ")}`,
73
- compileProjectionFrom(projection),
74
- ...compileProjectionJoins(projection)
75
- ].join(" ");
59
+ const head = [`select ${selectItems.join(", ")}`, fromClause].join(" ");
76
60
  return {
77
61
  entity: opts.entity,
78
62
  cursorField: cursorToken,
@@ -85,6 +69,49 @@ function fromDrizzleProjection(db, projection, opts) {
85
69
  }
86
70
  };
87
71
  }
72
+ /**
73
+ * The identity-only paging path `fromDrizzleProjection` takes when
74
+ * `cursorField` is omitted. Deliberately not a generalisation of the
75
+ * timestamp path above — it selects no timestamp cursor, pages on the
76
+ * identity expression alone, and always reports `cursorField`/`idField` as
77
+ * `"id"`, the alias every row carries either way.
78
+ */
79
+ function fromDrizzleProjectionByIdentity(client, projection, identityExpr, fromClause, opts) {
80
+ const selectItems = [`${identityExpr} AS ${quoteIdent("id")}`];
81
+ const emitted = /* @__PURE__ */ new Set();
82
+ for (const binding of Object.values(projection.fieldBindings)) {
83
+ const token = refToken(binding.from);
84
+ if (emitted.has(token)) continue;
85
+ emitted.add(token);
86
+ selectItems.push(`${refSql(binding.from)} AS ${quoteIdent(token)}`);
87
+ }
88
+ const head = [`select ${selectItems.join(", ")}`, fromClause].join(" ");
89
+ return {
90
+ entity: opts.entity,
91
+ cursorField: "id",
92
+ idField: "id",
93
+ ...opts.objectType === void 0 ? {} : { objectType: opts.objectType },
94
+ fetchPage: async ({ since, limit }) => {
95
+ const where = since ? sql` where ${sql.raw(identityExpr)} > ${since.id}` : sql``;
96
+ const query = sql`${sql.raw(head)}${where} order by ${sql.raw(identityExpr)} asc limit ${limit}`;
97
+ return normalizeRows(await client.execute(query));
98
+ }
99
+ };
100
+ }
101
+ //#endregion
102
+ //#region ../sdk/src/projection-preview.ts
103
+ /** `db.execute` returns either an array or `{ rows }`, depending on driver. */
104
+ function rowsOf(result) {
105
+ if (Array.isArray(result)) return result;
106
+ const rows = result.rows;
107
+ if (Array.isArray(rows)) return rows;
108
+ throw new Error("previewProjection: db.execute() returned neither an array of rows nor { rows }.");
109
+ }
110
+ async function previewProjection(db, projection, opts) {
111
+ const client = db;
112
+ const { sql } = await import("drizzle-orm");
113
+ return rowsOf(await client.execute(sql.raw(compileProjectionPreview(projection, opts.limit))));
114
+ }
88
115
  //#endregion
89
116
  //#region ../sdk/src/drizzle.ts
90
117
  function inferIdField(table) {
@@ -151,6 +178,13 @@ function drizzleIntrospector(db) {
151
178
  },
152
179
  runProjection(projection, opts) {
153
180
  return previewProjection(db, projection, opts);
181
+ },
182
+ projectionSource(projection, opts) {
183
+ return fromDrizzleProjection(db, projection, {
184
+ entity: opts.objectType,
185
+ objectType: opts.objectType,
186
+ ...opts.basePkColumn ? { basePkColumn: opts.basePkColumn } : {}
187
+ });
154
188
  }
155
189
  };
156
190
  }
@@ -1,4 +1,4 @@
1
- import { a as projectionSchema, c as boolean, d as record, f as strictObject, i as identityRefs, l as literal, m as union, o as _enum, p as string, s as array, t as BASE_REF, u as number } from "./projection-hnPSgH6G.mjs";
1
+ import { a as _enum, c as literal, d as strictObject, f as string, i as projectionSchema, l as number, o as array, p as union, r as identityRefs, s as boolean, t as BASE_REF, u as record } from "./projection-CSGJbZlZ.mjs";
2
2
  //#region ../core/src/schema-meta.ts
3
3
  /**
4
4
  * Accessors over a discovered table's schema-v2 metadata.
@@ -29,7 +29,17 @@ function coversUniqueKey(table, columns) {
29
29
  const present = new Set(columns);
30
30
  return (table.uniqueConstraints ?? []).some((key) => key.length > 0 && key.every((column) => present.has(column)));
31
31
  }
32
- /** Is this table's payload rich enough to validate a projection against? */
32
+ /**
33
+ * Is this table's payload rich enough to validate a projection against?
34
+ *
35
+ * A type predicate rather than a plain boolean so the narrowing is visible to
36
+ * the compiler: callers that guard on this can iterate `columnsMeta` directly
37
+ * instead of casting, and a cast that outlives its guard becomes a type error
38
+ * rather than a silent walk over `undefined`.
39
+ *
40
+ * The invariant is unchanged: this reports whether the metadata is *known*,
41
+ * never whether the table has keys. Absent metadata stays UNKNOWN.
42
+ */
33
43
  function hasRichMeta(table) {
34
44
  return Boolean(table.columnsMeta && table.uniqueConstraints);
35
45
  }
@@ -137,7 +147,7 @@ function checkTablesExist(errors, projection, resolver, base) {
137
147
  if (!hasRichMeta(table)) {
138
148
  errors.push({
139
149
  path,
140
- message: `table "${name}" has no key/column metadata — upgrade @clivly/sdk and re-run discovery before using a projection`
150
+ message: `table "${name}" was discovered without column types or unique keys, which a projection needs to prove its id is unique. Redeploy or restart the app so it re-reports its schema (or run \`clivly push-schema\`); if the table is declared by hand as \`{ name, columns }\`, use \`discoverFromDrizzle\` so keys and types come with it.`
141
151
  });
142
152
  ok = false;
143
153
  }
@@ -182,10 +192,27 @@ function checkRefs(errors, projection, resolver, base, basePk) {
182
192
  for (const [field, binding] of Object.entries(projection.fieldBindings)) checkRef(errors, resolver, `${base}.projection.fieldBindings.${field}`, binding.from);
183
193
  for (const ref of identityRefs(projection.identity, basePk)) checkRef(errors, resolver, `${base}.projection.identity`, ref);
184
194
  }
195
+ /**
196
+ * Prove that a single-column identity (`column`, or `base_pk` with an
197
+ * explicit column) is actually unique.
198
+ *
199
+ * `coversUniqueKey` fails closed on absent metadata, same as every other
200
+ * check in this file: a column not provably covered by a unique key is
201
+ * rejected, never assumed safe.
202
+ */
203
+ function checkSingleColumnIdentity(errors, resolver, path, ref) {
204
+ const table = resolver.tableFor(ref.table);
205
+ if (!table) return;
206
+ if (!coversUniqueKey(table, [ref.column])) errors.push({
207
+ path,
208
+ message: `identity column "${ref.table}.${ref.column}" is not covered by a unique key of "${table.name}" — pick a column with a unique constraint, or use a composite identity that is`
209
+ });
210
+ }
185
211
  function checkIdentitySafety(errors, projection, resolver, base, baseTable) {
186
212
  const path = `${base}.projection.identity`;
187
213
  const pk = primaryKeyColumns(baseTable);
188
- if (projection.identity.kind === "base_pk" && !projection.identity.column) {
214
+ const { identity } = projection;
215
+ if (identity.kind === "base_pk" && !identity.column) {
189
216
  if (pk.length === 0) {
190
217
  errors.push({
191
218
  path,
@@ -200,9 +227,21 @@ function checkIdentitySafety(errors, projection, resolver, base, baseTable) {
200
227
  });
201
228
  return;
202
229
  }
230
+ return;
231
+ }
232
+ if (identity.kind === "base_pk" && identity.column) {
233
+ checkSingleColumnIdentity(errors, resolver, path, {
234
+ table: BASE_REF,
235
+ column: identity.column
236
+ });
237
+ return;
238
+ }
239
+ if (identity.kind === "column") {
240
+ checkSingleColumnIdentity(errors, resolver, path, identity.from);
241
+ return;
203
242
  }
204
- if (projection.identity.kind !== "composite") return;
205
- for (const part of projection.identity.parts) {
243
+ if (identity.kind !== "composite") return;
244
+ for (const part of identity.parts) {
206
245
  const table = resolver.tableFor(part.table);
207
246
  const meta = table && columnMetaFor(table, part.column);
208
247
  if (!meta) continue;
@@ -244,6 +283,64 @@ function checkFanOut(errors, projection, resolver, base, basePk) {
244
283
  });
245
284
  }
246
285
  /**
286
+ * One error naming a filter column that is not on the projection's base table,
287
+ * and the base table it would have to be on.
288
+ */
289
+ function columnOnBase(column, baseTable, path) {
290
+ if (baseTable?.columns.includes(column)) return [];
291
+ return [{
292
+ path,
293
+ message: `filter column "${column}" does not exist on "${baseTable?.name ?? "the base table"}" — a derived object is filtered by its base table's columns only, so name one of those, or move the condition into a join's \`on\``
294
+ }];
295
+ }
296
+ /**
297
+ * A derived object's filter is evaluated in the cloud against pushed rows, so
298
+ * it can only name columns of the base table.
299
+ *
300
+ * Every rejected shape here fails *silently* today, which is the whole reason
301
+ * the check exists — a filter that cannot be honoured must error, never quietly
302
+ * return the wrong rows. The three shapes fail in different directions:
303
+ *
304
+ * - `$raw` is opaque SQL meant for the embedded model. The cloud path cannot
305
+ * evaluate it and passes every row, so the filter is ignored and the object
306
+ * syncs UNFILTERED.
307
+ * - A joined-table column resolves to nothing on a pushed row, so under a
308
+ * positive operator (`eq`, `in`) no row matches and the object syncs EMPTY.
309
+ * - The same unresolvable column under a NEGATIVE operator (`ne`, `isNull`,
310
+ * `notIn`) is the dangerous one: the missing cell reads as null, so the
311
+ * predicate is true for every row and a filter meant to narrow the sync
312
+ * ADMITS EVERYTHING. Nobody notices extra rows arriving.
313
+ *
314
+ * Rejecting an unresolvable column closes the last two together.
315
+ */
316
+ function validateProjectionFilter(filter, projection, schema, base) {
317
+ if (!filter) return [];
318
+ const path = `${base}.filter`;
319
+ if ("$raw" in filter) return [{
320
+ path,
321
+ message: "a $raw filter cannot be evaluated against a derived object's rows — it is opaque SQL, so the cloud passes every row through unfiltered. Express it as column conditions on the base table instead"
322
+ }];
323
+ const baseTable = schema.find((t) => t.name === projection.baseTable);
324
+ const errors = [];
325
+ for (const column of Object.keys(filter)) {
326
+ if (column.includes(".")) {
327
+ const [ref, ...rest] = column.split(".");
328
+ const bare = rest.join(".");
329
+ if (ref !== "base") {
330
+ errors.push({
331
+ path,
332
+ message: `filter column "${column}" names the join "${ref}", but a derived object is filtered by its base table ("${projection.baseTable}") only — filter on a base column, or move the condition into that join's \`on\``
333
+ });
334
+ continue;
335
+ }
336
+ errors.push(...columnOnBase(bare, baseTable, path));
337
+ continue;
338
+ }
339
+ errors.push(...columnOnBase(column, baseTable, path));
340
+ }
341
+ return errors;
342
+ }
343
+ /**
247
344
  * Validate a projection against the discovered schema. Returns every error
248
345
  * found (not just the first) so a builder UI can show them all at once.
249
346
  */
@@ -508,6 +605,15 @@ function customObjectDeclarations(config) {
508
605
  * Qualified rather than bare: two bindings can pull the same column name from
509
606
  * different tables (`cl.full_name` and `adv.full_name`), which a bare column
510
607
  * name cannot tell apart.
608
+ *
609
+ * This is the single derivation of that map, and both consumers depend on it
610
+ * emitting ref tokens. `mappingsToEntitiesConfig` populates a projection
611
+ * entity's required `fields`; the cloud ingest path needs the same map because
612
+ * a projection's persisted `crm_entity_mappings.field_map` is empty by design,
613
+ * so `rowToSourceRow` derives the effective field map from the projection
614
+ * instead. The tokens emitted here are exactly how `fromDrizzleProjection` keys
615
+ * the rows it pushes (`drizzle-projection.ts` `refToken`), so the two line up.
616
+ * Deriving this a second time anywhere would let the copies drift.
511
617
  */
512
618
  function projectionFields(projection) {
513
619
  const fields = {};
@@ -646,7 +752,7 @@ function validateEntity(v, config, key, entity, schema) {
646
752
  if (entity.source !== entity.projection.baseTable) v.report(`${base}.source`, `"source" ("${entity.source}") must match "projection.baseTable" ("${entity.projection.baseTable}") — the view compiler reads baseTable and the sync engine reads source, so a mismatch makes them disagree about which table this entity is`);
647
753
  for (const error of validateProjection(entity.projection, schema, base)) v.report(error.path, error.message);
648
754
  validateReadOnly(v, base, entity);
649
- validateFilter(v, base, entity);
755
+ for (const error of validateProjectionFilter(entity.filter, entity.projection, schema, base)) v.report(error.path, error.message);
650
756
  return;
651
757
  }
652
758
  validateFields(v, base, entity);
@@ -672,4 +778,4 @@ function validateEntitiesConfig(config, schema) {
672
778
  };
673
779
  }
674
780
  //#endregion
675
- export { columnMetaFor as _, MATERIALIZING_CONCEPTS as a, primaryKeyColumns as b, entitiesConfigSchema as c, relationshipSchema as d, relationshipsSchema as f, joinFansOut as g, fanOutJoins as h, ClivlyConfigError as i, filterSchema as l, validateProjection as m, CRM_CONCEPTS as n, customObjectDeclarations as o, validateEntitiesConfig as p, CUSTOM_CONCEPT as r, defineClivlyConfig as s, CANONICAL_FIELDS as t, projectionFields as u, coversUniqueKey as v, hasRichMeta as y };
781
+ export { joinFansOut as _, MATERIALIZING_CONCEPTS as a, hasRichMeta as b, entitiesConfigSchema as c, relationshipSchema as d, relationshipsSchema as f, fanOutJoins as g, validateProjectionFilter as h, ClivlyConfigError as i, filterSchema as l, validateProjection as m, CRM_CONCEPTS as n, customObjectDeclarations as o, validateEntitiesConfig as p, CUSTOM_CONCEPT as r, defineClivlyConfig as s, CANONICAL_FIELDS as t, projectionFields as u, columnMetaFor as v, primaryKeyColumns as x, coversUniqueKey as y };