clivly 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -3
- package/adapter-nLfZpgIG.d.cts +40 -0
- package/adapter-xs04z0KX.d.mts +40 -0
- package/auth-adapter-CBOKDhlc.cjs +11 -0
- package/auth-adapter-FEOR1nx-.d.mts +30 -0
- package/auth-adapter-wqnnEjo3.mjs +6 -0
- package/auth-adapter-wvfGKsOJ.d.cts +30 -0
- package/auth-better-auth.cjs +28 -0
- package/auth-better-auth.d.cts +33 -0
- package/auth-better-auth.d.mts +33 -0
- package/auth-better-auth.mjs +26 -0
- package/auth-clerk.cjs +34 -0
- package/auth-clerk.d.cts +32 -0
- package/auth-clerk.d.mts +32 -0
- package/auth-clerk.mjs +32 -0
- package/auth-workos.cjs +47 -0
- package/auth-workos.d.cts +30 -0
- package/auth-workos.d.mts +30 -0
- package/auth-workos.mjs +45 -0
- package/core-adapter.cjs +0 -0
- package/core-adapter.d.cts +2 -0
- package/core-adapter.d.mts +2 -0
- package/core-adapter.mjs +1 -0
- package/core-auth-adapter.cjs +3 -0
- package/core-auth-adapter.d.cts +2 -0
- package/core-auth-adapter.d.mts +2 -0
- package/core-auth-adapter.mjs +2 -0
- package/core-drizzle.cjs +32 -0
- package/core-drizzle.d.cts +21 -0
- package/core-drizzle.d.mts +21 -0
- package/core-drizzle.mjs +31 -0
- package/core-entity-config.cjs +13 -0
- package/core-entity-config.d.cts +2 -0
- package/core-entity-config.d.mts +2 -0
- package/core-entity-config.mjs +2 -0
- package/core-entity-heuristics.cjs +442 -0
- package/core-entity-heuristics.d.cts +68 -0
- package/core-entity-heuristics.d.mts +68 -0
- package/core-entity-heuristics.mjs +431 -0
- package/core-mapping-form.cjs +5 -0
- package/core-mapping-form.d.cts +2 -0
- package/core-mapping-form.d.mts +2 -0
- package/core-mapping-form.mjs +2 -0
- package/core-mapping-score.cjs +12 -0
- package/core-mapping-score.d.cts +2 -0
- package/core-mapping-score.d.mts +2 -0
- package/core-mapping-score.mjs +2 -0
- package/core-mappings-config.cjs +3 -0
- package/core-mappings-config.d.cts +2 -0
- package/core-mappings-config.d.mts +2 -0
- package/core-mappings-config.mjs +2 -0
- package/core-sync-engine.cjs +6 -0
- package/core-sync-engine.d.cts +2 -0
- package/core-sync-engine.d.mts +2 -0
- package/core-sync-engine.mjs +2 -0
- package/core-types.cjs +0 -0
- package/core-types.d.cts +2 -0
- package/core-types.d.mts +2 -0
- package/core-types.mjs +1 -0
- package/core-view-compiler.cjs +5 -0
- package/core-view-compiler.d.cts +2 -0
- package/core-view-compiler.d.mts +2 -0
- package/core-view-compiler.mjs +2 -0
- package/core.cjs +27 -0
- package/core.d.cts +9 -0
- package/core.d.mts +9 -0
- package/core.mjs +7 -0
- package/drizzle-meta-BGn0BqGb.cjs +9 -0
- package/drizzle-meta-CnC336L-.mjs +4 -0
- package/drizzle.cjs +107 -0
- package/drizzle.d.cts +28 -0
- package/drizzle.d.mts +28 -0
- package/drizzle.mjs +105 -0
- package/entity-config-Cvjo1cpv.cjs +4598 -0
- package/entity-config-D1DFyeUp.d.mts +2403 -0
- package/entity-config-DoR0khce.mjs +4533 -0
- package/entity-config-GczjD3y8.d.cts +2403 -0
- package/index.cjs +926 -0
- package/index.d.cts +56 -0
- package/index.d.mts +56 -0
- package/{dist/index.mjs → index.mjs} +430 -47
- package/mapping-form-BHtPexzI.mjs +47 -0
- package/mapping-form-CUlFVfG8.d.cts +35 -0
- package/mapping-form-DdmDebC3.cjs +64 -0
- package/mapping-form-kjSiJaCX.d.mts +35 -0
- package/mapping-score-A2lRnlpk.d.mts +49 -0
- package/mapping-score-BJNe0lFn.mjs +87 -0
- package/mapping-score-BcjC0ZQs.d.cts +49 -0
- package/mapping-score-D9gfhtRu.cjs +146 -0
- package/mappings-config-CYPrzB3K.mjs +99 -0
- package/mappings-config-DTu_2cyx.cjs +104 -0
- package/mappings-config-DjRLCb2Q.d.cts +42 -0
- package/mappings-config-GxiYsSBQ.d.mts +42 -0
- package/namespace-probe-BtS0nXcr.d.cts +299 -0
- package/namespace-probe-CYMie-BI.d.mts +299 -0
- package/package.json +223 -26
- package/sdk-BZUn6wzs.mjs +764 -0
- package/sdk-CP_mYZa5.cjs +793 -0
- package/sdk.cjs +7 -0
- package/sdk.d.cts +33 -0
- package/sdk.d.mts +33 -0
- package/sdk.mjs +2 -0
- package/sync-engine-DUc0qWgo.cjs +230 -0
- package/sync-engine-DWnQPjV3.d.mts +183 -0
- package/sync-engine-DedXngop.mjs +207 -0
- package/sync-engine-uhfzKM-e.d.cts +183 -0
- package/types-C4POUcvk.d.mts +158 -0
- package/types-LJTBhkcN.d.cts +158 -0
- package/view-compiler-B4UYTvRM.d.cts +71 -0
- package/view-compiler-BHzbI9b7.cjs +202 -0
- package/view-compiler-CosFGar8.mjs +185 -0
- package/view-compiler-i_xFf-L0.d.mts +71 -0
- package/vite.cjs +38 -0
- package/vite.d.cts +23 -0
- package/vite.d.mts +23 -0
- package/vite.mjs +37 -0
package/core.d.mts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { C as UpdateDealInput, S as UpdateContactInput, _ as Task, a as ContactFilters, b as TaskPriority, c as CreateCompanyInput, d as CreateTaskInput, f as CrmRole, g as RecordSource, h as Note, i as Contact, 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 TaskEntityType, w as UpdateTaskInput, x as TaskStatus, y as TaskFilters } from "./types-C4POUcvk.mjs";
|
|
2
|
+
import { a as authCustom, i as MembershipResolver, n as ClivlyUser, r as CrmMembership, t as ClivlyAuthAdapter } from "./auth-adapter-FEOR1nx-.mjs";
|
|
3
|
+
import { t as CRMAdapter } from "./adapter-xs04z0KX.mjs";
|
|
4
|
+
import { C as validateEntitiesConfig, S as relationshipsSchema, _ as RelationshipsMap, a as ClivlyEntitiesConfig, b as filterSchema, c as ConfigValidationResult, d as FilterExpr, f as FilterValue, g as RelationshipVia, h as RelationshipSpec, i as ClivlyConfigError, l as CrmConcept, m as MaterializingConcept, n as CRM_CONCEPTS, o as ClivlyEntityConfig, p as MATERIALIZING_CONCEPTS, s as ConfigValidationError, t as CANONICAL_FIELDS, u as DiscoveredSchemaTable, v as defineClivlyConfig, x as relationshipSchema, y as entitiesConfigSchema } from "./entity-config-D1DFyeUp.mjs";
|
|
5
|
+
import { i as relationshipViaSignature, n as buildFilterFromDiscriminator, r as buildRelationships, t as RelationshipCandidate } from "./mapping-form-kjSiJaCX.mjs";
|
|
6
|
+
import { n as mappingsToEntitiesConfig, t as EntityMappingRow } from "./mappings-config-GxiYsSBQ.mjs";
|
|
7
|
+
import { a as compileEntityViews, i as compileEntityView, n as CompiledView, o as explainEntitiesConfig, r as ExplainResult, t as CompileOptions } from "./view-compiler-i_xFf-L0.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-DWnQPjV3.mjs";
|
|
9
|
+
export { Activity, ActivityType, CANONICAL_FIELDS, CRMAdapter, CRM_CONCEPTS, ClivlyAuthAdapter, ClivlyConfigError, ClivlyEntitiesConfig, ClivlyEntityConfig, ClivlyUser, Company, CompileOptions, CompiledView, ConfigValidationError, ConfigValidationResult, Contact, ContactFilters, ContactStatus, CreateActivityInput, CreateCompanyInput, CreateContactInput, CreateDealInput, CreateTaskInput, CrmConcept, CrmMembership, CrmRole, Deal, DealStage, DiscoveredSchemaTable, EntityMappingRow, EntitySyncResult, ExplainResult, FilterExpr, FilterValue, MATERIALIZING_CONCEPTS, MaterializingConcept, MembershipResolver, MirrorRecord, Note, PersistAction, RecordSource, RelationshipCandidate, RelationshipSpec, RelationshipVia, RelationshipsMap, SourceRow, SyncAction, SyncResult, SyncStore, Task, TaskEntityType, TaskFilters, TaskPriority, TaskStatus, UpdateContactInput, UpdateDealInput, UpdateTaskInput, authCustom, buildFilterFromDiscriminator, buildRelationships, compileEntityView, compileEntityViews, defineClivlyConfig, entitiesConfigSchema, explainEntitiesConfig, filterSchema, mappingsToEntitiesConfig, reconcile, relationshipSchema, relationshipViaSignature, relationshipsSchema, runSync, validateEntitiesConfig };
|
package/core.mjs
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { a as MATERIALIZING_CONCEPTS, c as filterSchema, d as validateEntitiesConfig, i as ClivlyConfigError, l as relationshipSchema, n as CRM_CONCEPTS, o as defineClivlyConfig, s as entitiesConfigSchema, t as CANONICAL_FIELDS, u as relationshipsSchema } from "./entity-config-DoR0khce.mjs";
|
|
2
|
+
import { t as authCustom } from "./auth-adapter-wqnnEjo3.mjs";
|
|
3
|
+
import { n as buildRelationships, r as relationshipViaSignature, t as buildFilterFromDiscriminator } from "./mapping-form-BHtPexzI.mjs";
|
|
4
|
+
import { t as mappingsToEntitiesConfig } from "./mappings-config-CYPrzB3K.mjs";
|
|
5
|
+
import { n as compileEntityViews, r as explainEntitiesConfig, t as compileEntityView } from "./view-compiler-CosFGar8.mjs";
|
|
6
|
+
import { i as runSync, r as reconcile } from "./sync-engine-DedXngop.mjs";
|
|
7
|
+
export { CANONICAL_FIELDS, CRM_CONCEPTS, ClivlyConfigError, MATERIALIZING_CONCEPTS, authCustom, buildFilterFromDiscriminator, buildRelationships, compileEntityView, compileEntityViews, defineClivlyConfig, entitiesConfigSchema, explainEntitiesConfig, filterSchema, mappingsToEntitiesConfig, reconcile, relationshipSchema, relationshipViaSignature, relationshipsSchema, runSync, validateEntitiesConfig };
|
package/drizzle.cjs
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_drizzle_meta = require("./drizzle-meta-BGn0BqGb.cjs");
|
|
3
|
+
let drizzle_orm = require("drizzle-orm");
|
|
4
|
+
let drizzle_orm_pg_core = require("drizzle-orm/pg-core");
|
|
5
|
+
//#region ../sdk/src/drizzle.ts
|
|
6
|
+
function buildColumnsMeta(table) {
|
|
7
|
+
const columns = (0, drizzle_orm.getTableColumns)(table);
|
|
8
|
+
const fkByColumn = /* @__PURE__ */ new Map();
|
|
9
|
+
try {
|
|
10
|
+
for (const fk of (0, drizzle_orm_pg_core.getTableConfig)(table).foreignKeys) {
|
|
11
|
+
const ref = fk.reference();
|
|
12
|
+
const foreignTable = (0, drizzle_orm.getTableName)(ref.foreignTable);
|
|
13
|
+
ref.columns.forEach((col, i) => {
|
|
14
|
+
const foreignCol = ref.foreignColumns[i];
|
|
15
|
+
if (foreignCol) fkByColumn.set(col.name, {
|
|
16
|
+
table: foreignTable,
|
|
17
|
+
column: foreignCol.name
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
} catch {}
|
|
22
|
+
return Object.values(columns).map((col) => {
|
|
23
|
+
const references = fkByColumn.get(col.name);
|
|
24
|
+
let type;
|
|
25
|
+
try {
|
|
26
|
+
type = col.getSQLType();
|
|
27
|
+
} catch {
|
|
28
|
+
type = void 0;
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
name: col.name,
|
|
32
|
+
type,
|
|
33
|
+
nullable: !col.notNull,
|
|
34
|
+
isPrimaryKey: Boolean(col.primary),
|
|
35
|
+
isForeignKey: references !== void 0,
|
|
36
|
+
...references ? { references } : {}
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function inferIdField(table) {
|
|
41
|
+
const columns = (0, drizzle_orm.getTableColumns)(table);
|
|
42
|
+
const primaryKeys = Object.entries(columns).filter(([, column]) => column.primary);
|
|
43
|
+
if (primaryKeys.length === 1) {
|
|
44
|
+
const primaryKeyField = primaryKeys[0]?.[0];
|
|
45
|
+
if (!primaryKeyField) throw new Error(`fromDrizzle: unable to extract primary key field name from table "${(0, drizzle_orm.getTableName)(table)}".`);
|
|
46
|
+
return primaryKeyField;
|
|
47
|
+
}
|
|
48
|
+
const kind = primaryKeys.length === 0 ? "no" : "a composite";
|
|
49
|
+
throw new Error(`fromDrizzle: table "${(0, drizzle_orm.getTableName)(table)}" has ${kind} single-column primary key — pass { idField } explicitly.`);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Build a `SyncSource` from a Drizzle table, generating the keyset-paginated
|
|
53
|
+
* `fetchPage` the SDK needs. `cursorField`/`idField` are drizzle property keys;
|
|
54
|
+
* `idField` defaults to the table's single-column primary key.
|
|
55
|
+
*
|
|
56
|
+
* `drizzle-orm` is an optional peer dependency — installed only when you import
|
|
57
|
+
* `@clivly/sdk/drizzle`.
|
|
58
|
+
*/
|
|
59
|
+
function fromDrizzle(db, table, opts) {
|
|
60
|
+
const drizzleDb = db;
|
|
61
|
+
const idField = opts.idField ?? inferIdField(table);
|
|
62
|
+
const columns = (0, drizzle_orm.getTableColumns)(table);
|
|
63
|
+
const cursorColumn = columns[opts.cursorField];
|
|
64
|
+
const idColumn = columns[idField];
|
|
65
|
+
if (!cursorColumn) throw new Error(`fromDrizzle: cursorField "${opts.cursorField}" is not a column on "${(0, drizzle_orm.getTableName)(table)}".`);
|
|
66
|
+
if (!idColumn) throw new Error(`fromDrizzle: idField "${idField}" is not a column on "${(0, drizzle_orm.getTableName)(table)}".`);
|
|
67
|
+
const source = {
|
|
68
|
+
entity: opts.entity,
|
|
69
|
+
cursorField: opts.cursorField,
|
|
70
|
+
idField,
|
|
71
|
+
fetchPage: ({ since, limit }) => drizzleDb.select().from(table).where(since ? drizzle_orm.sql`(${cursorColumn}, ${idColumn}) > (${since.time}, ${since.id})` : void 0).orderBy((0, drizzle_orm.asc)(cursorColumn), (0, drizzle_orm.asc)(idColumn)).limit(limit)
|
|
72
|
+
};
|
|
73
|
+
const meta = {
|
|
74
|
+
columnKeys: Object.keys(columns),
|
|
75
|
+
cursorField: opts.cursorField,
|
|
76
|
+
idField,
|
|
77
|
+
tableName: (0, drizzle_orm.getTableName)(table),
|
|
78
|
+
columnsMeta: buildColumnsMeta(table)
|
|
79
|
+
};
|
|
80
|
+
Object.defineProperty(source, require_drizzle_meta.DRIZZLE_META, {
|
|
81
|
+
value: meta,
|
|
82
|
+
enumerable: false
|
|
83
|
+
});
|
|
84
|
+
return source;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Build a `NamespaceIntrospector` from any Drizzle client that exposes
|
|
88
|
+
* `.execute()`. Reads `information_schema` in the connection's default schema
|
|
89
|
+
* (`current_schema()`), so it reports exactly the tables the app can reach.
|
|
90
|
+
*/
|
|
91
|
+
function drizzleIntrospector(db) {
|
|
92
|
+
const client = db;
|
|
93
|
+
return {
|
|
94
|
+
async listTables() {
|
|
95
|
+
return (await client.execute(drizzle_orm.sql`
|
|
96
|
+
select table_name from information_schema.tables
|
|
97
|
+
where table_schema = current_schema()
|
|
98
|
+
`)).rows.map((r) => String(r.table_name));
|
|
99
|
+
},
|
|
100
|
+
async sampleSelect(table) {
|
|
101
|
+
await client.execute(drizzle_orm.sql`select 1 from ${drizzle_orm.sql.identifier(table)} limit 1`);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
//#endregion
|
|
106
|
+
exports.drizzleIntrospector = drizzleIntrospector;
|
|
107
|
+
exports.fromDrizzle = fromDrizzle;
|
package/drizzle.d.cts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { d as SyncSource, t as NamespaceIntrospector } from "./namespace-probe-BtS0nXcr.cjs";
|
|
2
|
+
import { Table } from "drizzle-orm";
|
|
3
|
+
|
|
4
|
+
//#region ../sdk/src/drizzle.d.ts
|
|
5
|
+
interface DrizzleDb {
|
|
6
|
+
select: (...args: any[]) => any;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Build a `SyncSource` from a Drizzle table, generating the keyset-paginated
|
|
10
|
+
* `fetchPage` the SDK needs. `cursorField`/`idField` are drizzle property keys;
|
|
11
|
+
* `idField` defaults to the table's single-column primary key.
|
|
12
|
+
*
|
|
13
|
+
* `drizzle-orm` is an optional peer dependency — installed only when you import
|
|
14
|
+
* `@clivly/sdk/drizzle`.
|
|
15
|
+
*/
|
|
16
|
+
declare function fromDrizzle(db: DrizzleDb, table: Table, opts: {
|
|
17
|
+
entity: string;
|
|
18
|
+
cursorField: string;
|
|
19
|
+
idField?: string;
|
|
20
|
+
}): SyncSource;
|
|
21
|
+
/**
|
|
22
|
+
* Build a `NamespaceIntrospector` from any Drizzle client that exposes
|
|
23
|
+
* `.execute()`. Reads `information_schema` in the connection's default schema
|
|
24
|
+
* (`current_schema()`), so it reports exactly the tables the app can reach.
|
|
25
|
+
*/
|
|
26
|
+
declare function drizzleIntrospector(db: unknown): NamespaceIntrospector;
|
|
27
|
+
//#endregion
|
|
28
|
+
export { drizzleIntrospector, fromDrizzle };
|
package/drizzle.d.mts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { d as SyncSource, t as NamespaceIntrospector } from "./namespace-probe-CYMie-BI.mjs";
|
|
2
|
+
import { Table } from "drizzle-orm";
|
|
3
|
+
|
|
4
|
+
//#region ../sdk/src/drizzle.d.ts
|
|
5
|
+
interface DrizzleDb {
|
|
6
|
+
select: (...args: any[]) => any;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Build a `SyncSource` from a Drizzle table, generating the keyset-paginated
|
|
10
|
+
* `fetchPage` the SDK needs. `cursorField`/`idField` are drizzle property keys;
|
|
11
|
+
* `idField` defaults to the table's single-column primary key.
|
|
12
|
+
*
|
|
13
|
+
* `drizzle-orm` is an optional peer dependency — installed only when you import
|
|
14
|
+
* `@clivly/sdk/drizzle`.
|
|
15
|
+
*/
|
|
16
|
+
declare function fromDrizzle(db: DrizzleDb, table: Table, opts: {
|
|
17
|
+
entity: string;
|
|
18
|
+
cursorField: string;
|
|
19
|
+
idField?: string;
|
|
20
|
+
}): SyncSource;
|
|
21
|
+
/**
|
|
22
|
+
* Build a `NamespaceIntrospector` from any Drizzle client that exposes
|
|
23
|
+
* `.execute()`. Reads `information_schema` in the connection's default schema
|
|
24
|
+
* (`current_schema()`), so it reports exactly the tables the app can reach.
|
|
25
|
+
*/
|
|
26
|
+
declare function drizzleIntrospector(db: unknown): NamespaceIntrospector;
|
|
27
|
+
//#endregion
|
|
28
|
+
export { drizzleIntrospector, fromDrizzle };
|
package/drizzle.mjs
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { t as DRIZZLE_META } from "./drizzle-meta-CnC336L-.mjs";
|
|
2
|
+
import { asc, getTableColumns, getTableName, sql } from "drizzle-orm";
|
|
3
|
+
import { getTableConfig } from "drizzle-orm/pg-core";
|
|
4
|
+
//#region ../sdk/src/drizzle.ts
|
|
5
|
+
function buildColumnsMeta(table) {
|
|
6
|
+
const columns = getTableColumns(table);
|
|
7
|
+
const fkByColumn = /* @__PURE__ */ new Map();
|
|
8
|
+
try {
|
|
9
|
+
for (const fk of getTableConfig(table).foreignKeys) {
|
|
10
|
+
const ref = fk.reference();
|
|
11
|
+
const foreignTable = getTableName(ref.foreignTable);
|
|
12
|
+
ref.columns.forEach((col, i) => {
|
|
13
|
+
const foreignCol = ref.foreignColumns[i];
|
|
14
|
+
if (foreignCol) fkByColumn.set(col.name, {
|
|
15
|
+
table: foreignTable,
|
|
16
|
+
column: foreignCol.name
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
} catch {}
|
|
21
|
+
return Object.values(columns).map((col) => {
|
|
22
|
+
const references = fkByColumn.get(col.name);
|
|
23
|
+
let type;
|
|
24
|
+
try {
|
|
25
|
+
type = col.getSQLType();
|
|
26
|
+
} catch {
|
|
27
|
+
type = void 0;
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
name: col.name,
|
|
31
|
+
type,
|
|
32
|
+
nullable: !col.notNull,
|
|
33
|
+
isPrimaryKey: Boolean(col.primary),
|
|
34
|
+
isForeignKey: references !== void 0,
|
|
35
|
+
...references ? { references } : {}
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
function inferIdField(table) {
|
|
40
|
+
const columns = getTableColumns(table);
|
|
41
|
+
const primaryKeys = Object.entries(columns).filter(([, column]) => column.primary);
|
|
42
|
+
if (primaryKeys.length === 1) {
|
|
43
|
+
const primaryKeyField = primaryKeys[0]?.[0];
|
|
44
|
+
if (!primaryKeyField) throw new Error(`fromDrizzle: unable to extract primary key field name from table "${getTableName(table)}".`);
|
|
45
|
+
return primaryKeyField;
|
|
46
|
+
}
|
|
47
|
+
const kind = primaryKeys.length === 0 ? "no" : "a composite";
|
|
48
|
+
throw new Error(`fromDrizzle: table "${getTableName(table)}" has ${kind} single-column primary key — pass { idField } explicitly.`);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Build a `SyncSource` from a Drizzle table, generating the keyset-paginated
|
|
52
|
+
* `fetchPage` the SDK needs. `cursorField`/`idField` are drizzle property keys;
|
|
53
|
+
* `idField` defaults to the table's single-column primary key.
|
|
54
|
+
*
|
|
55
|
+
* `drizzle-orm` is an optional peer dependency — installed only when you import
|
|
56
|
+
* `@clivly/sdk/drizzle`.
|
|
57
|
+
*/
|
|
58
|
+
function fromDrizzle(db, table, opts) {
|
|
59
|
+
const drizzleDb = db;
|
|
60
|
+
const idField = opts.idField ?? inferIdField(table);
|
|
61
|
+
const columns = getTableColumns(table);
|
|
62
|
+
const cursorColumn = columns[opts.cursorField];
|
|
63
|
+
const idColumn = columns[idField];
|
|
64
|
+
if (!cursorColumn) throw new Error(`fromDrizzle: cursorField "${opts.cursorField}" is not a column on "${getTableName(table)}".`);
|
|
65
|
+
if (!idColumn) throw new Error(`fromDrizzle: idField "${idField}" is not a column on "${getTableName(table)}".`);
|
|
66
|
+
const source = {
|
|
67
|
+
entity: opts.entity,
|
|
68
|
+
cursorField: opts.cursorField,
|
|
69
|
+
idField,
|
|
70
|
+
fetchPage: ({ since, limit }) => drizzleDb.select().from(table).where(since ? sql`(${cursorColumn}, ${idColumn}) > (${since.time}, ${since.id})` : void 0).orderBy(asc(cursorColumn), asc(idColumn)).limit(limit)
|
|
71
|
+
};
|
|
72
|
+
const meta = {
|
|
73
|
+
columnKeys: Object.keys(columns),
|
|
74
|
+
cursorField: opts.cursorField,
|
|
75
|
+
idField,
|
|
76
|
+
tableName: getTableName(table),
|
|
77
|
+
columnsMeta: buildColumnsMeta(table)
|
|
78
|
+
};
|
|
79
|
+
Object.defineProperty(source, DRIZZLE_META, {
|
|
80
|
+
value: meta,
|
|
81
|
+
enumerable: false
|
|
82
|
+
});
|
|
83
|
+
return source;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Build a `NamespaceIntrospector` from any Drizzle client that exposes
|
|
87
|
+
* `.execute()`. Reads `information_schema` in the connection's default schema
|
|
88
|
+
* (`current_schema()`), so it reports exactly the tables the app can reach.
|
|
89
|
+
*/
|
|
90
|
+
function drizzleIntrospector(db) {
|
|
91
|
+
const client = db;
|
|
92
|
+
return {
|
|
93
|
+
async listTables() {
|
|
94
|
+
return (await client.execute(sql`
|
|
95
|
+
select table_name from information_schema.tables
|
|
96
|
+
where table_schema = current_schema()
|
|
97
|
+
`)).rows.map((r) => String(r.table_name));
|
|
98
|
+
},
|
|
99
|
+
async sampleSelect(table) {
|
|
100
|
+
await client.execute(sql`select 1 from ${sql.identifier(table)} limit 1`);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
//#endregion
|
|
105
|
+
export { drizzleIntrospector, fromDrizzle };
|