@revojs/storage 0.2.8 → 0.2.10
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/dist/commands/generate.d.ts +1 -0
- package/dist/commands/generate.js +33 -15
- package/dist/index.d.ts +20 -3
- package/dist/index.js +109 -16
- package/dist/module/index.d.ts +13 -2
- package/dist/module/index.js +5 -2
- package/dist/plugins/index.js +12 -7
- package/dist/protocols/mysql.d.ts +7 -1
- package/dist/protocols/mysql.js +19 -3
- package/dist/protocols/postgresql.d.ts +4 -0
- package/dist/protocols/postgresql.js +10 -1
- package/dist/protocols/sqlite.d.ts +2 -1
- package/dist/protocols/sqlite.js +4 -1
- package/dist/providers/bun-sqlite.d.ts +22 -7
- package/dist/providers/bun-sqlite.js +65 -8
- package/dist/providers/d1.d.ts +2 -1
- package/dist/providers/d1.js +3 -0
- package/dist/types/index.d.ts +3 -9
- package/package.json +3 -2
|
@@ -1,45 +1,63 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import { STORAGE_CONTEXT } from "../index.js";
|
|
2
|
+
import { getContext } from "revojs";
|
|
3
3
|
import { defineCommand } from "revojs/module";
|
|
4
4
|
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "fs";
|
|
5
5
|
import { join, resolve } from "path";
|
|
6
|
-
import { loadEnv } from "vite";
|
|
7
6
|
//#region src/commands/generate.ts
|
|
8
7
|
var generate_default = defineCommand({
|
|
9
8
|
description: "Generate migration files from the storage schema",
|
|
10
9
|
arguments: { directory: {
|
|
11
10
|
type: "string",
|
|
12
11
|
short: "d",
|
|
12
|
+
default: "migrations",
|
|
13
13
|
description: "Migration output directory"
|
|
14
14
|
} },
|
|
15
|
-
async run(
|
|
16
|
-
const databases =
|
|
15
|
+
async run(scope, context) {
|
|
16
|
+
const databases = new Array();
|
|
17
|
+
const names = /* @__PURE__ */ new Set();
|
|
18
|
+
for (const files of Object.values(getContext(scope, STORAGE_CONTEXT))) for (const [name, database] of Object.entries(files)) {
|
|
19
|
+
if (names.has(name)) throw new Error("Migration database names must be unique across storage scopes.");
|
|
20
|
+
names.add(name);
|
|
21
|
+
databases.push({
|
|
22
|
+
name,
|
|
23
|
+
database
|
|
24
|
+
});
|
|
25
|
+
}
|
|
17
26
|
if (databases.length === 0) {
|
|
18
27
|
console.log("No storage databases found.");
|
|
19
28
|
return;
|
|
20
29
|
}
|
|
21
|
-
const
|
|
22
|
-
hooks: {},
|
|
23
|
-
context: { [VARIABLE_CONTEXT]: loadEnv(environment.config.mode, environment.config.envDir, "") }
|
|
24
|
-
};
|
|
25
|
-
for (const [name, load] of databases) {
|
|
26
|
-
const database = (await load())(scope);
|
|
30
|
+
for (const { name, database } of databases) {
|
|
27
31
|
const current = database.toMeta();
|
|
28
|
-
const directory = resolve(
|
|
29
|
-
|
|
32
|
+
const directory = resolve(context.arguments.directory, name);
|
|
33
|
+
let snapshot;
|
|
34
|
+
if (existsSync(directory)) {
|
|
35
|
+
const entries = readdirSync(directory).sort();
|
|
36
|
+
for (let index = entries.length - 1; index >= 0; index--) {
|
|
37
|
+
const path = join(directory, entries[index], "meta.json");
|
|
38
|
+
if (existsSync(path)) {
|
|
39
|
+
snapshot = path;
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
30
44
|
const changes = database.$migration.diff(snapshot ? JSON.parse(readFileSync(snapshot, "utf8")) : void 0, current);
|
|
31
45
|
if (changes.length === 0) {
|
|
32
46
|
console.log(`No schema changes detected for "${name}".`);
|
|
33
47
|
continue;
|
|
34
48
|
}
|
|
49
|
+
const statements = database.$migration.toSql(changes, current);
|
|
50
|
+
if (statements.length === 0) {
|
|
51
|
+
console.log(`No SQL schema changes detected for "${name}".`);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
35
54
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/\D/g, "").slice(0, 14);
|
|
36
55
|
let order = timestamp;
|
|
37
56
|
for (let index = 2; existsSync(join(directory, order)); index++) order = `${timestamp}-${index}`;
|
|
38
57
|
const target = join(directory, order);
|
|
39
|
-
const statements = database.$migration.toSql(changes, current);
|
|
40
58
|
mkdirSync(target, { recursive: true });
|
|
41
59
|
writeFileSync(join(target, "meta.json"), `${JSON.stringify(current, null, 4)}\n`);
|
|
42
|
-
writeFileSync(join(target, "migration.sql"),
|
|
60
|
+
writeFileSync(join(target, "migration.sql"), `${statements.join("\n\n")}\n`);
|
|
43
61
|
console.log(`Created migration "${name}/${order}" with ${changes.length} change(s).`);
|
|
44
62
|
}
|
|
45
63
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type Scope, type Source, type SourceScope, type SourceValue } from "revojs";
|
|
2
|
-
import type { Primitive } from "revojs/shared";
|
|
1
|
+
import { type Resolvable, type Scope, type Source, type SourceScope, type SourceValue } from "revojs";
|
|
2
|
+
import type { Awaitable, Primitive } from "revojs/shared";
|
|
3
3
|
export type DefaultValue<T> = undefined | T | (() => T);
|
|
4
4
|
export type References = undefined | (() => Column);
|
|
5
5
|
export type ReferentialAction = "cascade" | "restrict" | "no action" | "set null" | "set default";
|
|
@@ -165,6 +165,7 @@ export declare abstract class Statement<T = unknown> extends Sql<T> {
|
|
|
165
165
|
protected $session: Session;
|
|
166
166
|
protected $fields: Array<[string, Column]>;
|
|
167
167
|
constructor(session: Session, value: Table | Record<string, Column>, ...chunks: Array<Chunk>);
|
|
168
|
+
run(): unknown;
|
|
168
169
|
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
|
|
169
170
|
protected mapRow(row: Array<unknown>): Record<string, unknown>;
|
|
170
171
|
}
|
|
@@ -176,6 +177,8 @@ export declare class SelectStatement<TSelection = Table | Record<string, Column>
|
|
|
176
177
|
table: Table;
|
|
177
178
|
nullable: boolean;
|
|
178
179
|
}[];
|
|
180
|
+
protected $limit: Sql | undefined;
|
|
181
|
+
protected $offset: Sql | undefined;
|
|
179
182
|
constructor(session: Session, value: TSelection);
|
|
180
183
|
from(table: Table): this & Record<"from", never>;
|
|
181
184
|
leftJoin<TTable extends Table>(table: TTable, on: Chunk): SelectStatement<AppendToSelection<TSelection, TTable, TMode>, TMode extends "partial" ? "partial" : "multiple", AppendToNullabilityMap<TNullability, TTable, "left">>;
|
|
@@ -187,6 +190,7 @@ export declare class SelectStatement<TSelection = Table | Record<string, Column>
|
|
|
187
190
|
having(chunk: Chunk): this & Record<"having", never>;
|
|
188
191
|
orderBy(...chunks: Array<Chunk>): this & Record<"orderBy", never>;
|
|
189
192
|
limit(count: number): this & Record<"limit", never>;
|
|
193
|
+
first(): Promise<SelectResult<TSelection, TMode, TNullability> | undefined>;
|
|
190
194
|
offset(count: number): this & Record<"offset", never>;
|
|
191
195
|
protected mapRow(row: Array<unknown>): Record<string, unknown>;
|
|
192
196
|
}
|
|
@@ -220,6 +224,7 @@ export declare abstract class PreparedQuery {
|
|
|
220
224
|
abstract values(parameters: Array<Primitive>): unknown;
|
|
221
225
|
}
|
|
222
226
|
export declare abstract class Session {
|
|
227
|
+
transaction<T>(run: (session: Session) => Awaitable<T>): Promise<T>;
|
|
223
228
|
run(query: Query): unknown;
|
|
224
229
|
all(query: Query): unknown;
|
|
225
230
|
get(query: Query): unknown;
|
|
@@ -270,14 +275,17 @@ export declare abstract class Database<T extends Record<string, Table> = Record<
|
|
|
270
275
|
abstract insert<TValue extends Table>(table: TValue): InsertStatement<TValue>;
|
|
271
276
|
abstract update<TValue extends Table>(table: TValue): UpdateStatement<TValue>;
|
|
272
277
|
abstract delete<TValue extends Table>(table: TValue): DeleteStatement<TValue>;
|
|
278
|
+
abstract transaction<TResult>(run: (database: Database<T>) => Awaitable<TResult>): Promise<TResult>;
|
|
273
279
|
}
|
|
274
280
|
export declare abstract class Table<TName extends string = string, TColumns extends Record<string, Column> = Record<string, Column>> {
|
|
275
281
|
readonly $name: TName;
|
|
276
282
|
readonly $columns: TColumns;
|
|
277
283
|
readonly $definitions: Array<Definition>;
|
|
284
|
+
readonly $base: Table | undefined;
|
|
278
285
|
constructor(name: TName, columns: TColumns, definitions: Array<Definition>);
|
|
279
286
|
toMeta(): TableMeta;
|
|
280
287
|
toSql(): Sql<unknown>;
|
|
288
|
+
hasReference(reference: Table): boolean;
|
|
281
289
|
}
|
|
282
290
|
export declare abstract class Column<TDataType = unknown> {
|
|
283
291
|
$name: string;
|
|
@@ -322,7 +330,11 @@ export declare class PrimaryKeyConstraint {
|
|
|
322
330
|
export declare class ForeignKeyConstraint {
|
|
323
331
|
$columns: Array<Column>;
|
|
324
332
|
$foreignColumns: Array<Column>;
|
|
333
|
+
$onDelete: ReferentialAction | undefined;
|
|
334
|
+
$onUpdate: ReferentialAction | undefined;
|
|
325
335
|
constructor(columns: Array<Column>, foreignColumns: Array<Column>);
|
|
336
|
+
onDelete(action: ReferentialAction): this;
|
|
337
|
+
onUpdate(action: ReferentialAction): this;
|
|
326
338
|
toMeta(): ForeignKeyConstraintMeta;
|
|
327
339
|
}
|
|
328
340
|
export declare class Index {
|
|
@@ -355,6 +367,11 @@ export declare function and<T>(...chunks: Array<Chunk>): Sql<T>;
|
|
|
355
367
|
export declare function or<T>(...chunks: Array<Chunk>): Sql<T>;
|
|
356
368
|
export declare function asc<T>(chunk: Chunk): Sql<T>;
|
|
357
369
|
export declare function desc<T>(chunk: Chunk): Sql<T>;
|
|
358
|
-
export declare function
|
|
370
|
+
export declare function mergeTable<TTable extends Table, TColumns extends Record<string, Column>>(table: TTable, columns: TColumns, definitions?: (columns: TTable["$columns"] & TColumns) => Array<Definition>): TTable & TColumns & {
|
|
371
|
+
readonly $columns: TTable["$columns"] & TColumns;
|
|
372
|
+
};
|
|
373
|
+
export declare function useReferenceStorage<TSchema extends Record<string, Table>>(scope: Scope, references: TSchema): Database<TSchema>;
|
|
374
|
+
export declare function useStorageProvider<TProvider>(scope: Scope, providers: ReadonlyArray<TProvider>, getReferences: (provider: TProvider) => Record<string, Table>): TProvider;
|
|
375
|
+
export declare function useStorage<TSource extends Source<Resolvable<Awaitable<Database>>> = typeof import("#storage").default, TScope extends SourceScope<TSource> = SourceScope<TSource>>(scope: Scope, scopeName: TScope): { [TKey in SourceValue<TSource, TScope>]: Awaited<ReturnType<Awaited<ReturnType<TSource[TScope][TKey]>>>>; };
|
|
359
376
|
export declare const STORAGE_CONTEXT: import("revojs").Descriptor<Record<string, Record<string, Database<Record<string, Table<string, Record<string, Column<unknown>>>>>>>>;
|
|
360
377
|
export {};
|
package/dist/index.js
CHANGED
|
@@ -51,6 +51,9 @@ var Statement = class extends Sql {
|
|
|
51
51
|
this.$session = session;
|
|
52
52
|
this.$fields = Object.entries(value instanceof Table ? value.$columns : value);
|
|
53
53
|
}
|
|
54
|
+
run() {
|
|
55
|
+
return this.$session.run(this.toQuery());
|
|
56
|
+
}
|
|
54
57
|
async then(onfulfilled, onrejected) {
|
|
55
58
|
let value;
|
|
56
59
|
try {
|
|
@@ -75,6 +78,8 @@ var SelectStatement = class extends Statement {
|
|
|
75
78
|
$selection;
|
|
76
79
|
$baseNullable = false;
|
|
77
80
|
$joins = new Array();
|
|
81
|
+
$limit;
|
|
82
|
+
$offset;
|
|
78
83
|
constructor(session, value) {
|
|
79
84
|
super(session, value);
|
|
80
85
|
this.$value = value;
|
|
@@ -148,11 +153,18 @@ var SelectStatement = class extends Statement {
|
|
|
148
153
|
return this;
|
|
149
154
|
}
|
|
150
155
|
limit(count) {
|
|
151
|
-
this
|
|
156
|
+
this.$limit = sql`LIMIT ${new Parameter(count)}`;
|
|
157
|
+
this.push(this.$limit);
|
|
152
158
|
return this;
|
|
153
159
|
}
|
|
160
|
+
async first() {
|
|
161
|
+
const query = this.$limit ? this.toQuery() : new Sql(...this.$chunks.filter((chunk) => chunk !== this.$offset)).push(sql`LIMIT ${new Parameter(1)}`, ...this.$offset ? [this.$offset] : []).toQuery();
|
|
162
|
+
const row = await this.$session.get(query);
|
|
163
|
+
return row ? this.mapRow(row) : void 0;
|
|
164
|
+
}
|
|
154
165
|
offset(count) {
|
|
155
|
-
this
|
|
166
|
+
this.$offset = sql`OFFSET ${new Parameter(count)}`;
|
|
167
|
+
this.push(this.$offset);
|
|
156
168
|
return this;
|
|
157
169
|
}
|
|
158
170
|
mapRow(row) {
|
|
@@ -248,6 +260,9 @@ var PreparedQuery = class {
|
|
|
248
260
|
}
|
|
249
261
|
};
|
|
250
262
|
var Session = class {
|
|
263
|
+
async transaction(run) {
|
|
264
|
+
throw new Error("This storage provider does not support interactive transactions.");
|
|
265
|
+
}
|
|
251
266
|
run(query) {
|
|
252
267
|
return this.prepareQuery(query).run(query.parameters);
|
|
253
268
|
}
|
|
@@ -387,18 +402,16 @@ var Migration = class {
|
|
|
387
402
|
}
|
|
388
403
|
toCreateTableChange(change, name = change.table.name) {
|
|
389
404
|
const definitions = new Array();
|
|
390
|
-
for (const column of Object.values(change.table.columns)) {
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
}, true));
|
|
401
|
-
}
|
|
405
|
+
for (const column of Object.values(change.table.columns)) definitions.push(...this.toCreateColumnChange({
|
|
406
|
+
kind: "createColumn",
|
|
407
|
+
table: change.table.name,
|
|
408
|
+
column
|
|
409
|
+
}, true));
|
|
410
|
+
for (const column of Object.values(change.table.columns)) for (const constraint of this.columnConstraints(column)) definitions.push(...this.toCreateConstraintChange({
|
|
411
|
+
kind: "createConstraint",
|
|
412
|
+
table: change.table.name,
|
|
413
|
+
constraint
|
|
414
|
+
}, true));
|
|
402
415
|
for (const definition of change.table.definitions) if (definition.kind !== "index" && definition.kind !== "uniqueIndex") definitions.push(...this.toCreateConstraintChange({
|
|
403
416
|
kind: "createConstraint",
|
|
404
417
|
table: change.table.name,
|
|
@@ -584,6 +597,7 @@ var Table = class {
|
|
|
584
597
|
$name;
|
|
585
598
|
$columns;
|
|
586
599
|
$definitions;
|
|
600
|
+
$base;
|
|
587
601
|
constructor(name, columns, definitions) {
|
|
588
602
|
this.$name = name;
|
|
589
603
|
this.$columns = columns;
|
|
@@ -600,6 +614,15 @@ var Table = class {
|
|
|
600
614
|
toSql() {
|
|
601
615
|
return new Sql(`"${this.$name}"`);
|
|
602
616
|
}
|
|
617
|
+
hasReference(reference) {
|
|
618
|
+
if (this === reference) return true;
|
|
619
|
+
let table = this.$base;
|
|
620
|
+
while (table) {
|
|
621
|
+
if (table === reference) return true;
|
|
622
|
+
table = table.$base;
|
|
623
|
+
}
|
|
624
|
+
return false;
|
|
625
|
+
}
|
|
603
626
|
};
|
|
604
627
|
var Column = class {
|
|
605
628
|
$name;
|
|
@@ -719,10 +742,20 @@ var PrimaryKeyConstraint = class {
|
|
|
719
742
|
var ForeignKeyConstraint = class {
|
|
720
743
|
$columns;
|
|
721
744
|
$foreignColumns;
|
|
745
|
+
$onDelete;
|
|
746
|
+
$onUpdate;
|
|
722
747
|
constructor(columns, foreignColumns) {
|
|
723
748
|
this.$columns = columns;
|
|
724
749
|
this.$foreignColumns = foreignColumns;
|
|
725
750
|
}
|
|
751
|
+
onDelete(action) {
|
|
752
|
+
this.$onDelete = action;
|
|
753
|
+
return this;
|
|
754
|
+
}
|
|
755
|
+
onUpdate(action) {
|
|
756
|
+
this.$onUpdate = action;
|
|
757
|
+
return this;
|
|
758
|
+
}
|
|
726
759
|
toMeta() {
|
|
727
760
|
const foreignTables = new Set(this.$foreignColumns.map((column) => column.$table?.$name));
|
|
728
761
|
if (foreignTables.size !== 1 || foreignTables.has(void 0)) throw new Error("Foreign key columns must belong to the same table");
|
|
@@ -730,7 +763,9 @@ var ForeignKeyConstraint = class {
|
|
|
730
763
|
kind: "foreignKey",
|
|
731
764
|
columns: this.$columns.map((column) => column.$name),
|
|
732
765
|
foreignTable: [...foreignTables][0],
|
|
733
|
-
foreignColumns: this.$foreignColumns.map((column) => column.$name)
|
|
766
|
+
foreignColumns: this.$foreignColumns.map((column) => column.$name),
|
|
767
|
+
onDelete: this.$onDelete,
|
|
768
|
+
onUpdate: this.$onUpdate
|
|
734
769
|
};
|
|
735
770
|
}
|
|
736
771
|
};
|
|
@@ -830,6 +865,64 @@ function asc(chunk) {
|
|
|
830
865
|
function desc(chunk) {
|
|
831
866
|
return sql`${chunk} DESC`;
|
|
832
867
|
}
|
|
868
|
+
function mergeTable(table, columns, definitions) {
|
|
869
|
+
const mergedColumns = {};
|
|
870
|
+
const names = /* @__PURE__ */ new Set();
|
|
871
|
+
for (const [key, column] of Object.entries(table.$columns)) {
|
|
872
|
+
mergedColumns[key] = Object.assign(Object.create(Object.getPrototypeOf(column)), column);
|
|
873
|
+
names.add(column.$name);
|
|
874
|
+
}
|
|
875
|
+
for (const [key, column] of Object.entries(columns)) {
|
|
876
|
+
if (key in table) throw new Error(`Cannot replace table field "${key}" when extending "${table.$name}".`);
|
|
877
|
+
if (names.has(column.$name)) throw new Error(`Duplicate SQL column "${column.$name}" when extending "${table.$name}".`);
|
|
878
|
+
mergedColumns[key] = Object.assign(Object.create(Object.getPrototypeOf(column)), column);
|
|
879
|
+
names.add(column.$name);
|
|
880
|
+
}
|
|
881
|
+
const merged = Object.create(Object.getPrototypeOf(table));
|
|
882
|
+
Object.assign(merged, table, mergedColumns, {
|
|
883
|
+
$base: table,
|
|
884
|
+
$columns: mergedColumns,
|
|
885
|
+
$definitions: [...table.$definitions]
|
|
886
|
+
});
|
|
887
|
+
for (const column of Object.values(mergedColumns)) column.$table = merged;
|
|
888
|
+
if (definitions) merged.$definitions.push(...definitions(merged.$columns));
|
|
889
|
+
return merged;
|
|
890
|
+
}
|
|
891
|
+
function useReferenceStorage(scope, references) {
|
|
892
|
+
const tables = Object.values(references);
|
|
893
|
+
if (tables.length === 0) throw new Error("Expected at least one table reference.");
|
|
894
|
+
const databases = new Array();
|
|
895
|
+
for (const files of Object.values(getContext(scope, STORAGE_CONTEXT))) for (const database of Object.values(files)) {
|
|
896
|
+
let matches = true;
|
|
897
|
+
for (const reference of tables) {
|
|
898
|
+
let found = false;
|
|
899
|
+
for (const table of Object.values(database.$schema)) if (table.hasReference(reference)) {
|
|
900
|
+
found = true;
|
|
901
|
+
break;
|
|
902
|
+
}
|
|
903
|
+
if (!found) {
|
|
904
|
+
matches = false;
|
|
905
|
+
break;
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
if (matches) databases.push(database);
|
|
909
|
+
}
|
|
910
|
+
if (databases.length !== 1) throw new Error(`Expected one initialized storage containing tables ${tables.map((table) => `"${table.$name}"`).join(", ")}, found ${databases.length}.`);
|
|
911
|
+
for (const [key, table] of Object.entries(references)) if (!databases[0].$schema[key]?.hasReference(table)) throw new Error(`Storage schema key "${key}" does not contain the supplied table reference.`);
|
|
912
|
+
return databases[0];
|
|
913
|
+
}
|
|
914
|
+
function useStorageProvider(scope, providers, getReferences) {
|
|
915
|
+
const databases = Object.values(getContext(scope, STORAGE_CONTEXT)).flatMap((files) => Object.values(files));
|
|
916
|
+
const matches = new Array();
|
|
917
|
+
for (const provider of providers) {
|
|
918
|
+
const tables = Object.values(getReferences(provider));
|
|
919
|
+
if (tables.length === 0) throw new Error("Expected at least one table reference.");
|
|
920
|
+
for (const database of databases) if (tables.every((reference) => Object.values(database.$schema).some((table) => table.hasReference(reference)))) matches.push(provider);
|
|
921
|
+
}
|
|
922
|
+
if (matches.length !== 1) throw new Error(`Expected one initialized storage matching a provider, found ${matches.length}.`);
|
|
923
|
+
useReferenceStorage(scope, getReferences(matches[0]));
|
|
924
|
+
return matches[0];
|
|
925
|
+
}
|
|
833
926
|
function useStorage(scope, scopeName) {
|
|
834
927
|
const storages = getContext(scope, STORAGE_CONTEXT);
|
|
835
928
|
const storage = storages[scopeName] ?? {};
|
|
@@ -839,4 +932,4 @@ function useStorage(scope, scopeName) {
|
|
|
839
932
|
}
|
|
840
933
|
var STORAGE_CONTEXT = defineContext("STORAGE_CONTEXT");
|
|
841
934
|
//#endregion
|
|
842
|
-
export { CheckConstraint, Column, Database, DeleteStatement, ForeignKeyConstraint, Index, InsertStatement, Migration, Parameter, PreparedQuery, PrimaryKeyConstraint, STORAGE_CONTEXT, SelectStatement, Session, Sql, Statement, Table, UniqueConstraint, UniqueIndex, UpdateStatement, and, asc, between, combine, contains, desc, equals, exists, greater, greaterEquals, like, lower, lowerEquals, not, nullish, or, sql, toParameter, useStorage };
|
|
935
|
+
export { CheckConstraint, Column, Database, DeleteStatement, ForeignKeyConstraint, Index, InsertStatement, Migration, Parameter, PreparedQuery, PrimaryKeyConstraint, STORAGE_CONTEXT, SelectStatement, Session, Sql, Statement, Table, UniqueConstraint, UniqueIndex, UpdateStatement, and, asc, between, combine, contains, desc, equals, exists, greater, greaterEquals, like, lower, lowerEquals, mergeTable, not, nullish, or, sql, toParameter, useReferenceStorage, useStorage, useStorageProvider };
|
package/dist/module/index.d.ts
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
declare const _default: import("revojs/module").Module<"storage", {
|
|
2
|
+
storage: {
|
|
3
|
+
match: ("!**/*.d.ts" | "**/*.js" | "**/*.ts")[];
|
|
4
|
+
from: "./storage"[];
|
|
5
|
+
format: "object";
|
|
6
|
+
};
|
|
7
|
+
plugins: {
|
|
8
|
+
from: string[];
|
|
9
|
+
};
|
|
10
|
+
commands: {
|
|
11
|
+
from: string[];
|
|
12
|
+
};
|
|
13
|
+
}, []>;
|
|
3
14
|
export default _default;
|
package/dist/module/index.js
CHANGED
|
@@ -2,12 +2,15 @@ import { defineModule, useModule } from "revojs/module";
|
|
|
2
2
|
//#region src/module/index.ts
|
|
3
3
|
var module_default = defineModule({
|
|
4
4
|
name: "storage",
|
|
5
|
-
config: () => ({}),
|
|
6
5
|
setup() {
|
|
7
6
|
const { fromModule } = useModule(import.meta.url);
|
|
8
7
|
return { sources: {
|
|
9
8
|
storage: {
|
|
10
|
-
match: [
|
|
9
|
+
match: [
|
|
10
|
+
"**/*.js",
|
|
11
|
+
"**/*.ts",
|
|
12
|
+
"!**/*.d.ts"
|
|
13
|
+
],
|
|
11
14
|
from: ["./storage"],
|
|
12
15
|
format: "object"
|
|
13
16
|
},
|
package/dist/plugins/index.js
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import { STORAGE_CONTEXT } from "../index.js";
|
|
2
2
|
import { definePlugin, getContext, setContext } from "revojs";
|
|
3
|
-
import
|
|
3
|
+
import { isServer } from "#variables";
|
|
4
4
|
//#region src/plugins/index.ts
|
|
5
5
|
var plugins_default = definePlugin({ async setup(scope) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
if (isServer) {
|
|
7
|
+
const databases = getContext(scope, STORAGE_CONTEXT);
|
|
8
|
+
for (const [scopeName, files] of Object.entries((await import("#storage")).default)) {
|
|
9
|
+
const entries = databases[scopeName] ?? {};
|
|
10
|
+
for (const [name, resolve] of Object.entries(files)) {
|
|
11
|
+
if (entries[name]) continue;
|
|
12
|
+
entries[name] = await (await resolve())(scope);
|
|
13
|
+
}
|
|
14
|
+
databases[scopeName] = entries;
|
|
15
|
+
}
|
|
16
|
+
setContext(scope, STORAGE_CONTEXT, databases);
|
|
11
17
|
}
|
|
12
|
-
setContext(scope, STORAGE_CONTEXT, storages);
|
|
13
18
|
} });
|
|
14
19
|
//#endregion
|
|
15
20
|
export { plugins_default as default };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { Awaitable } from "revojs/shared";
|
|
2
|
+
import { CheckConstraint, Column, Database, DeleteStatement, ForeignKeyConstraint, Index, InsertStatement, Migration, PrimaryKeyConstraint, SelectStatement, Sql, Table, UniqueConstraint, UniqueIndex, UpdateStatement, type Definition, type DeleteConstraintChange, type DeleteIndexChange, type Session, type UpdateColumnChange } from "../index";
|
|
2
3
|
export interface CharOptions {
|
|
3
4
|
length?: number;
|
|
4
5
|
}
|
|
@@ -12,6 +13,7 @@ export interface VarcharOptions {
|
|
|
12
13
|
export declare abstract class MysqlColumn<TDataType = unknown> extends Column<TDataType> {
|
|
13
14
|
autoincrement<This extends MysqlColumn>(this: This): This & Record<"autoincrement", never>;
|
|
14
15
|
type<TData>(): this & Record<"$type", TData>;
|
|
16
|
+
toSqlName(): Sql<unknown>;
|
|
15
17
|
}
|
|
16
18
|
export declare class BigintColumn extends MysqlColumn<bigint> {
|
|
17
19
|
toSqlType(): string;
|
|
@@ -31,6 +33,8 @@ export declare class DateColumn extends MysqlColumn<Date> {
|
|
|
31
33
|
toSqlType(): string;
|
|
32
34
|
}
|
|
33
35
|
export declare class DatetimeColumn extends MysqlColumn<Date> {
|
|
36
|
+
fromDriverValue(value: unknown): Date;
|
|
37
|
+
toDriverValue(value: Date): string;
|
|
34
38
|
toSqlType(): string;
|
|
35
39
|
}
|
|
36
40
|
export declare class DecimalColumn extends MysqlColumn<string> {
|
|
@@ -124,6 +128,7 @@ export declare class MysqlUpdateStatement<T extends Table> extends UpdateStateme
|
|
|
124
128
|
export declare class MysqlDeleteStatement<T extends Table> extends DeleteStatement<T> {
|
|
125
129
|
}
|
|
126
130
|
export declare class MysqlTable<TName extends string = string, TColumns extends Record<string, MysqlColumn> = Record<string, MysqlColumn>> extends Table<TName, TColumns> {
|
|
131
|
+
toSql(): Sql<unknown>;
|
|
127
132
|
}
|
|
128
133
|
export declare class MysqlMigration extends Migration {
|
|
129
134
|
readonly $dialect = "mysql";
|
|
@@ -139,6 +144,7 @@ export declare class MysqlDatabase<T extends Record<string, MysqlTable>> extends
|
|
|
139
144
|
insert<T extends Table>(table: T): MysqlInsertStatement<T>;
|
|
140
145
|
update<T extends Table>(table: T): MysqlUpdateStatement<T>;
|
|
141
146
|
delete<T extends Table>(table: T): MysqlDeleteStatement<T>;
|
|
147
|
+
transaction<TResult>(run: (database: MysqlDatabase<T>) => Awaitable<TResult>): Promise<TResult>;
|
|
142
148
|
}
|
|
143
149
|
export declare function bigint(name: string): BigintColumn;
|
|
144
150
|
export declare function binary(name: string): BinaryColumn;
|
package/dist/protocols/mysql.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CheckConstraint, Column, Database, DeleteStatement, ForeignKeyConstraint, Index, InsertStatement, Migration, PrimaryKeyConstraint, SelectStatement, Table, UniqueConstraint, UniqueIndex, UpdateStatement } from "../index.js";
|
|
1
|
+
import { CheckConstraint, Column, Database, DeleteStatement, ForeignKeyConstraint, Index, InsertStatement, Migration, PrimaryKeyConstraint, SelectStatement, Sql, Table, UniqueConstraint, UniqueIndex, UpdateStatement } from "../index.js";
|
|
2
2
|
//#region src/protocols/mysql.ts
|
|
3
3
|
var MysqlColumn = class extends Column {
|
|
4
4
|
autoincrement() {
|
|
@@ -7,6 +7,9 @@ var MysqlColumn = class extends Column {
|
|
|
7
7
|
type() {
|
|
8
8
|
return this;
|
|
9
9
|
}
|
|
10
|
+
toSqlName() {
|
|
11
|
+
return new Sql(`\`${this.$name.replaceAll("`", "``")}\``);
|
|
12
|
+
}
|
|
10
13
|
};
|
|
11
14
|
var BigintColumn = class extends MysqlColumn {
|
|
12
15
|
toSqlType() {
|
|
@@ -39,6 +42,12 @@ var DateColumn = class extends MysqlColumn {
|
|
|
39
42
|
}
|
|
40
43
|
};
|
|
41
44
|
var DatetimeColumn = class extends MysqlColumn {
|
|
45
|
+
fromDriverValue(value) {
|
|
46
|
+
return value instanceof Date ? value : new Date(String(value).replace(/^(\d{4}-\d{2}-\d{2})[ T](\d{2}:\d{2}:\d{2}(?:\.\d+)?)$/, "$1T$2Z"));
|
|
47
|
+
}
|
|
48
|
+
toDriverValue(value) {
|
|
49
|
+
return value.toISOString().slice(0, 19).replace("T", " ");
|
|
50
|
+
}
|
|
42
51
|
toSqlType() {
|
|
43
52
|
return "datetime";
|
|
44
53
|
}
|
|
@@ -183,7 +192,11 @@ var MysqlSelectStatement = class extends SelectStatement {};
|
|
|
183
192
|
var MysqlInsertStatement = class extends InsertStatement {};
|
|
184
193
|
var MysqlUpdateStatement = class extends UpdateStatement {};
|
|
185
194
|
var MysqlDeleteStatement = class extends DeleteStatement {};
|
|
186
|
-
var MysqlTable = class extends Table {
|
|
195
|
+
var MysqlTable = class extends Table {
|
|
196
|
+
toSql() {
|
|
197
|
+
return new Sql(`\`${this.$name.replaceAll("`", "``")}\``);
|
|
198
|
+
}
|
|
199
|
+
};
|
|
187
200
|
var MysqlMigration = class extends Migration {
|
|
188
201
|
$dialect = "mysql";
|
|
189
202
|
toUpdateColumnChange(change) {
|
|
@@ -205,7 +218,7 @@ var MysqlMigration = class extends Migration {
|
|
|
205
218
|
return `\`${value.replaceAll("`", "``")}\``;
|
|
206
219
|
}
|
|
207
220
|
};
|
|
208
|
-
var MysqlDatabase = class extends Database {
|
|
221
|
+
var MysqlDatabase = class MysqlDatabase extends Database {
|
|
209
222
|
$migration;
|
|
210
223
|
constructor(session, schema) {
|
|
211
224
|
super(session, schema);
|
|
@@ -223,6 +236,9 @@ var MysqlDatabase = class extends Database {
|
|
|
223
236
|
delete(table) {
|
|
224
237
|
return new MysqlDeleteStatement(this.$session, table);
|
|
225
238
|
}
|
|
239
|
+
transaction(run) {
|
|
240
|
+
return this.$session.transaction((session) => run(new MysqlDatabase(session, this.$schema)));
|
|
241
|
+
}
|
|
226
242
|
};
|
|
227
243
|
function bigint(name) {
|
|
228
244
|
return new BigintColumn(name);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Awaitable } from "revojs/shared";
|
|
1
2
|
import { CheckConstraint, Column, Database, DeleteStatement, ForeignKeyConstraint, Index, InsertStatement, Migration, PrimaryKeyConstraint, SelectStatement, Table, UniqueConstraint, UniqueIndex, UpdateStatement, type AppendToNullabilityMap, type AppendToSelection, type Definition, type SelectMode, type Session, type Sql } from "../index";
|
|
2
3
|
export type TimestampMode = "date" | "string";
|
|
3
4
|
export interface CharOptions {
|
|
@@ -111,6 +112,8 @@ export declare class TimeColumn extends PostgresqlColumn<string> {
|
|
|
111
112
|
export declare class TimestampColumn extends PostgresqlColumn<Date> {
|
|
112
113
|
protected $options: TimestampOptions | undefined;
|
|
113
114
|
constructor(name: string, options?: TimestampOptions);
|
|
115
|
+
fromDriverValue(value: unknown): Date;
|
|
116
|
+
toDriverValue(value: Date): string;
|
|
114
117
|
toSqlType(): string;
|
|
115
118
|
}
|
|
116
119
|
export declare class UuidColumn extends PostgresqlColumn<string> {
|
|
@@ -166,6 +169,7 @@ export declare class PostgresqlDatabase<T extends Record<string, PostgresqlTable
|
|
|
166
169
|
insert<T extends Table>(table: T): PostgresqlInsertStatement<T>;
|
|
167
170
|
update<T extends Table>(table: T): PostgresqlUpdateStatement<T>;
|
|
168
171
|
delete<T extends Table>(table: T): PostgresqlDeleteStatement<T>;
|
|
172
|
+
transaction<TResult>(run: (database: PostgresqlDatabase<T>) => Awaitable<TResult>): Promise<TResult>;
|
|
169
173
|
}
|
|
170
174
|
export declare function bigint(name: string): BigintColumn;
|
|
171
175
|
export declare function bigserial(name: string): BigserialColumn;
|
|
@@ -159,6 +159,12 @@ var TimestampColumn = class extends PostgresqlColumn {
|
|
|
159
159
|
super(name);
|
|
160
160
|
this.$options = options;
|
|
161
161
|
}
|
|
162
|
+
fromDriverValue(value) {
|
|
163
|
+
return value instanceof Date ? value : new Date(String(value).replace(/^(\d{4}-\d{2}-\d{2})[ T](\d{2}:\d{2}:\d{2}(?:\.\d+)?)$/, "$1T$2Z"));
|
|
164
|
+
}
|
|
165
|
+
toDriverValue(value) {
|
|
166
|
+
return value.toISOString().replace("T", " ").replace("Z", "");
|
|
167
|
+
}
|
|
162
168
|
toSqlType() {
|
|
163
169
|
return this.$options?.precision === void 0 ? "timestamp" : `timestamp(${this.$options.precision})`;
|
|
164
170
|
}
|
|
@@ -245,7 +251,7 @@ var PostgresqlMigration = class extends Migration {
|
|
|
245
251
|
return `"${value.replaceAll("\"", "\"\"")}"`;
|
|
246
252
|
}
|
|
247
253
|
};
|
|
248
|
-
var PostgresqlDatabase = class extends Database {
|
|
254
|
+
var PostgresqlDatabase = class PostgresqlDatabase extends Database {
|
|
249
255
|
$migration;
|
|
250
256
|
constructor(session, schema) {
|
|
251
257
|
super(session, schema);
|
|
@@ -263,6 +269,9 @@ var PostgresqlDatabase = class extends Database {
|
|
|
263
269
|
delete(table) {
|
|
264
270
|
return new PostgresqlDeleteStatement(this.$session, table);
|
|
265
271
|
}
|
|
272
|
+
transaction(run) {
|
|
273
|
+
return this.$session.transaction((session) => run(new PostgresqlDatabase(session, this.$schema)));
|
|
274
|
+
}
|
|
266
275
|
};
|
|
267
276
|
function bigint(name) {
|
|
268
277
|
return new BigintColumn(name);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Primitive } from "revojs/shared";
|
|
1
|
+
import type { Awaitable, Primitive } from "revojs/shared";
|
|
2
2
|
import { CheckConstraint, Column, Database, DeleteStatement, ForeignKeyConstraint, Index, InsertStatement, Migration, PrimaryKeyConstraint, SelectStatement, Table, UniqueConstraint, UniqueIndex, UpdateStatement, type AppendToNullabilityMap, type AppendToSelection, type ColumnMeta, type Definition, type DeleteConstraintChange, type MigrationContext, type SelectMode, type Session, type Sql, type UpdateColumnChange } from "../index";
|
|
3
3
|
export type IntegerMode = "number" | "timestamp" | "timestamp_ms" | "boolean";
|
|
4
4
|
export type IntegerData<TMode> = TMode extends "timestamp" | "timestamp_ms" ? Date : TMode extends "boolean" ? boolean : number;
|
|
@@ -81,6 +81,7 @@ export declare class SqliteDatabase<T extends Record<string, SqliteTable>> exten
|
|
|
81
81
|
insert<T extends Table>(table: T): SqliteInsertStatement<T>;
|
|
82
82
|
update<T extends Table>(table: T): SqliteUpdateStatement<T>;
|
|
83
83
|
delete<T extends Table>(table: T): SqliteDeleteStatement<T>;
|
|
84
|
+
transaction<TResult>(run: (database: SqliteDatabase<T>) => Awaitable<TResult>): Promise<TResult>;
|
|
84
85
|
}
|
|
85
86
|
export declare function blob(name: string): BlobColumn;
|
|
86
87
|
export declare function integer<TMode extends IntegerMode = "number">(name: string, options?: IntegerOptions<TMode>): IntegerColumn<TMode>;
|
package/dist/protocols/sqlite.js
CHANGED
|
@@ -158,7 +158,7 @@ var SqliteMigration = class extends Migration {
|
|
|
158
158
|
return super.serializeLiteral(value);
|
|
159
159
|
}
|
|
160
160
|
};
|
|
161
|
-
var SqliteDatabase = class extends Database {
|
|
161
|
+
var SqliteDatabase = class SqliteDatabase extends Database {
|
|
162
162
|
$migration;
|
|
163
163
|
constructor(session, schema) {
|
|
164
164
|
super(session, schema);
|
|
@@ -176,6 +176,9 @@ var SqliteDatabase = class extends Database {
|
|
|
176
176
|
delete(table) {
|
|
177
177
|
return new SqliteDeleteStatement(this.$session, table);
|
|
178
178
|
}
|
|
179
|
+
transaction(run) {
|
|
180
|
+
return this.$session.transaction((session) => run(new SqliteDatabase(session, this.$schema)));
|
|
181
|
+
}
|
|
179
182
|
};
|
|
180
183
|
function blob(name) {
|
|
181
184
|
return new BlobColumn(name);
|
|
@@ -1,18 +1,33 @@
|
|
|
1
1
|
import type { Database, Statement } from "bun:sqlite";
|
|
2
|
-
import
|
|
2
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
3
|
+
import type { Awaitable, Primitive } from "revojs/shared";
|
|
3
4
|
import { PreparedQuery, Session, type Query } from "../index";
|
|
4
5
|
import { SqliteDatabase, type SqliteTable } from "../protocols/sqlite";
|
|
6
|
+
interface BunSqliteTransaction {
|
|
7
|
+
active: boolean;
|
|
8
|
+
}
|
|
9
|
+
interface BunSqliteConnection {
|
|
10
|
+
context: AsyncLocalStorage<BunSqliteTransaction>;
|
|
11
|
+
queue: Promise<void>;
|
|
12
|
+
error?: Error;
|
|
13
|
+
}
|
|
5
14
|
export declare class BunSqlitePreparedQuery extends PreparedQuery {
|
|
6
15
|
protected $statement: Statement;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
16
|
+
protected $session: BunSqliteSession;
|
|
17
|
+
constructor(query: Query, statement: Statement, session: BunSqliteSession);
|
|
18
|
+
run(parameters: Array<Primitive>): Promise<import("bun:sqlite").Changes>;
|
|
19
|
+
all(parameters: Array<Primitive>): Promise<(string | number | bigint | boolean | Uint8Array<ArrayBufferLike>)[][]>;
|
|
20
|
+
get(parameters: Array<Primitive>): Promise<(string | number | bigint | boolean | Uint8Array<ArrayBufferLike>)[]>;
|
|
21
|
+
values(parameters: Array<Primitive>): Promise<(string | number | bigint | boolean | Uint8Array<ArrayBufferLike>)[][]>;
|
|
12
22
|
}
|
|
13
23
|
export declare class BunSqliteSession extends Session {
|
|
14
24
|
protected $client: Database;
|
|
15
|
-
|
|
25
|
+
protected $connection: BunSqliteConnection;
|
|
26
|
+
protected $transaction: BunSqliteTransaction | undefined;
|
|
27
|
+
constructor(client: Database, transaction?: BunSqliteTransaction);
|
|
28
|
+
execute<T>(run: () => Awaitable<T>): Promise<T>;
|
|
29
|
+
transaction<T>(run: (session: Session) => Awaitable<T>): Promise<T>;
|
|
16
30
|
prepareQuery(query: Query): BunSqlitePreparedQuery;
|
|
17
31
|
}
|
|
18
32
|
export declare function bunSqlite<T extends Record<string, SqliteTable>>(client: Database, schema: T): SqliteDatabase<T>;
|
|
33
|
+
export {};
|
|
@@ -1,37 +1,94 @@
|
|
|
1
1
|
import { PreparedQuery, Session } from "../index.js";
|
|
2
2
|
import { SqliteDatabase } from "../protocols/sqlite.js";
|
|
3
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
3
4
|
//#region src/providers/bun-sqlite.ts
|
|
4
5
|
var BunSqlitePreparedQuery = class extends PreparedQuery {
|
|
5
6
|
$statement;
|
|
6
|
-
|
|
7
|
+
$session;
|
|
8
|
+
constructor(query, statement, session) {
|
|
7
9
|
super(query);
|
|
8
10
|
this.$statement = statement;
|
|
11
|
+
this.$session = session;
|
|
9
12
|
}
|
|
10
13
|
run(parameters) {
|
|
11
|
-
return this.$statement.run(...parameters);
|
|
14
|
+
return this.$session.execute(() => this.$statement.run(...parameters));
|
|
12
15
|
}
|
|
13
16
|
all(parameters) {
|
|
14
|
-
return this.$statement.values(...parameters);
|
|
17
|
+
return this.$session.execute(() => this.$statement.values(...parameters));
|
|
15
18
|
}
|
|
16
19
|
get(parameters) {
|
|
17
|
-
return this.$statement.values(...parameters)[0];
|
|
20
|
+
return this.$session.execute(() => this.$statement.values(...parameters)[0]);
|
|
18
21
|
}
|
|
19
22
|
values(parameters) {
|
|
20
|
-
return this.$statement.values(...parameters);
|
|
23
|
+
return this.$session.execute(() => this.$statement.values(...parameters));
|
|
21
24
|
}
|
|
22
25
|
};
|
|
23
|
-
var BunSqliteSession = class extends Session {
|
|
26
|
+
var BunSqliteSession = class BunSqliteSession extends Session {
|
|
24
27
|
$client;
|
|
25
|
-
|
|
28
|
+
$connection;
|
|
29
|
+
$transaction;
|
|
30
|
+
constructor(client, transaction) {
|
|
26
31
|
super();
|
|
27
32
|
this.$client = client;
|
|
33
|
+
this.$transaction = transaction;
|
|
34
|
+
const connection = connections.get(client) ?? {
|
|
35
|
+
context: new AsyncLocalStorage(),
|
|
36
|
+
queue: Promise.resolve()
|
|
37
|
+
};
|
|
38
|
+
connections.set(client, connection);
|
|
39
|
+
this.$connection = connection;
|
|
40
|
+
}
|
|
41
|
+
async execute(run) {
|
|
42
|
+
if (this.$connection.error) throw this.$connection.error;
|
|
43
|
+
const transaction = this.$transaction ?? this.$connection.context.getStore();
|
|
44
|
+
if (transaction) {
|
|
45
|
+
if (!transaction.active) throw new Error("This transaction has already completed.");
|
|
46
|
+
return run();
|
|
47
|
+
}
|
|
48
|
+
const previous = this.$connection.queue;
|
|
49
|
+
const { promise, resolve } = Promise.withResolvers();
|
|
50
|
+
this.$connection.queue = promise;
|
|
51
|
+
await previous;
|
|
52
|
+
try {
|
|
53
|
+
if (this.$connection.error) throw this.$connection.error;
|
|
54
|
+
return await run();
|
|
55
|
+
} finally {
|
|
56
|
+
resolve();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async transaction(run) {
|
|
60
|
+
if (this.$transaction || this.$connection.context.getStore()) throw new Error("Nested Bun SQLite transactions are not supported.");
|
|
61
|
+
return this.execute(async () => {
|
|
62
|
+
if (this.$client.inTransaction) throw new Error("The Bun SQLite connection already has an externally managed transaction.");
|
|
63
|
+
this.$client.run("BEGIN IMMEDIATE");
|
|
64
|
+
const transaction = { active: true };
|
|
65
|
+
try {
|
|
66
|
+
const result = await this.$connection.context.run(transaction, () => run(new BunSqliteSession(this.$client, transaction)));
|
|
67
|
+
this.$client.run("COMMIT");
|
|
68
|
+
return result;
|
|
69
|
+
} catch (error) {
|
|
70
|
+
try {
|
|
71
|
+
this.$client.run("ROLLBACK");
|
|
72
|
+
} catch (rollbackError) {
|
|
73
|
+
this.$connection.error = new AggregateError([error, rollbackError], "Bun SQLite rollback failed; this connection can no longer be used safely.");
|
|
74
|
+
throw this.$connection.error;
|
|
75
|
+
}
|
|
76
|
+
throw error;
|
|
77
|
+
} finally {
|
|
78
|
+
transaction.active = false;
|
|
79
|
+
}
|
|
80
|
+
});
|
|
28
81
|
}
|
|
29
82
|
prepareQuery(query) {
|
|
30
|
-
|
|
83
|
+
if (this.$connection.error) throw this.$connection.error;
|
|
84
|
+
const transaction = this.$transaction ?? this.$connection.context.getStore();
|
|
85
|
+
if (transaction && !transaction.active) throw new Error("This transaction has already completed.");
|
|
86
|
+
return new BunSqlitePreparedQuery(query, this.$client.prepare(query.sql), this);
|
|
31
87
|
}
|
|
32
88
|
};
|
|
33
89
|
function bunSqlite(client, schema) {
|
|
34
90
|
return new SqliteDatabase(new BunSqliteSession(client), schema);
|
|
35
91
|
}
|
|
92
|
+
var connections = /* @__PURE__ */ new WeakMap();
|
|
36
93
|
//#endregion
|
|
37
94
|
export { BunSqlitePreparedQuery, BunSqliteSession, bunSqlite };
|
package/dist/providers/d1.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { D1Database, D1DatabaseSession, D1PreparedStatement } from "@cloudflare/workers-types";
|
|
2
|
-
import type { Primitive } from "revojs/shared";
|
|
2
|
+
import type { Awaitable, Primitive } from "revojs/shared";
|
|
3
3
|
import { PreparedQuery, Session, type Query } from "../index";
|
|
4
4
|
import { SqliteDatabase, type SqliteTable } from "../protocols/sqlite";
|
|
5
5
|
export declare class D1PreparedQuery extends PreparedQuery {
|
|
@@ -13,6 +13,7 @@ export declare class D1PreparedQuery extends PreparedQuery {
|
|
|
13
13
|
export declare class D1Session extends Session {
|
|
14
14
|
protected $client: D1Database | D1DatabaseSession;
|
|
15
15
|
constructor(client: D1Database | D1DatabaseSession);
|
|
16
|
+
transaction<T>(run: (session: Session) => Awaitable<T>): Promise<T>;
|
|
16
17
|
prepareQuery(query: Query): D1PreparedQuery;
|
|
17
18
|
}
|
|
18
19
|
export declare function d1<T extends Record<string, SqliteTable>>(client: D1Database | D1DatabaseSession, schema: T): SqliteDatabase<T>;
|
package/dist/providers/d1.js
CHANGED
|
@@ -26,6 +26,9 @@ var D1Session = class extends Session {
|
|
|
26
26
|
super();
|
|
27
27
|
this.$client = client;
|
|
28
28
|
}
|
|
29
|
+
async transaction(run) {
|
|
30
|
+
throw new Error("Cloudflare D1 does not support interactive transactions; use its atomic batch API instead.");
|
|
31
|
+
}
|
|
29
32
|
prepareQuery(query) {
|
|
30
33
|
return new D1PreparedQuery(query, this.$client.prepare(query.sql));
|
|
31
34
|
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,14 +1,8 @@
|
|
|
1
|
-
declare module "#config/storage" {
|
|
2
|
-
import type { StorageConfig } from "@revojs/storage/module";
|
|
3
|
-
|
|
4
|
-
const config: StorageConfig;
|
|
5
|
-
export default config;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
1
|
declare module "#storage" {
|
|
9
2
|
import type { Database } from "../index";
|
|
10
|
-
import type {
|
|
3
|
+
import type { Resolvable, Source } from "revojs";
|
|
4
|
+
import type { Awaitable } from "revojs/shared";
|
|
11
5
|
|
|
12
|
-
const entries: Source<
|
|
6
|
+
const entries: Source<Resolvable<Awaitable<Database>>>;
|
|
13
7
|
export default entries;
|
|
14
8
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@revojs/storage",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.10",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
"scripts": {
|
|
35
35
|
"build": "vite build",
|
|
36
|
+
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
36
37
|
"watch": "vite build --watch"
|
|
37
38
|
},
|
|
38
39
|
"dependencies": {
|
|
@@ -42,7 +43,7 @@
|
|
|
42
43
|
"@revojs/tsconfig": "*"
|
|
43
44
|
},
|
|
44
45
|
"optionalDependencies": {
|
|
45
|
-
"@cloudflare/workers-types": "^5.
|
|
46
|
+
"@cloudflare/workers-types": "^5.20261009.1",
|
|
46
47
|
"@types/bun": "^1.4.2"
|
|
47
48
|
}
|
|
48
49
|
}
|