clivly 0.12.0 → 0.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +10 -3
  2. package/{adapter-DhPBRNpi.d.mts → adapter-B-iBMhl0.d.mts} +13 -0
  3. package/{adapter-DTMeGGsl.d.cts → adapter-JpXSAnj-.d.cts} +13 -0
  4. package/core-adapter.d.cts +1 -1
  5. package/core-adapter.d.mts +1 -1
  6. package/core-sync-engine.cjs +3 -1
  7. package/core-sync-engine.d.cts +2 -2
  8. package/core-sync-engine.d.mts +2 -2
  9. package/core-sync-engine.mjs +2 -2
  10. package/core.cjs +3 -1
  11. package/core.d.cts +3 -3
  12. package/core.d.mts +3 -3
  13. package/core.mjs +2 -2
  14. package/drizzle.cjs +65 -0
  15. package/drizzle.d.cts +51 -1
  16. package/drizzle.d.mts +51 -1
  17. package/drizzle.mjs +64 -1
  18. package/index.cjs +102 -1
  19. package/index.mjs +102 -1
  20. package/internal-adapter.d.cts +1 -1
  21. package/internal-adapter.d.mts +1 -1
  22. package/internal-sync-engine.cjs +3 -1
  23. package/internal-sync-engine.d.cts +2 -2
  24. package/internal-sync-engine.d.mts +2 -2
  25. package/internal-sync-engine.mjs +2 -2
  26. package/internal.cjs +3 -1
  27. package/internal.d.cts +3 -3
  28. package/internal.d.mts +3 -3
  29. package/internal.mjs +2 -2
  30. package/{namespace-probe-CNQKSmxz.d.mts → namespace-probe-DykR0kgh.d.mts} +42 -0
  31. package/{namespace-probe-C5RLl74M.d.cts → namespace-probe-H7yWc0JV.d.cts} +42 -0
  32. package/package.json +1 -1
  33. package/{sdk-C-Pjxj2y.mjs → sdk-DLoVPlGB.mjs} +177 -6
  34. package/{sdk-BvGSxBQc.cjs → sdk-ZMy4C4VK.cjs} +194 -5
  35. package/sdk.cjs +4 -1
  36. package/sdk.d.cts +33 -1
  37. package/sdk.d.mts +33 -1
  38. package/sdk.mjs +2 -2
  39. package/{sync-engine-Dwm_KDUS.cjs → sync-engine-BGVDsrOQ.cjs} +131 -71
  40. package/{sync-engine-V3_UutGv.d.cts → sync-engine-CYsWOujz.d.cts} +63 -22
  41. package/{sync-engine--M9EaONC.d.mts → sync-engine-C_5TpvfX.d.mts} +63 -22
  42. package/{sync-engine-Df2MCs_n.mjs → sync-engine-DH058G3w.mjs} +120 -72
  43. package/vite.d.cts +1 -1
  44. package/vite.d.mts +1 -1
package/README.md CHANGED
@@ -290,7 +290,8 @@ It answers two questions under two headings:
290
290
  scope; `clivly doctor` is local by definition and omits it.
291
291
  - **This project** — the local ladder, run here on your machine: credential →
292
292
  Clivly reachable → `clivly.config` loads → `clivly.config` is edge-safe →
293
- boot hook wired → setup checks → dashboard-authored objects → sync trigger URL.
293
+ sync cursor persists → boot hook wired → setup checks → dashboard-authored
294
+ objects → sync trigger URL.
294
295
 
295
296
  ```text
296
297
  Clivly status
@@ -303,11 +304,17 @@ Workspace
303
304
  🔒 Let Clivly start a sync
304
305
 
305
306
  This project
306
- ✅ Step 1 of 8 · API key present
307
- ✅ Step 2 of 8 · Clivly reachable — Acme
307
+ ✅ Step 1 of 9 · API key present
308
+ ✅ Step 2 of 9 · Clivly reachable — Acme
308
309
  ...
309
310
  ```
310
311
 
312
+ **Sync cursor persists** warns when a config that targets an edge runtime sets
313
+ no `cursorStore`. Without one the in-memory default is discarded between
314
+ invocations, so every delta sync re-reads your entire source tables — a full
315
+ sync on every run, reported as a success. It is a warning, not a failure: a
316
+ long-lived Node host is correct with the in-memory default.
317
+
311
318
  **Dashboard-authored objects** is new in `0.9.7`. It reports how many derived
312
319
  objects authored in Clivly ran on the last sync and how many were quarantined —
313
320
  and, when your config has no `introspector`, warns that such objects cannot run
@@ -76,6 +76,19 @@ interface CRMAdapter {
76
76
  listDealsPage(orgId: string, filters?: {
77
77
  source?: RecordSource;
78
78
  }, page?: PageRequest): Promise<Page<Deal>>;
79
+ /**
80
+ * One page of tasks, newest-created first. See
81
+ * {@link CRMAdapter.listCompaniesPage}.
82
+ *
83
+ * `filters.entityType`/`entityId` match the task's own polymorphic-link
84
+ * columns. `filters.additionalIds`, when given, extends that match with an
85
+ * explicit id allowlist — `services/tasks.ts`'s `listTasks` uses it to fold
86
+ * in tasks linked only via `crm_record_links` (the multi-link table),
87
+ * without falling back to an unbounded read.
88
+ */
89
+ listTasksPage(orgId: string, filters?: TaskFilters & {
90
+ additionalIds?: string[];
91
+ }, page?: PageRequest): Promise<Page<Task>>;
79
92
  /**
80
93
  * Move a deal to `stage` and reorder it directly after `afterId` (null = top
81
94
  * of the column). The adapter computes the fractional `position` from the
@@ -76,6 +76,19 @@ interface CRMAdapter {
76
76
  listDealsPage(orgId: string, filters?: {
77
77
  source?: RecordSource;
78
78
  }, page?: PageRequest): Promise<Page<Deal>>;
79
+ /**
80
+ * One page of tasks, newest-created first. See
81
+ * {@link CRMAdapter.listCompaniesPage}.
82
+ *
83
+ * `filters.entityType`/`entityId` match the task's own polymorphic-link
84
+ * columns. `filters.additionalIds`, when given, extends that match with an
85
+ * explicit id allowlist — `services/tasks.ts`'s `listTasks` uses it to fold
86
+ * in tasks linked only via `crm_record_links` (the multi-link table),
87
+ * without falling back to an unbounded read.
88
+ */
89
+ listTasksPage(orgId: string, filters?: TaskFilters & {
90
+ additionalIds?: string[];
91
+ }, page?: PageRequest): Promise<Page<Task>>;
79
92
  /**
80
93
  * Move a deal to `stage` and reorder it directly after `afterId` (null = top
81
94
  * of the column). The adapter computes the fractional `position` from the
@@ -1,2 +1,2 @@
1
- import { t as CRMAdapter } from "./adapter-DTMeGGsl.cjs";
1
+ import { t as CRMAdapter } from "./adapter-JpXSAnj-.cjs";
2
2
  export { CRMAdapter };
@@ -1,2 +1,2 @@
1
- import { t as CRMAdapter } from "./adapter-DhPBRNpi.mjs";
1
+ import { t as CRMAdapter } from "./adapter-B-iBMhl0.mjs";
2
2
  export { CRMAdapter };
@@ -1,11 +1,13 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_sync_engine = require("./sync-engine-Dwm_KDUS.cjs");
2
+ const require_sync_engine = require("./sync-engine-BGVDsrOQ.cjs");
3
3
  const require_deprecate_subpath = require("./deprecate-subpath-B9ngvizt.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");
7
7
  //#endregion
8
8
  exports.computeSampleWarnings = require_sync_engine.computeSampleWarnings;
9
+ exports.isRemovalAction = require_sync_engine.isRemovalAction;
9
10
  exports.previewSync = require_sync_engine.previewSync;
10
11
  exports.reconcile = require_sync_engine.reconcile;
12
+ exports.resolveActions = require_sync_engine.resolveActions;
11
13
  exports.runSync = require_sync_engine.runSync;
@@ -1,2 +1,2 @@
1
- import { a as PreviewWarning, c as SyncResult, d as previewSync, f as reconcile, i as PreviewResult, l as SyncStore, n as MirrorRecord, o as SourceRow, p as runSync, r as PersistAction, s as SyncAction, t as EntitySyncResult, u as computeSampleWarnings } from "./sync-engine-V3_UutGv.cjs";
2
- export { EntitySyncResult, MirrorRecord, PersistAction, PreviewResult, PreviewWarning, SourceRow, SyncAction, SyncResult, SyncStore, computeSampleWarnings, previewSync, reconcile, runSync };
1
+ import { a as PreviewWarning, c as SyncAction, d as computeSampleWarnings, f as isRemovalAction, g as runSync, h as resolveActions, i as PreviewResult, l as SyncResult, m as reconcile, n as MirrorRecord, o as ResolvedMembership, p as previewSync, r as PersistAction, s as SourceRow, t as EntitySyncResult, u as SyncStore } from "./sync-engine-CYsWOujz.cjs";
2
+ export { EntitySyncResult, MirrorRecord, PersistAction, PreviewResult, PreviewWarning, ResolvedMembership, SourceRow, SyncAction, SyncResult, SyncStore, computeSampleWarnings, isRemovalAction, previewSync, reconcile, resolveActions, runSync };
@@ -1,2 +1,2 @@
1
- import { a as PreviewWarning, c as SyncResult, d as previewSync, f as reconcile, i as PreviewResult, l as SyncStore, n as MirrorRecord, o as SourceRow, p as runSync, r as PersistAction, s as SyncAction, t as EntitySyncResult, u as computeSampleWarnings } from "./sync-engine--M9EaONC.mjs";
2
- export { EntitySyncResult, MirrorRecord, PersistAction, PreviewResult, PreviewWarning, SourceRow, SyncAction, SyncResult, SyncStore, computeSampleWarnings, previewSync, reconcile, runSync };
1
+ import { a as PreviewWarning, c as SyncAction, d as computeSampleWarnings, f as isRemovalAction, g as runSync, h as resolveActions, i as PreviewResult, l as SyncResult, m as reconcile, n as MirrorRecord, o as ResolvedMembership, p as previewSync, r as PersistAction, s as SourceRow, t as EntitySyncResult, u as SyncStore } from "./sync-engine-C_5TpvfX.mjs";
2
+ export { EntitySyncResult, MirrorRecord, PersistAction, PreviewResult, PreviewWarning, ResolvedMembership, SourceRow, SyncAction, SyncResult, SyncStore, computeSampleWarnings, isRemovalAction, previewSync, reconcile, resolveActions, runSync };
@@ -1,7 +1,7 @@
1
- import { i as runSync, n as previewSync, r as reconcile, t as computeSampleWarnings } from "./sync-engine-Df2MCs_n.mjs";
1
+ import { a as resolveActions, i as reconcile, n as isRemovalAction, o as runSync, r as previewSync, t as computeSampleWarnings } from "./sync-engine-DH058G3w.mjs";
2
2
  import { t as warnDeprecatedSubpath } from "./deprecate-subpath-CmvZtCpE.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");
6
6
  //#endregion
7
- export { computeSampleWarnings, previewSync, reconcile, runSync };
7
+ export { computeSampleWarnings, isRemovalAction, previewSync, reconcile, resolveActions, runSync };
package/core.cjs CHANGED
@@ -7,7 +7,7 @@ const require_internal = require("./internal-BxtvxF7Z.cjs");
7
7
  const require_mapping_form = require("./mapping-form-BpfON_ME.cjs");
8
8
  const require_projection_sql = require("./projection-sql-DuCtFE9t.cjs");
9
9
  const require_view_compiler = require("./view-compiler-xiwm5iar.cjs");
10
- const require_sync_engine = require("./sync-engine-Dwm_KDUS.cjs");
10
+ const require_sync_engine = require("./sync-engine-BGVDsrOQ.cjs");
11
11
  const require_types = require("./types-Cq5gHCTq.cjs");
12
12
  //#region src/core.ts
13
13
  require("./deprecate-subpath-B9ngvizt.cjs").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).");
@@ -46,6 +46,7 @@ exports.hostOwnedFieldMessage = require_internal.hostOwnedFieldMessage;
46
46
  exports.identityRefs = require_projection.identityRefs;
47
47
  exports.isClosedStageType = require_types.isClosedStageType;
48
48
  exports.isHostOwned = require_internal.isHostOwned;
49
+ exports.isRemovalAction = require_sync_engine.isRemovalAction;
49
50
  exports.joinFansOut = require_entity_config.joinFansOut;
50
51
  exports.mappingsToEntitiesConfig = require_mappings_config.mappingsToEntitiesConfig;
51
52
  exports.matchesCondition = require_internal.matchesCondition;
@@ -61,6 +62,7 @@ exports.relationshipSchema = require_entity_config.relationshipSchema;
61
62
  exports.relationshipViaSignature = require_mapping_form.relationshipViaSignature;
62
63
  exports.relationshipsSchema = require_entity_config.relationshipsSchema;
63
64
  exports.requiredFieldsFor = require_entity_config.requiredFieldsFor;
65
+ exports.resolveActions = require_sync_engine.resolveActions;
64
66
  exports.runSync = require_sync_engine.runSync;
65
67
  exports.slugify = require_internal.slugify;
66
68
  exports.toObjectTypeSlug = require_internal.toObjectTypeSlug;
package/core.d.cts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { A as relationshipsSchema, B as identityRefs, D as missingRequiredFields, E as filterSchema, F as ProjectionFieldBinding, I as ProjectionIdentity, L as ProjectionJoin, M as validateEntitiesConfig, N as BASE_REF, O as projectionFields, P as PROJECTION_KEY_PATTERN, R as ProjectionMapping, S as RelationshipsMap, T as entitiesConfigSchema, V as projectionSchema, _ as MATERIALIZING_CONCEPTS, a as ClivlyEntitiesConfig, b as RelationshipSpec, d as CrmConcept, g as FilterValue, h as FilterExpr, i as ClivlyConfigError, j as requiredFieldsFor, k as relationshipSchema, 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 defineClivlyConfig, x as RelationshipVia, y as REQUIRED_FIELDS, z as ProjectionRef } from "./entity-config-ApnT5j3X.cjs";
2
2
  import { A as UpdateCompanyInput, C as RecordSource, D as TaskFilters, E as TaskEntityType, F as isClosedStageType, M as UpdateDealInput, N as UpdateTaskInput, O as TaskPriority, P as ValueInterval, S as PipelineStageConfig, T as Task, _ as OPEN_STAGE_TYPE, a as Contact, b as PipelineConfig, c as CreateActivityInput, d as CreateDealInput, f as CreateTaskInput, g as Note, h as DealStage, i as CompanyFilters, j as UpdateContactInput, k as TaskStatus, l as CreateCompanyInput, m as Deal, n as ActivityType, o as ContactFilters, p as CrmRole, r as Company, s as ContactStatus, t as Activity, u as CreateContactInput, v as Page, w as StageType, x as PipelineKind, y as PageRequest } from "./types-B17TWEOL.cjs";
3
3
  import { a as authCustom, i as MembershipResolver, n as ClivlyUser, r as CrmMembership, t as ClivlyAuthAdapter } from "./auth-adapter-Csk9KkvI.cjs";
4
- import { t as CRMAdapter } from "./adapter-DTMeGGsl.cjs";
4
+ import { t as CRMAdapter } from "./adapter-JpXSAnj-.cjs";
5
5
  import { i as relationshipViaSignature, n as buildFilterFromDiscriminator, r as buildRelationships, t as RelationshipCandidate } from "./mapping-form-XsLLCqW_.cjs";
6
6
  import { i as mappingsToEntitiesConfig, t as EntityMappingRow } from "./mappings-config-iJzbcUMp.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-Cq8apvZ4.cjs";
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-V3_UutGv.cjs";
8
+ import { c as SyncAction, f as isRemovalAction, g as runSync, h as resolveActions, l as SyncResult, m as reconcile, n as MirrorRecord, o as ResolvedMembership, r as PersistAction, s as SourceRow, t as EntitySyncResult, u as SyncStore } from "./sync-engine-CYsWOujz.cjs";
9
9
  import { A as PerSeatValueSource, C as HostOwnedCompanyField, D as isHostOwned, E as hostOwnedFieldMessage, O as rejectedCompanyFields, S as joinFansOut, T as SourcedRecord, _ 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, j as computeDealValue, k as rejectedContactFields, 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, w as HostOwnedContactField, x as fanOutJoins, y as compileProjectionSelect } from "./internal-vH5Rlg6Q.cjs";
10
10
  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-BA4c0RbD.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 CompanyFilters, 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 HostOwnedCompanyField, type HostOwnedContactField, 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 Page, type PageRequest, type PerSeatValueSource, type PersistAction, type PipelineConfig, type PipelineKind, type PipelineStageConfig, type ProjectionFieldBinding, type ProjectionIdentity, type ProjectionJoin, type ProjectionMapping, type ProjectionRef, REQUIRED_FIELDS, type RecordSource, type RelationshipCandidate, type RelationshipSpec, type RelationshipVia, type RelationshipsMap, type SourceRow, type SourcedRecord, 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 UpdateCompanyInput, type UpdateContactInput, type UpdateDealInput, type UpdateTaskInput, type ValueInterval, authCustom, buildFilterFromDiscriminator, buildRelationships, columnMetaFor, compileEntityView, compileEntityViews, compileProjectionFrom, compileProjectionIdentity, compileProjectionJoins, compileProjectionPreview, compileProjectionSelect, computeDealValue, coversUniqueKey, defineClivlyConfig, entitiesConfigSchema, evaluateStage, explainEntitiesConfig, fanOutJoins, filterSchema, hasRichMeta, hostOwnedFieldMessage, identityRefs, isClosedStageType, isHostOwned, joinFansOut, mappingsToEntitiesConfig, matchesCondition, missingRequiredFields, primaryKeyColumns, projectionFields, projectionSchema, quoteIdent, reconcile, rejectedCompanyFields, rejectedContactFields, relationshipSchema, relationshipViaSignature, relationshipsSchema, requiredFieldsFor, runSync, slugify, toObjectTypeSlug, validateEntitiesConfig, validateProjection, validateProjectionFilter };
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 CompanyFilters, 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 HostOwnedCompanyField, type HostOwnedContactField, 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 Page, type PageRequest, type PerSeatValueSource, type PersistAction, type PipelineConfig, type PipelineKind, type PipelineStageConfig, type ProjectionFieldBinding, type ProjectionIdentity, type ProjectionJoin, type ProjectionMapping, type ProjectionRef, REQUIRED_FIELDS, type RecordSource, type RelationshipCandidate, type RelationshipSpec, type RelationshipVia, type RelationshipsMap, type ResolvedMembership, type SourceRow, type SourcedRecord, 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 UpdateCompanyInput, type UpdateContactInput, type UpdateDealInput, type UpdateTaskInput, type ValueInterval, authCustom, buildFilterFromDiscriminator, buildRelationships, columnMetaFor, compileEntityView, compileEntityViews, compileProjectionFrom, compileProjectionIdentity, compileProjectionJoins, compileProjectionPreview, compileProjectionSelect, computeDealValue, coversUniqueKey, defineClivlyConfig, entitiesConfigSchema, evaluateStage, explainEntitiesConfig, fanOutJoins, filterSchema, hasRichMeta, hostOwnedFieldMessage, identityRefs, isClosedStageType, isHostOwned, isRemovalAction, joinFansOut, mappingsToEntitiesConfig, matchesCondition, missingRequiredFields, primaryKeyColumns, projectionFields, projectionSchema, quoteIdent, reconcile, rejectedCompanyFields, rejectedContactFields, relationshipSchema, relationshipViaSignature, relationshipsSchema, requiredFieldsFor, resolveActions, runSync, slugify, toObjectTypeSlug, validateEntitiesConfig, validateProjection, validateProjectionFilter };
package/core.d.mts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { A as relationshipsSchema, B as identityRefs, D as missingRequiredFields, E as filterSchema, F as ProjectionFieldBinding, I as ProjectionIdentity, L as ProjectionJoin, M as validateEntitiesConfig, N as BASE_REF, O as projectionFields, P as PROJECTION_KEY_PATTERN, R as ProjectionMapping, S as RelationshipsMap, T as entitiesConfigSchema, V as projectionSchema, _ as MATERIALIZING_CONCEPTS, a as ClivlyEntitiesConfig, b as RelationshipSpec, d as CrmConcept, g as FilterValue, h as FilterExpr, i as ClivlyConfigError, j as requiredFieldsFor, k as relationshipSchema, 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 defineClivlyConfig, x as RelationshipVia, y as REQUIRED_FIELDS, z as ProjectionRef } from "./entity-config-CKcj4-M_.mjs";
2
2
  import { A as UpdateCompanyInput, C as RecordSource, D as TaskFilters, E as TaskEntityType, F as isClosedStageType, M as UpdateDealInput, N as UpdateTaskInput, O as TaskPriority, P as ValueInterval, S as PipelineStageConfig, T as Task, _ as OPEN_STAGE_TYPE, a as Contact, b as PipelineConfig, c as CreateActivityInput, d as CreateDealInput, f as CreateTaskInput, g as Note, h as DealStage, i as CompanyFilters, j as UpdateContactInput, k as TaskStatus, l as CreateCompanyInput, m as Deal, n as ActivityType, o as ContactFilters, p as CrmRole, r as Company, s as ContactStatus, t as Activity, u as CreateContactInput, v as Page, w as StageType, x as PipelineKind, y as PageRequest } from "./types-B17TWEOL.mjs";
3
3
  import { a as authCustom, i as MembershipResolver, n as ClivlyUser, r as CrmMembership, t as ClivlyAuthAdapter } from "./auth-adapter-C6rDx3XH.mjs";
4
- import { t as CRMAdapter } from "./adapter-DhPBRNpi.mjs";
4
+ import { t as CRMAdapter } from "./adapter-B-iBMhl0.mjs";
5
5
  import { i as relationshipViaSignature, n as buildFilterFromDiscriminator, r as buildRelationships, t as RelationshipCandidate } from "./mapping-form-Btn-7gzv.mjs";
6
6
  import { i as mappingsToEntitiesConfig, t as EntityMappingRow } from "./mappings-config-D6_oCi2Q.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-CwKVoK1w.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--M9EaONC.mjs";
8
+ import { c as SyncAction, f as isRemovalAction, g as runSync, h as resolveActions, l as SyncResult, m as reconcile, n as MirrorRecord, o as ResolvedMembership, r as PersistAction, s as SourceRow, t as EntitySyncResult, u as SyncStore } from "./sync-engine-C_5TpvfX.mjs";
9
9
  import { A as PerSeatValueSource, C as HostOwnedCompanyField, D as isHostOwned, E as hostOwnedFieldMessage, O as rejectedCompanyFields, S as joinFansOut, T as SourcedRecord, _ 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, j as computeDealValue, k as rejectedContactFields, 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, w as HostOwnedContactField, x as fanOutJoins, y as compileProjectionSelect } from "./internal-Cmx7Zevf.mjs";
10
10
  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-BA4c0RbD.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 CompanyFilters, 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 HostOwnedCompanyField, type HostOwnedContactField, 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 Page, type PageRequest, type PerSeatValueSource, type PersistAction, type PipelineConfig, type PipelineKind, type PipelineStageConfig, type ProjectionFieldBinding, type ProjectionIdentity, type ProjectionJoin, type ProjectionMapping, type ProjectionRef, REQUIRED_FIELDS, type RecordSource, type RelationshipCandidate, type RelationshipSpec, type RelationshipVia, type RelationshipsMap, type SourceRow, type SourcedRecord, 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 UpdateCompanyInput, type UpdateContactInput, type UpdateDealInput, type UpdateTaskInput, type ValueInterval, authCustom, buildFilterFromDiscriminator, buildRelationships, columnMetaFor, compileEntityView, compileEntityViews, compileProjectionFrom, compileProjectionIdentity, compileProjectionJoins, compileProjectionPreview, compileProjectionSelect, computeDealValue, coversUniqueKey, defineClivlyConfig, entitiesConfigSchema, evaluateStage, explainEntitiesConfig, fanOutJoins, filterSchema, hasRichMeta, hostOwnedFieldMessage, identityRefs, isClosedStageType, isHostOwned, joinFansOut, mappingsToEntitiesConfig, matchesCondition, missingRequiredFields, primaryKeyColumns, projectionFields, projectionSchema, quoteIdent, reconcile, rejectedCompanyFields, rejectedContactFields, relationshipSchema, relationshipViaSignature, relationshipsSchema, requiredFieldsFor, runSync, slugify, toObjectTypeSlug, validateEntitiesConfig, validateProjection, validateProjectionFilter };
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 CompanyFilters, 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 HostOwnedCompanyField, type HostOwnedContactField, 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 Page, type PageRequest, type PerSeatValueSource, type PersistAction, type PipelineConfig, type PipelineKind, type PipelineStageConfig, type ProjectionFieldBinding, type ProjectionIdentity, type ProjectionJoin, type ProjectionMapping, type ProjectionRef, REQUIRED_FIELDS, type RecordSource, type RelationshipCandidate, type RelationshipSpec, type RelationshipVia, type RelationshipsMap, type ResolvedMembership, type SourceRow, type SourcedRecord, 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 UpdateCompanyInput, type UpdateContactInput, type UpdateDealInput, type UpdateTaskInput, type ValueInterval, authCustom, buildFilterFromDiscriminator, buildRelationships, columnMetaFor, compileEntityView, compileEntityViews, compileProjectionFrom, compileProjectionIdentity, compileProjectionJoins, compileProjectionPreview, compileProjectionSelect, computeDealValue, coversUniqueKey, defineClivlyConfig, entitiesConfigSchema, evaluateStage, explainEntitiesConfig, fanOutJoins, filterSchema, hasRichMeta, hostOwnedFieldMessage, identityRefs, isClosedStageType, isHostOwned, isRemovalAction, joinFansOut, mappingsToEntitiesConfig, matchesCondition, missingRequiredFields, primaryKeyColumns, projectionFields, projectionSchema, quoteIdent, reconcile, rejectedCompanyFields, rejectedContactFields, relationshipSchema, relationshipViaSignature, relationshipsSchema, requiredFieldsFor, resolveActions, runSync, slugify, toObjectTypeSlug, validateEntitiesConfig, validateProjection, validateProjectionFilter };
package/core.mjs CHANGED
@@ -6,10 +6,10 @@ import { a as hostOwnedFieldMessage, c as rejectedContactFields, i as toObjectTy
6
6
  import { n as buildRelationships, r as relationshipViaSignature, t as buildFilterFromDiscriminator } from "./mapping-form-DigkuvFc.mjs";
7
7
  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-DweUaWRc.mjs";
8
8
  import { i as explainEntitiesConfig, n as compileEntityView, r as compileEntityViews, t as DEFAULT_VIEW_PREFIX } from "./view-compiler-C-6RydKK.mjs";
9
- import { i as runSync, r as reconcile } from "./sync-engine-Df2MCs_n.mjs";
9
+ import { a as resolveActions, i as reconcile, n as isRemovalAction, o as runSync } from "./sync-engine-DH058G3w.mjs";
10
10
  import { n as isClosedStageType, t as OPEN_STAGE_TYPE } from "./types-YJTkXKzU.mjs";
11
11
  import { t as warnDeprecatedSubpath } from "./deprecate-subpath-CmvZtCpE.mjs";
12
12
  //#region src/core.ts
13
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).");
14
14
  //#endregion
15
- export { BASE_REF, CANONICAL_FIELDS, CRM_CONCEPTS, ClivlyConfigError, DEFAULT_VIEW_PREFIX, MATERIALIZING_CONCEPTS, OPEN_STAGE_TYPE, PREVIEW_MAX_ROWS, PROJECTION_KEY_PATTERN, REQUIRED_FIELDS, authCustom, buildFilterFromDiscriminator, buildRelationships, columnMetaFor, compileEntityView, compileEntityViews, compileProjectionFrom, compileProjectionIdentity, compileProjectionJoins, compileProjectionPreview, compileProjectionSelect, computeDealValue, coversUniqueKey, defineClivlyConfig, entitiesConfigSchema, evaluateStage, explainEntitiesConfig, fanOutJoins, filterSchema, hasRichMeta, hostOwnedFieldMessage, identityRefs, isClosedStageType, isHostOwned, joinFansOut, mappingsToEntitiesConfig, matchesCondition, missingRequiredFields, primaryKeyColumns, projectionFields, projectionSchema, quoteIdent, reconcile, rejectedCompanyFields, rejectedContactFields, relationshipSchema, relationshipViaSignature, relationshipsSchema, requiredFieldsFor, runSync, slugify, toObjectTypeSlug, validateEntitiesConfig, validateProjection, validateProjectionFilter };
15
+ export { BASE_REF, CANONICAL_FIELDS, CRM_CONCEPTS, ClivlyConfigError, DEFAULT_VIEW_PREFIX, MATERIALIZING_CONCEPTS, OPEN_STAGE_TYPE, PREVIEW_MAX_ROWS, PROJECTION_KEY_PATTERN, REQUIRED_FIELDS, authCustom, buildFilterFromDiscriminator, buildRelationships, columnMetaFor, compileEntityView, compileEntityViews, compileProjectionFrom, compileProjectionIdentity, compileProjectionJoins, compileProjectionPreview, compileProjectionSelect, computeDealValue, coversUniqueKey, defineClivlyConfig, entitiesConfigSchema, evaluateStage, explainEntitiesConfig, fanOutJoins, filterSchema, hasRichMeta, hostOwnedFieldMessage, identityRefs, isClosedStageType, isHostOwned, isRemovalAction, joinFansOut, mappingsToEntitiesConfig, matchesCondition, missingRequiredFields, primaryKeyColumns, projectionFields, projectionSchema, quoteIdent, reconcile, rejectedCompanyFields, rejectedContactFields, relationshipSchema, relationshipViaSignature, relationshipsSchema, requiredFieldsFor, resolveActions, runSync, slugify, toObjectTypeSlug, validateEntitiesConfig, validateProjection, validateProjectionFilter };
package/drizzle.cjs CHANGED
@@ -164,6 +164,69 @@ function fromDrizzle(db, table, opts) {
164
164
  return source;
165
165
  }
166
166
  /**
167
+ * Insert a row into a mapped Drizzle table and push it to Clivly immediately
168
+ * — the "one call does both" instant-push API (see
169
+ * docs/reviews/2026-09-19-near-real-time-sync-plan.md, question 1). Returns
170
+ * only after the write completes; the push itself is fire-and-forget (see
171
+ * `pushOne`), so this resolves at the same time a plain `db.insert(...)`
172
+ * would.
173
+ *
174
+ * Created once per mapped table, mirroring `fromDrizzle`'s own convention —
175
+ * no per-call table-to-entity lookup, so a table two entities share (e.g.
176
+ * `user` for both `user` and `organizationOwner`) is never ambiguous:
177
+ * ```ts
178
+ * const insertUser = insertAndPush(clivly, db, schema.user, { entity: "user" });
179
+ * // in the signup handler:
180
+ * const created = await insertUser(newUserValues, c.executionCtx);
181
+ * ```
182
+ *
183
+ * `waitUntil`, when provided (Hono exposes it as `c.executionCtx.waitUntil`),
184
+ * extends the request's lifetime past the response so the push survives on
185
+ * Cloudflare Workers and similar runtimes, which otherwise kill background
186
+ * work the instant a response is sent. Omit it on a long-lived process where
187
+ * nothing tears the request down early.
188
+ *
189
+ * Table property keys are translated to real database column names before
190
+ * the push — the same translation `fromDrizzle` performs on `fetchPage` rows
191
+ * — because a raw `.returning()` result is keyed by Drizzle property name
192
+ * (`fullName`), and every consumer downstream of a push (the fieldMap, the
193
+ * cloud's ingest) addresses columns by their database name (`full_name`).
194
+ * Skipping this would silently push empty fields with no error anywhere.
195
+ */
196
+ /**
197
+ * Translate a Drizzle-property-keyed row (e.g. a `.returning()` result, or a
198
+ * plain unprojected `select()`) to real database column names — the same
199
+ * translation `fromDrizzle` performs on `fetchPage` rows. Every consumer
200
+ * downstream of a push (the fieldMap, the cloud's ingest) addresses columns
201
+ * by their database name (`full_name`), not the property name (`fullName`);
202
+ * skipping this would silently push empty fields with no error anywhere.
203
+ *
204
+ * Exported so a host can build the same translated row from a table it read
205
+ * some other way — e.g. re-querying a row inside an auth library's own
206
+ * lifecycle hook, where there is no `insertAndPush` call site to wrap
207
+ * because the library performs the insert internally.
208
+ */
209
+ function toColumnKeyedRow(table, row) {
210
+ const columns = (0, drizzle_orm.getTableColumns)(table);
211
+ const columnNameByPropertyKey = /* @__PURE__ */ new Map();
212
+ for (const [propertyKey, column] of Object.entries(columns)) columnNameByPropertyKey.set(propertyKey, column.name);
213
+ const out = {};
214
+ for (const [propertyKey, value] of Object.entries(row)) out[columnNameByPropertyKey.get(propertyKey) ?? propertyKey] = value;
215
+ return out;
216
+ }
217
+ function insertAndPush(clivly, db, table, opts) {
218
+ const insertableDb = db;
219
+ return async (values, waitUntil) => {
220
+ const [created] = await insertableDb.insert(table).values(values).returning();
221
+ if (!created) throw new Error(`insertAndPush: insert into "${(0, drizzle_orm.getTableName)(table)}" returned no row.`);
222
+ const row = toColumnKeyedRow(table, created);
223
+ const pushed = clivly.pushOne(opts.entity, row);
224
+ if (waitUntil) waitUntil(pushed);
225
+ else await pushed;
226
+ return created;
227
+ };
228
+ }
229
+ /**
167
230
  * Build a `NamespaceIntrospector` from any Drizzle client that exposes
168
231
  * `.execute()`. Reads `information_schema` in the connection's default schema
169
232
  * (`current_schema()`), so it reports exactly the tables the app can reach.
@@ -198,3 +261,5 @@ exports.discoverFromDrizzle = require_drizzle.discoverFromDrizzle;
198
261
  exports.drizzleIntrospector = drizzleIntrospector;
199
262
  exports.fromDrizzle = fromDrizzle;
200
263
  exports.fromDrizzleProjection = fromDrizzleProjection;
264
+ exports.insertAndPush = insertAndPush;
265
+ exports.toColumnKeyedRow = toColumnKeyedRow;
package/drizzle.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { R as ProjectionMapping, z as ProjectionRef } from "./entity-config-ApnT5j3X.cjs";
2
2
  import { n as buildUniqueConstraints, r as discoverFromDrizzle } from "./drizzle-CiK37zJm.cjs";
3
- import { t as NamespaceIntrospector, v as SyncSource } from "./namespace-probe-C5RLl74M.cjs";
3
+ import { t as NamespaceIntrospector, v as SyncSource } from "./namespace-probe-H7yWc0JV.cjs";
4
4
  import { Table } from "drizzle-orm";
5
5
  //#region ../sdk/src/drizzle-projection.d.ts
6
6
  /**
@@ -115,6 +115,56 @@ export declare function fromDrizzle(db: DrizzleDb, table: Table, opts: FromDrizz
115
115
  objectType: string;
116
116
  };
117
117
  export declare function fromDrizzle(db: DrizzleDb, table: Table, opts: FromDrizzleOptions): SyncSource;
118
+ interface PushOneCapable {
119
+ pushOne(entityKey: string, row: Record<string, unknown>): Promise<void>;
120
+ }
121
+ /**
122
+ * Insert a row into a mapped Drizzle table and push it to Clivly immediately
123
+ * — the "one call does both" instant-push API (see
124
+ * docs/reviews/2026-09-19-near-real-time-sync-plan.md, question 1). Returns
125
+ * only after the write completes; the push itself is fire-and-forget (see
126
+ * `pushOne`), so this resolves at the same time a plain `db.insert(...)`
127
+ * would.
128
+ *
129
+ * Created once per mapped table, mirroring `fromDrizzle`'s own convention —
130
+ * no per-call table-to-entity lookup, so a table two entities share (e.g.
131
+ * `user` for both `user` and `organizationOwner`) is never ambiguous:
132
+ * ```ts
133
+ * const insertUser = insertAndPush(clivly, db, schema.user, { entity: "user" });
134
+ * // in the signup handler:
135
+ * const created = await insertUser(newUserValues, c.executionCtx);
136
+ * ```
137
+ *
138
+ * `waitUntil`, when provided (Hono exposes it as `c.executionCtx.waitUntil`),
139
+ * extends the request's lifetime past the response so the push survives on
140
+ * Cloudflare Workers and similar runtimes, which otherwise kill background
141
+ * work the instant a response is sent. Omit it on a long-lived process where
142
+ * nothing tears the request down early.
143
+ *
144
+ * Table property keys are translated to real database column names before
145
+ * the push — the same translation `fromDrizzle` performs on `fetchPage` rows
146
+ * — because a raw `.returning()` result is keyed by Drizzle property name
147
+ * (`fullName`), and every consumer downstream of a push (the fieldMap, the
148
+ * cloud's ingest) addresses columns by their database name (`full_name`).
149
+ * Skipping this would silently push empty fields with no error anywhere.
150
+ */
151
+ /**
152
+ * Translate a Drizzle-property-keyed row (e.g. a `.returning()` result, or a
153
+ * plain unprojected `select()`) to real database column names — the same
154
+ * translation `fromDrizzle` performs on `fetchPage` rows. Every consumer
155
+ * downstream of a push (the fieldMap, the cloud's ingest) addresses columns
156
+ * by their database name (`full_name`), not the property name (`fullName`);
157
+ * skipping this would silently push empty fields with no error anywhere.
158
+ *
159
+ * Exported so a host can build the same translated row from a table it read
160
+ * some other way — e.g. re-querying a row inside an auth library's own
161
+ * lifecycle hook, where there is no `insertAndPush` call site to wrap
162
+ * because the library performs the insert internally.
163
+ */
164
+ export declare function toColumnKeyedRow(table: Table, row: Record<string, unknown>): Record<string, unknown>;
165
+ export declare function insertAndPush(clivly: PushOneCapable, db: unknown, table: Table, opts: {
166
+ entity: string;
167
+ }): (values: Record<string, unknown>, waitUntil?: (promise: Promise<unknown>) => void) => Promise<Record<string, unknown>>;
118
168
  /**
119
169
  * Build a `NamespaceIntrospector` from any Drizzle client that exposes
120
170
  * `.execute()`. Reads `information_schema` in the connection's default schema
package/drizzle.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { R as ProjectionMapping, z as ProjectionRef } from "./entity-config-CKcj4-M_.mjs";
2
2
  import { n as buildUniqueConstraints, r as discoverFromDrizzle } from "./drizzle-ehVWLSrN.mjs";
3
- import { t as NamespaceIntrospector, v as SyncSource } from "./namespace-probe-CNQKSmxz.mjs";
3
+ import { t as NamespaceIntrospector, v as SyncSource } from "./namespace-probe-DykR0kgh.mjs";
4
4
  import { Table } from "drizzle-orm";
5
5
  //#region ../sdk/src/drizzle-projection.d.ts
6
6
  /**
@@ -115,6 +115,56 @@ export declare function fromDrizzle(db: DrizzleDb, table: Table, opts: FromDrizz
115
115
  objectType: string;
116
116
  };
117
117
  export declare function fromDrizzle(db: DrizzleDb, table: Table, opts: FromDrizzleOptions): SyncSource;
118
+ interface PushOneCapable {
119
+ pushOne(entityKey: string, row: Record<string, unknown>): Promise<void>;
120
+ }
121
+ /**
122
+ * Insert a row into a mapped Drizzle table and push it to Clivly immediately
123
+ * — the "one call does both" instant-push API (see
124
+ * docs/reviews/2026-09-19-near-real-time-sync-plan.md, question 1). Returns
125
+ * only after the write completes; the push itself is fire-and-forget (see
126
+ * `pushOne`), so this resolves at the same time a plain `db.insert(...)`
127
+ * would.
128
+ *
129
+ * Created once per mapped table, mirroring `fromDrizzle`'s own convention —
130
+ * no per-call table-to-entity lookup, so a table two entities share (e.g.
131
+ * `user` for both `user` and `organizationOwner`) is never ambiguous:
132
+ * ```ts
133
+ * const insertUser = insertAndPush(clivly, db, schema.user, { entity: "user" });
134
+ * // in the signup handler:
135
+ * const created = await insertUser(newUserValues, c.executionCtx);
136
+ * ```
137
+ *
138
+ * `waitUntil`, when provided (Hono exposes it as `c.executionCtx.waitUntil`),
139
+ * extends the request's lifetime past the response so the push survives on
140
+ * Cloudflare Workers and similar runtimes, which otherwise kill background
141
+ * work the instant a response is sent. Omit it on a long-lived process where
142
+ * nothing tears the request down early.
143
+ *
144
+ * Table property keys are translated to real database column names before
145
+ * the push — the same translation `fromDrizzle` performs on `fetchPage` rows
146
+ * — because a raw `.returning()` result is keyed by Drizzle property name
147
+ * (`fullName`), and every consumer downstream of a push (the fieldMap, the
148
+ * cloud's ingest) addresses columns by their database name (`full_name`).
149
+ * Skipping this would silently push empty fields with no error anywhere.
150
+ */
151
+ /**
152
+ * Translate a Drizzle-property-keyed row (e.g. a `.returning()` result, or a
153
+ * plain unprojected `select()`) to real database column names — the same
154
+ * translation `fromDrizzle` performs on `fetchPage` rows. Every consumer
155
+ * downstream of a push (the fieldMap, the cloud's ingest) addresses columns
156
+ * by their database name (`full_name`), not the property name (`fullName`);
157
+ * skipping this would silently push empty fields with no error anywhere.
158
+ *
159
+ * Exported so a host can build the same translated row from a table it read
160
+ * some other way — e.g. re-querying a row inside an auth library's own
161
+ * lifecycle hook, where there is no `insertAndPush` call site to wrap
162
+ * because the library performs the insert internally.
163
+ */
164
+ export declare function toColumnKeyedRow(table: Table, row: Record<string, unknown>): Record<string, unknown>;
165
+ export declare function insertAndPush(clivly: PushOneCapable, db: unknown, table: Table, opts: {
166
+ entity: string;
167
+ }): (values: Record<string, unknown>, waitUntil?: (promise: Promise<unknown>) => void) => Promise<Record<string, unknown>>;
118
168
  /**
119
169
  * Build a `NamespaceIntrospector` from any Drizzle client that exposes
120
170
  * `.execute()`. Reads `information_schema` in the connection's default schema
package/drizzle.mjs CHANGED
@@ -163,6 +163,69 @@ function fromDrizzle(db, table, opts) {
163
163
  return source;
164
164
  }
165
165
  /**
166
+ * Insert a row into a mapped Drizzle table and push it to Clivly immediately
167
+ * — the "one call does both" instant-push API (see
168
+ * docs/reviews/2026-09-19-near-real-time-sync-plan.md, question 1). Returns
169
+ * only after the write completes; the push itself is fire-and-forget (see
170
+ * `pushOne`), so this resolves at the same time a plain `db.insert(...)`
171
+ * would.
172
+ *
173
+ * Created once per mapped table, mirroring `fromDrizzle`'s own convention —
174
+ * no per-call table-to-entity lookup, so a table two entities share (e.g.
175
+ * `user` for both `user` and `organizationOwner`) is never ambiguous:
176
+ * ```ts
177
+ * const insertUser = insertAndPush(clivly, db, schema.user, { entity: "user" });
178
+ * // in the signup handler:
179
+ * const created = await insertUser(newUserValues, c.executionCtx);
180
+ * ```
181
+ *
182
+ * `waitUntil`, when provided (Hono exposes it as `c.executionCtx.waitUntil`),
183
+ * extends the request's lifetime past the response so the push survives on
184
+ * Cloudflare Workers and similar runtimes, which otherwise kill background
185
+ * work the instant a response is sent. Omit it on a long-lived process where
186
+ * nothing tears the request down early.
187
+ *
188
+ * Table property keys are translated to real database column names before
189
+ * the push — the same translation `fromDrizzle` performs on `fetchPage` rows
190
+ * — because a raw `.returning()` result is keyed by Drizzle property name
191
+ * (`fullName`), and every consumer downstream of a push (the fieldMap, the
192
+ * cloud's ingest) addresses columns by their database name (`full_name`).
193
+ * Skipping this would silently push empty fields with no error anywhere.
194
+ */
195
+ /**
196
+ * Translate a Drizzle-property-keyed row (e.g. a `.returning()` result, or a
197
+ * plain unprojected `select()`) to real database column names — the same
198
+ * translation `fromDrizzle` performs on `fetchPage` rows. Every consumer
199
+ * downstream of a push (the fieldMap, the cloud's ingest) addresses columns
200
+ * by their database name (`full_name`), not the property name (`fullName`);
201
+ * skipping this would silently push empty fields with no error anywhere.
202
+ *
203
+ * Exported so a host can build the same translated row from a table it read
204
+ * some other way — e.g. re-querying a row inside an auth library's own
205
+ * lifecycle hook, where there is no `insertAndPush` call site to wrap
206
+ * because the library performs the insert internally.
207
+ */
208
+ function toColumnKeyedRow(table, row) {
209
+ const columns = getTableColumns(table);
210
+ const columnNameByPropertyKey = /* @__PURE__ */ new Map();
211
+ for (const [propertyKey, column] of Object.entries(columns)) columnNameByPropertyKey.set(propertyKey, column.name);
212
+ const out = {};
213
+ for (const [propertyKey, value] of Object.entries(row)) out[columnNameByPropertyKey.get(propertyKey) ?? propertyKey] = value;
214
+ return out;
215
+ }
216
+ function insertAndPush(clivly, db, table, opts) {
217
+ const insertableDb = db;
218
+ return async (values, waitUntil) => {
219
+ const [created] = await insertableDb.insert(table).values(values).returning();
220
+ if (!created) throw new Error(`insertAndPush: insert into "${getTableName(table)}" returned no row.`);
221
+ const row = toColumnKeyedRow(table, created);
222
+ const pushed = clivly.pushOne(opts.entity, row);
223
+ if (waitUntil) waitUntil(pushed);
224
+ else await pushed;
225
+ return created;
226
+ };
227
+ }
228
+ /**
166
229
  * Build a `NamespaceIntrospector` from any Drizzle client that exposes
167
230
  * `.execute()`. Reads `information_schema` in the connection's default schema
168
231
  * (`current_schema()`), so it reports exactly the tables the app can reach.
@@ -192,4 +255,4 @@ function drizzleIntrospector(db) {
192
255
  };
193
256
  }
194
257
  //#endregion
195
- export { buildUniqueConstraints, discoverFromDrizzle, drizzleIntrospector, fromDrizzle, fromDrizzleProjection };
258
+ export { buildUniqueConstraints, discoverFromDrizzle, drizzleIntrospector, fromDrizzle, fromDrizzleProjection, insertAndPush, toColumnKeyedRow };