@lobomfz/db 0.3.1 → 0.3.3
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/package.json +1 -1
- package/src/database.ts +8 -1
- package/src/plugin.ts +57 -34
package/package.json
CHANGED
package/src/database.ts
CHANGED
|
@@ -63,6 +63,7 @@ export class Database<T extends SchemaRecord> {
|
|
|
63
63
|
private sqlite: BunDatabase;
|
|
64
64
|
|
|
65
65
|
private columns: ColumnsMap = new Map();
|
|
66
|
+
private tableColumns = new Map<string, Set<string>>();
|
|
66
67
|
|
|
67
68
|
readonly infer: TablesFromSchemas<T> = undefined as any;
|
|
68
69
|
|
|
@@ -82,7 +83,7 @@ export class Database<T extends SchemaRecord> {
|
|
|
82
83
|
|
|
83
84
|
this.kysely = new Kysely<TablesFromSchemas<T>>({
|
|
84
85
|
dialect: new BunSqliteDialect({ database: this.sqlite }),
|
|
85
|
-
plugins: [new DeserializePlugin(this.columns, validation), new ParseJSONResultsPlugin()],
|
|
86
|
+
plugins: [new DeserializePlugin(this.columns, this.tableColumns, validation), new ParseJSONResultsPlugin()],
|
|
86
87
|
});
|
|
87
88
|
}
|
|
88
89
|
|
|
@@ -264,6 +265,8 @@ export class Database<T extends SchemaRecord> {
|
|
|
264
265
|
}
|
|
265
266
|
|
|
266
267
|
private registerColumns(tableName: string, props: Prop[]) {
|
|
268
|
+
this.tableColumns.set(tableName, new Set(props.map((p) => p.key)));
|
|
269
|
+
|
|
267
270
|
const colMap = new Map<string, ColumnCoercion>();
|
|
268
271
|
|
|
269
272
|
for (const prop of props) {
|
|
@@ -365,8 +368,12 @@ export class Database<T extends SchemaRecord> {
|
|
|
365
368
|
reset(table?: keyof T & string): void {
|
|
366
369
|
const tables = table ? [table] : Object.keys(this.options.schema.tables);
|
|
367
370
|
|
|
371
|
+
this.sqlite.run("PRAGMA foreign_keys = OFF");
|
|
372
|
+
|
|
368
373
|
for (const t of tables) {
|
|
369
374
|
this.sqlite.run(`DELETE FROM "${t}"`);
|
|
370
375
|
}
|
|
376
|
+
|
|
377
|
+
this.sqlite.run("PRAGMA foreign_keys = ON");
|
|
371
378
|
}
|
|
372
379
|
}
|
package/src/plugin.ts
CHANGED
|
@@ -23,6 +23,7 @@ export class DeserializePlugin implements KyselyPlugin {
|
|
|
23
23
|
|
|
24
24
|
constructor(
|
|
25
25
|
private columns: ColumnsMap,
|
|
26
|
+
private tableColumns: Map<string, Set<string>>,
|
|
26
27
|
private validation: Required<JsonValidation>,
|
|
27
28
|
) {}
|
|
28
29
|
|
|
@@ -149,47 +150,51 @@ export class DeserializePlugin implements KyselyPlugin {
|
|
|
149
150
|
}
|
|
150
151
|
}
|
|
151
152
|
|
|
152
|
-
private
|
|
153
|
-
|
|
154
|
-
if (
|
|
155
|
-
|
|
153
|
+
private coerceSingle(table: string, row: UnknownRow, col: string, coercion: ColumnCoercion) {
|
|
154
|
+
if (coercion === "boolean") {
|
|
155
|
+
if (typeof row[col] === "number") {
|
|
156
|
+
row[col] = row[col] === 1;
|
|
156
157
|
}
|
|
157
158
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
row[col] = row[col] === 1;
|
|
161
|
-
}
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
162
161
|
|
|
163
|
-
|
|
162
|
+
if (coercion === "date") {
|
|
163
|
+
if (typeof row[col] === "number") {
|
|
164
|
+
row[col] = new Date(row[col] * 1000);
|
|
164
165
|
}
|
|
165
166
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
row[col] = new Date(row[col] * 1000);
|
|
169
|
-
}
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
170
169
|
|
|
171
|
-
|
|
172
|
-
|
|
170
|
+
if (typeof row[col] !== "string") {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
173
|
|
|
174
|
-
|
|
175
|
-
continue;
|
|
176
|
-
}
|
|
174
|
+
const value = row[col];
|
|
177
175
|
|
|
178
|
-
|
|
176
|
+
let parsed: unknown;
|
|
179
177
|
|
|
180
|
-
|
|
178
|
+
try {
|
|
179
|
+
parsed = JSON.parse(value);
|
|
180
|
+
} catch (e) {
|
|
181
|
+
throw new JsonParseError(table, col, value, e);
|
|
182
|
+
}
|
|
181
183
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
184
|
+
if (this.validation.onRead) {
|
|
185
|
+
this.validateJsonValue(table, col, parsed, coercion.schema);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
row[col] = parsed;
|
|
189
|
+
}
|
|
187
190
|
|
|
188
|
-
|
|
189
|
-
|
|
191
|
+
private coerceRow(table: string, row: UnknownRow, cols: Map<string, ColumnCoercion>) {
|
|
192
|
+
for (const [col, coercion] of cols) {
|
|
193
|
+
if (!(col in row)) {
|
|
194
|
+
continue;
|
|
190
195
|
}
|
|
191
196
|
|
|
192
|
-
row
|
|
197
|
+
this.coerceSingle(table, row, col, coercion);
|
|
193
198
|
}
|
|
194
199
|
}
|
|
195
200
|
|
|
@@ -206,14 +211,32 @@ export class DeserializePlugin implements KyselyPlugin {
|
|
|
206
211
|
return args.result;
|
|
207
212
|
}
|
|
208
213
|
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
if (!cols) {
|
|
212
|
-
return args.result;
|
|
213
|
-
}
|
|
214
|
+
const mainCols = this.columns.get(table);
|
|
215
|
+
const mainTableColumns = this.tableColumns.get(table);
|
|
214
216
|
|
|
215
217
|
for (const row of args.result.rows) {
|
|
216
|
-
|
|
218
|
+
if (mainCols) {
|
|
219
|
+
this.coerceRow(table, row, mainCols);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
for (const col of Object.keys(row)) {
|
|
223
|
+
if (mainTableColumns?.has(col)) {
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
for (const [otherTable, otherCols] of this.columns) {
|
|
228
|
+
if (otherTable === table) {
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const coercion = otherCols.get(col);
|
|
233
|
+
|
|
234
|
+
if (coercion) {
|
|
235
|
+
this.coerceSingle(otherTable, row, col, coercion);
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
217
240
|
}
|
|
218
241
|
|
|
219
242
|
return { ...args.result };
|