clivly 0.9.6 → 0.9.7

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 (58) hide show
  1. package/README.md +15 -3
  2. package/core-auth-adapter.cjs +1 -1
  3. package/core-auth-adapter.mjs +1 -1
  4. package/core-drizzle.cjs +1 -1
  5. package/core-drizzle.d.cts +1 -1
  6. package/core-drizzle.d.mts +1 -1
  7. package/core-drizzle.mjs +1 -1
  8. package/core-entity-config.cjs +1 -1
  9. package/core-entity-config.mjs +1 -1
  10. package/core-mapping-form.cjs +1 -1
  11. package/core-mapping-form.mjs +1 -1
  12. package/core-mappings-config.cjs +1 -1
  13. package/core-mappings-config.mjs +1 -1
  14. package/core-sync-engine.cjs +1 -1
  15. package/core-sync-engine.mjs +1 -1
  16. package/core-view-compiler.cjs +1 -1
  17. package/core-view-compiler.mjs +1 -1
  18. package/core.cjs +4 -5
  19. package/core.mjs +4 -4
  20. package/{drizzle-CiK8MMEZ.d.mts → drizzle-BmDDgAIF.d.mts} +3 -1
  21. package/{drizzle-bfjVzYR6.cjs → drizzle-DcB7OfBp.cjs} +9 -1
  22. package/{drizzle-DEtRrqtc.d.cts → drizzle-ixVV4pPN.d.cts} +3 -1
  23. package/{drizzle-3kvhkwO7.mjs → drizzle-wbcuG-cy.mjs} +9 -1
  24. package/drizzle.cjs +56 -22
  25. package/drizzle.d.cts +9 -3
  26. package/drizzle.d.mts +9 -3
  27. package/drizzle.mjs +56 -22
  28. package/{entity-config-CusbTOJ1.mjs → entity-config-C8IIkrmX.mjs} +33 -4
  29. package/{entity-config-DE30_RpU.cjs → entity-config-CPM-Tp-d.cjs} +33 -4
  30. package/index.cjs +34 -3
  31. package/index.mjs +34 -3
  32. package/{internal-BQ47iN6f.cjs → internal-BLKMnIIZ.cjs} +1 -1
  33. package/{internal-ChufvXE6.mjs → internal-BpVh_J77.mjs} +1 -1
  34. package/internal-drizzle.cjs +1 -1
  35. package/internal-drizzle.d.cts +1 -1
  36. package/internal-drizzle.d.mts +1 -1
  37. package/internal-drizzle.mjs +1 -1
  38. package/internal-entity-config.cjs +1 -1
  39. package/internal-entity-config.mjs +1 -1
  40. package/internal-entity-heuristics.cjs +1 -1
  41. package/internal-entity-heuristics.mjs +1 -1
  42. package/internal-mappings-config.cjs +1 -1
  43. package/internal-mappings-config.mjs +1 -1
  44. package/internal.cjs +3 -3
  45. package/internal.mjs +3 -3
  46. package/{mappings-config-CjCmT-aU.cjs → mappings-config-CBwL3FVh.cjs} +1 -1
  47. package/{mappings-config-7qQ47p9K.mjs → mappings-config-DUKBe6OS.mjs} +1 -1
  48. package/{namespace-probe-Ckn9yJ6F.d.mts → namespace-probe-BQ4imnV7.d.mts} +41 -1
  49. package/{namespace-probe-DaTJINS-.d.cts → namespace-probe-DZIGdvlm.d.cts} +41 -1
  50. package/package.json +1 -1
  51. package/{sdk-w8Kv_XnW.cjs → sdk-BL9BCzyD.cjs} +324 -14
  52. package/{sdk-Dkq6ELkf.mjs → sdk-CubnsyD9.mjs} +324 -14
  53. package/sdk.cjs +2 -2
  54. package/sdk.d.cts +2 -2
  55. package/sdk.d.mts +2 -2
  56. package/sdk.mjs +2 -2
  57. package/vite.d.cts +1 -1
  58. package/vite.d.mts +1 -1
@@ -137,7 +137,7 @@ function checkTablesExist(errors, projection, resolver, base) {
137
137
  if (!hasRichMeta(table)) {
138
138
  errors.push({
139
139
  path,
140
- message: `table "${name}" has no key/column metadata — upgrade @clivly/sdk and re-run discovery before using a projection`
140
+ message: `table "${name}" was discovered without column types or unique keys, which a projection needs to prove its id is unique. Redeploy or restart the app so it re-reports its schema (or run \`clivly push-schema\`); if the table is declared by hand as \`{ name, columns }\`, use \`discoverFromDrizzle\` so keys and types come with it.`
141
141
  });
142
142
  ok = false;
143
143
  }
@@ -182,10 +182,27 @@ function checkRefs(errors, projection, resolver, base, basePk) {
182
182
  for (const [field, binding] of Object.entries(projection.fieldBindings)) checkRef(errors, resolver, `${base}.projection.fieldBindings.${field}`, binding.from);
183
183
  for (const ref of require_projection.identityRefs(projection.identity, basePk)) checkRef(errors, resolver, `${base}.projection.identity`, ref);
184
184
  }
185
+ /**
186
+ * Prove that a single-column identity (`column`, or `base_pk` with an
187
+ * explicit column) is actually unique.
188
+ *
189
+ * `coversUniqueKey` fails closed on absent metadata, same as every other
190
+ * check in this file: a column not provably covered by a unique key is
191
+ * rejected, never assumed safe.
192
+ */
193
+ function checkSingleColumnIdentity(errors, resolver, path, ref) {
194
+ const table = resolver.tableFor(ref.table);
195
+ if (!table) return;
196
+ if (!coversUniqueKey(table, [ref.column])) errors.push({
197
+ path,
198
+ message: `identity column "${ref.table}.${ref.column}" is not covered by a unique key of "${table.name}" — pick a column with a unique constraint, or use a composite identity that is`
199
+ });
200
+ }
185
201
  function checkIdentitySafety(errors, projection, resolver, base, baseTable) {
186
202
  const path = `${base}.projection.identity`;
187
203
  const pk = primaryKeyColumns(baseTable);
188
- if (projection.identity.kind === "base_pk" && !projection.identity.column) {
204
+ const { identity } = projection;
205
+ if (identity.kind === "base_pk" && !identity.column) {
189
206
  if (pk.length === 0) {
190
207
  errors.push({
191
208
  path,
@@ -200,9 +217,21 @@ function checkIdentitySafety(errors, projection, resolver, base, baseTable) {
200
217
  });
201
218
  return;
202
219
  }
220
+ return;
221
+ }
222
+ if (identity.kind === "base_pk" && identity.column) {
223
+ checkSingleColumnIdentity(errors, resolver, path, {
224
+ table: require_projection.BASE_REF,
225
+ column: identity.column
226
+ });
227
+ return;
228
+ }
229
+ if (identity.kind === "column") {
230
+ checkSingleColumnIdentity(errors, resolver, path, identity.from);
231
+ return;
203
232
  }
204
- if (projection.identity.kind !== "composite") return;
205
- for (const part of projection.identity.parts) {
233
+ if (identity.kind !== "composite") return;
234
+ for (const part of identity.parts) {
206
235
  const table = resolver.tableFor(part.table);
207
236
  const meta = table && columnMetaFor(table, part.column);
208
237
  if (!meta) continue;
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-DE30_RpU.cjs");
3
+ const require_entity_config = require("./entity-config-CPM-Tp-d.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-w8Kv_XnW.cjs");
6
+ const require_sdk = require("./sdk-BL9BCzyD.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");
@@ -1871,6 +1871,7 @@ function renderImports(plan) {
1871
1871
  "import { createClivlySDK, defineClivlyConfig } from \"clivly/sdk\";",
1872
1872
  "import { fromDrizzle } from \"clivly/drizzle\";",
1873
1873
  "import { discoverFromDrizzle } from \"clivly/drizzle\";",
1874
+ "import { drizzleIntrospector } from \"clivly/drizzle\";",
1874
1875
  `import * as schema from "${plan.importPath}";`
1875
1876
  ];
1876
1877
  if (plan.db === null) {
@@ -1903,6 +1904,9 @@ export default createClivlySDK({
1903
1904
  // Every table in your Drizzle schema, so the Clivly dashboard can offer them
1904
1905
  // all when you add a mapping — not just the ones wired up as sources below.
1905
1906
  schema: discoverFromDrizzle(schema),
1907
+ // Lets derived objects authored in the dashboard run against this database.
1908
+ // Without it they are fetched, validated and then skipped.
1909
+ introspector: drizzleIntrospector(${dbExpr}),
1906
1910
  source: {
1907
1911
  // Keyed by CRM concept — contacts/companies/deals/custom.
1908
1912
  // NOT by your entity key. The entity's own \`source:\` above is a table name.
@@ -3201,6 +3205,32 @@ const STATUS_STAGES = [
3201
3205
  }
3202
3206
  },
3203
3207
  sdkChecksStage,
3208
+ {
3209
+ id: "derived-objects",
3210
+ label: "Dashboard-authored objects",
3211
+ needs: [configStage.id],
3212
+ run(ctx) {
3213
+ const remote = ctx.sdk?.describeRemoteProjections?.();
3214
+ if (!remote) return Promise.resolve({
3215
+ state: "skip",
3216
+ detail: "This app's installed clivly predates dashboard-authored objects."
3217
+ });
3218
+ if (!remote.capable) return Promise.resolve({
3219
+ state: "warn",
3220
+ detail: "Objects authored in the dashboard cannot run against this app.",
3221
+ hint: "Add `introspector: drizzleIntrospector(db)` to clivly.config.ts."
3222
+ });
3223
+ if (!remote.ran) return Promise.resolve({
3224
+ state: "pass",
3225
+ detail: "Ready; no sync has run in this process yet."
3226
+ });
3227
+ const broken = remote.invalid + remote.failed;
3228
+ return Promise.resolve({
3229
+ state: broken > 0 ? "warn" : "pass",
3230
+ detail: broken > 0 ? `${remote.ok} running, ${broken} not — open the object in Clivly for the reason.` : `${remote.ok} running.`
3231
+ });
3232
+ }
3233
+ },
3204
3234
  triggerUrlStage
3205
3235
  ];
3206
3236
  function defaultLoadSdk(path) {
@@ -3254,7 +3284,8 @@ const ALIAS_STAGE_IDS = {
3254
3284
  "config",
3255
3285
  "runtime",
3256
3286
  "boot-hook",
3257
- "setup-checks"
3287
+ "setup-checks",
3288
+ "derived-objects"
3258
3289
  ],
3259
3290
  connect: [
3260
3291
  "api-key",
package/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { t as CANONICAL_FIELDS } from "./entity-config-CusbTOJ1.mjs";
2
+ import { t as CANONICAL_FIELDS } from "./entity-config-C8IIkrmX.mjs";
3
3
  import "./mapping-score-C68uAqGB.mjs";
4
4
  import { matchesConcept, requiredFieldsFor, scoreFieldMap, scoreRelationships, suggestCursorField, toFieldMap } from "./internal-entity-heuristics.mjs";
5
- import { s as isPlaceholderUrl, t as createClivlySDK } from "./sdk-Dkq6ELkf.mjs";
5
+ import { s as isPlaceholderUrl, t as createClivlySDK } from "./sdk-CubnsyD9.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";
@@ -1870,6 +1870,7 @@ function renderImports(plan) {
1870
1870
  "import { createClivlySDK, defineClivlyConfig } from \"clivly/sdk\";",
1871
1871
  "import { fromDrizzle } from \"clivly/drizzle\";",
1872
1872
  "import { discoverFromDrizzle } from \"clivly/drizzle\";",
1873
+ "import { drizzleIntrospector } from \"clivly/drizzle\";",
1873
1874
  `import * as schema from "${plan.importPath}";`
1874
1875
  ];
1875
1876
  if (plan.db === null) {
@@ -1902,6 +1903,9 @@ export default createClivlySDK({
1902
1903
  // Every table in your Drizzle schema, so the Clivly dashboard can offer them
1903
1904
  // all when you add a mapping — not just the ones wired up as sources below.
1904
1905
  schema: discoverFromDrizzle(schema),
1906
+ // Lets derived objects authored in the dashboard run against this database.
1907
+ // Without it they are fetched, validated and then skipped.
1908
+ introspector: drizzleIntrospector(${dbExpr}),
1905
1909
  source: {
1906
1910
  // Keyed by CRM concept — contacts/companies/deals/custom.
1907
1911
  // NOT by your entity key. The entity's own \`source:\` above is a table name.
@@ -3200,6 +3204,32 @@ const STATUS_STAGES = [
3200
3204
  }
3201
3205
  },
3202
3206
  sdkChecksStage,
3207
+ {
3208
+ id: "derived-objects",
3209
+ label: "Dashboard-authored objects",
3210
+ needs: [configStage.id],
3211
+ run(ctx) {
3212
+ const remote = ctx.sdk?.describeRemoteProjections?.();
3213
+ if (!remote) return Promise.resolve({
3214
+ state: "skip",
3215
+ detail: "This app's installed clivly predates dashboard-authored objects."
3216
+ });
3217
+ if (!remote.capable) return Promise.resolve({
3218
+ state: "warn",
3219
+ detail: "Objects authored in the dashboard cannot run against this app.",
3220
+ hint: "Add `introspector: drizzleIntrospector(db)` to clivly.config.ts."
3221
+ });
3222
+ if (!remote.ran) return Promise.resolve({
3223
+ state: "pass",
3224
+ detail: "Ready; no sync has run in this process yet."
3225
+ });
3226
+ const broken = remote.invalid + remote.failed;
3227
+ return Promise.resolve({
3228
+ state: broken > 0 ? "warn" : "pass",
3229
+ detail: broken > 0 ? `${remote.ok} running, ${broken} not — open the object in Clivly for the reason.` : `${remote.ok} running.`
3230
+ });
3231
+ }
3232
+ },
3203
3233
  triggerUrlStage
3204
3234
  ];
3205
3235
  function defaultLoadSdk(path) {
@@ -3253,7 +3283,8 @@ const ALIAS_STAGE_IDS = {
3253
3283
  "config",
3254
3284
  "runtime",
3255
3285
  "boot-hook",
3256
- "setup-checks"
3286
+ "setup-checks",
3287
+ "derived-objects"
3257
3288
  ],
3258
3289
  connect: [
3259
3290
  "api-key",
@@ -1,5 +1,5 @@
1
1
  const require_projection = require("./projection-DEwL-D8R.cjs");
2
- const require_entity_config = require("./entity-config-DE30_RpU.cjs");
2
+ const require_entity_config = require("./entity-config-CPM-Tp-d.cjs");
3
3
  //#region ../core/src/projection-draft.ts
4
4
  function emptyProjectionDraft(baseTable) {
5
5
  return {
@@ -1,5 +1,5 @@
1
1
  import { i as identityRefs, n as PROJECTION_KEY_MESSAGE, r as PROJECTION_KEY_PATTERN, t as BASE_REF } from "./projection-hnPSgH6G.mjs";
2
- import { h as fanOutJoins, m as validateProjection } from "./entity-config-CusbTOJ1.mjs";
2
+ import { h as fanOutJoins, m as validateProjection } from "./entity-config-C8IIkrmX.mjs";
3
3
  //#region ../core/src/projection-draft.ts
4
4
  function emptyProjectionDraft(baseTable) {
5
5
  return {
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_drizzle = require("./drizzle-bfjVzYR6.cjs");
2
+ const require_drizzle = require("./drizzle-DcB7OfBp.cjs");
3
3
  exports.buildColumnsMeta = require_drizzle.buildColumnsMeta;
4
4
  exports.buildUniqueConstraints = require_drizzle.buildUniqueConstraints;
5
5
  exports.discoverFromDrizzle = require_drizzle.discoverFromDrizzle;
@@ -1,2 +1,2 @@
1
- import { n as buildUniqueConstraints, r as discoverFromDrizzle, t as buildColumnsMeta } from "./drizzle-DEtRrqtc.cjs";
1
+ import { n as buildUniqueConstraints, r as discoverFromDrizzle, t as buildColumnsMeta } from "./drizzle-ixVV4pPN.cjs";
2
2
  export { buildColumnsMeta, buildUniqueConstraints, discoverFromDrizzle };
@@ -1,2 +1,2 @@
1
- import { n as buildUniqueConstraints, r as discoverFromDrizzle, t as buildColumnsMeta } from "./drizzle-CiK8MMEZ.mjs";
1
+ import { n as buildUniqueConstraints, r as discoverFromDrizzle, t as buildColumnsMeta } from "./drizzle-BmDDgAIF.mjs";
2
2
  export { buildColumnsMeta, buildUniqueConstraints, discoverFromDrizzle };
@@ -1,2 +1,2 @@
1
- import { n as buildUniqueConstraints, r as discoverFromDrizzle, t as buildColumnsMeta } from "./drizzle-3kvhkwO7.mjs";
1
+ import { n as buildUniqueConstraints, r as discoverFromDrizzle, t as buildColumnsMeta } from "./drizzle-wbcuG-cy.mjs";
2
2
  export { buildColumnsMeta, buildUniqueConstraints, discoverFromDrizzle };
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_entity_config = require("./entity-config-DE30_RpU.cjs");
2
+ const require_entity_config = require("./entity-config-CPM-Tp-d.cjs");
3
3
  exports.CANONICAL_FIELDS = require_entity_config.CANONICAL_FIELDS;
4
4
  exports.CRM_CONCEPTS = require_entity_config.CRM_CONCEPTS;
5
5
  exports.CUSTOM_CONCEPT = require_entity_config.CUSTOM_CONCEPT;
@@ -1,2 +1,2 @@
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";
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-C8IIkrmX.mjs";
2
2
  export { CANONICAL_FIELDS, CRM_CONCEPTS, CUSTOM_CONCEPT, ClivlyConfigError, MATERIALIZING_CONCEPTS, customObjectDeclarations, defineClivlyConfig, entitiesConfigSchema, filterSchema, projectionFields, relationshipSchema, relationshipsSchema, validateEntitiesConfig };
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_entity_config = require("./entity-config-DE30_RpU.cjs");
2
+ const require_entity_config = require("./entity-config-CPM-Tp-d.cjs");
3
3
  const require_mapping_score = require("./mapping-score-CaB3F4Uu.cjs");
4
4
  //#region ../core/src/entity-heuristics.ts
5
5
  const TARGET_CONCEPTS = [
@@ -1,4 +1,4 @@
1
- import { a as MATERIALIZING_CONCEPTS } from "./entity-config-CusbTOJ1.mjs";
1
+ import { a as MATERIALIZING_CONCEPTS } from "./entity-config-C8IIkrmX.mjs";
2
2
  import { a as W, c as isTextLike, i as RELATIONSHIP_TIERS, l as isTimestampLike, n as CONCEPT_TIERS, o as isAmbiguous, r as FIELD_TIERS, s as isNumericLike, u as tierFor } from "./mapping-score-C68uAqGB.mjs";
3
3
  //#region ../core/src/entity-heuristics.ts
4
4
  const TARGET_CONCEPTS = [
@@ -1,4 +1,4 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_mappings_config = require("./mappings-config-CjCmT-aU.cjs");
2
+ const require_mappings_config = require("./mappings-config-CBwL3FVh.cjs");
3
3
  exports.entitiesToMappings = require_mappings_config.entitiesToMappings;
4
4
  exports.mappingsToEntitiesConfig = require_mappings_config.mappingsToEntitiesConfig;
@@ -1,2 +1,2 @@
1
- import { n as mappingsToEntitiesConfig, t as entitiesToMappings } from "./mappings-config-7qQ47p9K.mjs";
1
+ import { n as mappingsToEntitiesConfig, t as entitiesToMappings } from "./mappings-config-DUKBe6OS.mjs";
2
2
  export { entitiesToMappings, mappingsToEntitiesConfig };
package/internal.cjs CHANGED
@@ -1,10 +1,10 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
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");
3
+ const require_entity_config = require("./entity-config-CPM-Tp-d.cjs");
4
+ const require_mappings_config = require("./mappings-config-CBwL3FVh.cjs");
5
5
  const require_auth_adapter = require("./auth-adapter-CiEXcweZ.cjs");
6
6
  const require_mapping_form = require("./mapping-form-BpfON_ME.cjs");
7
- const require_internal = require("./internal-BQ47iN6f.cjs");
7
+ const require_internal = require("./internal-BLKMnIIZ.cjs");
8
8
  const require_projection_sql = require("./projection-sql-iHy-Cx6V.cjs");
9
9
  const require_view_compiler = require("./view-compiler-BHI5E4QI.cjs");
10
10
  const require_sync_engine = require("./sync-engine-BLgwLpR6.cjs");
package/internal.mjs CHANGED
@@ -1,9 +1,9 @@
1
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";
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-C8IIkrmX.mjs";
3
+ import { n as mappingsToEntitiesConfig } from "./mappings-config-DUKBe6OS.mjs";
4
4
  import { t as authCustom } from "./auth-adapter-gfVDxf3d.mjs";
5
5
  import { n as buildRelationships, r as relationshipViaSignature, t as buildFilterFromDiscriminator } from "./mapping-form-DigkuvFc.mjs";
6
- 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";
6
+ 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-BpVh_J77.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-9zzTVGvf.mjs";
8
8
  import { i as explainEntitiesConfig, n as compileEntityView, r as compileEntityViews, t as DEFAULT_VIEW_PREFIX } from "./view-compiler-D_6gfXFr.mjs";
9
9
  import { i as runSync, r as reconcile } from "./sync-engine-B_IzoUSx.mjs";
@@ -1,4 +1,4 @@
1
- const require_entity_config = require("./entity-config-DE30_RpU.cjs");
1
+ const require_entity_config = require("./entity-config-CPM-Tp-d.cjs");
2
2
  //#region ../core/src/mappings-config.ts
3
3
  const RESERVED_FIELD = "id";
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as CANONICAL_FIELDS } from "./entity-config-CusbTOJ1.mjs";
1
+ import { t as CANONICAL_FIELDS } from "./entity-config-C8IIkrmX.mjs";
2
2
  //#region ../core/src/mappings-config.ts
3
3
  const RESERVED_FIELD = "id";
4
4
  /**
@@ -354,6 +354,17 @@ interface SyncTriggerDescription {
354
354
  */
355
355
  resolved?: string;
356
356
  }
357
+ /** @see ClivlySDK.describeRemoteProjections */
358
+ interface RemoteProjectionsDescription {
359
+ /** False when no `introspector` is configured — nothing can run. */
360
+ capable: boolean;
361
+ failed: number;
362
+ invalid: number;
363
+ ok: number;
364
+ /** False until a sync has run in this process. */
365
+ ran: boolean;
366
+ skipped: number;
367
+ }
357
368
  interface ClivlySDK {
358
369
  /**
359
370
  * Send a single heartbeat and report the outcome richly: `ok`, the HTTP
@@ -389,6 +400,15 @@ interface ClivlySDK {
389
400
  * anyone who can reach it — set a secret if it's publicly routable.
390
401
  */
391
402
  createClivlyHandler(): (req: Request) => Promise<Response>;
403
+ /**
404
+ * What this app would tell Clivly about dashboard-authored derived objects,
405
+ * right now. Counts rather than the outcomes themselves: this reports
406
+ * health, and the per-object reasons already travel to the dashboard, which
407
+ * is where an author fixes them.
408
+ *
409
+ * Read by `clivly status`.
410
+ */
411
+ describeRemoteProjections(): RemoteProjectionsDescription;
392
412
  /**
393
413
  * What this app would tell Clivly about its sync trigger route, right now.
394
414
  *
@@ -477,6 +497,26 @@ interface ClivlySDK {
477
497
  interface NamespaceIntrospector {
478
498
  /** All base table names in the reachable schema. */
479
499
  listTables(): Promise<string[]>;
500
+ /**
501
+ * Build a runnable sync source from a projection, for derived objects
502
+ * authored in the dashboard rather than in `clivly.config.ts`.
503
+ *
504
+ * Optional for the same reason `runProjection` is: an introspector may be
505
+ * hand-written. Absent, remote projections report `skipped` with a reason
506
+ * naming this method, rather than failing the run.
507
+ *
508
+ * This is deliberately the only route to a database handle for remote
509
+ * projections. `drizzleIntrospector(db)` already closes over the
510
+ * connection, so `introspector:` is the single config line that turns
511
+ * dashboard-authored objects on — and the SDK core never holds a raw
512
+ * client.
513
+ */
514
+ projectionSource?(projection: ProjectionMapping, opts: {
515
+ basePkColumn?: string;
516
+ objectType: string;
517
+ }): SyncSource & {
518
+ objectType: string;
519
+ };
480
520
  /**
481
521
  * Read a few rows through an unsaved projection, for the dashboard's derived
482
522
  * object preview. Rows are keyed by field name.
@@ -498,4 +538,4 @@ interface NamespaceIntrospector {
498
538
  sampleSelect(table: string): Promise<void>;
499
539
  }
500
540
  //#endregion
501
- export { SyncSource as _, ClivlyConnectResult as a, ClivlyUser as c, DiscoveredTable as d, DoctorCheck as f, EnsuredObjectTypeResult as g, EnsuredMappingResult as h, ClivlyConnectReason as i, CreateChatSessionHandlerOptions as l, EnsureSchemaResult as m, ChatSessionRequestBody as n, ClivlySDK as o, DoctorReport as p, ChatWidgetVisitor as r, ClivlySDKConfig as s, NamespaceIntrospector as t, CursorStore as u, SyncTriggerDescription as v };
541
+ export { RemoteProjectionsDescription as _, ClivlyConnectResult as a, ClivlyUser as c, DiscoveredTable as d, DoctorCheck as f, EnsuredObjectTypeResult as g, EnsuredMappingResult as h, ClivlyConnectReason as i, CreateChatSessionHandlerOptions as l, EnsureSchemaResult as m, ChatSessionRequestBody as n, ClivlySDK as o, DoctorReport as p, ChatWidgetVisitor as r, ClivlySDKConfig as s, NamespaceIntrospector as t, CursorStore as u, SyncSource as v, SyncTriggerDescription as y };
@@ -354,6 +354,17 @@ interface SyncTriggerDescription {
354
354
  */
355
355
  resolved?: string;
356
356
  }
357
+ /** @see ClivlySDK.describeRemoteProjections */
358
+ interface RemoteProjectionsDescription {
359
+ /** False when no `introspector` is configured — nothing can run. */
360
+ capable: boolean;
361
+ failed: number;
362
+ invalid: number;
363
+ ok: number;
364
+ /** False until a sync has run in this process. */
365
+ ran: boolean;
366
+ skipped: number;
367
+ }
357
368
  interface ClivlySDK {
358
369
  /**
359
370
  * Send a single heartbeat and report the outcome richly: `ok`, the HTTP
@@ -389,6 +400,15 @@ interface ClivlySDK {
389
400
  * anyone who can reach it — set a secret if it's publicly routable.
390
401
  */
391
402
  createClivlyHandler(): (req: Request) => Promise<Response>;
403
+ /**
404
+ * What this app would tell Clivly about dashboard-authored derived objects,
405
+ * right now. Counts rather than the outcomes themselves: this reports
406
+ * health, and the per-object reasons already travel to the dashboard, which
407
+ * is where an author fixes them.
408
+ *
409
+ * Read by `clivly status`.
410
+ */
411
+ describeRemoteProjections(): RemoteProjectionsDescription;
392
412
  /**
393
413
  * What this app would tell Clivly about its sync trigger route, right now.
394
414
  *
@@ -477,6 +497,26 @@ interface ClivlySDK {
477
497
  interface NamespaceIntrospector {
478
498
  /** All base table names in the reachable schema. */
479
499
  listTables(): Promise<string[]>;
500
+ /**
501
+ * Build a runnable sync source from a projection, for derived objects
502
+ * authored in the dashboard rather than in `clivly.config.ts`.
503
+ *
504
+ * Optional for the same reason `runProjection` is: an introspector may be
505
+ * hand-written. Absent, remote projections report `skipped` with a reason
506
+ * naming this method, rather than failing the run.
507
+ *
508
+ * This is deliberately the only route to a database handle for remote
509
+ * projections. `drizzleIntrospector(db)` already closes over the
510
+ * connection, so `introspector:` is the single config line that turns
511
+ * dashboard-authored objects on — and the SDK core never holds a raw
512
+ * client.
513
+ */
514
+ projectionSource?(projection: ProjectionMapping, opts: {
515
+ basePkColumn?: string;
516
+ objectType: string;
517
+ }): SyncSource & {
518
+ objectType: string;
519
+ };
480
520
  /**
481
521
  * Read a few rows through an unsaved projection, for the dashboard's derived
482
522
  * object preview. Rows are keyed by field name.
@@ -498,4 +538,4 @@ interface NamespaceIntrospector {
498
538
  sampleSelect(table: string): Promise<void>;
499
539
  }
500
540
  //#endregion
501
- export { SyncSource as _, ClivlyConnectResult as a, ClivlyUser as c, DiscoveredTable as d, DoctorCheck as f, EnsuredObjectTypeResult as g, EnsuredMappingResult as h, ClivlyConnectReason as i, CreateChatSessionHandlerOptions as l, EnsureSchemaResult as m, ChatSessionRequestBody as n, ClivlySDK as o, DoctorReport as p, ChatWidgetVisitor as r, ClivlySDKConfig as s, NamespaceIntrospector as t, CursorStore as u, SyncTriggerDescription as v };
541
+ export { RemoteProjectionsDescription as _, ClivlyConnectResult as a, ClivlyUser as c, DiscoveredTable as d, DoctorCheck as f, EnsuredObjectTypeResult as g, EnsuredMappingResult as h, ClivlyConnectReason as i, CreateChatSessionHandlerOptions as l, EnsureSchemaResult as m, ChatSessionRequestBody as n, ClivlySDK as o, DoctorReport as p, ChatWidgetVisitor as r, ClivlySDKConfig as s, NamespaceIntrospector as t, CursorStore as u, SyncSource as v, SyncTriggerDescription as y };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clivly",
3
- "version": "0.9.6",
3
+ "version": "0.9.7",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Clivly CLI — scaffold a CRM into your app (clivly init).",