@metaobjectsdev/runtime-ts 0.5.0-rc.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/LICENSE +189 -0
- package/README.md +102 -0
- package/dist/constants.d.ts +5 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +6 -0
- package/dist/constants.js.map +1 -0
- package/dist/drivers/drizzle-driver.d.ts +25 -0
- package/dist/drivers/drizzle-driver.d.ts.map +1 -0
- package/dist/drivers/drizzle-driver.js +405 -0
- package/dist/drivers/drizzle-driver.js.map +1 -0
- package/dist/drivers/in-memory-driver.d.ts +11 -0
- package/dist/drivers/in-memory-driver.d.ts.map +1 -0
- package/dist/drivers/in-memory-driver.js +232 -0
- package/dist/drivers/in-memory-driver.js.map +1 -0
- package/dist/drivers/index.d.ts +4 -0
- package/dist/drivers/index.d.ts.map +1 -0
- package/dist/drivers/index.js +4 -0
- package/dist/drivers/index.js.map +1 -0
- package/dist/drivers/kysely-driver.d.ts +12 -0
- package/dist/drivers/kysely-driver.d.ts.map +1 -0
- package/dist/drivers/kysely-driver.js +203 -0
- package/dist/drivers/kysely-driver.js.map +1 -0
- package/dist/drizzle-fastify/filter-allowlist.d.ts +19 -0
- package/dist/drizzle-fastify/filter-allowlist.d.ts.map +1 -0
- package/dist/drizzle-fastify/filter-allowlist.js +10 -0
- package/dist/drizzle-fastify/filter-allowlist.js.map +1 -0
- package/dist/drizzle-fastify/filter-parser.d.ts +28 -0
- package/dist/drizzle-fastify/filter-parser.d.ts.map +1 -0
- package/dist/drizzle-fastify/filter-parser.js +185 -0
- package/dist/drizzle-fastify/filter-parser.js.map +1 -0
- package/dist/drizzle-fastify/index.d.ts +48 -0
- package/dist/drizzle-fastify/index.d.ts.map +1 -0
- package/dist/drizzle-fastify/index.js +181 -0
- package/dist/drizzle-fastify/index.js.map +1 -0
- package/dist/drizzle-fastify/mount-read-only.d.ts +17 -0
- package/dist/drizzle-fastify/mount-read-only.d.ts.map +1 -0
- package/dist/drizzle-fastify/mount-read-only.js +159 -0
- package/dist/drizzle-fastify/mount-read-only.js.map +1 -0
- package/dist/drizzle-fastify/util.d.ts +5 -0
- package/dist/drizzle-fastify/util.d.ts.map +1 -0
- package/dist/drizzle-fastify/util.js +12 -0
- package/dist/drizzle-fastify/util.js.map +1 -0
- package/dist/errors.d.ts +68 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +86 -0
- package/dist/errors.js.map +1 -0
- package/dist/fastify/index.d.ts +65 -0
- package/dist/fastify/index.d.ts.map +1 -0
- package/dist/fastify/index.js +118 -0
- package/dist/fastify/index.js.map +1 -0
- package/dist/identity-strategy.d.ts +10 -0
- package/dist/identity-strategy.d.ts.map +1 -0
- package/dist/identity-strategy.js +67 -0
- package/dist/identity-strategy.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/n2m-resolver.d.ts +27 -0
- package/dist/n2m-resolver.d.ts.map +1 -0
- package/dist/n2m-resolver.js +103 -0
- package/dist/n2m-resolver.js.map +1 -0
- package/dist/object-manager.d.ts +51 -0
- package/dist/object-manager.d.ts.map +1 -0
- package/dist/object-manager.js +355 -0
- package/dist/object-manager.js.map +1 -0
- package/dist/persistence-driver.d.ts +88 -0
- package/dist/persistence-driver.d.ts.map +1 -0
- package/dist/persistence-driver.js +5 -0
- package/dist/persistence-driver.js.map +1 -0
- package/dist/query-builder.d.ts +35 -0
- package/dist/query-builder.d.ts.map +1 -0
- package/dist/query-builder.js +178 -0
- package/dist/query-builder.js.map +1 -0
- package/dist/ref-codec.d.ts +8 -0
- package/dist/ref-codec.d.ts.map +1 -0
- package/dist/ref-codec.js +42 -0
- package/dist/ref-codec.js.map +1 -0
- package/dist/relation-resolver.d.ts +27 -0
- package/dist/relation-resolver.d.ts.map +1 -0
- package/dist/relation-resolver.js +136 -0
- package/dist/relation-resolver.js.map +1 -0
- package/dist/type-coercer.d.ts +5 -0
- package/dist/type-coercer.d.ts.map +1 -0
- package/dist/type-coercer.js +43 -0
- package/dist/type-coercer.js.map +1 -0
- package/dist/validator-runner.d.ts +14 -0
- package/dist/validator-runner.d.ts.map +1 -0
- package/dist/validator-runner.js +155 -0
- package/dist/validator-runner.js.map +1 -0
- package/dist/view.d.ts +19 -0
- package/dist/view.d.ts.map +1 -0
- package/dist/view.js +60 -0
- package/dist/view.js.map +1 -0
- package/package.json +87 -0
- package/src/constants.ts +7 -0
- package/src/drivers/drizzle-driver.ts +474 -0
- package/src/drivers/in-memory-driver.ts +256 -0
- package/src/drivers/index.ts +3 -0
- package/src/drivers/kysely-driver.ts +240 -0
- package/src/drizzle-fastify/filter-allowlist.ts +31 -0
- package/src/drizzle-fastify/filter-parser.ts +229 -0
- package/src/drizzle-fastify/index.ts +225 -0
- package/src/drizzle-fastify/mount-read-only.ts +187 -0
- package/src/drizzle-fastify/util.ts +10 -0
- package/src/errors.ts +114 -0
- package/src/fastify/index.ts +181 -0
- package/src/identity-strategy.ts +92 -0
- package/src/index.ts +24 -0
- package/src/n2m-resolver.ts +152 -0
- package/src/object-manager.ts +444 -0
- package/src/persistence-driver.ts +92 -0
- package/src/query-builder.ts +224 -0
- package/src/ref-codec.ts +64 -0
- package/src/relation-resolver.ts +171 -0
- package/src/type-coercer.ts +39 -0
- package/src/validator-runner.ts +168 -0
- package/src/view.ts +82 -0
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
// Drizzle driver for ObjectManager.
|
|
2
|
+
//
|
|
3
|
+
// Lets a consumer that already has Drizzle wired up (schema, connection, types)
|
|
4
|
+
// also expose the same database via ObjectManager — no second connection, no
|
|
5
|
+
// separate ORM. The driver is dynamic: it resolves table names from the user's
|
|
6
|
+
// schema object at construction time and dispatches per-request.
|
|
7
|
+
//
|
|
8
|
+
// Why exists: runtime-ts ships with Kysely + in-memory drivers, but most TS
|
|
9
|
+
// apps use Drizzle. Shipping a Drizzle driver lets ObjectManager layer on top
|
|
10
|
+
// of an existing Drizzle setup instead of forcing a parallel ORM stack.
|
|
11
|
+
//
|
|
12
|
+
// Java analog: ObjectConnection backed by a JDBC DataSource.
|
|
13
|
+
import { and as drzAnd, eq as drzEq, ne as drzNe, gt as drzGt, gte as drzGte, lt as drzLt, lte as drzLte, like as drzLike, inArray as drzInArray, isNull as drzIsNull, isNotNull as drzIsNotNull, asc as drzAsc, desc as drzDesc, count as drzCount, getTableName, getTableColumns, } from "drizzle-orm";
|
|
14
|
+
import { ConstraintViolationError } from "../errors.js";
|
|
15
|
+
export function drizzleDriver(opts) {
|
|
16
|
+
const tables = indexTables(opts.schema);
|
|
17
|
+
return makeDrizzleDriver(opts.db, tables, opts.dialect);
|
|
18
|
+
}
|
|
19
|
+
function indexTables(schema) {
|
|
20
|
+
const index = new Map();
|
|
21
|
+
for (const value of Object.values(schema)) {
|
|
22
|
+
if (!isDrizzleTable(value))
|
|
23
|
+
continue;
|
|
24
|
+
const tableName = getTableName(value);
|
|
25
|
+
if (typeof tableName === "string")
|
|
26
|
+
index.set(tableName, value);
|
|
27
|
+
}
|
|
28
|
+
return index;
|
|
29
|
+
}
|
|
30
|
+
function isDrizzleTable(v) {
|
|
31
|
+
// Drizzle tables expose a non-enumerable Symbol-keyed metadata block.
|
|
32
|
+
// We don't depend on the exact symbol; `getTableName` will throw for non-tables,
|
|
33
|
+
// so we let `try { getTableName(v) }` discriminate.
|
|
34
|
+
if (v === null || typeof v !== "object")
|
|
35
|
+
return false;
|
|
36
|
+
try {
|
|
37
|
+
return typeof getTableName(v) === "string";
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function makeDrizzleDriver(db, tables, dialect) {
|
|
44
|
+
function requireTable(name) {
|
|
45
|
+
const t = tables.get(name);
|
|
46
|
+
if (!t) {
|
|
47
|
+
throw new Error(`drizzleDriver: no table named '${name}' in the provided schema (known: ${[...tables.keys()].sort().join(", ") || "<none>"})`);
|
|
48
|
+
}
|
|
49
|
+
return t;
|
|
50
|
+
}
|
|
51
|
+
/** Build a `dbColumnName → DrizzleColumn` map for a table. */
|
|
52
|
+
function columnMap(table) {
|
|
53
|
+
const m = new Map();
|
|
54
|
+
const cols = getTableColumns(table);
|
|
55
|
+
for (const col of Object.values(cols)) {
|
|
56
|
+
// `col.name` is the SQL column name; the JS key is the JS field name.
|
|
57
|
+
const dbName = col.name;
|
|
58
|
+
if (typeof dbName === "string")
|
|
59
|
+
m.set(dbName, col);
|
|
60
|
+
}
|
|
61
|
+
return m;
|
|
62
|
+
}
|
|
63
|
+
/** Build a `jsFieldName → DrizzleColumn` map (used when constructing input rows). */
|
|
64
|
+
function jsColumnMap(table) {
|
|
65
|
+
const m = new Map();
|
|
66
|
+
const cols = getTableColumns(table);
|
|
67
|
+
for (const [jsKey, col] of Object.entries(cols)) {
|
|
68
|
+
m.set(jsKey, col);
|
|
69
|
+
}
|
|
70
|
+
return m;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Convert spec.values (keyed by DB column names) into the JS-keyed object
|
|
74
|
+
* Drizzle's `.values()`/`.set()` expects. Skips columns not present on the
|
|
75
|
+
* table.
|
|
76
|
+
*/
|
|
77
|
+
function toJsValues(table, dbKeyed) {
|
|
78
|
+
const dbToJs = new Map();
|
|
79
|
+
const cols = getTableColumns(table);
|
|
80
|
+
for (const [jsKey, col] of Object.entries(cols)) {
|
|
81
|
+
dbToJs.set(col.name, jsKey);
|
|
82
|
+
}
|
|
83
|
+
const out = {};
|
|
84
|
+
for (const [dbKey, val] of Object.entries(dbKeyed)) {
|
|
85
|
+
const jsKey = dbToJs.get(dbKey);
|
|
86
|
+
if (jsKey)
|
|
87
|
+
out[jsKey] = val;
|
|
88
|
+
}
|
|
89
|
+
return out;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Result rows from `db.select({alias: column})` are already keyed by the
|
|
93
|
+
* alias we passed. Since `buildSelectMap` uses DB names as aliases, the
|
|
94
|
+
* row is already in the DB-keyed shape that ObjectManager expects — no
|
|
95
|
+
* translation needed.
|
|
96
|
+
*/
|
|
97
|
+
function toDbKeyedRow(_table, row) {
|
|
98
|
+
return row ?? {};
|
|
99
|
+
}
|
|
100
|
+
function applyWhere(qb, where, table) {
|
|
101
|
+
if (!where)
|
|
102
|
+
return undefined;
|
|
103
|
+
return buildExpression(where, columnMap(table));
|
|
104
|
+
}
|
|
105
|
+
function applyOrder(qb, orderBy, table) {
|
|
106
|
+
if (!orderBy)
|
|
107
|
+
return qb;
|
|
108
|
+
const cols = columnMap(table);
|
|
109
|
+
const exprs = orderBy
|
|
110
|
+
.map((ob) => {
|
|
111
|
+
const c = cols.get(ob.column);
|
|
112
|
+
if (!c)
|
|
113
|
+
return undefined;
|
|
114
|
+
return ob.direction === "desc" ? drzDesc(c) : drzAsc(c);
|
|
115
|
+
})
|
|
116
|
+
.filter((e) => e !== undefined);
|
|
117
|
+
return exprs.length > 0 ? qb.orderBy(...exprs) : qb;
|
|
118
|
+
}
|
|
119
|
+
function pickJsCols(table, dbColumnNames) {
|
|
120
|
+
const map = columnMap(table);
|
|
121
|
+
const out = [];
|
|
122
|
+
for (const dbName of dbColumnNames) {
|
|
123
|
+
const c = map.get(dbName);
|
|
124
|
+
if (c)
|
|
125
|
+
out.push(c);
|
|
126
|
+
}
|
|
127
|
+
return out;
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
db,
|
|
131
|
+
dialect,
|
|
132
|
+
async selectOne(spec) {
|
|
133
|
+
const table = requireTable(spec.table);
|
|
134
|
+
const selectArg = buildSelectMap(table, spec.columns);
|
|
135
|
+
let q = db.select(selectArg).from(table);
|
|
136
|
+
const w = applyWhere(table, spec.where, table);
|
|
137
|
+
if (w !== undefined)
|
|
138
|
+
q = q.where(w);
|
|
139
|
+
q = applyOrder(q, spec.orderBy, table);
|
|
140
|
+
q = q.limit(1);
|
|
141
|
+
const rows = await q;
|
|
142
|
+
const first = rows[0];
|
|
143
|
+
return first ? toDbKeyedRow(table, jsKeyedFromSelect(first, selectArg)) : null;
|
|
144
|
+
},
|
|
145
|
+
async selectMany(spec) {
|
|
146
|
+
const table = requireTable(spec.table);
|
|
147
|
+
const selectArg = buildSelectMap(table, spec.columns);
|
|
148
|
+
let q = db.select(selectArg).from(table);
|
|
149
|
+
const w = applyWhere(table, spec.where, table);
|
|
150
|
+
if (w !== undefined)
|
|
151
|
+
q = q.where(w);
|
|
152
|
+
q = applyOrder(q, spec.orderBy, table);
|
|
153
|
+
if (spec.limit !== undefined)
|
|
154
|
+
q = q.limit(spec.limit);
|
|
155
|
+
if (spec.offset !== undefined)
|
|
156
|
+
q = q.offset(spec.offset);
|
|
157
|
+
const rows = (await q);
|
|
158
|
+
return rows.map((r) => toDbKeyedRow(table, jsKeyedFromSelect(r, selectArg)));
|
|
159
|
+
},
|
|
160
|
+
async count(spec) {
|
|
161
|
+
const table = requireTable(spec.table);
|
|
162
|
+
let q = db.select({ c: drzCount() }).from(table);
|
|
163
|
+
const w = applyWhere(table, spec.where, table);
|
|
164
|
+
if (w !== undefined)
|
|
165
|
+
q = q.where(w);
|
|
166
|
+
const rows = (await q);
|
|
167
|
+
const v = rows[0]?.c;
|
|
168
|
+
return typeof v === "number" ? v : Number(v ?? 0);
|
|
169
|
+
},
|
|
170
|
+
async insert(spec) {
|
|
171
|
+
const table = requireTable(spec.table);
|
|
172
|
+
try {
|
|
173
|
+
const result = await db
|
|
174
|
+
.insert(table)
|
|
175
|
+
.values(toJsValues(table, spec.values))
|
|
176
|
+
.returning(buildSelectMap(table, spec.returning));
|
|
177
|
+
const first = result[0];
|
|
178
|
+
if (!first) {
|
|
179
|
+
throw new Error(`drizzleDriver.insert: no row returned for '${spec.table}'`);
|
|
180
|
+
}
|
|
181
|
+
return toDbKeyedRow(table, jsKeyedFromSelect(first, buildSelectMap(table, spec.returning)));
|
|
182
|
+
}
|
|
183
|
+
catch (err) {
|
|
184
|
+
throw mapDriverError(err, spec.table, dialect);
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
async insertMany(spec) {
|
|
188
|
+
const table = requireTable(spec.table);
|
|
189
|
+
try {
|
|
190
|
+
const values = spec.rows.map((r) => toJsValues(table, r));
|
|
191
|
+
const rows = (await db
|
|
192
|
+
.insert(table)
|
|
193
|
+
.values(values)
|
|
194
|
+
.returning(buildSelectMap(table, spec.returning)));
|
|
195
|
+
return rows.map((r) => toDbKeyedRow(table, jsKeyedFromSelect(r, buildSelectMap(table, spec.returning))));
|
|
196
|
+
}
|
|
197
|
+
catch (err) {
|
|
198
|
+
throw mapDriverError(err, spec.table, dialect);
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
async update(spec) {
|
|
202
|
+
const table = requireTable(spec.table);
|
|
203
|
+
try {
|
|
204
|
+
let q = db.update(table).set(toJsValues(table, spec.values));
|
|
205
|
+
const w = applyWhere(table, spec.where, table);
|
|
206
|
+
if (w !== undefined)
|
|
207
|
+
q = q.where(w);
|
|
208
|
+
const rows = (await q.returning(buildSelectMap(table, spec.returning)));
|
|
209
|
+
const first = rows[0];
|
|
210
|
+
return first
|
|
211
|
+
? toDbKeyedRow(table, jsKeyedFromSelect(first, buildSelectMap(table, spec.returning)))
|
|
212
|
+
: null;
|
|
213
|
+
}
|
|
214
|
+
catch (err) {
|
|
215
|
+
throw mapDriverError(err, spec.table, dialect);
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
async updateMany(spec) {
|
|
219
|
+
const table = requireTable(spec.table);
|
|
220
|
+
try {
|
|
221
|
+
let q = db.update(table).set(toJsValues(table, spec.values));
|
|
222
|
+
const w = applyWhere(table, spec.where, table);
|
|
223
|
+
if (w !== undefined)
|
|
224
|
+
q = q.where(w);
|
|
225
|
+
const result = await q;
|
|
226
|
+
return extractRowCount(result);
|
|
227
|
+
}
|
|
228
|
+
catch (err) {
|
|
229
|
+
throw mapDriverError(err, spec.table, dialect);
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
async delete(spec) {
|
|
233
|
+
const table = requireTable(spec.table);
|
|
234
|
+
try {
|
|
235
|
+
let q = db.delete(table);
|
|
236
|
+
const w = applyWhere(table, spec.where, table);
|
|
237
|
+
if (w !== undefined)
|
|
238
|
+
q = q.where(w);
|
|
239
|
+
const result = await q;
|
|
240
|
+
return extractRowCount(result);
|
|
241
|
+
}
|
|
242
|
+
catch (err) {
|
|
243
|
+
throw mapDriverError(err, spec.table, dialect);
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
async deleteMany(spec) {
|
|
247
|
+
const table = requireTable(spec.table);
|
|
248
|
+
try {
|
|
249
|
+
let q = db.delete(table);
|
|
250
|
+
const w = applyWhere(table, spec.where, table);
|
|
251
|
+
if (w !== undefined)
|
|
252
|
+
q = q.where(w);
|
|
253
|
+
const result = await q;
|
|
254
|
+
return extractRowCount(result);
|
|
255
|
+
}
|
|
256
|
+
catch (err) {
|
|
257
|
+
throw mapDriverError(err, spec.table, dialect);
|
|
258
|
+
}
|
|
259
|
+
},
|
|
260
|
+
async transaction(fn) {
|
|
261
|
+
return await db.transaction(async (tx) => {
|
|
262
|
+
const txDriver = makeDrizzleDriver(tx, tables, dialect);
|
|
263
|
+
return await fn(txDriver);
|
|
264
|
+
});
|
|
265
|
+
},
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Build the `select` arg for Drizzle by mapping DB column names back to
|
|
270
|
+
* the table's JS columns. Drizzle expects a `Record<aliasKey, column>`;
|
|
271
|
+
* we use the DB column name as the alias key so result rows are easy to
|
|
272
|
+
* normalize back to a DB-keyed shape.
|
|
273
|
+
*/
|
|
274
|
+
function buildSelectMap(table, dbColumnNames) {
|
|
275
|
+
const allCols = getTableColumns(table);
|
|
276
|
+
const dbToCol = new Map();
|
|
277
|
+
for (const col of Object.values(allCols)) {
|
|
278
|
+
const name = col.name;
|
|
279
|
+
if (typeof name === "string")
|
|
280
|
+
dbToCol.set(name, col);
|
|
281
|
+
}
|
|
282
|
+
const out = {};
|
|
283
|
+
for (const dbName of dbColumnNames) {
|
|
284
|
+
const c = dbToCol.get(dbName);
|
|
285
|
+
if (c)
|
|
286
|
+
out[dbName] = c;
|
|
287
|
+
}
|
|
288
|
+
return out;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Result rows from Drizzle are already keyed by whatever alias we passed in.
|
|
292
|
+
* Since we used DB names as aliases in buildSelectMap, the result row is
|
|
293
|
+
* already DB-keyed — we just pass it through to keep the function symmetric.
|
|
294
|
+
*/
|
|
295
|
+
function jsKeyedFromSelect(row, _selectMap) {
|
|
296
|
+
return row;
|
|
297
|
+
}
|
|
298
|
+
function extractRowCount(result) {
|
|
299
|
+
// Drizzle's update/delete return shape varies by backend. We support the
|
|
300
|
+
// common shapes; unknown shapes fall through to 0.
|
|
301
|
+
if (typeof result === "number")
|
|
302
|
+
return result;
|
|
303
|
+
if (Array.isArray(result))
|
|
304
|
+
return result.length;
|
|
305
|
+
if (result && typeof result === "object") {
|
|
306
|
+
const obj = result;
|
|
307
|
+
if (typeof obj.rowsAffected === "number")
|
|
308
|
+
return obj.rowsAffected;
|
|
309
|
+
if (typeof obj.rowsAffected === "bigint")
|
|
310
|
+
return Number(obj.rowsAffected);
|
|
311
|
+
if (typeof obj.rowCount === "number")
|
|
312
|
+
return obj.rowCount;
|
|
313
|
+
}
|
|
314
|
+
return 0;
|
|
315
|
+
}
|
|
316
|
+
function buildExpression(w, cols) {
|
|
317
|
+
switch (w.kind) {
|
|
318
|
+
case "eq": {
|
|
319
|
+
const c = cols.get(w.column);
|
|
320
|
+
return w.value === null ? drzIsNull(c) : drzEq(c, w.value);
|
|
321
|
+
}
|
|
322
|
+
case "ne": {
|
|
323
|
+
const c = cols.get(w.column);
|
|
324
|
+
return w.value === null ? drzIsNotNull(c) : drzNe(c, w.value);
|
|
325
|
+
}
|
|
326
|
+
case "gt": return drzGt(cols.get(w.column), w.value);
|
|
327
|
+
case "gte": return drzGte(cols.get(w.column), w.value);
|
|
328
|
+
case "lt": return drzLt(cols.get(w.column), w.value);
|
|
329
|
+
case "lte": return drzLte(cols.get(w.column), w.value);
|
|
330
|
+
case "like": return drzLike(cols.get(w.column), w.pattern);
|
|
331
|
+
case "in": return drzInArray(cols.get(w.column), w.values);
|
|
332
|
+
case "isNull": return w.not ? drzIsNotNull(cols.get(w.column)) : drzIsNull(cols.get(w.column));
|
|
333
|
+
case "and": {
|
|
334
|
+
// drzAnd is typed as accepting SQLWrapper; our recursive return is
|
|
335
|
+
// structurally compatible but typed as unknown. Cast at the boundary.
|
|
336
|
+
const parts = w.clauses.map((c) => buildExpression(c, cols));
|
|
337
|
+
return drzAnd(...parts);
|
|
338
|
+
}
|
|
339
|
+
default: {
|
|
340
|
+
const exhaustive = w;
|
|
341
|
+
throw new Error(`Unhandled WhereClause kind: ${JSON.stringify(exhaustive)}`);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
// ---------------------------------------------------------------------------
|
|
346
|
+
// Error normalization — same shape as kysely-driver so callers see one error
|
|
347
|
+
// type regardless of which driver they wired up.
|
|
348
|
+
// ---------------------------------------------------------------------------
|
|
349
|
+
function mapDriverError(err, table, dialect) {
|
|
350
|
+
if (!(err instanceof Error))
|
|
351
|
+
return err;
|
|
352
|
+
const msg = err.message;
|
|
353
|
+
const code = err.code;
|
|
354
|
+
if (dialect === "sqlite") {
|
|
355
|
+
const kind = sqliteConstraintKind(code, msg);
|
|
356
|
+
if (kind !== null) {
|
|
357
|
+
const field = extractSqliteField(kind, msg);
|
|
358
|
+
return new ConstraintViolationError(msg, {
|
|
359
|
+
kind, table, ...(field !== undefined ? { field } : {}), cause: err,
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
return err;
|
|
363
|
+
}
|
|
364
|
+
// pg-style SQLSTATE codes.
|
|
365
|
+
if (code === "23505")
|
|
366
|
+
return new ConstraintViolationError(msg, { kind: "unique", table, cause: err });
|
|
367
|
+
if (code === "23503")
|
|
368
|
+
return new ConstraintViolationError(msg, { kind: "foreign_key", table, cause: err });
|
|
369
|
+
if (code === "23502")
|
|
370
|
+
return new ConstraintViolationError(msg, { kind: "not_null", table, cause: err });
|
|
371
|
+
if (code === "23514")
|
|
372
|
+
return new ConstraintViolationError(msg, { kind: "check", table, cause: err });
|
|
373
|
+
return err;
|
|
374
|
+
}
|
|
375
|
+
function sqliteConstraintKind(code, msg) {
|
|
376
|
+
if (code === "SQLITE_CONSTRAINT_UNIQUE" || code === "SQLITE_CONSTRAINT_PRIMARYKEY")
|
|
377
|
+
return "unique";
|
|
378
|
+
if (code === "SQLITE_CONSTRAINT_FOREIGNKEY")
|
|
379
|
+
return "foreign_key";
|
|
380
|
+
if (code === "SQLITE_CONSTRAINT_NOTNULL")
|
|
381
|
+
return "not_null";
|
|
382
|
+
if (code === "SQLITE_CONSTRAINT_CHECK")
|
|
383
|
+
return "check";
|
|
384
|
+
if (code === "SQLITE_CONSTRAINT" || code === undefined) {
|
|
385
|
+
if (msg.includes("UNIQUE constraint failed"))
|
|
386
|
+
return "unique";
|
|
387
|
+
if (msg.includes("FOREIGN KEY constraint failed"))
|
|
388
|
+
return "foreign_key";
|
|
389
|
+
if (msg.includes("NOT NULL constraint failed"))
|
|
390
|
+
return "not_null";
|
|
391
|
+
if (msg.includes("CHECK constraint failed"))
|
|
392
|
+
return "check";
|
|
393
|
+
}
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
396
|
+
function extractSqliteField(kind, msg) {
|
|
397
|
+
const pattern = kind === "unique" ? /UNIQUE constraint failed: ([^\s,]+)/
|
|
398
|
+
: kind === "not_null" ? /NOT NULL constraint failed: ([^\s,]+)/
|
|
399
|
+
: null;
|
|
400
|
+
if (!pattern)
|
|
401
|
+
return undefined;
|
|
402
|
+
const m = msg.match(pattern);
|
|
403
|
+
return m ? m[1]?.split(".")[1] : undefined;
|
|
404
|
+
}
|
|
405
|
+
//# sourceMappingURL=drizzle-driver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drizzle-driver.js","sourceRoot":"","sources":["../../src/drivers/drizzle-driver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { PersistenceDriver, Row } from "../persistence-driver.js";
|
|
2
|
+
export interface InMemoryDriverOptions {
|
|
3
|
+
/** Initial table data: { tableName: Row[] }. */
|
|
4
|
+
seed?: Record<string, Row[]>;
|
|
5
|
+
/** Per-table PK field names (used to detect collisions + auto-increment). Default: ["id"]. */
|
|
6
|
+
pkFields?: Record<string, string[]>;
|
|
7
|
+
/** Auto-increment counter starting value per table. Default: 1 + max existing PK. */
|
|
8
|
+
startCounters?: Record<string, number>;
|
|
9
|
+
}
|
|
10
|
+
export declare function inMemoryDriver(opts?: InMemoryDriverOptions): PersistenceDriver;
|
|
11
|
+
//# sourceMappingURL=in-memory-driver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"in-memory-driver.d.ts","sourceRoot":"","sources":["../../src/drivers/in-memory-driver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACoD,GAAG,EACzE,MAAM,0BAA0B,CAAC;AAGlC,MAAM,WAAW,qBAAqB;IACpC,gDAAgD;IAChD,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;IAC7B,8FAA8F;IAC9F,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACpC,qFAAqF;IACrF,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxC;AASD,wBAAgB,cAAc,CAAC,IAAI,GAAE,qBAA0B,GAAG,iBAAiB,CAGlF"}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { ConstraintViolationError } from "../errors.js";
|
|
2
|
+
export function inMemoryDriver(opts = {}) {
|
|
3
|
+
const state = createState(opts);
|
|
4
|
+
return makeDriver(state);
|
|
5
|
+
}
|
|
6
|
+
function createState(opts) {
|
|
7
|
+
const tables = new Map();
|
|
8
|
+
const pkFields = new Map();
|
|
9
|
+
const counters = new Map();
|
|
10
|
+
for (const [tableName, rows] of Object.entries(opts.seed ?? {})) {
|
|
11
|
+
const pk = opts.pkFields?.[tableName] ?? ["id"];
|
|
12
|
+
pkFields.set(tableName, pk);
|
|
13
|
+
const map = new Map();
|
|
14
|
+
let maxNumericPk = 0;
|
|
15
|
+
for (const row of rows) {
|
|
16
|
+
const key = pkKey(row, pk);
|
|
17
|
+
map.set(key, structuredClone(row));
|
|
18
|
+
const v = row[pk[0]];
|
|
19
|
+
if (typeof v === "number" && v > maxNumericPk)
|
|
20
|
+
maxNumericPk = v;
|
|
21
|
+
}
|
|
22
|
+
tables.set(tableName, map);
|
|
23
|
+
counters.set(tableName, opts.startCounters?.[tableName] ?? maxNumericPk + 1);
|
|
24
|
+
}
|
|
25
|
+
return { tables, pkFields, counters };
|
|
26
|
+
}
|
|
27
|
+
function makeDriver(state) {
|
|
28
|
+
const ensureTable = (table) => {
|
|
29
|
+
let t = state.tables.get(table);
|
|
30
|
+
if (!t) {
|
|
31
|
+
t = new Map();
|
|
32
|
+
state.tables.set(table, t);
|
|
33
|
+
state.pkFields.set(table, ["id"]);
|
|
34
|
+
state.counters.set(table, 1);
|
|
35
|
+
}
|
|
36
|
+
return t;
|
|
37
|
+
};
|
|
38
|
+
const ensurePk = (table) => {
|
|
39
|
+
let pk = state.pkFields.get(table);
|
|
40
|
+
if (!pk) {
|
|
41
|
+
pk = ["id"];
|
|
42
|
+
state.pkFields.set(table, pk);
|
|
43
|
+
}
|
|
44
|
+
return pk;
|
|
45
|
+
};
|
|
46
|
+
return {
|
|
47
|
+
dialect: "memory",
|
|
48
|
+
async selectOne(spec) {
|
|
49
|
+
const rows = await this.selectMany({ ...spec, limit: 1 });
|
|
50
|
+
return rows[0] ?? null;
|
|
51
|
+
},
|
|
52
|
+
async selectMany(spec) {
|
|
53
|
+
const t = state.tables.get(spec.table);
|
|
54
|
+
if (!t)
|
|
55
|
+
return [];
|
|
56
|
+
let rows = [...t.values()].filter((r) => matchesWhere(r, spec.where));
|
|
57
|
+
if (spec.orderBy) {
|
|
58
|
+
for (const ob of [...spec.orderBy].reverse()) {
|
|
59
|
+
rows.sort((a, b) => compareValues(a[ob.column], b[ob.column]) * (ob.direction === "asc" ? 1 : -1));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (spec.offset)
|
|
63
|
+
rows = rows.slice(spec.offset);
|
|
64
|
+
if (spec.limit !== undefined)
|
|
65
|
+
rows = rows.slice(0, spec.limit);
|
|
66
|
+
return rows.map((r) => projectColumns(r, spec.columns));
|
|
67
|
+
},
|
|
68
|
+
async count(spec) {
|
|
69
|
+
const t = state.tables.get(spec.table);
|
|
70
|
+
if (!t)
|
|
71
|
+
return 0;
|
|
72
|
+
return [...t.values()].filter((r) => matchesWhere(r, spec.where)).length;
|
|
73
|
+
},
|
|
74
|
+
async insert(spec) {
|
|
75
|
+
const t = ensureTable(spec.table);
|
|
76
|
+
const pk = ensurePk(spec.table);
|
|
77
|
+
const row = { ...spec.values };
|
|
78
|
+
for (const f of pk) {
|
|
79
|
+
if (row[f] === undefined || row[f] === null) {
|
|
80
|
+
if (pk.length !== 1) {
|
|
81
|
+
throw new ConstraintViolationError(`Composite PK requires all values; missing ${f}`, { kind: "not_null", table: spec.table, field: f });
|
|
82
|
+
}
|
|
83
|
+
const next = state.counters.get(spec.table) ?? 1;
|
|
84
|
+
row[f] = next;
|
|
85
|
+
state.counters.set(spec.table, next + 1);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const key = pkKey(row, pk);
|
|
89
|
+
if (t.has(key)) {
|
|
90
|
+
throw new ConstraintViolationError(`Unique violation on ${spec.table} PK ${key}`, { kind: "unique", table: spec.table, field: pk[0] });
|
|
91
|
+
}
|
|
92
|
+
t.set(key, structuredClone(row));
|
|
93
|
+
return projectColumns(row, spec.returning);
|
|
94
|
+
},
|
|
95
|
+
async insertMany(spec) {
|
|
96
|
+
const out = [];
|
|
97
|
+
for (const values of spec.rows) {
|
|
98
|
+
out.push(await this.insert({ table: spec.table, values, returning: spec.returning }));
|
|
99
|
+
}
|
|
100
|
+
return out;
|
|
101
|
+
},
|
|
102
|
+
async update(spec) {
|
|
103
|
+
const t = state.tables.get(spec.table);
|
|
104
|
+
if (!t)
|
|
105
|
+
return null;
|
|
106
|
+
const matches = [...t.entries()].filter(([, r]) => matchesWhere(r, spec.where));
|
|
107
|
+
if (matches.length === 0)
|
|
108
|
+
return null;
|
|
109
|
+
const [key, row] = matches[0];
|
|
110
|
+
const updated = { ...row, ...spec.values };
|
|
111
|
+
t.set(key, structuredClone(updated));
|
|
112
|
+
return projectColumns(updated, spec.returning);
|
|
113
|
+
},
|
|
114
|
+
async updateMany(spec) {
|
|
115
|
+
const t = state.tables.get(spec.table);
|
|
116
|
+
if (!t)
|
|
117
|
+
return 0;
|
|
118
|
+
let n = 0;
|
|
119
|
+
for (const [key, row] of t.entries()) {
|
|
120
|
+
if (!matchesWhere(row, spec.where))
|
|
121
|
+
continue;
|
|
122
|
+
t.set(key, structuredClone({ ...row, ...spec.values }));
|
|
123
|
+
n++;
|
|
124
|
+
}
|
|
125
|
+
return n;
|
|
126
|
+
},
|
|
127
|
+
async delete(spec) {
|
|
128
|
+
return this.deleteMany(spec);
|
|
129
|
+
},
|
|
130
|
+
async deleteMany(spec) {
|
|
131
|
+
const t = state.tables.get(spec.table);
|
|
132
|
+
if (!t)
|
|
133
|
+
return 0;
|
|
134
|
+
const keysToDelete = [...t.entries()].filter(([, r]) => matchesWhere(r, spec.where)).map(([k]) => k);
|
|
135
|
+
for (const k of keysToDelete)
|
|
136
|
+
t.delete(k);
|
|
137
|
+
return keysToDelete.length;
|
|
138
|
+
},
|
|
139
|
+
async transaction(fn) {
|
|
140
|
+
const snapshot = snapshotState(state);
|
|
141
|
+
try {
|
|
142
|
+
return await fn(this);
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
restoreState(state, snapshot);
|
|
146
|
+
throw err;
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
function projectColumns(row, columns) {
|
|
152
|
+
if (columns.length === 0)
|
|
153
|
+
return { ...row };
|
|
154
|
+
const out = {};
|
|
155
|
+
for (const c of columns) {
|
|
156
|
+
if (c in row)
|
|
157
|
+
out[c] = row[c];
|
|
158
|
+
}
|
|
159
|
+
return out;
|
|
160
|
+
}
|
|
161
|
+
function pkKey(row, pkFields) {
|
|
162
|
+
return pkFields.map((f) => String(row[f])).join(",");
|
|
163
|
+
}
|
|
164
|
+
function matchesWhere(row, where) {
|
|
165
|
+
if (!where)
|
|
166
|
+
return true;
|
|
167
|
+
switch (where.kind) {
|
|
168
|
+
case "eq":
|
|
169
|
+
return row[where.column] === where.value;
|
|
170
|
+
case "ne":
|
|
171
|
+
return row[where.column] !== where.value;
|
|
172
|
+
case "gt":
|
|
173
|
+
return compareValues(row[where.column], where.value) > 0;
|
|
174
|
+
case "gte":
|
|
175
|
+
return compareValues(row[where.column], where.value) >= 0;
|
|
176
|
+
case "lt":
|
|
177
|
+
return compareValues(row[where.column], where.value) < 0;
|
|
178
|
+
case "lte":
|
|
179
|
+
return compareValues(row[where.column], where.value) <= 0;
|
|
180
|
+
case "in":
|
|
181
|
+
return where.values.some((v) => row[where.column] === v);
|
|
182
|
+
case "like":
|
|
183
|
+
return likeMatch(row[where.column], where.pattern);
|
|
184
|
+
case "isNull": {
|
|
185
|
+
const isNull = row[where.column] === null || row[where.column] === undefined;
|
|
186
|
+
return where.not ? !isNull : isNull;
|
|
187
|
+
}
|
|
188
|
+
case "and":
|
|
189
|
+
return where.clauses.every((c) => matchesWhere(row, c));
|
|
190
|
+
default: {
|
|
191
|
+
const exhaustive = where;
|
|
192
|
+
throw new Error(`Unhandled WhereClause kind: ${JSON.stringify(exhaustive)}`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
function compareValues(a, b) {
|
|
197
|
+
if (a === b)
|
|
198
|
+
return 0;
|
|
199
|
+
if (a === null || a === undefined)
|
|
200
|
+
return -1;
|
|
201
|
+
if (b === null || b === undefined)
|
|
202
|
+
return 1;
|
|
203
|
+
if (typeof a === "number" && typeof b === "number")
|
|
204
|
+
return a - b;
|
|
205
|
+
return String(a).localeCompare(String(b));
|
|
206
|
+
}
|
|
207
|
+
// SQL LIKE: % → .*, _ → ., case-sensitive. Other regex metacharacters in `pattern` are escaped first.
|
|
208
|
+
function likeMatch(value, pattern) {
|
|
209
|
+
if (typeof value !== "string")
|
|
210
|
+
return false;
|
|
211
|
+
const re = new RegExp("^" + pattern.replace(/[.+*?^${}()|[\]\\]/g, "\\$&").replace(/%/g, ".*").replace(/_/g, ".") + "$");
|
|
212
|
+
return re.test(value);
|
|
213
|
+
}
|
|
214
|
+
function snapshotState(state) {
|
|
215
|
+
return {
|
|
216
|
+
tables: new Map([...state.tables.entries()].map(([t, m]) => [t, new Map([...m.entries()].map(([k, r]) => [k, structuredClone(r)]))])),
|
|
217
|
+
pkFields: new Map(state.pkFields),
|
|
218
|
+
counters: new Map(state.counters),
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
function restoreState(state, snapshot) {
|
|
222
|
+
state.tables.clear();
|
|
223
|
+
for (const [t, m] of snapshot.tables.entries())
|
|
224
|
+
state.tables.set(t, m);
|
|
225
|
+
state.pkFields.clear();
|
|
226
|
+
for (const [k, v] of snapshot.pkFields.entries())
|
|
227
|
+
state.pkFields.set(k, v);
|
|
228
|
+
state.counters.clear();
|
|
229
|
+
for (const [k, v] of snapshot.counters.entries())
|
|
230
|
+
state.counters.set(k, v);
|
|
231
|
+
}
|
|
232
|
+
//# sourceMappingURL=in-memory-driver.js.map
|