@fragno-dev/db 0.1.1 → 0.1.2
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/.turbo/turbo-build.log +61 -53
- package/CHANGELOG.md +12 -0
- package/dist/adapters/adapters.d.ts +11 -1
- package/dist/adapters/adapters.d.ts.map +1 -1
- package/dist/adapters/drizzle/drizzle-adapter.d.ts +9 -2
- package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +1 -1
- package/dist/adapters/drizzle/drizzle-adapter.js +21 -39
- package/dist/adapters/drizzle/drizzle-adapter.js.map +1 -1
- package/dist/adapters/drizzle/drizzle-query.d.ts.map +1 -1
- package/dist/adapters/drizzle/drizzle-query.js +3 -2
- package/dist/adapters/drizzle/drizzle-query.js.map +1 -1
- package/dist/adapters/drizzle/drizzle-uow-compiler.js +8 -6
- package/dist/adapters/drizzle/drizzle-uow-compiler.js.map +1 -1
- package/dist/adapters/drizzle/drizzle-uow-decoder.js.map +1 -1
- package/dist/adapters/drizzle/drizzle-uow-executor.js.map +1 -1
- package/dist/adapters/drizzle/generate.js +107 -34
- package/dist/adapters/drizzle/generate.js.map +1 -1
- package/dist/adapters/drizzle/shared.js +14 -1
- package/dist/adapters/drizzle/shared.js.map +1 -1
- package/dist/adapters/kysely/kysely-adapter.d.ts +2 -1
- package/dist/adapters/kysely/kysely-adapter.d.ts.map +1 -1
- package/dist/adapters/kysely/kysely-adapter.js +25 -30
- package/dist/adapters/kysely/kysely-adapter.js.map +1 -1
- package/dist/adapters/kysely/kysely-query-builder.js +48 -44
- package/dist/adapters/kysely/kysely-query-builder.js.map +1 -1
- package/dist/adapters/kysely/kysely-query-compiler.js +2 -2
- package/dist/adapters/kysely/kysely-query-compiler.js.map +1 -1
- package/dist/adapters/kysely/kysely-query.js +3 -2
- package/dist/adapters/kysely/kysely-query.js.map +1 -1
- package/dist/adapters/kysely/kysely-shared.js +18 -0
- package/dist/adapters/kysely/kysely-shared.js.map +1 -0
- package/dist/adapters/kysely/kysely-uow-compiler.js +4 -3
- package/dist/adapters/kysely/kysely-uow-compiler.js.map +1 -1
- package/dist/adapters/kysely/migration/execute.js +15 -12
- package/dist/adapters/kysely/migration/execute.js.map +1 -1
- package/dist/migration-engine/auto-from-schema.js +2 -8
- package/dist/migration-engine/auto-from-schema.js.map +1 -1
- package/dist/migration-engine/create.d.ts +1 -5
- package/dist/migration-engine/create.js +1 -1
- package/dist/migration-engine/create.js.map +1 -1
- package/dist/migration-engine/generation-engine.d.ts +51 -0
- package/dist/migration-engine/generation-engine.d.ts.map +1 -0
- package/dist/migration-engine/generation-engine.js +165 -0
- package/dist/migration-engine/generation-engine.js.map +1 -0
- package/dist/migration-engine/shared.d.ts +5 -2
- package/dist/migration-engine/shared.d.ts.map +1 -1
- package/dist/migration-engine/shared.js.map +1 -1
- package/dist/mod.d.ts +0 -8
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +0 -32
- package/dist/mod.js.map +1 -1
- package/dist/query/condition-builder.js.map +1 -1
- package/dist/query/result-transform.js +2 -1
- package/dist/query/result-transform.js.map +1 -1
- package/dist/schema/create.d.ts +74 -16
- package/dist/schema/create.d.ts.map +1 -1
- package/dist/schema/create.js +76 -11
- package/dist/schema/create.js.map +1 -1
- package/dist/schema/serialize.js.map +1 -1
- package/dist/shared/settings-schema.js +36 -0
- package/dist/shared/settings-schema.js.map +1 -0
- package/dist/util/import-generator.js.map +1 -1
- package/dist/util/parse.js.map +1 -1
- package/package.json +8 -2
- package/src/adapters/adapters.ts +10 -3
- package/src/adapters/drizzle/drizzle-adapter-pglite.test.ts +11 -7
- package/src/adapters/drizzle/drizzle-adapter.test.ts +77 -29
- package/src/adapters/drizzle/drizzle-adapter.ts +31 -78
- package/src/adapters/drizzle/drizzle-query.ts +4 -7
- package/src/adapters/drizzle/drizzle-uow-compiler.test.ts +9 -3
- package/src/adapters/drizzle/drizzle-uow-compiler.ts +12 -6
- package/src/adapters/drizzle/drizzle-uow-decoder.ts +1 -1
- package/src/adapters/drizzle/drizzle-uow-executor.ts +1 -1
- package/src/adapters/drizzle/generate.test.ts +573 -150
- package/src/adapters/drizzle/generate.ts +187 -36
- package/src/adapters/drizzle/migrate-drizzle.test.ts +30 -6
- package/src/adapters/drizzle/shared.ts +31 -1
- package/src/adapters/drizzle/test-utils.ts +3 -1
- package/src/adapters/kysely/kysely-adapter-pglite.test.ts +25 -27
- package/src/adapters/kysely/kysely-adapter.ts +35 -58
- package/src/adapters/kysely/kysely-query-builder.ts +75 -44
- package/src/adapters/kysely/kysely-query-compiler.ts +3 -1
- package/src/adapters/kysely/kysely-query.ts +8 -2
- package/src/adapters/kysely/kysely-shared.ts +23 -0
- package/src/adapters/kysely/kysely-uow-compiler.ts +5 -2
- package/src/adapters/kysely/migration/execute-mysql.test.ts +2 -2
- package/src/adapters/kysely/migration/execute-postgres.test.ts +19 -19
- package/src/adapters/kysely/migration/execute.ts +48 -17
- package/src/adapters/kysely/migration/kysely-migrator.test.ts +19 -37
- package/src/fragment.test.ts +1 -0
- package/src/migration-engine/auto-from-schema.ts +14 -18
- package/src/migration-engine/create.ts +1 -6
- package/src/migration-engine/generation-engine.test.ts +597 -0
- package/src/migration-engine/generation-engine.ts +356 -0
- package/src/migration-engine/shared.ts +1 -4
- package/src/mod.ts +0 -66
- package/src/query/condition-builder.ts +24 -8
- package/src/query/result-transform.ts +7 -1
- package/src/schema/create.test.ts +4 -1
- package/src/schema/create.ts +132 -24
- package/src/schema/serialize.ts +21 -7
- package/src/shared/settings-schema.ts +61 -0
- package/src/util/deep-equal.ts +21 -7
- package/src/util/import-generator.ts +3 -1
- package/src/util/parse.ts +3 -1
- package/tsdown.config.ts +1 -0
- package/.turbo/turbo-test.log +0 -37
- package/.turbo/turbo-types$colon$check.log +0 -1
package/src/schema/create.ts
CHANGED
|
@@ -151,15 +151,35 @@ export interface Table<
|
|
|
151
151
|
getVersionColumn: () => AnyColumn;
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
type
|
|
155
|
-
|
|
156
|
-
timestamp: "now";
|
|
157
|
-
string: "auto";
|
|
158
|
-
} & Record<`varchar(${number})`, "auto">;
|
|
154
|
+
type DBSpecial = { tag: "special"; value: "now" };
|
|
155
|
+
type RuntimeSpecial = { tag: "special"; value: "cuid" | "now" };
|
|
159
156
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
157
|
+
/**
|
|
158
|
+
* Builder for database-level default values.
|
|
159
|
+
*/
|
|
160
|
+
export interface DefaultBuilder {
|
|
161
|
+
/** Database-generated timestamp (DEFAULT NOW()) */
|
|
162
|
+
now(): DBSpecial;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Builder for runtime-generated default values.
|
|
167
|
+
*/
|
|
168
|
+
export interface RuntimeDefaultBuilder {
|
|
169
|
+
/** Generate CUID identifier */
|
|
170
|
+
cuid(): RuntimeSpecial;
|
|
171
|
+
/** Generate current timestamp */
|
|
172
|
+
now(): RuntimeSpecial;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const defaultBuilder: DefaultBuilder = {
|
|
176
|
+
now: () => ({ tag: "special", value: "now" }),
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const runtimeDefaultBuilder: RuntimeDefaultBuilder = {
|
|
180
|
+
cuid: () => ({ tag: "special", value: "cuid" }),
|
|
181
|
+
now: () => ({ tag: "special", value: "now" }),
|
|
182
|
+
};
|
|
163
183
|
|
|
164
184
|
type IdColumnType = `varchar(${number})`;
|
|
165
185
|
|
|
@@ -188,9 +208,8 @@ export class Column<TType extends keyof TypeMap, TIn = unknown, TOut = unknown>
|
|
|
188
208
|
|
|
189
209
|
default?:
|
|
190
210
|
| { value: TypeMap[TType] }
|
|
191
|
-
| {
|
|
192
|
-
|
|
193
|
-
};
|
|
211
|
+
| { dbSpecial: "now" }
|
|
212
|
+
| { runtime: "cuid" | "now" | (() => TypeMap[TType]) };
|
|
194
213
|
|
|
195
214
|
tableName: string = "";
|
|
196
215
|
|
|
@@ -214,25 +233,99 @@ export class Column<TType extends keyof TypeMap, TIn = unknown, TOut = unknown>
|
|
|
214
233
|
}
|
|
215
234
|
|
|
216
235
|
/**
|
|
217
|
-
* Generate default value
|
|
236
|
+
* Generate default value at runtime in application code (not in the database).
|
|
237
|
+
*
|
|
238
|
+
* Use this when you need values generated in your application code, either because:
|
|
239
|
+
* - Your database doesn't support the operation (e.g., generating CUIDs)
|
|
240
|
+
* - You want consistent behavior across all databases
|
|
241
|
+
* - You need custom generation logic
|
|
242
|
+
*
|
|
243
|
+
* @param value - Either a literal value or builder callback:
|
|
244
|
+
* - Literal: Any static value of the column type
|
|
245
|
+
* - `(b) => b.cuid()` - Generate a CUID identifier
|
|
246
|
+
* - `(b) => b.now()` - Generate current timestamp
|
|
247
|
+
* - `(b) => ...` - Custom function that returns the default value
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* ```ts
|
|
251
|
+
* column("string").defaultTo$((b) => b.cuid()) // Generate CUID at runtime
|
|
252
|
+
* column("timestamp").defaultTo$((b) => b.now()) // Generate timestamp at runtime
|
|
253
|
+
* column("integer").defaultTo$(42) // Static literal
|
|
254
|
+
* column("integer").defaultTo$((b) => Math.floor(Math.random() * 100)) // Custom function
|
|
255
|
+
* ```
|
|
218
256
|
*/
|
|
219
|
-
defaultTo$(
|
|
220
|
-
|
|
257
|
+
defaultTo$(
|
|
258
|
+
value: TypeMap[TType] | ((builder: RuntimeDefaultBuilder) => RuntimeSpecial | TypeMap[TType]),
|
|
259
|
+
): Column<TType, TIn | null, TOut> {
|
|
260
|
+
if (typeof value === "function") {
|
|
261
|
+
const fn = value as (builder: RuntimeDefaultBuilder) => RuntimeSpecial | TypeMap[TType];
|
|
262
|
+
const result = fn(runtimeDefaultBuilder);
|
|
263
|
+
if (
|
|
264
|
+
typeof result === "object" &&
|
|
265
|
+
result !== null &&
|
|
266
|
+
"tag" in result &&
|
|
267
|
+
result.tag === "special"
|
|
268
|
+
) {
|
|
269
|
+
this.default = { runtime: result.value };
|
|
270
|
+
} else {
|
|
271
|
+
// Custom function - we need to wrap the callback to call it again later
|
|
272
|
+
this.default = { runtime: () => fn(runtimeDefaultBuilder) as TypeMap[TType] };
|
|
273
|
+
}
|
|
274
|
+
} else {
|
|
275
|
+
// Direct literal value - wrap it in a function for runtime generation
|
|
276
|
+
this.default = { runtime: () => value };
|
|
277
|
+
}
|
|
221
278
|
return this;
|
|
222
279
|
}
|
|
223
280
|
|
|
224
281
|
/**
|
|
225
|
-
* Set a database-level default value
|
|
282
|
+
* Set a database-level default value (generated by the database, not application code).
|
|
283
|
+
*
|
|
284
|
+
* The database will generate the default value when inserting rows. If the database
|
|
285
|
+
* doesn't support the operation, Fragno will fall back to generating the value in
|
|
286
|
+
* application code.
|
|
287
|
+
*
|
|
288
|
+
* @param value - Either a literal value or builder callback:
|
|
289
|
+
* - Literal: Any static value of the column type
|
|
290
|
+
* - `(b) => b.now()` - Database-generated timestamp
|
|
226
291
|
*
|
|
227
|
-
*
|
|
292
|
+
* @example
|
|
293
|
+
* ```ts
|
|
294
|
+
* // Static defaults
|
|
295
|
+
* column("string").defaultTo("active")
|
|
296
|
+
* column("integer").defaultTo(0)
|
|
297
|
+
* column("boolean").defaultTo(true)
|
|
298
|
+
*
|
|
299
|
+
* // Database-generated timestamp (with fallback)
|
|
300
|
+
* column("timestamp").defaultTo((b) => b.now())
|
|
301
|
+
* ```
|
|
228
302
|
*/
|
|
229
|
-
defaultTo(
|
|
230
|
-
|
|
303
|
+
defaultTo(
|
|
304
|
+
value: TypeMap[TType] | ((builder: DefaultBuilder) => DBSpecial | TypeMap[TType]),
|
|
305
|
+
): Column<TType, TIn | null, TOut> {
|
|
306
|
+
if (typeof value === "function") {
|
|
307
|
+
const fn = value as (builder: DefaultBuilder) => DBSpecial | TypeMap[TType];
|
|
308
|
+
const result = fn(defaultBuilder);
|
|
309
|
+
if (
|
|
310
|
+
typeof result === "object" &&
|
|
311
|
+
result !== null &&
|
|
312
|
+
"tag" in result &&
|
|
313
|
+
result.tag === "special"
|
|
314
|
+
) {
|
|
315
|
+
this.default = { dbSpecial: result.value };
|
|
316
|
+
} else {
|
|
317
|
+
this.default = { value: result as TypeMap[TType] };
|
|
318
|
+
}
|
|
319
|
+
} else {
|
|
320
|
+
this.default = { value };
|
|
321
|
+
}
|
|
231
322
|
return this;
|
|
232
323
|
}
|
|
233
324
|
|
|
234
325
|
/**
|
|
235
|
-
* Generate default value for the column
|
|
326
|
+
* Generate default value for the column at runtime.
|
|
327
|
+
* Used for both runtime defaults (defaultTo$) and fallback generation for
|
|
328
|
+
* database defaults (defaultTo) when the database doesn't support them.
|
|
236
329
|
*/
|
|
237
330
|
generateDefaultValue(): TypeMap[TType] | undefined {
|
|
238
331
|
if (!this.default) {
|
|
@@ -242,13 +335,24 @@ export class Column<TType extends keyof TypeMap, TIn = unknown, TOut = unknown>
|
|
|
242
335
|
if ("value" in this.default) {
|
|
243
336
|
return this.default.value;
|
|
244
337
|
}
|
|
245
|
-
|
|
338
|
+
|
|
339
|
+
if ("dbSpecial" in this.default) {
|
|
340
|
+
// Fallback generation for database-level special functions
|
|
341
|
+
if (this.default.dbSpecial === "now") {
|
|
342
|
+
return new Date(Date.now()) as TypeMap[TType];
|
|
343
|
+
}
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Runtime defaults (defaultTo$)
|
|
348
|
+
if (this.default.runtime === "cuid") {
|
|
246
349
|
return createId() as TypeMap[TType];
|
|
247
350
|
}
|
|
248
351
|
if (this.default.runtime === "now") {
|
|
249
352
|
return new Date(Date.now()) as TypeMap[TType];
|
|
250
353
|
}
|
|
251
354
|
|
|
355
|
+
// Custom function
|
|
252
356
|
return this.default.runtime();
|
|
253
357
|
}
|
|
254
358
|
|
|
@@ -276,11 +380,15 @@ export class IdColumn<
|
|
|
276
380
|
> extends Column<TType, TIn, TOut> {
|
|
277
381
|
id = true;
|
|
278
382
|
|
|
279
|
-
override defaultTo$(
|
|
280
|
-
|
|
383
|
+
override defaultTo$(
|
|
384
|
+
value: TypeMap[TType] | ((builder: RuntimeDefaultBuilder) => RuntimeSpecial | TypeMap[TType]),
|
|
385
|
+
) {
|
|
386
|
+
return super.defaultTo$(value) as IdColumn<TType, TIn | null, TOut>;
|
|
281
387
|
}
|
|
282
388
|
|
|
283
|
-
override defaultTo(
|
|
389
|
+
override defaultTo(
|
|
390
|
+
value: TypeMap[TType] | ((builder: DefaultBuilder) => DBSpecial | TypeMap[TType]),
|
|
391
|
+
) {
|
|
284
392
|
return super.defaultTo(value) as IdColumn<TType, TIn | null, TOut>;
|
|
285
393
|
}
|
|
286
394
|
}
|
|
@@ -342,7 +450,7 @@ export function referenceColumn(): Column<
|
|
|
342
450
|
export function idColumn(): IdColumn<"varchar(30)", string | FragnoId | null, FragnoId> {
|
|
343
451
|
const col = new IdColumn<"varchar(30)", string | FragnoId | null, FragnoId>("varchar(30)");
|
|
344
452
|
col.role = "external-id";
|
|
345
|
-
col.defaultTo$(
|
|
453
|
+
col.defaultTo$((b) => b.cuid());
|
|
346
454
|
return col;
|
|
347
455
|
}
|
|
348
456
|
|
package/src/schema/serialize.ts
CHANGED
|
@@ -205,7 +205,9 @@ export function schemaToDBType(
|
|
|
205
205
|
return "real";
|
|
206
206
|
default:
|
|
207
207
|
// sqlite doesn't support varchar
|
|
208
|
-
if (type.startsWith("varchar"))
|
|
208
|
+
if (type.startsWith("varchar")) {
|
|
209
|
+
return "text";
|
|
210
|
+
}
|
|
209
211
|
}
|
|
210
212
|
}
|
|
211
213
|
|
|
@@ -225,7 +227,9 @@ export function schemaToDBType(
|
|
|
225
227
|
case "json":
|
|
226
228
|
return "varchar(max)";
|
|
227
229
|
default:
|
|
228
|
-
if (type.startsWith("varchar"))
|
|
230
|
+
if (type.startsWith("varchar")) {
|
|
231
|
+
return type as `varchar(${number})`;
|
|
232
|
+
}
|
|
229
233
|
return type;
|
|
230
234
|
}
|
|
231
235
|
}
|
|
@@ -241,7 +245,9 @@ export function schemaToDBType(
|
|
|
241
245
|
case "binary":
|
|
242
246
|
return "bytea";
|
|
243
247
|
default:
|
|
244
|
-
if (type.startsWith("varchar"))
|
|
248
|
+
if (type.startsWith("varchar")) {
|
|
249
|
+
return type as `varchar(${number})`;
|
|
250
|
+
}
|
|
245
251
|
return type;
|
|
246
252
|
}
|
|
247
253
|
}
|
|
@@ -255,7 +261,9 @@ export function schemaToDBType(
|
|
|
255
261
|
case "binary":
|
|
256
262
|
return "longblob";
|
|
257
263
|
default:
|
|
258
|
-
if (type.startsWith("varchar"))
|
|
264
|
+
if (type.startsWith("varchar")) {
|
|
265
|
+
return type as `varchar(${number})`;
|
|
266
|
+
}
|
|
259
267
|
return type;
|
|
260
268
|
}
|
|
261
269
|
}
|
|
@@ -269,7 +277,9 @@ const supportJson: SQLProvider[] = ["postgresql", "cockroachdb", "mysql"];
|
|
|
269
277
|
* Parse from driver value
|
|
270
278
|
*/
|
|
271
279
|
export function deserialize(value: unknown, col: AnyColumn, provider: SQLProvider) {
|
|
272
|
-
if (value === null)
|
|
280
|
+
if (value === null) {
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
273
283
|
|
|
274
284
|
if (!supportJson.includes(provider) && col.type === "json" && typeof value === "string") {
|
|
275
285
|
return JSON.parse(value);
|
|
@@ -283,7 +293,9 @@ export function deserialize(value: unknown, col: AnyColumn, provider: SQLProvide
|
|
|
283
293
|
return new Date(value);
|
|
284
294
|
}
|
|
285
295
|
|
|
286
|
-
if (col.type === "bool" && typeof value === "number")
|
|
296
|
+
if (col.type === "bool" && typeof value === "number") {
|
|
297
|
+
return value === 1;
|
|
298
|
+
}
|
|
287
299
|
|
|
288
300
|
if (col.type === "bigint" && value instanceof Buffer) {
|
|
289
301
|
return value.readBigInt64BE(0);
|
|
@@ -342,7 +354,9 @@ export function serialize(value: unknown, col: AnyColumn, provider: SQLProvider)
|
|
|
342
354
|
return value.getTime();
|
|
343
355
|
}
|
|
344
356
|
|
|
345
|
-
if (provider === "sqlite" && typeof value === "boolean")
|
|
357
|
+
if (provider === "sqlite" && typeof value === "boolean") {
|
|
358
|
+
return value ? 1 : 0;
|
|
359
|
+
}
|
|
346
360
|
|
|
347
361
|
if (provider === "sqlite" && typeof value === "bigint") {
|
|
348
362
|
const buf = Buffer.alloc(8);
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { AbstractQuery } from "../query/query";
|
|
2
|
+
import { schema, idColumn, column, type FragnoId } from "../schema/create";
|
|
3
|
+
|
|
4
|
+
export const SETTINGS_TABLE_NAME = "fragno_db_settings" as const;
|
|
5
|
+
export const SETTINGS_NAMESPACE = "fragno-db-settings" as const;
|
|
6
|
+
|
|
7
|
+
export const settingsSchema = schema((s) => {
|
|
8
|
+
return s.addTable(SETTINGS_TABLE_NAME, (t) => {
|
|
9
|
+
return t
|
|
10
|
+
.addColumn("id", idColumn())
|
|
11
|
+
.addColumn("key", column("string"))
|
|
12
|
+
.addColumn("value", column("string"))
|
|
13
|
+
.createIndex("unique_key", ["key"], { unique: true });
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export function createSettingsManager(
|
|
18
|
+
// oxlint-disable-next-line no-explicit-any
|
|
19
|
+
queryEngine: AbstractQuery<typeof settingsSchema, any>,
|
|
20
|
+
namespace: string,
|
|
21
|
+
) {
|
|
22
|
+
return {
|
|
23
|
+
async get(key: string): Promise<{ id: FragnoId; key: string; value: string } | undefined> {
|
|
24
|
+
const uow = queryEngine
|
|
25
|
+
.createUnitOfWork()
|
|
26
|
+
.find(SETTINGS_TABLE_NAME, (b) =>
|
|
27
|
+
b.whereIndex("unique_key", (eb) => eb("key", "=", `${namespace}.${key}`)),
|
|
28
|
+
);
|
|
29
|
+
const [[result]] = await uow.executeRetrieve();
|
|
30
|
+
return result; // Safe: result can be undefined if key doesn't exist
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
async set(key: string, value: string) {
|
|
34
|
+
const uow = queryEngine
|
|
35
|
+
.createUnitOfWork("createSettingsManager#set")
|
|
36
|
+
.find(SETTINGS_TABLE_NAME, (b) =>
|
|
37
|
+
b.whereIndex("unique_key", (eb) => eb("key", "=", `${namespace}.${key}`)),
|
|
38
|
+
);
|
|
39
|
+
const [[existing]] = await uow.executeRetrieve();
|
|
40
|
+
|
|
41
|
+
if (existing) {
|
|
42
|
+
uow.update(SETTINGS_TABLE_NAME, existing.id, (b) => b.set({ value }).check());
|
|
43
|
+
} else {
|
|
44
|
+
uow.create(SETTINGS_TABLE_NAME, {
|
|
45
|
+
key: `${namespace}.${key}`,
|
|
46
|
+
value,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const { success } = await uow.executeMutations();
|
|
51
|
+
|
|
52
|
+
if (!success) {
|
|
53
|
+
throw new Error("Failed to set schema version");
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
async delete(id: FragnoId) {
|
|
58
|
+
await queryEngine.delete(SETTINGS_TABLE_NAME, id);
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
package/src/util/deep-equal.ts
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
// Minimal deep equal utility for primitives, arrays, and plain objects
|
|
2
2
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
3
3
|
export function deepEqual(a: any, b: any): boolean {
|
|
4
|
-
if (a === b)
|
|
5
|
-
|
|
4
|
+
if (a === b) {
|
|
5
|
+
return true;
|
|
6
|
+
}
|
|
7
|
+
if (typeof a !== typeof b) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
6
10
|
|
|
7
11
|
if (Array.isArray(a) && Array.isArray(b)) {
|
|
8
|
-
if (a.length !== b.length)
|
|
12
|
+
if (a.length !== b.length) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
9
15
|
for (let i = 0; i < a.length; i++) {
|
|
10
|
-
if (!deepEqual(a[i], b[i]))
|
|
16
|
+
if (!deepEqual(a[i], b[i])) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
11
19
|
}
|
|
12
20
|
return true;
|
|
13
21
|
}
|
|
@@ -15,11 +23,17 @@ export function deepEqual(a: any, b: any): boolean {
|
|
|
15
23
|
if (typeof a === "object" && typeof b === "object") {
|
|
16
24
|
const aKeys = Object.keys(a);
|
|
17
25
|
const bKeys = Object.keys(b);
|
|
18
|
-
if (aKeys.length !== bKeys.length)
|
|
26
|
+
if (aKeys.length !== bKeys.length) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
19
29
|
for (const key of aKeys) {
|
|
20
|
-
if (!(key in b))
|
|
30
|
+
if (!(key in b)) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
21
33
|
|
|
22
|
-
if (!Object.hasOwn(b, key) || !deepEqual(a[key], b[key]))
|
|
34
|
+
if (!Object.hasOwn(b, key) || !deepEqual(a[key], b[key])) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
23
37
|
}
|
|
24
38
|
|
|
25
39
|
return true;
|
|
@@ -17,7 +17,9 @@ export function importGenerator() {
|
|
|
17
17
|
format(): string {
|
|
18
18
|
const v: string[] = [];
|
|
19
19
|
for (const [specifier, names] of map) {
|
|
20
|
-
if (names.length === 0)
|
|
20
|
+
if (names.length === 0) {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
21
23
|
|
|
22
24
|
v.push(`import { ${names.join(", ")} } from "${specifier}"`);
|
|
23
25
|
}
|
package/src/util/parse.ts
CHANGED
|
@@ -2,7 +2,9 @@ const RegexVarchar = /^varchar\((\d+)\)$/;
|
|
|
2
2
|
|
|
3
3
|
export function parseVarchar(template: string): number {
|
|
4
4
|
const match = RegexVarchar.exec(template);
|
|
5
|
-
if (!match)
|
|
5
|
+
if (!match) {
|
|
6
|
+
throw new Error("Failed to match varchar(n)");
|
|
7
|
+
}
|
|
6
8
|
return Number(match[1]);
|
|
7
9
|
}
|
|
8
10
|
|
package/tsdown.config.ts
CHANGED
package/.turbo/turbo-test.log
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
$ vitest run
|
|
2
|
-
|
|
3
|
-
[1m[46m RUN [49m[22m [36mv3.2.4 [39m[90m/home/runner/work/fragno/fragno/packages/fragno-db[39m
|
|
4
|
-
[2mCoverage enabled with [22m[33mistanbul[39m
|
|
5
|
-
|
|
6
|
-
[32m✓[39m src/adapters/kysely/migration/execute-postgres.test.ts [2m([22m[2m50 tests[22m[2m)[22m[33m 779[2mms[22m[39m
|
|
7
|
-
[32m✓[39m src/adapters/kysely/kysely-query-builder.test.ts [2m([22m[2m83 tests[22m[2m)[22m[33m 575[2mms[22m[39m
|
|
8
|
-
[32m✓[39m src/adapters/kysely/kysely-uow-joins.test.ts [2m([22m[2m26 tests[22m[2m)[22m[33m 422[2mms[22m[39m
|
|
9
|
-
[32m✓[39m src/adapters/kysely/kysely-uow-compiler.test.ts [2m([22m[2m42 tests[22m[2m)[22m[33m 467[2mms[22m[39m
|
|
10
|
-
[32m✓[39m src/schema/create.test.ts [2m([22m[2m28 tests[22m[2m)[22m[32m 208[2mms[22m[39m
|
|
11
|
-
[32m✓[39m src/adapters/kysely/migration/execute-mysql.test.ts [2m([22m[2m36 tests[22m[2m)[22m[33m 331[2mms[22m[39m
|
|
12
|
-
[32m✓[39m src/query/unit-of-work.test.ts [2m([22m[2m30 tests[22m[2m)[22m[32m 262[2mms[22m[39m
|
|
13
|
-
[32m✓[39m src/adapters/drizzle/generate.test.ts [2m([22m[2m13 tests[22m[2m)[22m[32m 154[2mms[22m[39m
|
|
14
|
-
[32m✓[39m src/query/result-transform.test.ts [2m([22m[2m47 tests[22m[2m)[22m[32m 173[2mms[22m[39m
|
|
15
|
-
[32m✓[39m src/schema/serialize.test.ts [2m([22m[2m86 tests[22m[2m)[22m[32m 206[2mms[22m[39m
|
|
16
|
-
[32m✓[39m src/adapters/drizzle/drizzle-uow-compiler.test.ts [2m([22m[2m45 tests[22m[2m)[22m[33m 24852[2mms[22m[39m
|
|
17
|
-
[32m✓[39m src/adapters/kysely/kysely-adapter-pglite.test.ts [2m([22m[2m7 tests[22m[2m)[22m[33m 10686[2mms[22m[39m
|
|
18
|
-
[33m[2m✓[22m[39m KyselyAdapter PGLite[2m > [22mshould run migrations and basic queries [33m 623[2mms[22m[39m
|
|
19
|
-
[33m[2m✓[22m[39m KyselyAdapter PGLite[2m > [22mshould support many-to-many queries through junction table [33m 343[2mms[22m[39m
|
|
20
|
-
[32m✓[39m src/query/query-type.test.ts [2m([22m[2m29 tests[22m[2m)[22m[32m 29[2mms[22m[39m
|
|
21
|
-
[32m✓[39m src/query/condition-builder.test.ts [2m([22m[2m20 tests[22m[2m)[22m[32m 34[2mms[22m[39m
|
|
22
|
-
[32m✓[39m src/migration-engine/create.test.ts [2m([22m[2m20 tests[22m[2m)[22m[32m 56[2mms[22m[39m
|
|
23
|
-
[32m✓[39m src/migration-engine/auto-from-schema.test.ts [2m([22m[2m13 tests[22m[2m)[22m[32m 76[2mms[22m[39m
|
|
24
|
-
[32m✓[39m src/adapters/drizzle/drizzle-adapter-pglite.test.ts [2m([22m[2m5 tests[22m[2m)[22m[33m 8905[2mms[22m[39m
|
|
25
|
-
[32m✓[39m src/adapters/drizzle/migrate-drizzle.test.ts [2m([22m[2m1 test[22m[2m)[22m[33m 491[2mms[22m[39m
|
|
26
|
-
[32m✓[39m src/fragment.test.ts [2m([22m[2m11 tests[22m[2m)[22m[32m 57[2mms[22m[39m
|
|
27
|
-
[32m✓[39m src/query/cursor.test.ts [2m([22m[2m18 tests[22m[2m)[22m[32m 41[2mms[22m[39m
|
|
28
|
-
[32m✓[39m src/query/unit-of-work-types.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m 37[2mms[22m[39m
|
|
29
|
-
[32m✓[39m src/adapters/kysely/migration/kysely-migrator.test.ts [2m([22m[2m9 tests[22m[2m)[22m[32m 142[2mms[22m[39m
|
|
30
|
-
[32m✓[39m src/adapters/drizzle/drizzle-adapter.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m 53[2mms[22m[39m
|
|
31
|
-
[32m✓[39m src/adapters/drizzle/join-column-utils.test.ts [2m([22m[2m8 tests[22m[2m)[22m[32m 23[2mms[22m[39m
|
|
32
|
-
|
|
33
|
-
[2m Test Files [22m [1m[32m24 passed[39m[22m[90m (24)[39m
|
|
34
|
-
[2m Tests [22m [1m[32m636 passed[39m[22m[90m (636)[39m
|
|
35
|
-
[2m Start at [22m 12:33:42
|
|
36
|
-
[2m Duration [22m 47.25s[2m (transform 20.15s, setup 0ms, collect 51.86s, tests 49.06s, environment 119ms, prepare 11.76s)[22m
|
|
37
|
-
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
$ tsc --noEmit
|