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/index.cjs CHANGED
@@ -3,7 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const require_entity_config = require("./entity-config-BI4RYNKL.cjs");
4
4
  require("./mapping-score-CaB3F4Uu.cjs");
5
5
  const require_internal_entity_heuristics = require("./internal-entity-heuristics.cjs");
6
- const require_sdk = require("./sdk-BvGSxBQc.cjs");
6
+ const require_sdk = require("./sdk-ZMy4C4VK.cjs");
7
7
  let node_child_process = require("node:child_process");
8
8
  let node_fs = require("node:fs");
9
9
  let node_module = require("node:module");
@@ -3357,6 +3357,87 @@ function checkBootHook(readFile) {
3357
3357
  };
3358
3358
  }
3359
3359
  //#endregion
3360
+ //#region src/cursor-store-check.ts
3361
+ /**
3362
+ * Whether a config that will run on a serverless runtime persists its sync
3363
+ * cursor.
3364
+ *
3365
+ * Without a persisted cursor, every `delta` sync starts from `null` and
3366
+ * re-reads the whole source table — because the SDK's default store lives in
3367
+ * memory, and a request-scoped runtime discards memory between invocations.
3368
+ * Nothing about this is visible from the outside: the run reports success, the
3369
+ * row counts look plausible, and the only symptom is the database bill. One
3370
+ * deployment on Workers burned a 5 GB monthly network allowance before launch
3371
+ * with two users, and `clivly status` was green the whole time.
3372
+ *
3373
+ * Read from source text rather than by loading the config: an edge config
3374
+ * frequently cannot be imported in Node at all, and that is exactly the case
3375
+ * that most needs an answer here.
3376
+ */
3377
+ /** `cursorStore:` or `cursorStore,` as a real property, not in a comment. */
3378
+ const CURSOR_STORE_PROPERTY = /(^|[{,\s])cursorStore\s*[:,}]/;
3379
+ /** Marker files that pin a project to a specific serverless platform. */
3380
+ const PLATFORM_MARKERS = [
3381
+ {
3382
+ file: "wrangler.jsonc",
3383
+ label: "Cloudflare Workers"
3384
+ },
3385
+ {
3386
+ file: "wrangler.json",
3387
+ label: "Cloudflare Workers"
3388
+ },
3389
+ {
3390
+ file: "wrangler.toml",
3391
+ label: "Cloudflare Workers"
3392
+ },
3393
+ {
3394
+ file: "vercel.json",
3395
+ label: "Vercel"
3396
+ },
3397
+ {
3398
+ file: "netlify.toml",
3399
+ label: "Netlify"
3400
+ }
3401
+ ];
3402
+ /** Next.js and friends: `export const runtime = "edge"`. */
3403
+ const INLINE_EDGE_RUNTIME = /export\s+const\s+runtime\s*=\s*["']edge["']/;
3404
+ /**
3405
+ * Strip comments and string literals before looking for the property.
3406
+ *
3407
+ * The scaffolded config ships `cursorStore` commented out as an example, and a
3408
+ * scan that counted that as configured would hand back a green rung for the
3409
+ * precise setup it exists to catch.
3410
+ */
3411
+ function stripCommentsAndStrings(source) {
3412
+ return source.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/(^|[^:])\/\/[^\n]*/g, "$1 ").replace(/"(?:[^"\\]|\\.)*"/g, "\"\"").replace(/'(?:[^'\\]|\\.)*'/g, "''").replace(/`(?:[^`\\]|\\.)*`/g, "``");
3413
+ }
3414
+ function detectEdgeRuntime(source, readFile) {
3415
+ for (const { file, label } of PLATFORM_MARKERS) if (readFile(file) !== null) return label;
3416
+ return INLINE_EDGE_RUNTIME.test(source) ? "edge runtime" : null;
3417
+ }
3418
+ /**
3419
+ * `readFile` resolves paths against the project root and is used only to spot
3420
+ * platform marker files. A project with none is treated as a long-lived host —
3421
+ * the safe default, since warning a Node host would be noise, and noise is
3422
+ * what teaches people to ignore warnings.
3423
+ */
3424
+ function detectCursorStore(source, readFile = () => null) {
3425
+ const configured = CURSOR_STORE_PROPERTY.test(stripCommentsAndStrings(source));
3426
+ const edgeRuntime = detectEdgeRuntime(source, readFile);
3427
+ return {
3428
+ configured,
3429
+ edgeRuntime,
3430
+ shouldWarn: edgeRuntime !== null && !configured
3431
+ };
3432
+ }
3433
+ /** The remediation shown under the warning. */
3434
+ const CURSOR_STORE_HINT = "Pass `cursorStore: kvCursorStore(env.MY_KV)` (exported from `@clivly/sdk`) so delta syncs resume instead of re-reading every table. See https://clivly.com/docs/concepts/sync#cursor-stores";
3435
+ function cursorStoreDetail(verdict) {
3436
+ if (verdict.configured) return "delta syncs resume from a persisted cursor";
3437
+ if (verdict.edgeRuntime === null) return "in-memory (fine on a long-lived host)";
3438
+ return `No \`cursorStore\` on ${verdict.edgeRuntime} — memory does not survive between invocations, so every delta sync re-reads your entire source tables.`;
3439
+ }
3440
+ //#endregion
3360
3441
  //#region src/edge-safety.ts
3361
3442
  const NODE_BUILTINS = /* @__PURE__ */ new Set([
3362
3443
  "assert",
@@ -3700,6 +3781,26 @@ const STATUS_STAGES = [
3700
3781
  });
3701
3782
  }
3702
3783
  },
3784
+ {
3785
+ id: "cursor-store",
3786
+ label: "Sync cursor persists",
3787
+ needs: [configStage.id],
3788
+ run(ctx) {
3789
+ const read = ctx.readConfigSource ?? defaultReadConfigSource;
3790
+ const source = read(ctx.configPath);
3791
+ if (source === null) return Promise.resolve({
3792
+ state: "skip",
3793
+ detail: "config not readable"
3794
+ });
3795
+ const root = (0, node_path.dirname)(ctx.configPath);
3796
+ const verdict = detectCursorStore(source, (relative) => read((0, node_path.resolve)(root, relative)));
3797
+ return Promise.resolve({
3798
+ state: verdict.shouldWarn ? "warn" : "pass",
3799
+ detail: cursorStoreDetail(verdict),
3800
+ ...verdict.shouldWarn ? { hint: CURSOR_STORE_HINT } : {}
3801
+ });
3802
+ }
3803
+ },
3703
3804
  {
3704
3805
  id: "boot-hook",
3705
3806
  label: "Boot hook wired",
package/index.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  import { t as CANONICAL_FIELDS } from "./entity-config-Ccfb2IL9.mjs";
3
3
  import "./mapping-score-C68uAqGB.mjs";
4
4
  import { hasDefiningColumn, isFrameworkTable, matchesConcept, requiredFieldsFor, scoreFieldMap, scoreRelationships, suggestCursorField, toFieldMap } from "./internal-entity-heuristics.mjs";
5
- import { s as isPlaceholderUrl, t as createClivlySDK } from "./sdk-C-Pjxj2y.mjs";
5
+ import { n as createClivlySDK, u as isPlaceholderUrl } from "./sdk-DLoVPlGB.mjs";
6
6
  import { createRequire } from "node:module";
7
7
  import { spawn } from "node:child_process";
8
8
  import { accessSync, constants, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, statSync, watch, writeFileSync } from "node:fs";
@@ -3356,6 +3356,87 @@ function checkBootHook(readFile) {
3356
3356
  };
3357
3357
  }
3358
3358
  //#endregion
3359
+ //#region src/cursor-store-check.ts
3360
+ /**
3361
+ * Whether a config that will run on a serverless runtime persists its sync
3362
+ * cursor.
3363
+ *
3364
+ * Without a persisted cursor, every `delta` sync starts from `null` and
3365
+ * re-reads the whole source table — because the SDK's default store lives in
3366
+ * memory, and a request-scoped runtime discards memory between invocations.
3367
+ * Nothing about this is visible from the outside: the run reports success, the
3368
+ * row counts look plausible, and the only symptom is the database bill. One
3369
+ * deployment on Workers burned a 5 GB monthly network allowance before launch
3370
+ * with two users, and `clivly status` was green the whole time.
3371
+ *
3372
+ * Read from source text rather than by loading the config: an edge config
3373
+ * frequently cannot be imported in Node at all, and that is exactly the case
3374
+ * that most needs an answer here.
3375
+ */
3376
+ /** `cursorStore:` or `cursorStore,` as a real property, not in a comment. */
3377
+ const CURSOR_STORE_PROPERTY = /(^|[{,\s])cursorStore\s*[:,}]/;
3378
+ /** Marker files that pin a project to a specific serverless platform. */
3379
+ const PLATFORM_MARKERS = [
3380
+ {
3381
+ file: "wrangler.jsonc",
3382
+ label: "Cloudflare Workers"
3383
+ },
3384
+ {
3385
+ file: "wrangler.json",
3386
+ label: "Cloudflare Workers"
3387
+ },
3388
+ {
3389
+ file: "wrangler.toml",
3390
+ label: "Cloudflare Workers"
3391
+ },
3392
+ {
3393
+ file: "vercel.json",
3394
+ label: "Vercel"
3395
+ },
3396
+ {
3397
+ file: "netlify.toml",
3398
+ label: "Netlify"
3399
+ }
3400
+ ];
3401
+ /** Next.js and friends: `export const runtime = "edge"`. */
3402
+ const INLINE_EDGE_RUNTIME = /export\s+const\s+runtime\s*=\s*["']edge["']/;
3403
+ /**
3404
+ * Strip comments and string literals before looking for the property.
3405
+ *
3406
+ * The scaffolded config ships `cursorStore` commented out as an example, and a
3407
+ * scan that counted that as configured would hand back a green rung for the
3408
+ * precise setup it exists to catch.
3409
+ */
3410
+ function stripCommentsAndStrings(source) {
3411
+ return source.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/(^|[^:])\/\/[^\n]*/g, "$1 ").replace(/"(?:[^"\\]|\\.)*"/g, "\"\"").replace(/'(?:[^'\\]|\\.)*'/g, "''").replace(/`(?:[^`\\]|\\.)*`/g, "``");
3412
+ }
3413
+ function detectEdgeRuntime(source, readFile) {
3414
+ for (const { file, label } of PLATFORM_MARKERS) if (readFile(file) !== null) return label;
3415
+ return INLINE_EDGE_RUNTIME.test(source) ? "edge runtime" : null;
3416
+ }
3417
+ /**
3418
+ * `readFile` resolves paths against the project root and is used only to spot
3419
+ * platform marker files. A project with none is treated as a long-lived host —
3420
+ * the safe default, since warning a Node host would be noise, and noise is
3421
+ * what teaches people to ignore warnings.
3422
+ */
3423
+ function detectCursorStore(source, readFile = () => null) {
3424
+ const configured = CURSOR_STORE_PROPERTY.test(stripCommentsAndStrings(source));
3425
+ const edgeRuntime = detectEdgeRuntime(source, readFile);
3426
+ return {
3427
+ configured,
3428
+ edgeRuntime,
3429
+ shouldWarn: edgeRuntime !== null && !configured
3430
+ };
3431
+ }
3432
+ /** The remediation shown under the warning. */
3433
+ const CURSOR_STORE_HINT = "Pass `cursorStore: kvCursorStore(env.MY_KV)` (exported from `@clivly/sdk`) so delta syncs resume instead of re-reading every table. See https://clivly.com/docs/concepts/sync#cursor-stores";
3434
+ function cursorStoreDetail(verdict) {
3435
+ if (verdict.configured) return "delta syncs resume from a persisted cursor";
3436
+ if (verdict.edgeRuntime === null) return "in-memory (fine on a long-lived host)";
3437
+ return `No \`cursorStore\` on ${verdict.edgeRuntime} — memory does not survive between invocations, so every delta sync re-reads your entire source tables.`;
3438
+ }
3439
+ //#endregion
3359
3440
  //#region src/edge-safety.ts
3360
3441
  const NODE_BUILTINS = /* @__PURE__ */ new Set([
3361
3442
  "assert",
@@ -3699,6 +3780,26 @@ const STATUS_STAGES = [
3699
3780
  });
3700
3781
  }
3701
3782
  },
3783
+ {
3784
+ id: "cursor-store",
3785
+ label: "Sync cursor persists",
3786
+ needs: [configStage.id],
3787
+ run(ctx) {
3788
+ const read = ctx.readConfigSource ?? defaultReadConfigSource;
3789
+ const source = read(ctx.configPath);
3790
+ if (source === null) return Promise.resolve({
3791
+ state: "skip",
3792
+ detail: "config not readable"
3793
+ });
3794
+ const root = dirname(ctx.configPath);
3795
+ const verdict = detectCursorStore(source, (relative) => read(resolve(root, relative)));
3796
+ return Promise.resolve({
3797
+ state: verdict.shouldWarn ? "warn" : "pass",
3798
+ detail: cursorStoreDetail(verdict),
3799
+ ...verdict.shouldWarn ? { hint: CURSOR_STORE_HINT } : {}
3800
+ });
3801
+ }
3802
+ },
3702
3803
  {
3703
3804
  id: "boot-hook",
3704
3805
  label: "Boot hook wired",
@@ -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,6 +1,8 @@
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
  exports.computeSampleWarnings = require_sync_engine.computeSampleWarnings;
4
+ exports.isRemovalAction = require_sync_engine.isRemovalAction;
4
5
  exports.previewSync = require_sync_engine.previewSync;
5
6
  exports.reconcile = require_sync_engine.reconcile;
7
+ exports.resolveActions = require_sync_engine.resolveActions;
6
8
  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,2 +1,2 @@
1
- import { i as runSync, n as previewSync, r as reconcile, t as computeSampleWarnings } from "./sync-engine-Df2MCs_n.mjs";
2
- export { computeSampleWarnings, previewSync, reconcile, runSync };
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
+ export { computeSampleWarnings, isRemovalAction, previewSync, reconcile, resolveActions, runSync };
package/internal.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
  exports.BASE_REF = require_projection.BASE_REF;
13
13
  exports.CANONICAL_FIELDS = require_entity_config.CANONICAL_FIELDS;
@@ -43,6 +43,7 @@ exports.hostOwnedFieldMessage = require_internal.hostOwnedFieldMessage;
43
43
  exports.identityRefs = require_projection.identityRefs;
44
44
  exports.isClosedStageType = require_types.isClosedStageType;
45
45
  exports.isHostOwned = require_internal.isHostOwned;
46
+ exports.isRemovalAction = require_sync_engine.isRemovalAction;
46
47
  exports.joinFansOut = require_entity_config.joinFansOut;
47
48
  exports.mappingsToEntitiesConfig = require_mappings_config.mappingsToEntitiesConfig;
48
49
  exports.matchesCondition = require_internal.matchesCondition;
@@ -58,6 +59,7 @@ exports.relationshipSchema = require_entity_config.relationshipSchema;
58
59
  exports.relationshipViaSignature = require_mapping_form.relationshipViaSignature;
59
60
  exports.relationshipsSchema = require_entity_config.relationshipsSchema;
60
61
  exports.requiredFieldsFor = require_entity_config.requiredFieldsFor;
62
+ exports.resolveActions = require_sync_engine.resolveActions;
61
63
  exports.runSync = require_sync_engine.runSync;
62
64
  exports.slugify = require_internal.slugify;
63
65
  exports.toObjectTypeSlug = require_internal.toObjectTypeSlug;
package/internal.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/internal.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/internal.mjs CHANGED
@@ -6,6 +6,6 @@ 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
- 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 };
11
+ 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 };
@@ -164,6 +164,23 @@ interface ClivlySDKConfig {
164
164
  */
165
165
  intervalMs?: number;
166
166
  batchSize?: number;
167
+ /**
168
+ * Opt into `pushOne()`/`insertAndPush()` pushing a single changed row to
169
+ * Clivly immediately, instead of waiting for the next delta sync. Off by
170
+ * default: turning it on changes a write's async failure surface (a push
171
+ * can fail independently of the write that triggered it, swallowed and
172
+ * left for the next delta sync to catch), which an existing install
173
+ * upgrading to a newer `clivly` should opt into deliberately rather than
174
+ * inherit silently. Requires a real scheduled delta sync running
175
+ * underneath as the safety net for anything the instant push misses (a
176
+ * failed push, a raw SQL write, a bulk import) — see
177
+ * docs/reviews/2026-09-19-near-real-time-sync-plan.md.
178
+ *
179
+ * Can also be disabled at runtime without a redeploy via the
180
+ * `CLIVLY_INSTANT_PUSH_DISABLED=true` environment variable — the fast
181
+ * rollback switch if this misbehaves in production.
182
+ */
183
+ instant?: boolean;
167
184
  };
168
185
  /**
169
186
  * The remote sync trigger: how Clivly Cloud asks this app to run a sync.
@@ -477,6 +494,31 @@ interface ClivlySDK {
477
494
  * own state.
478
495
  */
479
496
  ping(): Promise<ClivlyConnectResult>;
497
+ /**
498
+ * Push one row to Clivly immediately, instead of waiting for the next delta
499
+ * sync — the "instant" half of near-real-time sync (see
500
+ * docs/reviews/2026-09-19-near-real-time-sync-plan.md). No-ops unless
501
+ * `sync.instant` is set and `CLIVLY_INSTANT_PUSH_DISABLED` is unset.
502
+ *
503
+ * `entityKey` is a key of `config.entities.entities` (the same key
504
+ * `clivly.config.ts` declares the entity under), not a table name — an
505
+ * unresolvable key logs a warning and returns without throwing, the same
506
+ * fail-safe as every other call site here: a config mismatch never syncs
507
+ * the wrong thing, it just doesn't sync this row instantly (the safety-net
508
+ * delta sync still will).
509
+ *
510
+ * `row` must be keyed by the source table's real database column names
511
+ * (`full_name`, not `fullName`) — the same contract `fetchPage` rows
512
+ * satisfy. `insertAndPush` (from `clivly/drizzle`) performs this
513
+ * translation for you from a Drizzle table; calling `pushOne` directly with
514
+ * a raw Drizzle `.returning()` row will silently push empty fields.
515
+ *
516
+ * Never throws and never advances the delta cursor. Fire-and-forget by
517
+ * design: on Cloudflare Workers and similar runtimes, wrap the call in
518
+ * `ctx.waitUntil(...)` so it survives past the response, since nothing
519
+ * here blocks or awaits the caller's own write.
520
+ */
521
+ pushOne(entityKey: string, row: Record<string, unknown>): Promise<void>;
480
522
  /**
481
523
  * One-shot heartbeat + a single sync, with no keep-alive timers. The correct
482
524
  * entry point on serverless/edge (Workers, Vercel, Lambda), where `start()`'s
@@ -164,6 +164,23 @@ interface ClivlySDKConfig {
164
164
  */
165
165
  intervalMs?: number;
166
166
  batchSize?: number;
167
+ /**
168
+ * Opt into `pushOne()`/`insertAndPush()` pushing a single changed row to
169
+ * Clivly immediately, instead of waiting for the next delta sync. Off by
170
+ * default: turning it on changes a write's async failure surface (a push
171
+ * can fail independently of the write that triggered it, swallowed and
172
+ * left for the next delta sync to catch), which an existing install
173
+ * upgrading to a newer `clivly` should opt into deliberately rather than
174
+ * inherit silently. Requires a real scheduled delta sync running
175
+ * underneath as the safety net for anything the instant push misses (a
176
+ * failed push, a raw SQL write, a bulk import) — see
177
+ * docs/reviews/2026-09-19-near-real-time-sync-plan.md.
178
+ *
179
+ * Can also be disabled at runtime without a redeploy via the
180
+ * `CLIVLY_INSTANT_PUSH_DISABLED=true` environment variable — the fast
181
+ * rollback switch if this misbehaves in production.
182
+ */
183
+ instant?: boolean;
167
184
  };
168
185
  /**
169
186
  * The remote sync trigger: how Clivly Cloud asks this app to run a sync.
@@ -477,6 +494,31 @@ interface ClivlySDK {
477
494
  * own state.
478
495
  */
479
496
  ping(): Promise<ClivlyConnectResult>;
497
+ /**
498
+ * Push one row to Clivly immediately, instead of waiting for the next delta
499
+ * sync — the "instant" half of near-real-time sync (see
500
+ * docs/reviews/2026-09-19-near-real-time-sync-plan.md). No-ops unless
501
+ * `sync.instant` is set and `CLIVLY_INSTANT_PUSH_DISABLED` is unset.
502
+ *
503
+ * `entityKey` is a key of `config.entities.entities` (the same key
504
+ * `clivly.config.ts` declares the entity under), not a table name — an
505
+ * unresolvable key logs a warning and returns without throwing, the same
506
+ * fail-safe as every other call site here: a config mismatch never syncs
507
+ * the wrong thing, it just doesn't sync this row instantly (the safety-net
508
+ * delta sync still will).
509
+ *
510
+ * `row` must be keyed by the source table's real database column names
511
+ * (`full_name`, not `fullName`) — the same contract `fetchPage` rows
512
+ * satisfy. `insertAndPush` (from `clivly/drizzle`) performs this
513
+ * translation for you from a Drizzle table; calling `pushOne` directly with
514
+ * a raw Drizzle `.returning()` row will silently push empty fields.
515
+ *
516
+ * Never throws and never advances the delta cursor. Fire-and-forget by
517
+ * design: on Cloudflare Workers and similar runtimes, wrap the call in
518
+ * `ctx.waitUntil(...)` so it survives past the response, since nothing
519
+ * here blocks or awaits the caller's own write.
520
+ */
521
+ pushOne(entityKey: string, row: Record<string, unknown>): Promise<void>;
480
522
  /**
481
523
  * One-shot heartbeat + a single sync, with no keep-alive timers. The correct
482
524
  * entry point on serverless/edge (Workers, Vercel, Lambda), where `start()`'s
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clivly",
3
- "version": "0.12.0",
3
+ "version": "0.14.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Clivly CLI — scaffold a CRM into your app (clivly init).",