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