clivly 0.9.3 → 0.9.4
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/core-entity-config.cjs +1 -1
- package/core-entity-config.mjs +1 -1
- package/core-mappings-config.cjs +1 -1
- package/core-mappings-config.mjs +1 -1
- package/core-sync-engine.cjs +1 -1
- package/core-sync-engine.mjs +1 -1
- package/core-view-compiler.cjs +1 -1
- package/core-view-compiler.mjs +1 -1
- package/core.cjs +11 -6
- package/core.d.cts +2 -2
- package/core.d.mts +2 -2
- package/core.mjs +8 -7
- package/drizzle.cjs +74 -9
- package/drizzle.d.cts +83 -7
- package/drizzle.d.mts +83 -7
- package/drizzle.mjs +74 -10
- package/{entity-config-DtBsl2MQ.cjs → entity-config-7sGCk_nw.cjs} +1 -1
- package/{entity-config-kUHri9yA.mjs → entity-config-B74SPOUZ.mjs} +1 -1
- package/index.cjs +60 -18
- package/index.mjs +60 -18
- package/{internal-Df-PtOH_.mjs → internal-CykXpEGk.mjs} +2 -2
- package/{internal-CwnEG6Wl.cjs → internal-DqduZU3l.cjs} +2 -2
- package/internal-entity-config.cjs +1 -1
- package/internal-entity-config.mjs +1 -1
- package/internal-entity-heuristics.cjs +1 -1
- package/internal-entity-heuristics.mjs +1 -1
- package/internal-mappings-config.cjs +1 -1
- package/internal-mappings-config.mjs +1 -1
- package/{internal-CDY8g9Ic.d.mts → internal-o2M7FGlR.d.mts} +29 -1
- package/internal-sync-engine.cjs +1 -1
- package/internal-sync-engine.mjs +1 -1
- package/internal-view-compiler.cjs +1 -1
- package/internal-view-compiler.mjs +1 -1
- package/{internal-Da_dlcQ_.d.cts → internal-wCXSELDN.d.cts} +29 -1
- package/internal.cjs +11 -6
- package/internal.d.cts +2 -2
- package/internal.d.mts +2 -2
- package/internal.mjs +8 -7
- package/{mappings-config-B0RqFLxu.cjs → mappings-config-CLyEg0sf.cjs} +1 -1
- package/{mappings-config-B1b1HVBg.mjs → mappings-config-DQS_s4dg.mjs} +1 -1
- package/{namespace-probe-EYyxWZnf.d.cts → namespace-probe-BoGI18dQ.d.cts} +8 -0
- package/{namespace-probe-BmdGnYMn.d.mts → namespace-probe-Cn7voAd0.d.mts} +8 -0
- package/package.json +1 -1
- package/{projection-D7xmQP4S.mjs → projection-CSGJbZlZ.mjs} +25 -4
- package/{projection-C5244vGa.cjs → projection-Dz6_i1-w.cjs} +25 -4
- package/projection-sql-BgnfiGqF.mjs +65 -0
- package/projection-sql-Cl1qIn8m.cjs +94 -0
- package/{sdk-COLUHhJq.cjs → sdk-CM1UO-I7.cjs} +58 -15
- package/{sdk-CZNXBsgA.mjs → sdk-DYBDR939.mjs} +53 -16
- package/sdk.cjs +3 -2
- package/sdk.d.cts +5 -2
- package/sdk.d.mts +5 -2
- package/sdk.mjs +3 -3
- package/{sync-engine-abE94g6X.cjs → sync-engine-C4A5jgA4.cjs} +1 -1
- package/{sync-engine-SuxSzbZ4.mjs → sync-engine-Dt5QQSKO.mjs} +1 -1
- package/{view-compiler-Blu4OXJ7.cjs → view-compiler-B5nDal14.cjs} +21 -74
- package/{view-compiler-CQx8TRrW.mjs → view-compiler-CSYwEWf5.mjs} +2 -55
- package/vite.d.cts +1 -1
- package/vite.d.mts +1 -1
|
@@ -1,58 +1,5 @@
|
|
|
1
|
-
const require_projection = require("./projection-
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* SQL generation for projection-backed entities.
|
|
5
|
-
*
|
|
6
|
-
* Base and joins are aliased by their ref key (`base`, then each join's `key`),
|
|
7
|
-
* which is what allows the same table to be joined twice and keeps generated
|
|
8
|
-
* SQL independent of host table names.
|
|
9
|
-
*
|
|
10
|
-
* Pure string generation — no DB access. Identifiers are escaped so output is
|
|
11
|
-
* deterministic and injection-safe.
|
|
12
|
-
*/
|
|
13
|
-
/** Quote a single identifier part, escaping embedded double-quotes. */
|
|
14
|
-
function quoteIdent(name) {
|
|
15
|
-
return `"${name.replace(/"/g, "\"\"")}"`;
|
|
16
|
-
}
|
|
17
|
-
function refSql(ref) {
|
|
18
|
-
return `${quoteIdent(ref.table)}.${quoteIdent(ref.column)}`;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* The identity expression, aliased as `id`. Composite identities concatenate
|
|
22
|
-
* their parts with `::`; validation guarantees every part is NOT NULL and
|
|
23
|
-
* non-text, which is what makes the concatenation collision-free.
|
|
24
|
-
*/
|
|
25
|
-
function identitySql(projection, basePkColumn) {
|
|
26
|
-
const refs = require_projection.identityRefs(projection.identity, basePkColumn);
|
|
27
|
-
if (projection.identity.kind === "composite") return `CONCAT_WS('::', ${refs.map((ref) => `${refSql(ref)}::text`).join(", ")}) AS ${quoteIdent("id")}`;
|
|
28
|
-
const [ref] = refs;
|
|
29
|
-
if (!ref) throw new Error("projection identity resolved to no column");
|
|
30
|
-
return `${refSql(ref)} AS ${quoteIdent("id")}`;
|
|
31
|
-
}
|
|
32
|
-
function compileProjectionSelect(projection, basePkColumn) {
|
|
33
|
-
const selectItems = [identitySql(projection, basePkColumn)];
|
|
34
|
-
const columns = ["id"];
|
|
35
|
-
for (const [field, binding] of Object.entries(projection.fieldBindings)) {
|
|
36
|
-
selectItems.push(`${refSql(binding.from)} AS ${quoteIdent(field)}`);
|
|
37
|
-
columns.push(field);
|
|
38
|
-
}
|
|
39
|
-
return {
|
|
40
|
-
columns,
|
|
41
|
-
selectItems
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
function compileProjectionJoins(projection) {
|
|
45
|
-
return projection.joins.map((join) => {
|
|
46
|
-
const keyword = join.type === "inner" ? "INNER JOIN" : "LEFT JOIN";
|
|
47
|
-
const on = join.on.map((c) => `${refSql(c.left)} = ${refSql(c.right)}`).join(" AND ");
|
|
48
|
-
return `${keyword} ${quoteIdent(join.table)} AS ${quoteIdent(join.key)} ON ${on}`;
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
/** `FROM <baseTable> AS "base"` — the alias every ref resolves against. */
|
|
52
|
-
function compileProjectionFrom(projection) {
|
|
53
|
-
return `FROM ${quoteIdent(projection.baseTable)} AS ${quoteIdent(require_projection.BASE_REF)}`;
|
|
54
|
-
}
|
|
55
|
-
//#endregion
|
|
1
|
+
const require_projection = require("./projection-Dz6_i1-w.cjs");
|
|
2
|
+
const require_projection_sql = require("./projection-sql-Cl1qIn8m.cjs");
|
|
56
3
|
//#region ../core/src/view-compiler.ts
|
|
57
4
|
/**
|
|
58
5
|
* View compiler (Phase 2) — turns a validated entity config into read-only
|
|
@@ -88,7 +35,7 @@ function quoteList(values) {
|
|
|
88
35
|
}
|
|
89
36
|
/** Compile one column predicate into a SQL boolean expression. */
|
|
90
37
|
function compilePredicate(table, column, value) {
|
|
91
|
-
const col = `${quoteIdent(table)}.${quoteIdent(column)}`;
|
|
38
|
+
const col = `${require_projection_sql.quoteIdent(table)}.${require_projection_sql.quoteIdent(column)}`;
|
|
92
39
|
if (value === null || typeof value !== "object") return `${col} = ${quoteLiteral(value)}`;
|
|
93
40
|
if ("eq" in value) return `${col} = ${quoteLiteral(value.eq)}`;
|
|
94
41
|
if ("ne" in value) return `${col} <> ${quoteLiteral(value.ne)}`;
|
|
@@ -121,33 +68,33 @@ function refParts(ref, defaultTable) {
|
|
|
121
68
|
}
|
|
122
69
|
function compileRelationship(relName, rel, source, related) {
|
|
123
70
|
const refCol = `${relName}_ref`;
|
|
124
|
-
const refAlias = quoteIdent(refCol);
|
|
71
|
+
const refAlias = require_projection_sql.quoteIdent(refCol);
|
|
125
72
|
const { via } = rel;
|
|
126
73
|
if ("fkOn" in via) {
|
|
127
74
|
const relatedTable = related?.source ?? "";
|
|
128
75
|
if (via.fkOn === "company") {
|
|
129
76
|
const { table, column } = refParts(via.column, relatedTable);
|
|
130
77
|
const relatedFilter = compileFilterConditions(table, related?.filter);
|
|
131
|
-
const on = [`${quoteIdent(table)}.${quoteIdent(column)} = ${quoteIdent(source.source)}.${quoteIdent(SOURCE_KEY)}`, ...relatedFilter].join(" AND ");
|
|
78
|
+
const on = [`${require_projection_sql.quoteIdent(table)}.${require_projection_sql.quoteIdent(column)} = ${require_projection_sql.quoteIdent(source.source)}.${require_projection_sql.quoteIdent(SOURCE_KEY)}`, ...relatedFilter].join(" AND ");
|
|
132
79
|
return {
|
|
133
|
-
clause: `LEFT JOIN ${quoteIdent(table)} ON ${on}`,
|
|
134
|
-
refSelect: `${quoteIdent(table)}.${quoteIdent(SOURCE_KEY)} AS ${refAlias}`,
|
|
80
|
+
clause: `LEFT JOIN ${require_projection_sql.quoteIdent(table)} ON ${on}`,
|
|
81
|
+
refSelect: `${require_projection_sql.quoteIdent(table)}.${require_projection_sql.quoteIdent(SOURCE_KEY)} AS ${refAlias}`,
|
|
135
82
|
refColumn: refCol
|
|
136
83
|
};
|
|
137
84
|
}
|
|
138
85
|
const { table, column } = refParts(via.column, source.source);
|
|
139
|
-
const on = [`${quoteIdent(relatedTable)}.${quoteIdent(SOURCE_KEY)} = ${quoteIdent(table)}.${quoteIdent(column)}`, ...compileFilterConditions(relatedTable, related?.filter)].join(" AND ");
|
|
86
|
+
const on = [`${require_projection_sql.quoteIdent(relatedTable)}.${require_projection_sql.quoteIdent(SOURCE_KEY)} = ${require_projection_sql.quoteIdent(table)}.${require_projection_sql.quoteIdent(column)}`, ...compileFilterConditions(relatedTable, related?.filter)].join(" AND ");
|
|
140
87
|
return {
|
|
141
|
-
clause: `LEFT JOIN ${quoteIdent(relatedTable)} ON ${on}`,
|
|
142
|
-
refSelect: `${quoteIdent(relatedTable)}.${quoteIdent(SOURCE_KEY)} AS ${refAlias}`,
|
|
88
|
+
clause: `LEFT JOIN ${require_projection_sql.quoteIdent(relatedTable)} ON ${on}`,
|
|
89
|
+
refSelect: `${require_projection_sql.quoteIdent(relatedTable)}.${require_projection_sql.quoteIdent(SOURCE_KEY)} AS ${refAlias}`,
|
|
143
90
|
refColumn: refCol
|
|
144
91
|
};
|
|
145
92
|
}
|
|
146
93
|
if ("through" in via) {
|
|
147
|
-
const on = `${quoteIdent(via.through)}.${quoteIdent(via.localKey)} = ${quoteIdent(source.source)}.${quoteIdent(SOURCE_KEY)}`;
|
|
94
|
+
const on = `${require_projection_sql.quoteIdent(via.through)}.${require_projection_sql.quoteIdent(via.localKey)} = ${require_projection_sql.quoteIdent(source.source)}.${require_projection_sql.quoteIdent(SOURCE_KEY)}`;
|
|
148
95
|
return {
|
|
149
|
-
clause: `LEFT JOIN ${quoteIdent(via.through)} ON ${on}`,
|
|
150
|
-
refSelect: `${quoteIdent(via.through)}.${quoteIdent(via.foreignKey)} AS ${refAlias}`,
|
|
96
|
+
clause: `LEFT JOIN ${require_projection_sql.quoteIdent(via.through)} ON ${on}`,
|
|
97
|
+
refSelect: `${require_projection_sql.quoteIdent(via.through)}.${require_projection_sql.quoteIdent(via.foreignKey)} AS ${refAlias}`,
|
|
151
98
|
refColumn: refCol
|
|
152
99
|
};
|
|
153
100
|
}
|
|
@@ -159,10 +106,10 @@ function compileRelationship(relName, rel, source, related) {
|
|
|
159
106
|
}
|
|
160
107
|
/** SELECT items for a legacy single-table entity: source key, then fields. */
|
|
161
108
|
function legacySelect(entity, src) {
|
|
162
|
-
const selectItems = [`${quoteIdent(src)}.${quoteIdent(SOURCE_KEY)} AS ${quoteIdent("id")}`];
|
|
109
|
+
const selectItems = [`${require_projection_sql.quoteIdent(src)}.${require_projection_sql.quoteIdent(SOURCE_KEY)} AS ${require_projection_sql.quoteIdent("id")}`];
|
|
163
110
|
const columns = ["id"];
|
|
164
111
|
for (const [field, column] of Object.entries(entity.fields)) {
|
|
165
|
-
selectItems.push(`${quoteIdent(src)}.${quoteIdent(column)} AS ${quoteIdent(field)}`);
|
|
112
|
+
selectItems.push(`${require_projection_sql.quoteIdent(src)}.${require_projection_sql.quoteIdent(column)} AS ${require_projection_sql.quoteIdent(field)}`);
|
|
166
113
|
columns.push(field);
|
|
167
114
|
}
|
|
168
115
|
return {
|
|
@@ -209,14 +156,14 @@ function compileEntityView(config, entityKey, options = {}) {
|
|
|
209
156
|
const src = entity.source;
|
|
210
157
|
const projection = entity.projection;
|
|
211
158
|
const filterTable = projection ? require_projection.BASE_REF : src;
|
|
212
|
-
const { selectItems, columns } = projection ? compileProjectionSelect(projection, SOURCE_KEY) : legacySelect(entity, src);
|
|
213
|
-
const joins = projection ? compileProjectionJoins(projection) : legacyJoins(config, entity, columns, selectItems);
|
|
159
|
+
const { selectItems, columns } = projection ? require_projection_sql.compileProjectionSelect(projection, SOURCE_KEY) : legacySelect(entity, src);
|
|
160
|
+
const joins = projection ? require_projection_sql.compileProjectionJoins(projection) : legacyJoins(config, entity, columns, selectItems);
|
|
214
161
|
const conditions = compileFilterConditions(filterTable, entity.filter);
|
|
215
|
-
if (options.orgScope) conditions.push(`${quoteIdent(filterTable)}.${quoteIdent(options.orgScope.column)} = ${quoteLiteral(options.orgScope.value)}`);
|
|
162
|
+
if (options.orgScope) conditions.push(`${require_projection_sql.quoteIdent(filterTable)}.${require_projection_sql.quoteIdent(options.orgScope.column)} = ${quoteLiteral(options.orgScope.value)}`);
|
|
216
163
|
const lines = [
|
|
217
|
-
options.securityInvoker ?? true ? `CREATE OR REPLACE VIEW ${quoteIdent(viewName)} WITH (security_invoker = true) AS` : `CREATE OR REPLACE VIEW ${quoteIdent(viewName)} AS`,
|
|
164
|
+
options.securityInvoker ?? true ? `CREATE OR REPLACE VIEW ${require_projection_sql.quoteIdent(viewName)} WITH (security_invoker = true) AS` : `CREATE OR REPLACE VIEW ${require_projection_sql.quoteIdent(viewName)} AS`,
|
|
218
165
|
`SELECT ${selectItems.join(", ")}`,
|
|
219
|
-
projection ? compileProjectionFrom(projection) : `FROM ${quoteIdent(src)}`,
|
|
166
|
+
projection ? require_projection_sql.compileProjectionFrom(projection) : `FROM ${require_projection_sql.quoteIdent(src)}`,
|
|
220
167
|
...joins
|
|
221
168
|
];
|
|
222
169
|
if (conditions.length > 0) lines.push(`WHERE ${conditions.join(" AND ")}`);
|
|
@@ -229,7 +176,7 @@ function compileEntityView(config, entityKey, options = {}) {
|
|
|
229
176
|
sourceTable: src,
|
|
230
177
|
columns,
|
|
231
178
|
sql,
|
|
232
|
-
dropSql: `DROP VIEW IF EXISTS ${quoteIdent(viewName)};`
|
|
179
|
+
dropSql: `DROP VIEW IF EXISTS ${require_projection_sql.quoteIdent(viewName)};`
|
|
233
180
|
};
|
|
234
181
|
}
|
|
235
182
|
/** Compile every entity in the config into its view, in declaration order. */
|
|
@@ -1,58 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* SQL generation for projection-backed entities.
|
|
5
|
-
*
|
|
6
|
-
* Base and joins are aliased by their ref key (`base`, then each join's `key`),
|
|
7
|
-
* which is what allows the same table to be joined twice and keeps generated
|
|
8
|
-
* SQL independent of host table names.
|
|
9
|
-
*
|
|
10
|
-
* Pure string generation — no DB access. Identifiers are escaped so output is
|
|
11
|
-
* deterministic and injection-safe.
|
|
12
|
-
*/
|
|
13
|
-
/** Quote a single identifier part, escaping embedded double-quotes. */
|
|
14
|
-
function quoteIdent(name) {
|
|
15
|
-
return `"${name.replace(/"/g, "\"\"")}"`;
|
|
16
|
-
}
|
|
17
|
-
function refSql(ref) {
|
|
18
|
-
return `${quoteIdent(ref.table)}.${quoteIdent(ref.column)}`;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* The identity expression, aliased as `id`. Composite identities concatenate
|
|
22
|
-
* their parts with `::`; validation guarantees every part is NOT NULL and
|
|
23
|
-
* non-text, which is what makes the concatenation collision-free.
|
|
24
|
-
*/
|
|
25
|
-
function identitySql(projection, basePkColumn) {
|
|
26
|
-
const refs = identityRefs(projection.identity, basePkColumn);
|
|
27
|
-
if (projection.identity.kind === "composite") return `CONCAT_WS('::', ${refs.map((ref) => `${refSql(ref)}::text`).join(", ")}) AS ${quoteIdent("id")}`;
|
|
28
|
-
const [ref] = refs;
|
|
29
|
-
if (!ref) throw new Error("projection identity resolved to no column");
|
|
30
|
-
return `${refSql(ref)} AS ${quoteIdent("id")}`;
|
|
31
|
-
}
|
|
32
|
-
function compileProjectionSelect(projection, basePkColumn) {
|
|
33
|
-
const selectItems = [identitySql(projection, basePkColumn)];
|
|
34
|
-
const columns = ["id"];
|
|
35
|
-
for (const [field, binding] of Object.entries(projection.fieldBindings)) {
|
|
36
|
-
selectItems.push(`${refSql(binding.from)} AS ${quoteIdent(field)}`);
|
|
37
|
-
columns.push(field);
|
|
38
|
-
}
|
|
39
|
-
return {
|
|
40
|
-
columns,
|
|
41
|
-
selectItems
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
function compileProjectionJoins(projection) {
|
|
45
|
-
return projection.joins.map((join) => {
|
|
46
|
-
const keyword = join.type === "inner" ? "INNER JOIN" : "LEFT JOIN";
|
|
47
|
-
const on = join.on.map((c) => `${refSql(c.left)} = ${refSql(c.right)}`).join(" AND ");
|
|
48
|
-
return `${keyword} ${quoteIdent(join.table)} AS ${quoteIdent(join.key)} ON ${on}`;
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
/** `FROM <baseTable> AS "base"` — the alias every ref resolves against. */
|
|
52
|
-
function compileProjectionFrom(projection) {
|
|
53
|
-
return `FROM ${quoteIdent(projection.baseTable)} AS ${quoteIdent(BASE_REF)}`;
|
|
54
|
-
}
|
|
55
|
-
//#endregion
|
|
1
|
+
import { t as BASE_REF } from "./projection-CSGJbZlZ.mjs";
|
|
2
|
+
import { a as quoteIdent, i as compileProjectionSelect, r as compileProjectionJoins, t as compileProjectionFrom } from "./projection-sql-BgnfiGqF.mjs";
|
|
56
3
|
//#region ../core/src/view-compiler.ts
|
|
57
4
|
/**
|
|
58
5
|
* View compiler (Phase 2) — turns a validated entity config into read-only
|
package/vite.d.cts
CHANGED
package/vite.d.mts
CHANGED