clivly 0.9.4 → 0.9.6

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 (62) hide show
  1. package/README.md +30 -6
  2. package/core-entity-config.cjs +1 -1
  3. package/core-entity-config.mjs +1 -1
  4. package/core-mappings-config.cjs +1 -1
  5. package/core-mappings-config.mjs +1 -1
  6. package/core-sync-engine.cjs +1 -1
  7. package/core-sync-engine.mjs +1 -1
  8. package/core-view-compiler.cjs +1 -1
  9. package/core-view-compiler.mjs +1 -1
  10. package/core.cjs +13 -7
  11. package/core.d.cts +2 -2
  12. package/core.d.mts +2 -2
  13. package/core.mjs +8 -8
  14. package/drizzle.cjs +19 -2
  15. package/drizzle.d.cts +1 -1
  16. package/drizzle.d.mts +1 -1
  17. package/drizzle.mjs +19 -2
  18. package/{entity-config-B74SPOUZ.mjs → entity-config-CusbTOJ1.mjs} +1 -1
  19. package/{entity-config-7sGCk_nw.cjs → entity-config-DE30_RpU.cjs} +1 -1
  20. package/index.cjs +129 -11
  21. package/index.mjs +129 -11
  22. package/internal-BQ47iN6f.cjs +259 -0
  23. package/internal-ChufvXE6.mjs +212 -0
  24. package/{internal-o2M7FGlR.d.mts → internal-CvlFk3KC.d.mts} +82 -2
  25. package/{internal-wCXSELDN.d.cts → internal-DGUOLQAq.d.cts} +82 -2
  26. package/internal-entity-config.cjs +1 -1
  27. package/internal-entity-config.mjs +1 -1
  28. package/internal-entity-heuristics.cjs +1 -1
  29. package/internal-entity-heuristics.mjs +1 -1
  30. package/internal-mappings-config.cjs +1 -1
  31. package/internal-mappings-config.mjs +1 -1
  32. package/internal-sync-engine.cjs +1 -1
  33. package/internal-sync-engine.mjs +1 -1
  34. package/internal-view-compiler.cjs +1 -1
  35. package/internal-view-compiler.mjs +1 -1
  36. package/internal.cjs +13 -7
  37. package/internal.d.cts +2 -2
  38. package/internal.d.mts +2 -2
  39. package/internal.mjs +8 -8
  40. package/{mappings-config-DQS_s4dg.mjs → mappings-config-7qQ47p9K.mjs} +1 -1
  41. package/{mappings-config-CLyEg0sf.cjs → mappings-config-CjCmT-aU.cjs} +1 -1
  42. package/{namespace-probe-Cn7voAd0.d.mts → namespace-probe-Ckn9yJ6F.d.mts} +45 -2
  43. package/{namespace-probe-BoGI18dQ.d.cts → namespace-probe-DaTJINS-.d.cts} +45 -2
  44. package/package.json +1 -1
  45. package/{projection-Dz6_i1-w.cjs → projection-DEwL-D8R.cjs} +6 -0
  46. package/{projection-CSGJbZlZ.mjs → projection-hnPSgH6G.mjs} +1 -1
  47. package/{projection-sql-BgnfiGqF.mjs → projection-sql-9zzTVGvf.mjs} +34 -2
  48. package/{projection-sql-Cl1qIn8m.cjs → projection-sql-iHy-Cx6V.cjs} +45 -1
  49. package/{sdk-DYBDR939.mjs → sdk-Dkq6ELkf.mjs} +32 -8
  50. package/{sdk-CM1UO-I7.cjs → sdk-w8Kv_XnW.cjs} +32 -8
  51. package/sdk.cjs +2 -2
  52. package/sdk.d.cts +2 -2
  53. package/sdk.d.mts +2 -2
  54. package/sdk.mjs +2 -2
  55. package/{sync-engine-C4A5jgA4.cjs → sync-engine-BLgwLpR6.cjs} +1 -1
  56. package/{sync-engine-Dt5QQSKO.mjs → sync-engine-B_IzoUSx.mjs} +1 -1
  57. package/{view-compiler-B5nDal14.cjs → view-compiler-BHI5E4QI.cjs} +2 -2
  58. package/{view-compiler-CSYwEWf5.mjs → view-compiler-D_6gfXFr.mjs} +2 -2
  59. package/vite.d.cts +1 -1
  60. package/vite.d.mts +1 -1
  61. package/internal-CykXpEGk.mjs +0 -68
  62. package/internal-DqduZU3l.cjs +0 -97
package/README.md CHANGED
@@ -87,7 +87,10 @@ Detects your framework, ORM, auth adapter and app layout, then scaffolds:
87
87
  | The auth-verify route for your framework | Yes — `--force` to overwrite |
88
88
 
89
89
  Plus `CLIVLY_SECRET_KEY`, `CLIVLY_SYNC_TRIGGER_URL` and
90
- `CLIVLY_SYNC_TRIGGER_SECRET` placeholders in your env file.
90
+ `CLIVLY_SYNC_TRIGGER_SECRET` in your env file. The two secrets are written
91
+ empty, for you or `clivly login` to fill; the trigger URL gets a visible
92
+ `https://<yourDomain.com>/api/clivly/tick` template, because there the shape is
93
+ the documentation.
91
94
 
92
95
  | Flag | Purpose |
93
96
  | --- | --- |
@@ -233,7 +236,7 @@ the CLI requires pairing.
233
236
  | --- | --- | --- |
234
237
  | `CLIVLY_SECRET_KEY` | Dashboard → **Connect app**, or **Settings → API keys** | **Shown once.** Copy it immediately; you cannot retrieve it later, only regenerate. Regenerating **revokes the previous key**, so redeploy after rotating. The legacy name `CLIVLY_API_KEY` is still accepted as a fallback |
235
238
  | `CLIVLY_SYNC_TRIGGER_SECRET` | Dashboard → **Integrations → Remote sync** | Must match the value in your app's env exactly. A mismatch surfaces as a `401` on the signed trigger |
236
- | `CLIVLY_SYNC_TRIGGER_URL` | Your own deployment | The public URL of your mounted tick route, e.g. `https://app.example.com/api/clivly/tick`. Optional until you deploy — push-only setups can leave it unset |
239
+ | `CLIVLY_SYNC_TRIGGER_URL` | Your own deployment | The public URL of your mounted tick route. `init` and `login` both scaffold it as `https://<yourDomain.com>/api/clivly/tick` — the angle brackets mark it unedited, and the SDK ignores it until you replace them, so leaving it alone costs nothing. Optional until you deploy — push-only setups can leave it as the template |
237
240
  | `CLIVLY_PUBLISHABLE_KEY` | Same place as the secret key | Only needed for the chat widget. Safe to expose in client code |
238
241
 
239
242
  Write them into the env file of the package that imports `clivly`, then re-run
@@ -265,7 +268,7 @@ It answers two questions under two headings:
265
268
  scope; `clivly doctor` is local by definition and omits it.
266
269
  - **This project** — the local ladder, run here on your machine: credential →
267
270
  Clivly reachable → `clivly.config` loads → `clivly.config` is edge-safe →
268
- setup checks → sync trigger URL.
271
+ boot hook wired → setup checks → sync trigger URL.
269
272
 
270
273
  ```text
271
274
  Clivly status
@@ -278,11 +281,30 @@ Workspace
278
281
  🔒 Let Clivly start a sync
279
282
 
280
283
  This project
281
- ✅ Step 1 of 6 · API key present
282
- ✅ Step 2 of 6 · Clivly reachable — Acme
284
+ ✅ Step 1 of 7 · API key present
285
+ ✅ Step 2 of 7 · Clivly reachable — Acme
283
286
  ...
284
287
  ```
285
288
 
289
+ **Boot hook wired** is the rung to know about. It finds the boot site for your
290
+ framework and confirms something there actually starts Clivly — and on Next.js
291
+ below 15, that `experimental.instrumentationHook` is set in `next.config`,
292
+ without which `instrumentation.ts` is ignored outright and your app never checks
293
+ in. That failure is otherwise completely silent: the file is present, the config
294
+ loads, the credentials work, and the dashboard stays empty.
295
+
296
+ It is the one rung with no prerequisites, so it still reports when the config
297
+ above it fails to load. A framework the CLI does not recognise shows it as
298
+ skipped rather than passed — there is nowhere known to look, and a green step
299
+ for an unasked question is what made this worth adding.
300
+
301
+ **Sync trigger URL** distinguishes three states, which it previously could not:
302
+ a real URL passes, no URL at all warns, and the
303
+ `https://<yourDomain.com>/api/clivly/tick` template that `clivly login` writes
304
+ into `.env` reports as *still the scaffolded placeholder* — a value that is
305
+ present but cannot resolve. Reading that as "not set" sent people hunting for a
306
+ missing variable sitting in their own `.env`.
307
+
286
308
  If the Workspace section reads
287
309
  `⚠️ This Clivly server does not report setup progress`, or names a rejected key
288
310
  or an unreachable host, that means the question could not be asked — not that
@@ -406,7 +428,7 @@ work, and are kept because output and docs have recommended them — but prefer
406
428
  | --- | --- |
407
429
  | `clivly ping` | Credential + reachability |
408
430
  | `clivly connect` | The above, plus config and trigger URL |
409
- | `clivly doctor` | Config, setup checks and edge safety |
431
+ | `clivly doctor` | Config, edge safety, boot hook and setup checks |
410
432
 
411
433
  Each prints a deprecation notice, then the steps it covers, renumbered to its own
412
434
  scope:
@@ -478,6 +500,8 @@ socket reconnect. The CLI does not enable this setting on your behalf.
478
500
  | `init` cannot find your schema | Pass `--schema <path\|package>` |
479
501
  | `init` scaffolded a `db` import that doesn't resolve | The probe cannot evaluate a db module that throws without `DATABASE_URL`. Fix the `TODO(clivly)` import path it left, or pass `--db-import` |
480
502
  | `clivly login` exits non-zero, pairing unavailable | The backend has `CLIVLY_CLI_PAIRING_ENABLED` off. Use the manual credential path above |
503
+ | App runs, no errors, dashboard stays silent | Run `clivly status` — the **Boot hook wired** step names the cause. On Next.js below 15 it is almost always the missing `experimental: { instrumentationHook: true }` in `next.config` |
504
+ | `Clivly reachable` fails with `invalid_api_key` (401) | The key is not one this org accepts. Re-run `npx clivly login` to re-pair, and check the key belongs to the org whose dashboard you are watching |
481
505
  | `clivly dev` cannot start | Install `cloudflared`, or set `CLIVLY_SYNC_TRIGGER_URL` to a tunnel you run yourself |
482
506
  | Credentials written but the app never loads them | Wrong env file for your framework — see the table under `clivly login` |
483
507
 
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_entity_config = require("./entity-config-7sGCk_nw.cjs");
2
+ const require_entity_config = require("./entity-config-DE30_RpU.cjs");
3
3
  //#region src/core-entity-config.ts
4
4
  require("./deprecate-subpath-B9ngvizt.cjs").warnDeprecatedSubpath("clivly/core/entity-config", "clivly/internal/entity-config");
5
5
  //#endregion
@@ -1,4 +1,4 @@
1
- import { a as MATERIALIZING_CONCEPTS, c as entitiesConfigSchema, d as relationshipSchema, f as relationshipsSchema, i as ClivlyConfigError, l as filterSchema, n as CRM_CONCEPTS, o as customObjectDeclarations, p as validateEntitiesConfig, r as CUSTOM_CONCEPT, s as defineClivlyConfig, t as CANONICAL_FIELDS, u as projectionFields } from "./entity-config-B74SPOUZ.mjs";
1
+ import { a as MATERIALIZING_CONCEPTS, c as entitiesConfigSchema, d as relationshipSchema, f as relationshipsSchema, i as ClivlyConfigError, l as filterSchema, n as CRM_CONCEPTS, o as customObjectDeclarations, p as validateEntitiesConfig, r as CUSTOM_CONCEPT, s as defineClivlyConfig, t as CANONICAL_FIELDS, u as projectionFields } from "./entity-config-CusbTOJ1.mjs";
2
2
  import { t as warnDeprecatedSubpath } from "./deprecate-subpath-CmvZtCpE.mjs";
3
3
  //#region src/core-entity-config.ts
4
4
  warnDeprecatedSubpath("clivly/core/entity-config", "clivly/internal/entity-config");
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_mappings_config = require("./mappings-config-CLyEg0sf.cjs");
2
+ const require_mappings_config = require("./mappings-config-CjCmT-aU.cjs");
3
3
  const require_deprecate_subpath = require("./deprecate-subpath-B9ngvizt.cjs");
4
4
  require("./internal-mappings-config.cjs");
5
5
  //#region src/core-mappings-config.ts
@@ -1,4 +1,4 @@
1
- import { n as mappingsToEntitiesConfig, t as entitiesToMappings } from "./mappings-config-DQS_s4dg.mjs";
1
+ import { n as mappingsToEntitiesConfig, t as entitiesToMappings } from "./mappings-config-7qQ47p9K.mjs";
2
2
  import { t as warnDeprecatedSubpath } from "./deprecate-subpath-CmvZtCpE.mjs";
3
3
  import "./internal-mappings-config.mjs";
4
4
  //#region src/core-mappings-config.ts
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_deprecate_subpath = require("./deprecate-subpath-B9ngvizt.cjs");
3
- const require_sync_engine = require("./sync-engine-C4A5jgA4.cjs");
3
+ const require_sync_engine = require("./sync-engine-BLgwLpR6.cjs");
4
4
  require("./internal-sync-engine.cjs");
5
5
  //#region src/core-sync-engine.ts
6
6
  require_deprecate_subpath.warnDeprecatedSubpath("clivly/core/sync-engine", "clivly/internal/sync-engine");
@@ -1,5 +1,5 @@
1
1
  import { t as warnDeprecatedSubpath } from "./deprecate-subpath-CmvZtCpE.mjs";
2
- import { i as runSync, n as previewSync, r as reconcile, t as computeSampleWarnings } from "./sync-engine-Dt5QQSKO.mjs";
2
+ import { i as runSync, n as previewSync, r as reconcile, t as computeSampleWarnings } from "./sync-engine-B_IzoUSx.mjs";
3
3
  import "./internal-sync-engine.mjs";
4
4
  //#region src/core-sync-engine.ts
5
5
  warnDeprecatedSubpath("clivly/core/sync-engine", "clivly/internal/sync-engine");
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_deprecate_subpath = require("./deprecate-subpath-B9ngvizt.cjs");
3
- const require_view_compiler = require("./view-compiler-B5nDal14.cjs");
3
+ const require_view_compiler = require("./view-compiler-BHI5E4QI.cjs");
4
4
  require("./internal-view-compiler.cjs");
5
5
  //#region src/core-view-compiler.ts
6
6
  require_deprecate_subpath.warnDeprecatedSubpath("clivly/core/view-compiler", "clivly/internal/view-compiler");
@@ -1,5 +1,5 @@
1
1
  import { t as warnDeprecatedSubpath } from "./deprecate-subpath-CmvZtCpE.mjs";
2
- import { a as explainViewExecutionError, i as explainEntitiesConfig, n as compileEntityView, r as compileEntityViews, t as DEFAULT_VIEW_PREFIX } from "./view-compiler-CSYwEWf5.mjs";
2
+ import { a as explainViewExecutionError, i as explainEntitiesConfig, n as compileEntityView, r as compileEntityViews, t as DEFAULT_VIEW_PREFIX } from "./view-compiler-D_6gfXFr.mjs";
3
3
  import "./internal-view-compiler.mjs";
4
4
  //#region src/core-view-compiler.ts
5
5
  warnDeprecatedSubpath("clivly/core/view-compiler", "clivly/internal/view-compiler");
package/core.cjs CHANGED
@@ -1,14 +1,14 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_projection = require("./projection-Dz6_i1-w.cjs");
3
- const require_entity_config = require("./entity-config-7sGCk_nw.cjs");
4
- const require_mappings_config = require("./mappings-config-CLyEg0sf.cjs");
2
+ const require_projection = require("./projection-DEwL-D8R.cjs");
3
+ const require_entity_config = require("./entity-config-DE30_RpU.cjs");
4
+ const require_mappings_config = require("./mappings-config-CjCmT-aU.cjs");
5
5
  const require_deprecate_subpath = require("./deprecate-subpath-B9ngvizt.cjs");
6
6
  const require_auth_adapter = require("./auth-adapter-CiEXcweZ.cjs");
7
7
  const require_mapping_form = require("./mapping-form-BpfON_ME.cjs");
8
- const require_internal = require("./internal-DqduZU3l.cjs");
9
- const require_projection_sql = require("./projection-sql-Cl1qIn8m.cjs");
10
- const require_view_compiler = require("./view-compiler-B5nDal14.cjs");
11
- const require_sync_engine = require("./sync-engine-C4A5jgA4.cjs");
8
+ const require_internal = require("./internal-BQ47iN6f.cjs");
9
+ const require_projection_sql = require("./projection-sql-iHy-Cx6V.cjs");
10
+ const require_view_compiler = require("./view-compiler-BHI5E4QI.cjs");
11
+ const require_sync_engine = require("./sync-engine-BLgwLpR6.cjs");
12
12
  //#region src/core.ts
13
13
  require_deprecate_subpath.warnDeprecatedSubpath("clivly/core", "clivly/sdk", "Import \"defineClivlyConfig\" and its config types from \"clivly/sdk\"; import everything else from \"clivly/internal\" (no stability guarantee — see STABILITY.md).");
14
14
  //#endregion
@@ -18,6 +18,8 @@ exports.CRM_CONCEPTS = require_entity_config.CRM_CONCEPTS;
18
18
  exports.ClivlyConfigError = require_entity_config.ClivlyConfigError;
19
19
  exports.DEFAULT_VIEW_PREFIX = require_view_compiler.DEFAULT_VIEW_PREFIX;
20
20
  exports.MATERIALIZING_CONCEPTS = require_entity_config.MATERIALIZING_CONCEPTS;
21
+ exports.PREVIEW_MAX_ROWS = require_projection_sql.PREVIEW_MAX_ROWS;
22
+ exports.addDraftJoin = require_internal.addDraftJoin;
21
23
  exports.authCustom = require_auth_adapter.authCustom;
22
24
  exports.buildFilterFromDiscriminator = require_mapping_form.buildFilterFromDiscriminator;
23
25
  exports.buildRelationships = require_mapping_form.buildRelationships;
@@ -27,10 +29,13 @@ exports.compileEntityViews = require_view_compiler.compileEntityViews;
27
29
  exports.compileProjectionFrom = require_projection_sql.compileProjectionFrom;
28
30
  exports.compileProjectionIdentity = require_projection_sql.compileProjectionIdentity;
29
31
  exports.compileProjectionJoins = require_projection_sql.compileProjectionJoins;
32
+ exports.compileProjectionPreview = require_projection_sql.compileProjectionPreview;
33
+ exports.compileProjectionSelect = require_projection_sql.compileProjectionSelect;
30
34
  exports.coversUniqueKey = require_entity_config.coversUniqueKey;
31
35
  exports.defineClivlyConfig = require_entity_config.defineClivlyConfig;
32
36
  exports.describeCardinality = require_internal.describeCardinality;
33
37
  exports.draftErrors = require_internal.draftErrors;
38
+ exports.draftRefOptions = require_internal.draftRefOptions;
34
39
  exports.draftToProjection = require_internal.draftToProjection;
35
40
  exports.emptyProjectionDraft = require_internal.emptyProjectionDraft;
36
41
  exports.entitiesConfigSchema = require_entity_config.entitiesConfigSchema;
@@ -48,6 +53,7 @@ exports.reconcile = require_sync_engine.reconcile;
48
53
  exports.relationshipSchema = require_entity_config.relationshipSchema;
49
54
  exports.relationshipViaSignature = require_mapping_form.relationshipViaSignature;
50
55
  exports.relationshipsSchema = require_entity_config.relationshipsSchema;
56
+ exports.removeDraftJoin = require_internal.removeDraftJoin;
51
57
  exports.runSync = require_sync_engine.runSync;
52
58
  exports.suggestJoinConditions = require_internal.suggestJoinConditions;
53
59
  exports.validateEntitiesConfig = require_entity_config.validateEntitiesConfig;
package/core.d.cts CHANGED
@@ -7,5 +7,5 @@ import { i as mappingsToEntitiesConfig, t as EntityMappingRow } from "./mappings
7
7
  import { a as compileEntityView, i as ExplainResult, n as CompiledView, o as compileEntityViews, r as DEFAULT_VIEW_PREFIX, s as explainEntitiesConfig, t as CompileOptions } from "./view-compiler-CmEdAMwj.cjs";
8
8
  import { c as SyncResult, f as reconcile, l as SyncStore, n as MirrorRecord, o as SourceRow, p as runSync, r as PersistAction, s as SyncAction, t as EntitySyncResult } from "./sync-engine-BG2O1an2.cjs";
9
9
  import { a as IntegrationStep, c as StepProblem, i as IntegrationStatus, l as StepState, n as IntegrationFacts, o as NextAction, r as IntegrationState, s as StepId, t as ConnectionLiveness } from "./integration-state-BK-riZnm.cjs";
10
- import { _ as joinFansOut, a as validateProjection, c as compileProjectionJoins, d as describeCardinality, f as draftErrors, g as fanOutJoins, h as suggestJoinConditions, i as primaryKeyColumns, l as quoteIdent, m as emptyProjectionDraft, n as coversUniqueKey, o as compileProjectionFrom, p as draftToProjection, r as hasRichMeta, s as compileProjectionIdentity, t as columnMetaFor, u as ProjectionDraft } from "./internal-wCXSELDN.cjs";
11
- export { type Activity, type ActivityType, BASE_REF, CANONICAL_FIELDS, type CRMAdapter, CRM_CONCEPTS, type ClivlyAuthAdapter, ClivlyConfigError, type ClivlyEntitiesConfig, type ClivlyEntityConfig, type ClivlyUser, type Company, type CompileOptions, type CompiledView, type ConfigValidationError, type ConfigValidationResult, type ConnectionLiveness, type Contact, type ContactFilters, type ContactStatus, type CreateActivityInput, type CreateCompanyInput, type CreateContactInput, type CreateDealInput, type CreateTaskInput, type CrmConcept, type CrmMembership, type CrmRole, DEFAULT_VIEW_PREFIX, type Deal, type DealStage, type DiscoveredColumnMeta, type DiscoveredSchemaTable, type EntityMappingRow, type EntitySyncResult, type ExplainResult, type FilterExpr, type FilterValue, type IntegrationFacts, type IntegrationState, type IntegrationStatus, type IntegrationStep, MATERIALIZING_CONCEPTS, type MaterializingConcept, type MembershipResolver, type MirrorRecord, type NextAction, type Note, type PersistAction, type ProjectionDraft, type ProjectionFieldBinding, type ProjectionIdentity, type ProjectionJoin, type ProjectionMapping, type ProjectionRef, type RecordSource, type RelationshipCandidate, type RelationshipSpec, type RelationshipVia, type RelationshipsMap, type SourceRow, type StepId, type StepProblem, type StepState, type SyncAction, type SyncResult, type SyncStore, type Task, type TaskEntityType, type TaskFilters, type TaskPriority, type TaskStatus, type UpdateContactInput, type UpdateDealInput, type UpdateTaskInput, authCustom, buildFilterFromDiscriminator, buildRelationships, columnMetaFor, compileEntityView, compileEntityViews, compileProjectionFrom, compileProjectionIdentity, compileProjectionJoins, coversUniqueKey, defineClivlyConfig, describeCardinality, draftErrors, draftToProjection, emptyProjectionDraft, entitiesConfigSchema, explainEntitiesConfig, fanOutJoins, filterSchema, hasRichMeta, identityRefs, joinFansOut, mappingsToEntitiesConfig, primaryKeyColumns, projectionSchema, quoteIdent, reconcile, relationshipSchema, relationshipViaSignature, relationshipsSchema, runSync, suggestJoinConditions, validateEntitiesConfig, validateProjection };
10
+ import { C as fanOutJoins, S as suggestJoinConditions, _ as draftErrors, a as validateProjection, b as emptyProjectionDraft, c as compileProjectionIdentity, d as compileProjectionSelect, f as quoteIdent, g as describeCardinality, h as addDraftJoin, i as primaryKeyColumns, l as compileProjectionJoins, m as ProjectionDraft, n as coversUniqueKey, o as PREVIEW_MAX_ROWS, p as DraftRefOption, r as hasRichMeta, s as compileProjectionFrom, t as columnMetaFor, u as compileProjectionPreview, v as draftRefOptions, w as joinFansOut, x as removeDraftJoin, y as draftToProjection } from "./internal-DGUOLQAq.cjs";
11
+ export { type Activity, type ActivityType, BASE_REF, CANONICAL_FIELDS, type CRMAdapter, CRM_CONCEPTS, type ClivlyAuthAdapter, ClivlyConfigError, type ClivlyEntitiesConfig, type ClivlyEntityConfig, type ClivlyUser, type Company, type CompileOptions, type CompiledView, type ConfigValidationError, type ConfigValidationResult, type ConnectionLiveness, type Contact, type ContactFilters, type ContactStatus, type CreateActivityInput, type CreateCompanyInput, type CreateContactInput, type CreateDealInput, type CreateTaskInput, type CrmConcept, type CrmMembership, type CrmRole, DEFAULT_VIEW_PREFIX, type Deal, type DealStage, type DiscoveredColumnMeta, type DiscoveredSchemaTable, type DraftRefOption, type EntityMappingRow, type EntitySyncResult, type ExplainResult, type FilterExpr, type FilterValue, type IntegrationFacts, type IntegrationState, type IntegrationStatus, type IntegrationStep, MATERIALIZING_CONCEPTS, type MaterializingConcept, type MembershipResolver, type MirrorRecord, type NextAction, type Note, PREVIEW_MAX_ROWS, type PersistAction, type ProjectionDraft, type ProjectionFieldBinding, type ProjectionIdentity, type ProjectionJoin, type ProjectionMapping, type ProjectionRef, type RecordSource, type RelationshipCandidate, type RelationshipSpec, type RelationshipVia, type RelationshipsMap, type SourceRow, type StepId, type StepProblem, type StepState, type SyncAction, type SyncResult, type SyncStore, type Task, type TaskEntityType, type TaskFilters, type TaskPriority, type TaskStatus, type UpdateContactInput, type UpdateDealInput, type UpdateTaskInput, addDraftJoin, authCustom, buildFilterFromDiscriminator, buildRelationships, columnMetaFor, compileEntityView, compileEntityViews, compileProjectionFrom, compileProjectionIdentity, compileProjectionJoins, compileProjectionPreview, compileProjectionSelect, coversUniqueKey, defineClivlyConfig, describeCardinality, draftErrors, draftRefOptions, draftToProjection, emptyProjectionDraft, entitiesConfigSchema, explainEntitiesConfig, fanOutJoins, filterSchema, hasRichMeta, identityRefs, joinFansOut, mappingsToEntitiesConfig, primaryKeyColumns, projectionSchema, quoteIdent, reconcile, relationshipSchema, relationshipViaSignature, relationshipsSchema, removeDraftJoin, runSync, suggestJoinConditions, validateEntitiesConfig, validateProjection };
package/core.d.mts CHANGED
@@ -7,5 +7,5 @@ import { i as mappingsToEntitiesConfig, t as EntityMappingRow } from "./mappings
7
7
  import { a as compileEntityView, i as ExplainResult, n as CompiledView, o as compileEntityViews, r as DEFAULT_VIEW_PREFIX, s as explainEntitiesConfig, t as CompileOptions } from "./view-compiler-Bo7pqXW3.mjs";
8
8
  import { c as SyncResult, f as reconcile, l as SyncStore, n as MirrorRecord, o as SourceRow, p as runSync, r as PersistAction, s as SyncAction, t as EntitySyncResult } from "./sync-engine-DgQbrJON.mjs";
9
9
  import { a as IntegrationStep, c as StepProblem, i as IntegrationStatus, l as StepState, n as IntegrationFacts, o as NextAction, r as IntegrationState, s as StepId, t as ConnectionLiveness } from "./integration-state-BK-riZnm.mjs";
10
- import { _ as joinFansOut, a as validateProjection, c as compileProjectionJoins, d as describeCardinality, f as draftErrors, g as fanOutJoins, h as suggestJoinConditions, i as primaryKeyColumns, l as quoteIdent, m as emptyProjectionDraft, n as coversUniqueKey, o as compileProjectionFrom, p as draftToProjection, r as hasRichMeta, s as compileProjectionIdentity, t as columnMetaFor, u as ProjectionDraft } from "./internal-o2M7FGlR.mjs";
11
- export { type Activity, type ActivityType, BASE_REF, CANONICAL_FIELDS, type CRMAdapter, CRM_CONCEPTS, type ClivlyAuthAdapter, ClivlyConfigError, type ClivlyEntitiesConfig, type ClivlyEntityConfig, type ClivlyUser, type Company, type CompileOptions, type CompiledView, type ConfigValidationError, type ConfigValidationResult, type ConnectionLiveness, type Contact, type ContactFilters, type ContactStatus, type CreateActivityInput, type CreateCompanyInput, type CreateContactInput, type CreateDealInput, type CreateTaskInput, type CrmConcept, type CrmMembership, type CrmRole, DEFAULT_VIEW_PREFIX, type Deal, type DealStage, type DiscoveredColumnMeta, type DiscoveredSchemaTable, type EntityMappingRow, type EntitySyncResult, type ExplainResult, type FilterExpr, type FilterValue, type IntegrationFacts, type IntegrationState, type IntegrationStatus, type IntegrationStep, MATERIALIZING_CONCEPTS, type MaterializingConcept, type MembershipResolver, type MirrorRecord, type NextAction, type Note, type PersistAction, type ProjectionDraft, type ProjectionFieldBinding, type ProjectionIdentity, type ProjectionJoin, type ProjectionMapping, type ProjectionRef, type RecordSource, type RelationshipCandidate, type RelationshipSpec, type RelationshipVia, type RelationshipsMap, type SourceRow, type StepId, type StepProblem, type StepState, type SyncAction, type SyncResult, type SyncStore, type Task, type TaskEntityType, type TaskFilters, type TaskPriority, type TaskStatus, type UpdateContactInput, type UpdateDealInput, type UpdateTaskInput, authCustom, buildFilterFromDiscriminator, buildRelationships, columnMetaFor, compileEntityView, compileEntityViews, compileProjectionFrom, compileProjectionIdentity, compileProjectionJoins, coversUniqueKey, defineClivlyConfig, describeCardinality, draftErrors, draftToProjection, emptyProjectionDraft, entitiesConfigSchema, explainEntitiesConfig, fanOutJoins, filterSchema, hasRichMeta, identityRefs, joinFansOut, mappingsToEntitiesConfig, primaryKeyColumns, projectionSchema, quoteIdent, reconcile, relationshipSchema, relationshipViaSignature, relationshipsSchema, runSync, suggestJoinConditions, validateEntitiesConfig, validateProjection };
10
+ import { C as fanOutJoins, S as suggestJoinConditions, _ as draftErrors, a as validateProjection, b as emptyProjectionDraft, c as compileProjectionIdentity, d as compileProjectionSelect, f as quoteIdent, g as describeCardinality, h as addDraftJoin, i as primaryKeyColumns, l as compileProjectionJoins, m as ProjectionDraft, n as coversUniqueKey, o as PREVIEW_MAX_ROWS, p as DraftRefOption, r as hasRichMeta, s as compileProjectionFrom, t as columnMetaFor, u as compileProjectionPreview, v as draftRefOptions, w as joinFansOut, x as removeDraftJoin, y as draftToProjection } from "./internal-CvlFk3KC.mjs";
11
+ export { type Activity, type ActivityType, BASE_REF, CANONICAL_FIELDS, type CRMAdapter, CRM_CONCEPTS, type ClivlyAuthAdapter, ClivlyConfigError, type ClivlyEntitiesConfig, type ClivlyEntityConfig, type ClivlyUser, type Company, type CompileOptions, type CompiledView, type ConfigValidationError, type ConfigValidationResult, type ConnectionLiveness, type Contact, type ContactFilters, type ContactStatus, type CreateActivityInput, type CreateCompanyInput, type CreateContactInput, type CreateDealInput, type CreateTaskInput, type CrmConcept, type CrmMembership, type CrmRole, DEFAULT_VIEW_PREFIX, type Deal, type DealStage, type DiscoveredColumnMeta, type DiscoveredSchemaTable, type DraftRefOption, type EntityMappingRow, type EntitySyncResult, type ExplainResult, type FilterExpr, type FilterValue, type IntegrationFacts, type IntegrationState, type IntegrationStatus, type IntegrationStep, MATERIALIZING_CONCEPTS, type MaterializingConcept, type MembershipResolver, type MirrorRecord, type NextAction, type Note, PREVIEW_MAX_ROWS, type PersistAction, type ProjectionDraft, type ProjectionFieldBinding, type ProjectionIdentity, type ProjectionJoin, type ProjectionMapping, type ProjectionRef, type RecordSource, type RelationshipCandidate, type RelationshipSpec, type RelationshipVia, type RelationshipsMap, type SourceRow, type StepId, type StepProblem, type StepState, type SyncAction, type SyncResult, type SyncStore, type Task, type TaskEntityType, type TaskFilters, type TaskPriority, type TaskStatus, type UpdateContactInput, type UpdateDealInput, type UpdateTaskInput, addDraftJoin, authCustom, buildFilterFromDiscriminator, buildRelationships, columnMetaFor, compileEntityView, compileEntityViews, compileProjectionFrom, compileProjectionIdentity, compileProjectionJoins, compileProjectionPreview, compileProjectionSelect, coversUniqueKey, defineClivlyConfig, describeCardinality, draftErrors, draftRefOptions, draftToProjection, emptyProjectionDraft, entitiesConfigSchema, explainEntitiesConfig, fanOutJoins, filterSchema, hasRichMeta, identityRefs, joinFansOut, mappingsToEntitiesConfig, primaryKeyColumns, projectionSchema, quoteIdent, reconcile, relationshipSchema, relationshipViaSignature, relationshipsSchema, removeDraftJoin, runSync, suggestJoinConditions, validateEntitiesConfig, validateProjection };
package/core.mjs CHANGED
@@ -1,14 +1,14 @@
1
- import { i as projectionSchema, r as identityRefs, t as BASE_REF } from "./projection-CSGJbZlZ.mjs";
2
- import { _ as columnMetaFor, a as MATERIALIZING_CONCEPTS, b as primaryKeyColumns, c as entitiesConfigSchema, d as relationshipSchema, f as relationshipsSchema, g as joinFansOut, h as fanOutJoins, i as ClivlyConfigError, l as filterSchema, m as validateProjection, n as CRM_CONCEPTS, p as validateEntitiesConfig, s as defineClivlyConfig, t as CANONICAL_FIELDS, v as coversUniqueKey, y as hasRichMeta } from "./entity-config-B74SPOUZ.mjs";
3
- import { n as mappingsToEntitiesConfig } from "./mappings-config-DQS_s4dg.mjs";
1
+ import { a as projectionSchema, i as identityRefs, t as BASE_REF } from "./projection-hnPSgH6G.mjs";
2
+ import { _ as columnMetaFor, a as MATERIALIZING_CONCEPTS, b as primaryKeyColumns, c as entitiesConfigSchema, d as relationshipSchema, f as relationshipsSchema, g as joinFansOut, h as fanOutJoins, i as ClivlyConfigError, l as filterSchema, m as validateProjection, n as CRM_CONCEPTS, p as validateEntitiesConfig, s as defineClivlyConfig, t as CANONICAL_FIELDS, v as coversUniqueKey, y as hasRichMeta } from "./entity-config-CusbTOJ1.mjs";
3
+ import { n as mappingsToEntitiesConfig } from "./mappings-config-7qQ47p9K.mjs";
4
4
  import { t as warnDeprecatedSubpath } from "./deprecate-subpath-CmvZtCpE.mjs";
5
5
  import { t as authCustom } from "./auth-adapter-gfVDxf3d.mjs";
6
6
  import { n as buildRelationships, r as relationshipViaSignature, t as buildFilterFromDiscriminator } from "./mapping-form-DigkuvFc.mjs";
7
- import { a as suggestJoinConditions, i as emptyProjectionDraft, n as draftErrors, r as draftToProjection, t as describeCardinality } from "./internal-CykXpEGk.mjs";
8
- import { a as quoteIdent, n as compileProjectionIdentity, r as compileProjectionJoins, t as compileProjectionFrom } from "./projection-sql-BgnfiGqF.mjs";
9
- import { i as explainEntitiesConfig, n as compileEntityView, r as compileEntityViews, t as DEFAULT_VIEW_PREFIX } from "./view-compiler-CSYwEWf5.mjs";
10
- import { i as runSync, r as reconcile } from "./sync-engine-Dt5QQSKO.mjs";
7
+ import { a as draftToProjection, c as suggestJoinConditions, i as draftRefOptions, n as describeCardinality, o as emptyProjectionDraft, r as draftErrors, s as removeDraftJoin, t as addDraftJoin } from "./internal-ChufvXE6.mjs";
8
+ import { a as compileProjectionPreview, i as compileProjectionJoins, n as compileProjectionFrom, o as compileProjectionSelect, r as compileProjectionIdentity, s as quoteIdent, t as PREVIEW_MAX_ROWS } from "./projection-sql-9zzTVGvf.mjs";
9
+ import { i as explainEntitiesConfig, n as compileEntityView, r as compileEntityViews, t as DEFAULT_VIEW_PREFIX } from "./view-compiler-D_6gfXFr.mjs";
10
+ import { i as runSync, r as reconcile } from "./sync-engine-B_IzoUSx.mjs";
11
11
  //#region src/core.ts
12
12
  warnDeprecatedSubpath("clivly/core", "clivly/sdk", "Import \"defineClivlyConfig\" and its config types from \"clivly/sdk\"; import everything else from \"clivly/internal\" (no stability guarantee — see STABILITY.md).");
13
13
  //#endregion
14
- export { BASE_REF, CANONICAL_FIELDS, CRM_CONCEPTS, ClivlyConfigError, DEFAULT_VIEW_PREFIX, MATERIALIZING_CONCEPTS, authCustom, buildFilterFromDiscriminator, buildRelationships, columnMetaFor, compileEntityView, compileEntityViews, compileProjectionFrom, compileProjectionIdentity, compileProjectionJoins, coversUniqueKey, defineClivlyConfig, describeCardinality, draftErrors, draftToProjection, emptyProjectionDraft, entitiesConfigSchema, explainEntitiesConfig, fanOutJoins, filterSchema, hasRichMeta, identityRefs, joinFansOut, mappingsToEntitiesConfig, primaryKeyColumns, projectionSchema, quoteIdent, reconcile, relationshipSchema, relationshipViaSignature, relationshipsSchema, runSync, suggestJoinConditions, validateEntitiesConfig, validateProjection };
14
+ export { BASE_REF, CANONICAL_FIELDS, CRM_CONCEPTS, ClivlyConfigError, DEFAULT_VIEW_PREFIX, MATERIALIZING_CONCEPTS, PREVIEW_MAX_ROWS, addDraftJoin, authCustom, buildFilterFromDiscriminator, buildRelationships, columnMetaFor, compileEntityView, compileEntityViews, compileProjectionFrom, compileProjectionIdentity, compileProjectionJoins, compileProjectionPreview, compileProjectionSelect, coversUniqueKey, defineClivlyConfig, describeCardinality, draftErrors, draftRefOptions, draftToProjection, emptyProjectionDraft, entitiesConfigSchema, explainEntitiesConfig, fanOutJoins, filterSchema, hasRichMeta, identityRefs, joinFansOut, mappingsToEntitiesConfig, primaryKeyColumns, projectionSchema, quoteIdent, reconcile, relationshipSchema, relationshipViaSignature, relationshipsSchema, removeDraftJoin, runSync, suggestJoinConditions, validateEntitiesConfig, validateProjection };
package/drizzle.cjs CHANGED
@@ -1,9 +1,23 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_projection = require("./projection-Dz6_i1-w.cjs");
2
+ const require_projection = require("./projection-DEwL-D8R.cjs");
3
3
  const require_drizzle_meta = require("./drizzle-meta-Bb1JWYqf.cjs");
4
- const require_projection_sql = require("./projection-sql-Cl1qIn8m.cjs");
4
+ const require_projection_sql = require("./projection-sql-iHy-Cx6V.cjs");
5
5
  const require_drizzle = require("./drizzle-bfjVzYR6.cjs");
6
6
  let drizzle_orm = require("drizzle-orm");
7
+ //#region ../sdk/src/projection-preview.ts
8
+ /** `db.execute` returns either an array or `{ rows }`, depending on driver. */
9
+ function rowsOf(result) {
10
+ if (Array.isArray(result)) return result;
11
+ const rows = result.rows;
12
+ if (Array.isArray(rows)) return rows;
13
+ throw new Error("previewProjection: db.execute() returned neither an array of rows nor { rows }.");
14
+ }
15
+ async function previewProjection(db, projection, opts) {
16
+ const client = db;
17
+ const { sql } = await import("drizzle-orm");
18
+ return rowsOf(await client.execute(sql.raw(require_projection_sql.compileProjectionPreview(projection, opts.limit))));
19
+ }
20
+ //#endregion
7
21
  //#region ../sdk/src/drizzle-projection.ts
8
22
  /** `<ref>.<column>` — the token `fields` carries and cloud-ingest reads. */
9
23
  function refToken(ref) {
@@ -135,6 +149,9 @@ function drizzleIntrospector(db) {
135
149
  },
136
150
  async sampleSelect(table) {
137
151
  await client.execute(drizzle_orm.sql`select 1 from ${drizzle_orm.sql.identifier(table)} limit 1`);
152
+ },
153
+ runProjection(projection, opts) {
154
+ return previewProjection(db, projection, opts);
138
155
  }
139
156
  };
140
157
  }
package/drizzle.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { F as ProjectionRef, P as ProjectionMapping } from "./entity-config-B2RA53nw.cjs";
2
2
  import { n as buildUniqueConstraints, r as discoverFromDrizzle } from "./drizzle-DEtRrqtc.cjs";
3
- import { _ as SyncSource, t as NamespaceIntrospector } from "./namespace-probe-BoGI18dQ.cjs";
3
+ import { _ as SyncSource, t as NamespaceIntrospector } from "./namespace-probe-DaTJINS-.cjs";
4
4
  import { Table } from "drizzle-orm";
5
5
  //#region ../sdk/src/drizzle-projection.d.ts
6
6
  /**
package/drizzle.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { F as ProjectionRef, P as ProjectionMapping } from "./entity-config-B2RA53nw.mjs";
2
2
  import { n as buildUniqueConstraints, r as discoverFromDrizzle } from "./drizzle-CiK8MMEZ.mjs";
3
- import { _ as SyncSource, t as NamespaceIntrospector } from "./namespace-probe-Cn7voAd0.mjs";
3
+ import { _ as SyncSource, t as NamespaceIntrospector } from "./namespace-probe-Ckn9yJ6F.mjs";
4
4
  import { Table } from "drizzle-orm";
5
5
  //#region ../sdk/src/drizzle-projection.d.ts
6
6
  /**
package/drizzle.mjs CHANGED
@@ -1,8 +1,22 @@
1
- import { t as BASE_REF } from "./projection-CSGJbZlZ.mjs";
1
+ import { t as BASE_REF } from "./projection-hnPSgH6G.mjs";
2
2
  import { t as DRIZZLE_META } from "./drizzle-meta-D-5k3n0i.mjs";
3
- import { a as quoteIdent, n as compileProjectionIdentity, r as compileProjectionJoins, t as compileProjectionFrom } from "./projection-sql-BgnfiGqF.mjs";
3
+ import { a as compileProjectionPreview, i as compileProjectionJoins, n as compileProjectionFrom, r as compileProjectionIdentity, s as quoteIdent } from "./projection-sql-9zzTVGvf.mjs";
4
4
  import { n as buildUniqueConstraints, r as discoverFromDrizzle, t as buildColumnsMeta } from "./drizzle-3kvhkwO7.mjs";
5
5
  import { asc, getTableColumns, getTableName, sql } from "drizzle-orm";
6
+ //#region ../sdk/src/projection-preview.ts
7
+ /** `db.execute` returns either an array or `{ rows }`, depending on driver. */
8
+ function rowsOf(result) {
9
+ if (Array.isArray(result)) return result;
10
+ const rows = result.rows;
11
+ if (Array.isArray(rows)) return rows;
12
+ throw new Error("previewProjection: db.execute() returned neither an array of rows nor { rows }.");
13
+ }
14
+ async function previewProjection(db, projection, opts) {
15
+ const client = db;
16
+ const { sql } = await import("drizzle-orm");
17
+ return rowsOf(await client.execute(sql.raw(compileProjectionPreview(projection, opts.limit))));
18
+ }
19
+ //#endregion
6
20
  //#region ../sdk/src/drizzle-projection.ts
7
21
  /** `<ref>.<column>` — the token `fields` carries and cloud-ingest reads. */
8
22
  function refToken(ref) {
@@ -134,6 +148,9 @@ function drizzleIntrospector(db) {
134
148
  },
135
149
  async sampleSelect(table) {
136
150
  await client.execute(sql`select 1 from ${sql.identifier(table)} limit 1`);
151
+ },
152
+ runProjection(projection, opts) {
153
+ return previewProjection(db, projection, opts);
137
154
  }
138
155
  };
139
156
  }
@@ -1,4 +1,4 @@
1
- import { a as _enum, c as literal, d as strictObject, f as string, i as projectionSchema, l as number, o as array, p as union, r as identityRefs, s as boolean, t as BASE_REF, u as record } from "./projection-CSGJbZlZ.mjs";
1
+ import { a as projectionSchema, c as boolean, d as record, f as strictObject, i as identityRefs, l as literal, m as union, o as _enum, p as string, s as array, t as BASE_REF, u as number } from "./projection-hnPSgH6G.mjs";
2
2
  //#region ../core/src/schema-meta.ts
3
3
  /**
4
4
  * Accessors over a discovered table's schema-v2 metadata.
@@ -1,4 +1,4 @@
1
- const require_projection = require("./projection-Dz6_i1-w.cjs");
1
+ const require_projection = require("./projection-DEwL-D8R.cjs");
2
2
  //#region ../core/src/schema-meta.ts
3
3
  /**
4
4
  * Accessors over a discovered table's schema-v2 metadata.
package/index.cjs CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const require_entity_config = require("./entity-config-7sGCk_nw.cjs");
3
+ const require_entity_config = require("./entity-config-DE30_RpU.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-CM1UO-I7.cjs");
6
+ const require_sdk = require("./sdk-w8Kv_XnW.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");
@@ -974,7 +974,7 @@ function isKeySet(contents, key) {
974
974
  function appendEnvKeys(existing, entries) {
975
975
  const missing = entries.filter((e) => !hasKey$1(existing, e.key));
976
976
  if (missing.length === 0) return existing;
977
- const block = missing.map((e) => `${e.comment ? `# ${e.comment}\n` : ""}${e.key}=`).join("\n");
977
+ const block = missing.map((e) => `${e.comment ? `# ${e.comment}\n` : ""}${e.key}=${e.value ?? ""}`).join("\n");
978
978
  return `${existing}${existing.length > 0 && !existing.endsWith("\n") ? "\n" : ""}${existing.length > 0 ? "\n" : ""}# Clivly\n${block}\n`;
979
979
  }
980
980
  /**
@@ -1596,7 +1596,7 @@ function planInit(schema, overrides = {}) {
1596
1596
  todos.push(...candidateTodos);
1597
1597
  company = candidate;
1598
1598
  if (require_internal_entity_heuristics.matchesConcept(companyTable.tableName, "contact")) todos.push(`"${companyTable.tableName}" matches both contact and company naming — assigned to company. Swap it to your contact entity if that's wrong.`);
1599
- } else todos.push(`"${companyTable.tableName}" looked like a company but no fields could be mapped — left it out. Add it to \`entities\` once you know which columns map to name/domain.`);
1599
+ } else todos.push(`"${companyTable.tableName}" looked like a company but no fields could be mapped — left it out. Add it to \`entities\` once you know which columns map to name/domain, or build a derived object from it in Clivly (Integrations → Map as custom object) if the fields live in a joined table.`);
1600
1600
  }
1601
1601
  if (contactTable && contact) {
1602
1602
  const scored = require_internal_entity_heuristics.scoreRelationships(toScoredTable(contactTable), schema.tables.map(toScoredTable));
@@ -1810,7 +1810,8 @@ const CLIVLY_ENV_KEYS = [
1810
1810
  },
1811
1811
  {
1812
1812
  key: "CLIVLY_SYNC_TRIGGER_URL",
1813
- comment: "Public URL of your mounted tick route (e.g. https://app.example.com/api/clivly/tick)"
1813
+ value: TRIGGER_URL_PLACEHOLDER,
1814
+ comment: "Public URL of your tick route — replace <yourDomain.com> once deployed. Local dev: run `clivly dev` instead."
1814
1815
  },
1815
1816
  {
1816
1817
  key: "CLIVLY_SYNC_TRIGGER_SECRET",
@@ -2741,6 +2742,103 @@ function ladderExitCode(results) {
2741
2742
  return results.every((result) => result.state !== "fail" && result.state !== "pending") ? 0 : 1;
2742
2743
  }
2743
2744
  //#endregion
2745
+ //#region src/boot-hook-check.ts
2746
+ const REMIX_ENTRY_CANDIDATES = [
2747
+ "app/entry.server.tsx",
2748
+ "app/entry.server.ts",
2749
+ "app/entry.server.jsx",
2750
+ "app/entry.server.js"
2751
+ ];
2752
+ const NEXT_CONFIG_CANDIDATES = [
2753
+ "next.config.ts",
2754
+ "next.config.mjs",
2755
+ "next.config.js",
2756
+ "next.config.cjs",
2757
+ "next.config.mts"
2758
+ ];
2759
+ const CLIVLY_MENTION = /clivly/i;
2760
+ const INSTRUMENTATION_HOOK_ENABLED = /instrumentationHook\s*:\s*true/;
2761
+ /**
2762
+ * Where this framework's boot hook lives, most likely location first.
2763
+ *
2764
+ * The file-owning frameworks are asked of `boot-hook.ts` rather than restated,
2765
+ * so a path change there cannot leave this check hunting for a file `init` no
2766
+ * longer writes. The other two are patched into a file the app already owns.
2767
+ */
2768
+ function bootSiteCandidates(framework) {
2769
+ const owned = [bootHookPath(framework, "app"), bootHookPath(framework, "src/app")].filter((path) => path !== null);
2770
+ if (owned.length > 0) return [...new Set(owned)];
2771
+ if (framework === "tanstack-start") return [...VITE_CONFIG_CANDIDATES];
2772
+ if (framework === "remix") return REMIX_ENTRY_CANDIDATES;
2773
+ return [];
2774
+ }
2775
+ function declaredDeps(readFile) {
2776
+ const raw = readFile("package.json");
2777
+ if (raw === null) return null;
2778
+ try {
2779
+ const pkg = JSON.parse(raw);
2780
+ return {
2781
+ ...pkg.dependencies,
2782
+ ...pkg.devDependencies
2783
+ };
2784
+ } catch {
2785
+ return null;
2786
+ }
2787
+ }
2788
+ function findBootSite(readFile, framework) {
2789
+ for (const candidate of bootSiteCandidates(framework)) {
2790
+ const source = readFile(candidate);
2791
+ if (source !== null && CLIVLY_MENTION.test(source)) return candidate;
2792
+ }
2793
+ return null;
2794
+ }
2795
+ /**
2796
+ * On Next.js below 15 the hook file is ignored unless the flag is on, so a
2797
+ * present-and-correct instrumentation.ts is not evidence of anything. A missing
2798
+ * next.config is the same failure as one without the flag: either way nothing
2799
+ * switches the hook on.
2800
+ */
2801
+ function nextFlagVerdict(readFile, version, site) {
2802
+ if (!nextNeedsInstrumentationFlag(version)) return null;
2803
+ for (const candidate of NEXT_CONFIG_CANDIDATES) {
2804
+ const source = readFile(candidate);
2805
+ if (source !== null && INSTRUMENTATION_HOOK_ENABLED.test(source)) return null;
2806
+ }
2807
+ return {
2808
+ state: "broken",
2809
+ detail: `${site} exists, but Next.js ${version} ignores it — experimental.instrumentationHook is not enabled in next.config.`,
2810
+ hint: NEXT_INSTRUMENTATION_FLAG_STEP
2811
+ };
2812
+ }
2813
+ function checkBootHook(readFile) {
2814
+ const deps = declaredDeps(readFile);
2815
+ if (deps === null) return {
2816
+ state: "unknown",
2817
+ detail: "package.json not readable — cannot tell how this app boots."
2818
+ };
2819
+ const framework = detectFramework(deps);
2820
+ if (framework === "unknown") return {
2821
+ state: "unknown",
2822
+ detail: "No supported framework detected, so there is no known place to check."
2823
+ };
2824
+ const label = FRAMEWORK_LABELS[framework];
2825
+ const site = findBootSite(readFile, framework);
2826
+ if (site === null) return {
2827
+ state: "broken",
2828
+ detail: `No Clivly boot hook found in this ${label} app.`,
2829
+ hint: `Nothing starts the SDK, so your app never tells Clivly it is running — the dashboard stays silent with no error anywhere. Run \`clivly init\` to scaffold it, or call \`clivly.start()\` where your server boots (${bootSiteCandidates(framework)[0]}).`
2830
+ };
2831
+ const nextVersion = deps.next;
2832
+ if (framework === "nextjs" && nextVersion) {
2833
+ const broken = nextFlagVerdict(readFile, nextVersion, site);
2834
+ if (broken) return broken;
2835
+ }
2836
+ return {
2837
+ state: "ok",
2838
+ detail: site
2839
+ };
2840
+ }
2841
+ //#endregion
2744
2842
  //#region src/edge-safety.ts
2745
2843
  const NODE_BUILTINS = /* @__PURE__ */ new Set([
2746
2844
  "assert",
@@ -2927,7 +3025,7 @@ function pingOnce(ctx) {
2927
3025
  }
2928
3026
  const REASON_HINT = {
2929
3027
  ok: "",
2930
- invalid_api_key: "The key was rejected (401). Check CLIVLY_SECRET_KEY (or legacy CLIVLY_API_KEY).",
3028
+ invalid_api_key: "The key was rejected (401). Run `clivly login` to re-pair and rewrite the credentials, and check CLIVLY_SECRET_KEY (or legacy CLIVLY_API_KEY) belongs to the org whose dashboard you are watching.",
2931
3029
  forbidden: "The key is valid but lacks access to this org (403).",
2932
3030
  rate_limited: "Rate limited (429). Wait a moment and retry.",
2933
3031
  server_error: "Clivly returned a server error (5xx). Retry shortly.",
@@ -3026,15 +3124,16 @@ const triggerUrlStage = {
3026
3124
  label: "Sync trigger URL",
3027
3125
  needs: [configStage.id],
3028
3126
  run(ctx) {
3029
- const url = ctx.sdk?.syncTrigger?.url;
3030
- if (url && !require_sdk.isPlaceholderUrl(url)) return Promise.resolve({
3127
+ const trigger = ctx.sdk?.describeSyncTrigger?.();
3128
+ if (trigger?.resolved) return Promise.resolve({
3031
3129
  state: "pass",
3032
- detail: url
3130
+ detail: trigger.resolved
3033
3131
  });
3034
- const isPlaceholder = url !== void 0;
3132
+ const configured = trigger?.configured;
3133
+ const isPlaceholder = configured !== void 0 && require_sdk.isPlaceholderUrl(configured);
3035
3134
  return Promise.resolve({
3036
3135
  state: "warn",
3037
- detail: isPlaceholder ? `Still the placeholder (${url}) — remote sync cannot call back into this app.` : "Not set — remote sync cannot call back into this app.",
3136
+ detail: isPlaceholder ? `Still the scaffolded placeholder (${configured}) — remote sync cannot call back into this app.` : "Not set — remote sync cannot call back into this app.",
3038
3137
  hint: "Replace <yourDomain.com> with your deployed origin, or delete the line — on Vercel, Cloudflare Pages, Railway, Render and Fly the SDK derives the URL from the platform. For local development run `clivly dev`: it opens a tunnel and registers the URL for you, outranking whatever is in .env. Push-only setups can ignore this."
3039
3138
  });
3040
3139
  }
@@ -3083,6 +3182,24 @@ const STATUS_STAGES = [
3083
3182
  });
3084
3183
  }
3085
3184
  },
3185
+ {
3186
+ id: "boot-hook",
3187
+ label: "Boot hook wired",
3188
+ run(ctx) {
3189
+ const read = ctx.readConfigSource ?? defaultReadConfigSource;
3190
+ const root = (0, node_path.dirname)(ctx.configPath);
3191
+ const verdict = checkBootHook((relative) => read((0, node_path.resolve)(root, relative)));
3192
+ if (verdict.state === "ok") return Promise.resolve({
3193
+ state: "pass",
3194
+ detail: `starts Clivly from ${verdict.detail}`
3195
+ });
3196
+ return Promise.resolve({
3197
+ state: verdict.state === "unknown" ? "skip" : "fail",
3198
+ detail: verdict.detail,
3199
+ hint: verdict.hint
3200
+ });
3201
+ }
3202
+ },
3086
3203
  sdkChecksStage,
3087
3204
  triggerUrlStage
3088
3205
  ];
@@ -3136,6 +3253,7 @@ const ALIAS_STAGE_IDS = {
3136
3253
  doctor: [
3137
3254
  "config",
3138
3255
  "runtime",
3256
+ "boot-hook",
3139
3257
  "setup-checks"
3140
3258
  ],
3141
3259
  connect: [