bun-query-builder 0.2.44 → 0.2.46
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/bin/cli.js +48 -19
- package/dist/browser.d.ts +11 -5
- package/dist/client.d.ts +31 -30
- package/dist/db.d.ts +36 -6
- package/dist/dynamodb-client.d.ts +57 -18
- package/dist/dynamodb-single-table.d.ts +2 -2
- package/dist/dynamodb-tooling-adapter.d.ts +7 -6
- package/dist/meta.d.ts +1 -1
- package/dist/orm.d.ts +31 -13
- package/dist/schema.d.ts +35 -21
- package/dist/seeder.d.ts +11 -1
- package/dist/sql-fragments.d.ts +1 -1
- package/dist/src/browser.js +1 -1
- package/dist/src/index.js +47 -18
- package/dist/types.d.ts +34 -20
- package/package.json +1 -1
package/dist/bin/cli.js
CHANGED
|
@@ -140,7 +140,7 @@ class BrowserQueryBuilder {
|
|
|
140
140
|
return this;
|
|
141
141
|
}
|
|
142
142
|
andWhere(column, operatorOrValue, value) {
|
|
143
|
-
return this.where(column, operatorOrValue, value);
|
|
143
|
+
return value === undefined ? this.where(column, operatorOrValue) : this.where(column, operatorOrValue, value);
|
|
144
144
|
}
|
|
145
145
|
whereNull(column) {
|
|
146
146
|
return this.where(column, "is", null);
|
|
@@ -11862,6 +11862,12 @@ import { Database } from "bun:sqlite";
|
|
|
11862
11862
|
import { mkdirSync as mkdirSync5 } from "fs";
|
|
11863
11863
|
import { dirname as dirname5 } from "path";
|
|
11864
11864
|
import process21 from "process";
|
|
11865
|
+
function toBindings(params) {
|
|
11866
|
+
return params;
|
|
11867
|
+
}
|
|
11868
|
+
function asEmbeddedValue(value) {
|
|
11869
|
+
return value !== null && typeof value === "object" ? value : null;
|
|
11870
|
+
}
|
|
11865
11871
|
function bindNumberedPlaceholders(sql, params) {
|
|
11866
11872
|
if (params.length === 0 || !/\$\d/.test(sql))
|
|
11867
11873
|
return { sql, params };
|
|
@@ -12050,11 +12056,13 @@ function createSQLiteSQL(filename) {
|
|
|
12050
12056
|
const params = [];
|
|
12051
12057
|
for (let i = 0;i < values.length; i++) {
|
|
12052
12058
|
const value = values[i];
|
|
12053
|
-
|
|
12054
|
-
|
|
12055
|
-
|
|
12056
|
-
|
|
12057
|
-
|
|
12059
|
+
const embedded = asEmbeddedValue(value);
|
|
12060
|
+
if (embedded && typeof embedded.sql === "string" && Array.isArray(embedded.values)) {
|
|
12061
|
+
sql += embedded.sql + (strings[i + 1] || "");
|
|
12062
|
+
params.push(...embedded.values);
|
|
12063
|
+
} else if (embedded && (embedded.__raw || embedded.raw)) {
|
|
12064
|
+
const raw = embedded.raw;
|
|
12065
|
+
const rawValue = embedded.__raw ? embedded.value : typeof raw === "string" ? raw : raw();
|
|
12058
12066
|
sql += rawValue + (strings[i + 1] || "");
|
|
12059
12067
|
} else if (Array.isArray(value)) {
|
|
12060
12068
|
const placeholders = value.map(() => "?").join(", ");
|
|
@@ -12072,10 +12080,10 @@ function createSQLiteSQL(filename) {
|
|
|
12072
12080
|
try {
|
|
12073
12081
|
const trimmed = sql.trim().toUpperCase();
|
|
12074
12082
|
if (trimmed.startsWith("SELECT") || trimmed.startsWith("PRAGMA") || /\bRETURNING\b/.test(trimmed)) {
|
|
12075
|
-
const result = wrapper.query(sql, params);
|
|
12083
|
+
const result = wrapper.query(sql, toBindings(params));
|
|
12076
12084
|
return Promise.resolve(result);
|
|
12077
12085
|
} else {
|
|
12078
|
-
const result = wrapper.run(sql, params);
|
|
12086
|
+
const result = wrapper.run(sql, toBindings(params));
|
|
12079
12087
|
return Promise.resolve(result);
|
|
12080
12088
|
}
|
|
12081
12089
|
} catch (error) {
|
|
@@ -12102,10 +12110,10 @@ function createSQLiteSQL(filename) {
|
|
|
12102
12110
|
try {
|
|
12103
12111
|
const trimmed = sql.trim().toUpperCase();
|
|
12104
12112
|
if (trimmed.startsWith("SELECT") || trimmed.startsWith("PRAGMA") || /\bRETURNING\b/.test(trimmed)) {
|
|
12105
|
-
const result = wrapper.query(sql, params);
|
|
12113
|
+
const result = wrapper.query(sql, toBindings(params));
|
|
12106
12114
|
return Promise.resolve(result);
|
|
12107
12115
|
} else {
|
|
12108
|
-
const result = wrapper.run(sql, params);
|
|
12116
|
+
const result = wrapper.run(sql, toBindings(params));
|
|
12109
12117
|
return Promise.resolve(result);
|
|
12110
12118
|
}
|
|
12111
12119
|
} catch (error) {
|
|
@@ -12128,7 +12136,7 @@ function createSQLiteSQL(filename) {
|
|
|
12128
12136
|
};
|
|
12129
12137
|
sqlFunction.query = (sql, params) => {
|
|
12130
12138
|
try {
|
|
12131
|
-
const result = wrapper.query(sql, params || []);
|
|
12139
|
+
const result = wrapper.query(sql, toBindings(params || []));
|
|
12132
12140
|
return Promise.resolve(result);
|
|
12133
12141
|
} catch (error) {
|
|
12134
12142
|
return Promise.reject(error);
|
|
@@ -14936,6 +14944,10 @@ function createQueryBuilder(state) {
|
|
|
14936
14944
|
built = null;
|
|
14937
14945
|
return this;
|
|
14938
14946
|
},
|
|
14947
|
+
$call(callback) {
|
|
14948
|
+
callback(this);
|
|
14949
|
+
return this;
|
|
14950
|
+
},
|
|
14939
14951
|
union(other) {
|
|
14940
14952
|
appendSetOp("UNION", other);
|
|
14941
14953
|
return this;
|
|
@@ -26784,6 +26796,18 @@ class ModelQueryBuilder {
|
|
|
26784
26796
|
return "";
|
|
26785
26797
|
return this._trashed === "only" ? `${SOFT_DELETE_COLUMN} IS NOT NULL` : `${SOFT_DELETE_COLUMN} IS NULL`;
|
|
26786
26798
|
}
|
|
26799
|
+
assertNoUnappliedClauses(method) {
|
|
26800
|
+
const ignored = [];
|
|
26801
|
+
if (this._limit !== undefined)
|
|
26802
|
+
ignored.push("limit()");
|
|
26803
|
+
if (this._offset !== undefined)
|
|
26804
|
+
ignored.push("offset()");
|
|
26805
|
+
if (this._orderBy.length > 0)
|
|
26806
|
+
ignored.push("orderBy()");
|
|
26807
|
+
if (ignored.length > 0) {
|
|
26808
|
+
throw new TypeError(`[orm] ${method}() cannot apply ${ignored.join(", ")} \u2014 an UPDATE/DELETE takes no ORDER BY or LIMIT on every supported dialect. ` + `Previously these were ignored, so the statement affected every matching row. Narrow it with where() instead.`);
|
|
26809
|
+
}
|
|
26810
|
+
}
|
|
26787
26811
|
composeWhere(params) {
|
|
26788
26812
|
const userClause = this._wheres.length > 0 ? this.buildWhereClauses(params) : "";
|
|
26789
26813
|
const sd = this.softDeleteClause();
|
|
@@ -27033,6 +27057,7 @@ class ModelQueryBuilder {
|
|
|
27033
27057
|
}
|
|
27034
27058
|
async increment(column, amount = 1) {
|
|
27035
27059
|
assertValidIdentifier(column, "increment(column)");
|
|
27060
|
+
this.assertNoUnappliedClauses("increment");
|
|
27036
27061
|
const exec = getExecutor();
|
|
27037
27062
|
const params = [amount];
|
|
27038
27063
|
const incCol = sqlColumn(column);
|
|
@@ -27041,9 +27066,9 @@ class ModelQueryBuilder {
|
|
|
27041
27066
|
sql2 += `, updated_at = ?`;
|
|
27042
27067
|
params.push(formatNow());
|
|
27043
27068
|
}
|
|
27044
|
-
|
|
27045
|
-
|
|
27046
|
-
sql2 += ` WHERE ${
|
|
27069
|
+
const whereBody = this.composeWhere(params);
|
|
27070
|
+
if (whereBody) {
|
|
27071
|
+
sql2 += ` WHERE ${whereBody}`;
|
|
27047
27072
|
}
|
|
27048
27073
|
return (await exec.run(sql2, params)).changes;
|
|
27049
27074
|
}
|
|
@@ -27142,15 +27167,18 @@ class ModelQueryBuilder {
|
|
|
27142
27167
|
return Number(await this.aggregate("SUM", column) ?? 0) || 0;
|
|
27143
27168
|
}
|
|
27144
27169
|
async delete() {
|
|
27170
|
+
this.assertNoUnappliedClauses("delete");
|
|
27145
27171
|
const exec = getExecutor();
|
|
27146
27172
|
const params = [];
|
|
27147
27173
|
let sql2 = `DELETE FROM ${this._definition.table}`;
|
|
27148
|
-
|
|
27149
|
-
|
|
27174
|
+
const whereBody = this.composeWhere(params);
|
|
27175
|
+
if (whereBody) {
|
|
27176
|
+
sql2 += ` WHERE ${whereBody}`;
|
|
27150
27177
|
}
|
|
27151
27178
|
return (await exec.run(sql2, params)).changes;
|
|
27152
27179
|
}
|
|
27153
27180
|
async update(data) {
|
|
27181
|
+
this.assertNoUnappliedClauses("update");
|
|
27154
27182
|
const exec = getExecutor();
|
|
27155
27183
|
const entries = Object.entries(data);
|
|
27156
27184
|
const sets = entries.map(([k2]) => `${sqlColumn(k2)} = ?`).join(", ");
|
|
@@ -27159,8 +27187,9 @@ class ModelQueryBuilder {
|
|
|
27159
27187
|
params.push(formatNow());
|
|
27160
27188
|
}
|
|
27161
27189
|
let sql2 = `UPDATE ${this._definition.table} SET ${sets}${timestampsEnabled(this._definition) ? ", updated_at = ?" : ""}`;
|
|
27162
|
-
|
|
27163
|
-
|
|
27190
|
+
const whereBody = this.composeWhere(params);
|
|
27191
|
+
if (whereBody) {
|
|
27192
|
+
sql2 += ` WHERE ${whereBody}`;
|
|
27164
27193
|
}
|
|
27165
27194
|
return (await exec.run(sql2, params)).changes;
|
|
27166
27195
|
}
|
|
@@ -32515,7 +32544,7 @@ function getPrefix() {
|
|
|
32515
32544
|
}
|
|
32516
32545
|
var prefix = getPrefix();
|
|
32517
32546
|
// package.json
|
|
32518
|
-
var version2 = "0.2.
|
|
32547
|
+
var version2 = "0.2.46";
|
|
32519
32548
|
|
|
32520
32549
|
// bin/cli.ts
|
|
32521
32550
|
init_actions();
|
package/dist/browser.d.ts
CHANGED
|
@@ -282,13 +282,19 @@ export declare class BrowserQueryError extends Error {
|
|
|
282
282
|
export declare class BrowserQueryBuilder<T = any> {
|
|
283
283
|
constructor(table: string);
|
|
284
284
|
select(...columns: string[]): this;
|
|
285
|
-
where(column: string,
|
|
286
|
-
|
|
287
|
-
|
|
285
|
+
where(column: string, value: unknown): this;
|
|
286
|
+
where(column: string, operator: WhereOperator, value: unknown): this;
|
|
287
|
+
where(column: string, operatorOrValue: unknown, value?: unknown): this;
|
|
288
|
+
orWhere(column: string, value: unknown): this;
|
|
289
|
+
orWhere(column: string, operator: WhereOperator, value: unknown): this;
|
|
290
|
+
orWhere(column: string, operatorOrValue: unknown, value?: unknown): this;
|
|
291
|
+
andWhere(column: string, value: unknown): this;
|
|
292
|
+
andWhere(column: string, operator: WhereOperator, value: unknown): this;
|
|
293
|
+
andWhere(column: string, operatorOrValue: unknown, value?: unknown): this;
|
|
288
294
|
whereNull(column: string): this;
|
|
289
295
|
whereNotNull(column: string): this;
|
|
290
|
-
whereIn(column: string, values:
|
|
291
|
-
whereNotIn(column: string, values:
|
|
296
|
+
whereIn(column: string, values: readonly unknown[]): this;
|
|
297
|
+
whereNotIn(column: string, values: readonly unknown[]): this;
|
|
292
298
|
orderBy(column: string, direction?: 'asc' | 'desc'): this;
|
|
293
299
|
orderByDesc(column: string): this;
|
|
294
300
|
latest(column?: string): this;
|
package/dist/client.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { config } from './config';
|
|
2
2
|
import { resetConnection } from './db';
|
|
3
|
-
import type {
|
|
3
|
+
import type { AnyDatabaseSchema } from './schema';
|
|
4
4
|
import type { DriverConnection } from './db';
|
|
5
5
|
import type { QueryHooks, SupportedDialect } from './types';
|
|
6
6
|
import type { SchemaMeta } from './meta';
|
|
@@ -50,7 +50,7 @@ export declare function raw(strings: TemplateStringsArray | string, ...values: u
|
|
|
50
50
|
*/
|
|
51
51
|
export declare function escapeStringLiteral(value: string, dialect?: SupportedDialect): string;
|
|
52
52
|
// eslint-disable-next-line pickier/no-unused-vars
|
|
53
|
-
export declare function createQueryBuilder<DB extends
|
|
53
|
+
export declare function createQueryBuilder<DB extends AnyDatabaseSchema>(state?: Partial<InternalState>): QueryBuilder<DB>;
|
|
54
54
|
/**
|
|
55
55
|
* # `clearQueryCache()`
|
|
56
56
|
*
|
|
@@ -80,7 +80,7 @@ declare interface RawExpression {
|
|
|
80
80
|
export declare interface WhereRaw {
|
|
81
81
|
raw: SqlFragment
|
|
82
82
|
}
|
|
83
|
-
export declare interface BaseSelectQueryBuilder<DB extends
|
|
83
|
+
export declare interface BaseSelectQueryBuilder<DB extends AnyDatabaseSchema, TTable extends keyof DB & string, TSelected, TJoined extends string = TTable,> {
|
|
84
84
|
distinct: () => SelectQueryBuilder<DB, TTable, TSelected, TJoined>
|
|
85
85
|
distinctOn: (...columns: (keyof DB[TTable]['columns'] & string | string)[]) => SelectQueryBuilder<DB, TTable, TSelected, TJoined>
|
|
86
86
|
selectRaw: (fragment: SqlFragment) => SelectQueryBuilder<DB, TTable, TSelected, TJoined>
|
|
@@ -108,7 +108,7 @@ export declare interface BaseSelectQueryBuilder<DB extends DatabaseSchema<any>,
|
|
|
108
108
|
orWhereGroup: (callback: (builder: SelectQueryBuilder<DB, TTable, TSelected, TJoined>) => unknown) => SelectQueryBuilder<DB, TTable, TSelected, TJoined>
|
|
109
109
|
orWhereNull: (column: keyof DB[TTable]['columns'] & string) => SelectQueryBuilder<DB, TTable, TSelected, TJoined>
|
|
110
110
|
orWhereNotNull: (column: keyof DB[TTable]['columns'] & string) => SelectQueryBuilder<DB, TTable, TSelected, TJoined>
|
|
111
|
-
orWhereBetween:
|
|
111
|
+
orWhereBetween: <K extends keyof DB[TTable]['columns'] & string>(column: K, start: DB[TTable]['columns'][K], end: DB[TTable]['columns'][K]) => SelectQueryBuilder<DB, TTable, TSelected, TJoined>
|
|
112
112
|
orWhereExists: (subquery: { toSQL: () => any }) => SelectQueryBuilder<DB, TTable, TSelected, TJoined>
|
|
113
113
|
orWhereRaw: (fragment: SqlFragment) => SelectQueryBuilder<DB, TTable, TSelected, TJoined>
|
|
114
114
|
whereAny: <K extends keyof DB[TTable]['columns'] & string>(columns: K[], op: WhereOperator, value: DB[TTable]['columns'][K]) => SelectQueryBuilder<DB, TTable, TSelected, TJoined>
|
|
@@ -180,6 +180,7 @@ export declare interface BaseSelectQueryBuilder<DB extends DatabaseSchema<any>,
|
|
|
180
180
|
}
|
|
181
181
|
selectAll?: () => SelectQueryBuilder<DB, TTable, DB[TTable]['columns'], TJoined>
|
|
182
182
|
orderByRaw: (fragment: SqlFragment) => SelectQueryBuilder<DB, TTable, TSelected, TJoined>
|
|
183
|
+
$call: (callback: (query: SelectQueryBuilder<DB, TTable, TSelected, TJoined>) => unknown) => SelectQueryBuilder<DB, TTable, TSelected, TJoined>
|
|
183
184
|
union: (other: { toSQL: () => string }) => SelectQueryBuilder<DB, TTable, TSelected, TJoined>
|
|
184
185
|
unionAll: (other: { toSQL: () => string }) => SelectQueryBuilder<DB, TTable, TSelected, TJoined>
|
|
185
186
|
forPage: (page: number, perPage: number) => SelectQueryBuilder<DB, TTable, TSelected, TJoined>
|
|
@@ -265,7 +266,7 @@ export declare interface BaseSelectQueryBuilder<DB extends DatabaseSchema<any>,
|
|
|
265
266
|
denseRank?: (alias?: string, partitionBy?: string | string[], orderBy?: [string, 'asc' | 'desc'][]) => SelectQueryBuilder<DB, TTable, TSelected, TJoined>
|
|
266
267
|
rank?: (alias?: string, partitionBy?: string | string[], orderBy?: [string, 'asc' | 'desc'][]) => SelectQueryBuilder<DB, TTable, TSelected, TJoined>
|
|
267
268
|
}
|
|
268
|
-
export declare interface InsertQueryBuilder<DB extends
|
|
269
|
+
export declare interface InsertQueryBuilder<DB extends AnyDatabaseSchema, TTable extends keyof DB & string> {
|
|
269
270
|
values: (data: Partial<DB[TTable]['columns']> | Partial<DB[TTable]['columns']>[]) => InsertQueryBuilder<DB, TTable>
|
|
270
271
|
returning: <K extends keyof DB[TTable]['columns'] & string>(...cols: K[]) => SelectQueryBuilder<DB, TTable, Pick<DB[TTable]['columns'], K>>
|
|
271
272
|
toSQL: () => string
|
|
@@ -274,7 +275,7 @@ export declare interface InsertQueryBuilder<DB extends DatabaseSchema<any>, TTab
|
|
|
274
275
|
executeTakeFirst: () => Promise<DB[TTable]['columns'] | undefined>
|
|
275
276
|
executeTakeFirstOrThrow: () => Promise<DB[TTable]['columns']>
|
|
276
277
|
}
|
|
277
|
-
export declare interface UpdateQueryBuilder<DB extends
|
|
278
|
+
export declare interface UpdateQueryBuilder<DB extends AnyDatabaseSchema, TTable extends keyof DB & string> {
|
|
278
279
|
set: (values: Partial<{ [K in keyof DB[TTable]['columns']]: DB[TTable]['columns'][K] | SqlFragment }>) => UpdateQueryBuilder<DB, TTable>
|
|
279
280
|
where: <K extends keyof DB[TTable]['columns'] & string>(
|
|
280
281
|
expr: WhereExpression<DB[TTable]['columns']> | K | SqlFragment,
|
|
@@ -290,7 +291,7 @@ export declare interface UpdateQueryBuilder<DB extends DatabaseSchema<any>, TTab
|
|
|
290
291
|
executeTakeFirst: () => Promise<{ numUpdatedRows?: number }>
|
|
291
292
|
executeTakeFirstOrThrow: () => Promise<{ numUpdatedRows: number }>
|
|
292
293
|
}
|
|
293
|
-
export declare interface DeleteQueryBuilder<DB extends
|
|
294
|
+
export declare interface DeleteQueryBuilder<DB extends AnyDatabaseSchema, TTable extends keyof DB & string> {
|
|
294
295
|
where: <K extends keyof DB[TTable]['columns'] & string>(
|
|
295
296
|
expr: WhereExpression<DB[TTable]['columns']> | K,
|
|
296
297
|
op?: WhereOperator,
|
|
@@ -305,13 +306,13 @@ export declare interface DeleteQueryBuilder<DB extends DatabaseSchema<any>, TTab
|
|
|
305
306
|
executeTakeFirst: () => Promise<{ numDeletedRows?: number }>
|
|
306
307
|
executeTakeFirstOrThrow: () => Promise<{ numDeletedRows: number }>
|
|
307
308
|
}
|
|
308
|
-
export declare interface TableQueryBuilder<DB extends
|
|
309
|
+
export declare interface TableQueryBuilder<DB extends AnyDatabaseSchema, TTable extends keyof DB & string> {
|
|
309
310
|
insert: (data: Partial<DB[TTable]['columns']> | Partial<DB[TTable]['columns']>[]) => InsertQueryBuilder<DB, TTable>
|
|
310
311
|
update: (values: Partial<DB[TTable]['columns']>) => UpdateQueryBuilder<DB, TTable>
|
|
311
312
|
delete: () => DeleteQueryBuilder<DB, TTable>
|
|
312
313
|
select: <K extends keyof DB[TTable]['columns'] & string>(...columns: K[]) => SelectQueryBuilder<DB, TTable, Pick<DB[TTable]['columns'], K>>
|
|
313
314
|
}
|
|
314
|
-
export declare interface QueryBuilder<DB extends
|
|
315
|
+
export declare interface QueryBuilder<DB extends AnyDatabaseSchema> {
|
|
315
316
|
select: {
|
|
316
317
|
<TTable extends keyof DB & string, K extends keyof DB[TTable]['columns'] & string>(
|
|
317
318
|
table: TTable,
|
|
@@ -434,25 +435,25 @@ export declare interface QueryBuilder<DB extends DatabaseSchema<any>> {
|
|
|
434
435
|
getRelationshipTarget?: (table: string, relationName: string) => string | null
|
|
435
436
|
}
|
|
436
437
|
declare interface InternalState {
|
|
437
|
-
sql:
|
|
438
|
+
sql: DriverConnection
|
|
438
439
|
meta?: SchemaMeta
|
|
439
|
-
schema?:
|
|
440
|
+
schema?: AnyDatabaseSchema
|
|
440
441
|
txDefaults?: TransactionOptions
|
|
441
442
|
hooks?: QueryHooks
|
|
442
443
|
inTransaction?: boolean
|
|
443
444
|
}
|
|
444
445
|
declare interface TxBackoff { baseMs?: number, maxMs?: number, factor?: number, jitter?: boolean }
|
|
445
|
-
declare interface TxLoggerEvent { type: 'start' | 'retry' | 'commit' | 'rollback' | 'error', attempt: number, error?:
|
|
446
|
+
declare interface TxLoggerEvent { type: 'start' | 'retry' | 'commit' | 'rollback' | 'error', attempt: number, error?: unknown, durationMs?: number }
|
|
446
447
|
export declare interface TransactionOptions {
|
|
447
448
|
retries?: number
|
|
448
449
|
isolation?: TransactionIsolation
|
|
449
|
-
onRetry?: (attempt: number, error:
|
|
450
|
+
onRetry?: (attempt: number, error: unknown) => void
|
|
450
451
|
afterCommit?: () => void
|
|
451
452
|
sqlStates?: string[]
|
|
452
453
|
backoff?: TxBackoff
|
|
453
454
|
logger?: (event: TxLoggerEvent) => void
|
|
454
455
|
readOnly?: boolean
|
|
455
|
-
onRollback?: (error:
|
|
456
|
+
onRollback?: (error: unknown) => void
|
|
456
457
|
afterRollback?: () => void
|
|
457
458
|
}
|
|
458
459
|
// Where condition helpers
|
|
@@ -497,10 +498,10 @@ export type SortDirection = 'asc' | 'desc';
|
|
|
497
498
|
*
|
|
498
499
|
* Helper type extracting a string union of column names for a given table.
|
|
499
500
|
*/
|
|
500
|
-
export type ColumnName<DB extends
|
|
501
|
+
export type ColumnName<DB extends AnyDatabaseSchema, TTable extends keyof DB & string> = keyof DB[TTable]['columns'] & string;
|
|
501
502
|
// Named row alias to improve IDE hover readability
|
|
502
|
-
export type SelectedRow<DB extends
|
|
503
|
-
declare type PrimaryKeyValue<DB extends
|
|
503
|
+
export type SelectedRow<DB extends AnyDatabaseSchema, _TTable extends keyof DB & string, TSelected,> = Readonly<TSelected>;
|
|
504
|
+
declare type PrimaryKeyValue<DB extends AnyDatabaseSchema, TTable extends keyof DB & string> = DB[TTable]['primaryKey'] extends keyof DB[TTable]['columns']
|
|
504
505
|
? DB[TTable]['columns'][DB[TTable]['primaryKey']]
|
|
505
506
|
: unknown;
|
|
506
507
|
declare type NumericColumnName<Columns> = {
|
|
@@ -508,7 +509,7 @@ declare type NumericColumnName<Columns> = {
|
|
|
508
509
|
? K
|
|
509
510
|
: Exclude<Columns[K], null | undefined> extends number ? K : never
|
|
510
511
|
}[keyof Columns & string];
|
|
511
|
-
declare type JoinColumn<DB extends
|
|
512
|
+
declare type JoinColumn<DB extends AnyDatabaseSchema, TTables extends string> = TTables extends any
|
|
512
513
|
? `${TTables}.${keyof DB[TTables]['columns'] & string}`
|
|
513
514
|
: never;
|
|
514
515
|
/**
|
|
@@ -521,20 +522,20 @@ declare type JoinColumn<DB extends DatabaseSchema<any>, TTables extends string>
|
|
|
521
522
|
* untyped schemas keep compiling. A table that declares ZERO relations
|
|
522
523
|
* yields `never` — every relation name is rejected.
|
|
523
524
|
*/
|
|
524
|
-
export type TableRelationName<DB extends
|
|
525
|
+
export type TableRelationName<DB extends AnyDatabaseSchema, TTable extends keyof DB & string> = DB[TTable] extends { relations?: infer R }
|
|
525
526
|
? unknown extends R ? string : keyof NonNullable<R> & string
|
|
526
527
|
: string;
|
|
527
|
-
declare type RelatedTableName<DB extends
|
|
528
|
+
declare type RelatedTableName<DB extends AnyDatabaseSchema, TTable extends keyof DB & string, TRelation extends TableRelationName<DB, TTable>,> = DB[TTable] extends { relations?: infer Relations }
|
|
528
529
|
? TRelation extends keyof NonNullable<Relations>
|
|
529
530
|
? Extract<NonNullable<Relations>[TRelation], keyof DB & string>
|
|
530
531
|
: keyof DB & string
|
|
531
532
|
: keyof DB & string;
|
|
532
|
-
declare type RelationQueryBuilder<DB extends
|
|
533
|
+
declare type RelationQueryBuilder<DB extends AnyDatabaseSchema, TTable extends keyof DB & string, TRelation extends TableRelationName<DB, TTable>,> = SelectQueryBuilder<
|
|
533
534
|
DB,
|
|
534
535
|
RelatedTableName<DB, TTable, TRelation>,
|
|
535
536
|
DB[RelatedTableName<DB, TTable, TRelation>]['columns']
|
|
536
537
|
>;
|
|
537
|
-
declare type RelationConstraintRecord<DB extends
|
|
538
|
+
declare type RelationConstraintRecord<DB extends AnyDatabaseSchema, TTable extends keyof DB & string> = {
|
|
538
539
|
[R in TableRelationName<DB, TTable>]: Partial<Record<R, (qb: RelationQueryBuilder<DB, TTable, R>) => unknown>>
|
|
539
540
|
}[TableRelationName<DB, TTable>];
|
|
540
541
|
/**
|
|
@@ -546,7 +547,7 @@ declare type RelationConstraintRecord<DB extends DatabaseSchema<any>, TTable ext
|
|
|
546
547
|
* relations accepts nothing (the bare `Partial<Record<never, ...>>` would be
|
|
547
548
|
* `{}`, which strings are assignable to — hence the explicit never guard).
|
|
548
549
|
*/
|
|
549
|
-
export type WithRelationArg<DB extends
|
|
550
|
+
export type WithRelationArg<DB extends AnyDatabaseSchema, TTable extends keyof DB & string> = [TableRelationName<DB, TTable>] extends [never]
|
|
550
551
|
? never
|
|
551
552
|
:
|
|
552
553
|
| TableRelationName<DB, TTable>
|
|
@@ -559,7 +560,7 @@ declare type SnakeToPascal<S extends string> = S extends `${infer H}_${infer T}`
|
|
|
559
560
|
// Typed SQL builder (type-level only). We piggy-back on the runtime builder but
|
|
560
561
|
// thread a phantom TSql string through method signatures so hovers can show the
|
|
561
562
|
// composed SQL at compile-time for common operations.
|
|
562
|
-
declare type _TypedDynamicWhereMethods<DB extends
|
|
563
|
+
declare type _TypedDynamicWhereMethods<DB extends AnyDatabaseSchema, TTable extends keyof DB & string, TSelected, TJoined extends string, TSql extends string,> = {
|
|
563
564
|
[K in keyof DB[TTable]['columns'] & string as `where${SnakeToPascal<K>}`]: (
|
|
564
565
|
value: DB[TTable]['columns'][K],
|
|
565
566
|
) => TypedSelectQueryBuilder<DB, TTable, TSelected, TJoined, `${TSql} WHERE ${K} = ?`>
|
|
@@ -577,7 +578,7 @@ declare type _TypedDynamicWhereMethods<DB extends DatabaseSchema<any>, TTable ex
|
|
|
577
578
|
// untyped variant (returning a plain SelectQueryBuilder) would win overload
|
|
578
579
|
// resolution, silently downgrading `toSQL()` from the composed literal SQL
|
|
579
580
|
// type back to `string` after any dynamic-where call.
|
|
580
|
-
export type TypedSelectQueryBuilder<DB extends
|
|
581
|
+
export type TypedSelectQueryBuilder<DB extends AnyDatabaseSchema, TTable extends keyof DB & string, TSelected, TJoined extends string = TTable, TSql extends string = `SELECT * FROM ${TTable}`,> = Omit<
|
|
581
582
|
BaseSelectQueryBuilder<DB, TTable, TSelected, TJoined>,
|
|
582
583
|
'toSQL' | 'where' | 'andWhere' | 'orWhere' | 'orderBy' | 'limit'
|
|
583
584
|
> & _TypedDynamicWhereMethods<DB, TTable, TSelected, TJoined, TSql>
|
|
@@ -616,16 +617,16 @@ export type TypedSelectQueryBuilder<DB extends DatabaseSchema<any>, TTable exten
|
|
|
616
617
|
) => TypedSelectQueryBuilder<DB, TTable, TSelected, TJoined, `${TSql} ORDER BY ${C} ${D}`>
|
|
617
618
|
limit: <N extends number>(n: N) => TypedSelectQueryBuilder<DB, TTable, TSelected, TJoined, `${TSql} LIMIT ${N}`>
|
|
618
619
|
}
|
|
619
|
-
declare type DynamicWhereMethods<DB extends
|
|
620
|
+
declare type DynamicWhereMethods<DB extends AnyDatabaseSchema, TTable extends keyof DB & string, TSelected, TJoined extends string = TTable,> = {
|
|
620
621
|
[K in keyof DB[TTable]['columns'] & string as `where${SnakeToPascal<K>}`]: (value: DB[TTable]['columns'][K]) => SelectQueryBuilder<DB, TTable, TSelected, TJoined>
|
|
621
622
|
} & {
|
|
622
623
|
[K in keyof DB[TTable]['columns'] & string as `orWhere${SnakeToPascal<K>}`]: (value: DB[TTable]['columns'][K]) => SelectQueryBuilder<DB, TTable, TSelected, TJoined>
|
|
623
624
|
} & {
|
|
624
625
|
[K in keyof DB[TTable]['columns'] & string as `andWhere${SnakeToPascal<K>}`]: (value: DB[TTable]['columns'][K]) => SelectQueryBuilder<DB, TTable, TSelected, TJoined>
|
|
625
626
|
}
|
|
626
|
-
export type SelectQueryBuilder<DB extends
|
|
627
|
+
export type SelectQueryBuilder<DB extends AnyDatabaseSchema, TTable extends keyof DB & string, TSelected, TJoined extends string = TTable,> = BaseSelectQueryBuilder<DB, TTable, TSelected, TJoined> & DynamicWhereMethods<DB, TTable, TSelected, TJoined>;
|
|
627
628
|
// Typed INSERT builder to expose a structured SQL literal in hovers
|
|
628
|
-
export type TypedInsertQueryBuilder<DB extends
|
|
629
|
+
export type TypedInsertQueryBuilder<DB extends AnyDatabaseSchema, TTable extends keyof DB & string, TSql extends string = `INSERT INTO ${TTable}`,> = Omit<InsertQueryBuilder<DB, TTable>, 'toSQL' | 'values' | 'returning'> & {
|
|
629
630
|
toSQL: () => TSql
|
|
630
631
|
values: (
|
|
631
632
|
data: Partial<DB[TTable]['columns']> | Partial<DB[TTable]['columns']>[],
|
|
@@ -642,8 +643,8 @@ export type TypedInsertQueryBuilder<DB extends DatabaseSchema<any>, TTable exten
|
|
|
642
643
|
}
|
|
643
644
|
declare type TransactionIsolation = 'read committed' | 'repeatable read' | 'serializable';
|
|
644
645
|
declare class QueryCache {
|
|
645
|
-
get(key: string):
|
|
646
|
-
set(key: string, data:
|
|
646
|
+
get<T = unknown>(key: string): T | null;
|
|
647
|
+
set(key: string, data: unknown, ttlMs: number): void;
|
|
647
648
|
clear(): void;
|
|
648
649
|
setMaxSize(size: number): void;
|
|
649
650
|
}
|
package/dist/db.d.ts
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import { Database } from 'bun:sqlite';
|
|
2
2
|
import { SQL } from 'bun';
|
|
3
|
+
import type { SQLQueryBindings } from 'bun:sqlite';
|
|
3
4
|
import type { DatabaseConfig, PoolConfig, SupportedDialect } from './types';
|
|
5
|
+
/**
|
|
6
|
+
* The one place user values become driver bindings.
|
|
7
|
+
*
|
|
8
|
+
* Everything a caller interpolates arrives as `unknown` - that is honest, we
|
|
9
|
+
* do not know what it is. bun:sqlite accepts a narrower set. The conversion is
|
|
10
|
+
* unchecked because the driver itself is the validator: it throws a clear
|
|
11
|
+
* "can't bind" for anything it cannot take, and a check here would only
|
|
12
|
+
* duplicate that rule and drift from it. Kept as one named function so the
|
|
13
|
+
* boundary is visible, rather than an `any` at each of the six call sites.
|
|
14
|
+
*/
|
|
15
|
+
export declare function toBindings(params: readonly unknown[]): SQLQueryBindings[];
|
|
16
|
+
/** A template value seen as a possible fragment; null when it is a plain bind param. */
|
|
17
|
+
export declare function asEmbeddedValue(value: unknown): EmbeddedValue | null;
|
|
4
18
|
/**
|
|
5
19
|
* SQLite wrapper that provides a SQL-like tagged template literal interface
|
|
6
20
|
* using bun:sqlite's Database class for better compiled binary support.
|
|
@@ -29,7 +43,7 @@ import type { DatabaseConfig, PoolConfig, SupportedDialect } from './types';
|
|
|
29
43
|
* numbered placeholders is returned untouched, so `?` queries and Bun's own
|
|
30
44
|
* tagged-template output are unaffected.
|
|
31
45
|
*/
|
|
32
|
-
export declare function bindNumberedPlaceholders(sql: string, params:
|
|
46
|
+
export declare function bindNumberedPlaceholders<T>(sql: string, params: T[]): { sql: string, params: T[] };
|
|
33
47
|
export declare function splitSqlStatements(sql: string): string[];
|
|
34
48
|
/**
|
|
35
49
|
* Creates a database connection string based on the configured dialect and database settings.
|
|
@@ -108,6 +122,22 @@ export declare const bunSql: SQL;
|
|
|
108
122
|
* Both Bun's native `SQL` query and our `createSQLiteSQL` wrapper satisfy this.
|
|
109
123
|
* See stacksjs/bun-query-builder#1044.
|
|
110
124
|
*/
|
|
125
|
+
/**
|
|
126
|
+
* What a value interpolated into a tagged template can turn out to be.
|
|
127
|
+
*
|
|
128
|
+
* Three things arrive here: a plain bind param, a nested query (carries `sql`
|
|
129
|
+
* plus a `values` ARRAY), and a raw-SQL marker (carries `__raw`/`raw` and no
|
|
130
|
+
* `values`). Naming the shape is what lets the branches below read properties
|
|
131
|
+
* without an `any` - and the order of those branches is load-bearing, see
|
|
132
|
+
* stacksjs/bun-query-builder#1084.
|
|
133
|
+
*/
|
|
134
|
+
export declare interface EmbeddedValue {
|
|
135
|
+
sql?: unknown
|
|
136
|
+
values?: unknown
|
|
137
|
+
__raw?: unknown
|
|
138
|
+
raw?: unknown
|
|
139
|
+
value?: unknown
|
|
140
|
+
}
|
|
111
141
|
export declare interface DriverQuery {
|
|
112
142
|
execute: () => Promise<any>
|
|
113
143
|
values?: () => any
|
|
@@ -124,10 +154,10 @@ export declare interface DriverQuery {
|
|
|
124
154
|
* casts be dropped. See stacksjs/bun-query-builder#1044.
|
|
125
155
|
*/
|
|
126
156
|
export declare interface DriverConnection {
|
|
127
|
-
(strings: TemplateStringsArray, ...values:
|
|
157
|
+
(strings: TemplateStringsArray, ...values: unknown[]): DriverQuery
|
|
128
158
|
(value: any): any
|
|
129
|
-
unsafe: (sql: string, values?:
|
|
130
|
-
query?: (sql: string, params?:
|
|
159
|
+
unsafe: (sql: string, values?: unknown[]) => AwaitableDriverQuery
|
|
160
|
+
query?: (sql: string, params?: unknown[]) => any
|
|
131
161
|
close?: () => Promise<void> | void
|
|
132
162
|
_prepareStatement?: (sql: string) => any
|
|
133
163
|
[key: string]: any
|
|
@@ -136,8 +166,8 @@ export declare interface DriverConnection {
|
|
|
136
166
|
export type AwaitableDriverQuery = DriverQuery & PromiseLike<any>;
|
|
137
167
|
declare class SQLiteWrapper {
|
|
138
168
|
constructor(filename: string);
|
|
139
|
-
query(sql: string, params?:
|
|
140
|
-
run(sql: string, params?:
|
|
169
|
+
query(sql: string, params?: SQLQueryBindings[]): any[];
|
|
170
|
+
run(sql: string, params?: SQLQueryBindings[]): any;
|
|
141
171
|
close(): void;
|
|
142
172
|
get database(): Database;
|
|
143
173
|
}
|
|
@@ -11,12 +11,31 @@ export declare function createDynamoDBItemBuilder<T = any>(options: DynamoDBQuer
|
|
|
11
11
|
* Create a DynamoDB client with fluent query builder methods
|
|
12
12
|
*/
|
|
13
13
|
export declare function createDynamoDBClient(options: DynamoDBQueryBuilderOptions): DynamoDBClientMethods;
|
|
14
|
+
/**
|
|
15
|
+
* The AWS SDK client, described by the one method this package uses.
|
|
16
|
+
*
|
|
17
|
+
* `@aws-sdk/client-dynamodb` is not a dependency (callers bring their own),
|
|
18
|
+
* so the shape is structural: anything with a `send` satisfies it, including
|
|
19
|
+
* the real `DynamoDBClient` and a test double.
|
|
20
|
+
*/
|
|
21
|
+
export declare interface DynamoDBClientLike {
|
|
22
|
+
send: (command: unknown) => Promise<unknown>
|
|
23
|
+
[key: string]: unknown
|
|
24
|
+
}
|
|
25
|
+
/** What DynamoDB reports about the capacity a call consumed. */
|
|
26
|
+
export declare interface DynamoDBConsumedCapacity {
|
|
27
|
+
TableName?: string
|
|
28
|
+
CapacityUnits?: number
|
|
29
|
+
ReadCapacityUnits?: number
|
|
30
|
+
WriteCapacityUnits?: number
|
|
31
|
+
[key: string]: unknown
|
|
32
|
+
}
|
|
14
33
|
/**
|
|
15
34
|
* DynamoDB Query Builder Options
|
|
16
35
|
*/
|
|
17
36
|
export declare interface DynamoDBQueryBuilderOptions {
|
|
18
37
|
config: DynamoDBConfig
|
|
19
|
-
client?:
|
|
38
|
+
client?: DynamoDBClientLike
|
|
20
39
|
}
|
|
21
40
|
/**
|
|
22
41
|
* Result type for DynamoDB operations
|
|
@@ -27,7 +46,7 @@ export declare interface DynamoDBResult<T = any> {
|
|
|
27
46
|
count?: number
|
|
28
47
|
scannedCount?: number
|
|
29
48
|
lastEvaluatedKey?: Record<string, any>
|
|
30
|
-
consumedCapacity?:
|
|
49
|
+
consumedCapacity?: DynamoDBConsumedCapacity
|
|
31
50
|
}
|
|
32
51
|
/**
|
|
33
52
|
* DynamoDB Client Factory
|
|
@@ -41,6 +60,26 @@ export declare interface DynamoDBClientMethods {
|
|
|
41
60
|
registerEntity: (mapping: SingleTableEntityMapping) => void
|
|
42
61
|
buildKey: (entityType: string, values: Record<string, any>) => { pk: string, sk: string }
|
|
43
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* A value DynamoDB can store or compare against.
|
|
65
|
+
*
|
|
66
|
+
* DynamoDB's type system is small and closed - scalars, binary, lists and
|
|
67
|
+
* maps - so the attribute surface below says that rather than `any`. A value
|
|
68
|
+
* outside this set could never have round-tripped through the wire format.
|
|
69
|
+
*/
|
|
70
|
+
export type DynamoDBValue = | string
|
|
71
|
+
| number
|
|
72
|
+
| boolean
|
|
73
|
+
| null
|
|
74
|
+
| Uint8Array
|
|
75
|
+
| DynamoDBValue[]
|
|
76
|
+
| { [key: string]: DynamoDBValue }
|
|
77
|
+
/** Every operator a DynamoDB filter expression accepts. */
|
|
78
|
+
export type DynamoDBFilterOperator = | DynamoDBComparisonOperator
|
|
79
|
+
| 'contains'
|
|
80
|
+
| 'attribute_exists'
|
|
81
|
+
| 'attribute_not_exists'
|
|
82
|
+
| 'IN';
|
|
44
83
|
/**
|
|
45
84
|
* DynamoDB Query Builder
|
|
46
85
|
*
|
|
@@ -51,23 +90,23 @@ export declare class DynamoDBQueryBuilder<T = any> {
|
|
|
51
90
|
table(tableName: string): this;
|
|
52
91
|
index(indexName: string): this;
|
|
53
92
|
entity(entityType: string): this;
|
|
54
|
-
whereKey(attribute: string, operator: DynamoDBComparisonOperator, value:
|
|
55
|
-
wherePartitionKey(attribute: string, value:
|
|
56
|
-
whereSortKey(attribute: string, value:
|
|
93
|
+
whereKey(attribute: string, operator: DynamoDBComparisonOperator, value: DynamoDBValue): this;
|
|
94
|
+
wherePartitionKey(attribute: string, value: DynamoDBValue): this;
|
|
95
|
+
whereSortKey(attribute: string, value: DynamoDBValue): this;
|
|
57
96
|
whereSortKeyBeginsWith(attribute: string, prefix: string): this;
|
|
58
|
-
whereSortKeyBetween(attribute: string, start:
|
|
59
|
-
where(attribute: string, operator:
|
|
60
|
-
whereEquals(attribute: string, value:
|
|
61
|
-
whereLessThan(attribute: string, value:
|
|
62
|
-
whereLessThanOrEqual(attribute: string, value:
|
|
63
|
-
whereGreaterThan(attribute: string, value:
|
|
64
|
-
whereGreaterThanOrEqual(attribute: string, value:
|
|
65
|
-
whereBetween(attribute: string, start:
|
|
97
|
+
whereSortKeyBetween(attribute: string, start: DynamoDBValue, end: DynamoDBValue): this;
|
|
98
|
+
where(attribute: string, operator: DynamoDBFilterOperator, value?: DynamoDBValue): this;
|
|
99
|
+
whereEquals(attribute: string, value: DynamoDBValue): this;
|
|
100
|
+
whereLessThan(attribute: string, value: DynamoDBValue): this;
|
|
101
|
+
whereLessThanOrEqual(attribute: string, value: DynamoDBValue): this;
|
|
102
|
+
whereGreaterThan(attribute: string, value: DynamoDBValue): this;
|
|
103
|
+
whereGreaterThanOrEqual(attribute: string, value: DynamoDBValue): this;
|
|
104
|
+
whereBetween(attribute: string, start: DynamoDBValue, end: DynamoDBValue): this;
|
|
66
105
|
whereBeginsWith(attribute: string, prefix: string): this;
|
|
67
|
-
whereContains(attribute: string, value:
|
|
106
|
+
whereContains(attribute: string, value: DynamoDBValue): this;
|
|
68
107
|
whereExists(attribute: string): this;
|
|
69
108
|
whereNotExists(attribute: string): this;
|
|
70
|
-
whereIn(attribute: string, values:
|
|
109
|
+
whereIn(attribute: string, values: DynamoDBValue[]): this;
|
|
71
110
|
select(...attributes: string[]): this;
|
|
72
111
|
limit(count: number): this;
|
|
73
112
|
ascending(): this;
|
|
@@ -93,11 +132,11 @@ export declare class DynamoDBItemBuilder<T = any> {
|
|
|
93
132
|
table(tableName: string): this;
|
|
94
133
|
key(key: Record<string, any>): this;
|
|
95
134
|
item(data: Record<string, any>): this;
|
|
96
|
-
set(attribute: string, value:
|
|
135
|
+
set(attribute: string, value: DynamoDBValue): this;
|
|
97
136
|
setMany(values: Record<string, any>): this;
|
|
98
137
|
remove(attribute: string): this;
|
|
99
|
-
add(attribute: string, value:
|
|
100
|
-
deleteFromSet(attribute: string, values:
|
|
138
|
+
add(attribute: string, value: DynamoDBValue): this;
|
|
139
|
+
deleteFromSet(attribute: string, values: DynamoDBValue): this;
|
|
101
140
|
condition(expression: string): this;
|
|
102
141
|
ifNotExists(attribute?: string): this;
|
|
103
142
|
ifExists(attribute?: string): this;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DynamoDBQueryBuilderOptions } from './dynamodb-client';
|
|
1
|
+
import type { DynamoDBFilterOperator, DynamoDBQueryBuilderOptions, DynamoDBValue } from './dynamodb-client';
|
|
2
2
|
import type { DynamoDBTableDefinition } from './drivers/dynamodb';
|
|
3
3
|
/**
|
|
4
4
|
* Create a single table manager
|
|
@@ -135,7 +135,7 @@ export declare class SingleTableQueryBuilder<T> {
|
|
|
135
135
|
whereSortKey(skData: Record<string, any>): this;
|
|
136
136
|
whereSortKeyBeginsWith(prefix: string): this;
|
|
137
137
|
useIndex(indexName: string, pkData: Record<string, any>): this;
|
|
138
|
-
where(attribute: string, operator:
|
|
138
|
+
where(attribute: string, operator: DynamoDBFilterOperator, value?: DynamoDBValue): this;
|
|
139
139
|
select(...attributes: string[]): this;
|
|
140
140
|
limit(count: number): this;
|
|
141
141
|
descending(): this;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { DynamoDBItemBuilder, DynamoDBQueryBuilder } from './dynamodb-client';
|
|
2
2
|
import { SingleTableManager, SingleTableRepository } from './dynamodb-single-table';
|
|
3
|
-
import type {
|
|
3
|
+
import type { DynamoDBClientLike } from './dynamodb-client';
|
|
4
|
+
import type { DynamoDBDriver, DynamoDBTableDefinition } from './drivers/dynamodb';
|
|
4
5
|
/**
|
|
5
6
|
* Resolve key pattern placeholders with actual values
|
|
6
7
|
*/
|
|
@@ -8,7 +9,7 @@ export declare function resolveKeyPattern(keyPatterns: KeyPatterns, data: Record
|
|
|
8
9
|
/**
|
|
9
10
|
* Parse models from configuration (stub implementation)
|
|
10
11
|
*/
|
|
11
|
-
export declare function parseStacksModels(_config:
|
|
12
|
+
export declare function parseStacksModels(_config: unknown): Promise<{ models: Map<string, ParsedModel> }>;
|
|
12
13
|
/**
|
|
13
14
|
* Convert model instance to DynamoDB item format (stub)
|
|
14
15
|
*/
|
|
@@ -63,7 +64,7 @@ export declare interface ParsedAttribute {
|
|
|
63
64
|
nullable: boolean
|
|
64
65
|
unique: boolean
|
|
65
66
|
hidden: boolean
|
|
66
|
-
defaultValue?:
|
|
67
|
+
defaultValue?: unknown
|
|
67
68
|
cast?: string
|
|
68
69
|
dynamoDbType: 'S' | 'N' | 'B' | 'BOOL' | 'NULL' | 'M' | 'L' | 'SS' | 'NS' | 'BS'
|
|
69
70
|
}
|
|
@@ -127,7 +128,7 @@ export declare interface StacksModel {
|
|
|
127
128
|
nullable?: boolean
|
|
128
129
|
unique?: boolean
|
|
129
130
|
hidden?: boolean
|
|
130
|
-
default?:
|
|
131
|
+
default?: unknown
|
|
131
132
|
cast?: string
|
|
132
133
|
validation?: { rule?: string }
|
|
133
134
|
}>
|
|
@@ -177,7 +178,7 @@ export declare interface DynamoDBToolingConfig {
|
|
|
177
178
|
*/
|
|
178
179
|
export declare class DynamoDBToolingAdapter {
|
|
179
180
|
constructor(config: DynamoDBToolingConfig);
|
|
180
|
-
setClient(client:
|
|
181
|
+
setClient(client: DynamoDBClientLike): this;
|
|
181
182
|
discoverModels(): Promise<ParsedModel[]>;
|
|
182
183
|
registerModel(model: StacksModel): ParsedModel;
|
|
183
184
|
registerParsedModel(parsed: ParsedModel): ParsedModel;
|
|
@@ -192,6 +193,6 @@ export declare class DynamoDBToolingAdapter {
|
|
|
192
193
|
parseItem<T = any>(item: Record<string, any>): { type: string, data: T } | undefined;
|
|
193
194
|
getDriver(): DynamoDBDriver;
|
|
194
195
|
getSingleTableManager(): SingleTableManager;
|
|
195
|
-
generateTableDefinition():
|
|
196
|
+
generateTableDefinition(): DynamoDBTableDefinition;
|
|
196
197
|
generateAccessPatterns(modelName: string): AccessPattern[];
|
|
197
198
|
}
|
package/dist/meta.d.ts
CHANGED
|
@@ -17,6 +17,6 @@ export declare interface SchemaMeta {
|
|
|
17
17
|
morphToMany?: Record<string, string>
|
|
18
18
|
morphedByMany?: Record<string, string>
|
|
19
19
|
}>
|
|
20
|
-
scopes?: Record<string, Record<string, (qb: any, value?:
|
|
20
|
+
scopes?: Record<string, Record<string, (qb: any, value?: unknown) => unknown>>
|
|
21
21
|
models?: ModelRecord
|
|
22
22
|
}
|
package/dist/orm.d.ts
CHANGED
|
@@ -16,18 +16,9 @@ export type {
|
|
|
16
16
|
};
|
|
17
17
|
/** Drops the `createModel` models. Paired with `clearModelRegistry()`. */
|
|
18
18
|
export declare function clearLocalModels(): void;
|
|
19
|
-
|
|
20
|
-
* Extract an affected-row count from a Bun SQL driver result.
|
|
21
|
-
*
|
|
22
|
-
* Verified against live Postgres (Bun 1.3): a non-RETURNING `UPDATE`/`DELETE`
|
|
23
|
-
* returns an empty array carrying `{ count: <affected>, affectedRows: null,
|
|
24
|
-
* command: 'UPDATE' }`. So `count` must be checked BEFORE the `Array.length`
|
|
25
|
-
* fallback (which would be 0) — see stacksjs/bun-query-builder#1032. MySQL
|
|
26
|
-
* surfaces `affectedRows` instead.
|
|
27
|
-
*/
|
|
28
|
-
export declare function extractChanges(res: any): number;
|
|
19
|
+
export declare function extractChanges(res: WriteResultLike | null | undefined): number;
|
|
29
20
|
/** Extract a generated primary key from a Bun SQL driver result. */
|
|
30
|
-
export declare function extractInsertId(res:
|
|
21
|
+
export declare function extractInsertId(res: WriteResultLike | null | undefined): number | bigint | null;
|
|
31
22
|
export declare function configureOrm(options: { database?: string | Database; verbose?: boolean }): void;
|
|
32
23
|
/**
|
|
33
24
|
* Return the underlying `bun:sqlite` Database backing the model layer.
|
|
@@ -140,8 +131,8 @@ export declare interface ModelDefinition {
|
|
|
140
131
|
readonly attributes: {
|
|
141
132
|
readonly [key: string]: TypedAttribute<unknown>
|
|
142
133
|
}
|
|
143
|
-
readonly get?: Record<string, (attributes:
|
|
144
|
-
readonly set?: Record<string, (attributes:
|
|
134
|
+
readonly get?: Record<string, (attributes: Record<string, unknown>) => unknown>
|
|
135
|
+
readonly set?: Record<string, (attributes: Record<string, unknown>) => unknown>
|
|
145
136
|
readonly scopes?: Record<string, (value: unknown) => unknown>
|
|
146
137
|
readonly indexes?: readonly object[]
|
|
147
138
|
readonly dashboard?: { readonly enabled?: boolean; readonly highlight?: boolean | number }
|
|
@@ -162,6 +153,33 @@ declare interface OrmExecutor {
|
|
|
162
153
|
insert: (sql: string, params: unknown[], primaryKey: string) => Promise<RunResult>
|
|
163
154
|
readonly sqliteDb?: Database
|
|
164
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* Extract an affected-row count from a Bun SQL driver result.
|
|
158
|
+
*
|
|
159
|
+
* Verified against live Postgres (Bun 1.3): a non-RETURNING `UPDATE`/`DELETE`
|
|
160
|
+
* returns an empty array carrying `{ count: <affected>, affectedRows: null,
|
|
161
|
+
* command: 'UPDATE' }`. So `count` must be checked BEFORE the `Array.length`
|
|
162
|
+
* fallback (which would be 0) — see stacksjs/bun-query-builder#1032. MySQL
|
|
163
|
+
* surfaces `affectedRows` instead.
|
|
164
|
+
*/
|
|
165
|
+
/**
|
|
166
|
+
* What a driver hands back after a write.
|
|
167
|
+
*
|
|
168
|
+
* Each one reports the affected count under its own name - and Postgres
|
|
169
|
+
* returns an empty array carrying `count`, so the shape is genuinely a union
|
|
170
|
+
* rather than one thing. Naming the fields beats `any`: a caller reading this
|
|
171
|
+
* type learns which drivers report what.
|
|
172
|
+
*/
|
|
173
|
+
export declare interface WriteResultLike {
|
|
174
|
+
affectedRows?: number
|
|
175
|
+
count?: number
|
|
176
|
+
changes?: number
|
|
177
|
+
lastInsertRowid?: number | bigint
|
|
178
|
+
insertId?: number | bigint
|
|
179
|
+
command?: string
|
|
180
|
+
rows?: unknown[]
|
|
181
|
+
[key: string]: unknown
|
|
182
|
+
}
|
|
165
183
|
/**
|
|
166
184
|
* Resolve a relation from its name and the parent model's definition.
|
|
167
185
|
* Uses the model registry to find the related model's definition.
|
package/dist/schema.d.ts
CHANGED
|
@@ -171,15 +171,46 @@ export declare interface ModelOptions extends Base {
|
|
|
171
171
|
morphToMany?: MorphToMany<ModelNames>
|
|
172
172
|
morphedByMany?: MorphedByMany<ModelNames>
|
|
173
173
|
scopes?: {
|
|
174
|
-
[key: string]: (value: any) =>
|
|
174
|
+
[key: string]: (value: any) => unknown
|
|
175
175
|
}
|
|
176
176
|
get?: {
|
|
177
|
-
[key: string]: (value: any) =>
|
|
177
|
+
[key: string]: (value: any) => unknown
|
|
178
178
|
}
|
|
179
179
|
set?: {
|
|
180
|
-
[key: string]: (value: any) =>
|
|
180
|
+
[key: string]: (value: any) => unknown
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* # `DatabaseSchema<Models>`
|
|
185
|
+
*
|
|
186
|
+
* Maps model definitions to a concrete database schema shape containing the
|
|
187
|
+
* table columns and primary key. This is the primary input for the query
|
|
188
|
+
* builder's type-safety.
|
|
189
|
+
*
|
|
190
|
+
* The `relations` field is type-level only (phantom): `buildDatabaseSchema`
|
|
191
|
+
* never materializes it at runtime. It maps relation names to related table
|
|
192
|
+
* names so builder methods like `.with()` can narrow their accepted relation
|
|
193
|
+
* names per table.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```ts
|
|
197
|
+
* const models = defineModels({ User, Post })
|
|
198
|
+
* type Schema = DatabaseSchema<typeof models>
|
|
199
|
+
* ```
|
|
200
|
+
*/
|
|
201
|
+
/**
|
|
202
|
+
* Any database schema, described by its shape rather than by `any`.
|
|
203
|
+
*
|
|
204
|
+
* Generic constraints throughout the client read `DB extends DatabaseSchema<any>`,
|
|
205
|
+
* which says "a schema of anything" and drags `any` into every published
|
|
206
|
+
* signature that mentions one. This says the same thing accurately: a schema
|
|
207
|
+
* is tables, each with columns, a primary key, and optionally relations.
|
|
208
|
+
*/
|
|
209
|
+
export declare interface AnySchemaTable {
|
|
210
|
+
columns: Record<string, unknown>
|
|
211
|
+
primaryKey?: unknown
|
|
212
|
+
relations?: Record<string, string> | undefined
|
|
213
|
+
}
|
|
183
214
|
/**
|
|
184
215
|
* # `ValidatorMessage`
|
|
185
216
|
*
|
|
@@ -316,24 +347,7 @@ declare type RelatedTableName<MRecord extends ModelRecord, ModelName> = ModelNam
|
|
|
316
347
|
export type InferTableRelations<M, MRecord extends ModelRecord> = {
|
|
317
348
|
[K in keyof ModelRelationsRecord<UnwrapModelDefinition<M>> & string]: RelatedTableName<MRecord, ModelRelationsRecord<UnwrapModelDefinition<M>>[K]>
|
|
318
349
|
}
|
|
319
|
-
|
|
320
|
-
* # `DatabaseSchema<Models>`
|
|
321
|
-
*
|
|
322
|
-
* Maps model definitions to a concrete database schema shape containing the
|
|
323
|
-
* table columns and primary key. This is the primary input for the query
|
|
324
|
-
* builder's type-safety.
|
|
325
|
-
*
|
|
326
|
-
* The `relations` field is type-level only (phantom): `buildDatabaseSchema`
|
|
327
|
-
* never materializes it at runtime. It maps relation names to related table
|
|
328
|
-
* names so builder methods like `.with()` can narrow their accepted relation
|
|
329
|
-
* names per table.
|
|
330
|
-
*
|
|
331
|
-
* @example
|
|
332
|
-
* ```ts
|
|
333
|
-
* const models = defineModels({ User, Post })
|
|
334
|
-
* type Schema = DatabaseSchema<typeof models>
|
|
335
|
-
* ```
|
|
336
|
-
*/
|
|
350
|
+
export type AnyDatabaseSchema = Record<string, AnySchemaTable>;
|
|
337
351
|
export type DatabaseSchema<MRecord extends ModelRecord> = {
|
|
338
352
|
[MName in keyof MRecord & string as InferTableName<UnwrapModelDefinition<MRecord[MName]>>]: {
|
|
339
353
|
columns: InferAttributes<UnwrapModelDefinition<MRecord[MName]>>
|
package/dist/seeder.d.ts
CHANGED
|
@@ -17,12 +17,22 @@ export declare interface RunSeederOptions {
|
|
|
17
17
|
class?: string
|
|
18
18
|
verbose?: boolean
|
|
19
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* The query builder handed to a seeder.
|
|
22
|
+
*
|
|
23
|
+
* A seeder is written against the app's own schema, which this base class
|
|
24
|
+
* cannot know, so the handle stays `any` deliberately - narrowing it here
|
|
25
|
+
* would reject every real seeder's typed table access. Named rather than
|
|
26
|
+
* inline so the reason travels with it.
|
|
27
|
+
*/
|
|
28
|
+
// eslint-disable-next-line ts/no-explicit-any
|
|
29
|
+
export type SeederQueryBuilder = any;
|
|
20
30
|
/**
|
|
21
31
|
* Base seeder class that all seeders should extend.
|
|
22
32
|
* Provides access to query builder and faker for generating test data.
|
|
23
33
|
*/
|
|
24
34
|
export declare abstract class Seeder {
|
|
25
|
-
abstract run(qb:
|
|
35
|
+
abstract run(qb: SeederQueryBuilder): Promise<void>;
|
|
26
36
|
get order(): number;
|
|
27
37
|
get description(): string | undefined;
|
|
28
38
|
}
|
package/dist/sql-fragments.d.ts
CHANGED
|
@@ -32,7 +32,7 @@ export declare function renderWhereTerms(terms: readonly WhereTerm[]): string;
|
|
|
32
32
|
* happened to come back empty — the same shape of silent, widening-or-narrowing
|
|
33
33
|
* failure as the `IN ()` bug itself.
|
|
34
34
|
*/
|
|
35
|
-
export declare function renderInPredicate(column: string, values:
|
|
35
|
+
export declare function renderInPredicate(column: string, values: readonly unknown[], negated: boolean, placeholders: string): string;
|
|
36
36
|
/**
|
|
37
37
|
* Rewrite `?` placeholders into the numbered form Postgres requires.
|
|
38
38
|
*
|
package/dist/src/browser.js
CHANGED
|
@@ -139,7 +139,7 @@ class BrowserQueryBuilder {
|
|
|
139
139
|
return this;
|
|
140
140
|
}
|
|
141
141
|
andWhere(column, operatorOrValue, value) {
|
|
142
|
-
return this.where(column, operatorOrValue, value);
|
|
142
|
+
return value === undefined ? this.where(column, operatorOrValue) : this.where(column, operatorOrValue, value);
|
|
143
143
|
}
|
|
144
144
|
whereNull(column) {
|
|
145
145
|
return this.where(column, "is", null);
|
package/dist/src/index.js
CHANGED
|
@@ -139,7 +139,7 @@ class BrowserQueryBuilder {
|
|
|
139
139
|
return this;
|
|
140
140
|
}
|
|
141
141
|
andWhere(column, operatorOrValue, value) {
|
|
142
|
-
return this.where(column, operatorOrValue, value);
|
|
142
|
+
return value === undefined ? this.where(column, operatorOrValue) : this.where(column, operatorOrValue, value);
|
|
143
143
|
}
|
|
144
144
|
whereNull(column) {
|
|
145
145
|
return this.where(column, "is", null);
|
|
@@ -11861,6 +11861,12 @@ import { Database } from "bun:sqlite";
|
|
|
11861
11861
|
import { mkdirSync as mkdirSync5 } from "fs";
|
|
11862
11862
|
import { dirname as dirname5 } from "path";
|
|
11863
11863
|
import process21 from "process";
|
|
11864
|
+
function toBindings(params) {
|
|
11865
|
+
return params;
|
|
11866
|
+
}
|
|
11867
|
+
function asEmbeddedValue(value) {
|
|
11868
|
+
return value !== null && typeof value === "object" ? value : null;
|
|
11869
|
+
}
|
|
11864
11870
|
function bindNumberedPlaceholders(sql, params) {
|
|
11865
11871
|
if (params.length === 0 || !/\$\d/.test(sql))
|
|
11866
11872
|
return { sql, params };
|
|
@@ -12049,11 +12055,13 @@ function createSQLiteSQL(filename) {
|
|
|
12049
12055
|
const params = [];
|
|
12050
12056
|
for (let i = 0;i < values.length; i++) {
|
|
12051
12057
|
const value = values[i];
|
|
12052
|
-
|
|
12053
|
-
|
|
12054
|
-
|
|
12055
|
-
|
|
12056
|
-
|
|
12058
|
+
const embedded = asEmbeddedValue(value);
|
|
12059
|
+
if (embedded && typeof embedded.sql === "string" && Array.isArray(embedded.values)) {
|
|
12060
|
+
sql += embedded.sql + (strings[i + 1] || "");
|
|
12061
|
+
params.push(...embedded.values);
|
|
12062
|
+
} else if (embedded && (embedded.__raw || embedded.raw)) {
|
|
12063
|
+
const raw = embedded.raw;
|
|
12064
|
+
const rawValue = embedded.__raw ? embedded.value : typeof raw === "string" ? raw : raw();
|
|
12057
12065
|
sql += rawValue + (strings[i + 1] || "");
|
|
12058
12066
|
} else if (Array.isArray(value)) {
|
|
12059
12067
|
const placeholders = value.map(() => "?").join(", ");
|
|
@@ -12071,10 +12079,10 @@ function createSQLiteSQL(filename) {
|
|
|
12071
12079
|
try {
|
|
12072
12080
|
const trimmed = sql.trim().toUpperCase();
|
|
12073
12081
|
if (trimmed.startsWith("SELECT") || trimmed.startsWith("PRAGMA") || /\bRETURNING\b/.test(trimmed)) {
|
|
12074
|
-
const result = wrapper.query(sql, params);
|
|
12082
|
+
const result = wrapper.query(sql, toBindings(params));
|
|
12075
12083
|
return Promise.resolve(result);
|
|
12076
12084
|
} else {
|
|
12077
|
-
const result = wrapper.run(sql, params);
|
|
12085
|
+
const result = wrapper.run(sql, toBindings(params));
|
|
12078
12086
|
return Promise.resolve(result);
|
|
12079
12087
|
}
|
|
12080
12088
|
} catch (error) {
|
|
@@ -12101,10 +12109,10 @@ function createSQLiteSQL(filename) {
|
|
|
12101
12109
|
try {
|
|
12102
12110
|
const trimmed = sql.trim().toUpperCase();
|
|
12103
12111
|
if (trimmed.startsWith("SELECT") || trimmed.startsWith("PRAGMA") || /\bRETURNING\b/.test(trimmed)) {
|
|
12104
|
-
const result = wrapper.query(sql, params);
|
|
12112
|
+
const result = wrapper.query(sql, toBindings(params));
|
|
12105
12113
|
return Promise.resolve(result);
|
|
12106
12114
|
} else {
|
|
12107
|
-
const result = wrapper.run(sql, params);
|
|
12115
|
+
const result = wrapper.run(sql, toBindings(params));
|
|
12108
12116
|
return Promise.resolve(result);
|
|
12109
12117
|
}
|
|
12110
12118
|
} catch (error) {
|
|
@@ -12127,7 +12135,7 @@ function createSQLiteSQL(filename) {
|
|
|
12127
12135
|
};
|
|
12128
12136
|
sqlFunction.query = (sql, params) => {
|
|
12129
12137
|
try {
|
|
12130
|
-
const result = wrapper.query(sql, params || []);
|
|
12138
|
+
const result = wrapper.query(sql, toBindings(params || []));
|
|
12131
12139
|
return Promise.resolve(result);
|
|
12132
12140
|
} catch (error) {
|
|
12133
12141
|
return Promise.reject(error);
|
|
@@ -14935,6 +14943,10 @@ function createQueryBuilder(state) {
|
|
|
14935
14943
|
built = null;
|
|
14936
14944
|
return this;
|
|
14937
14945
|
},
|
|
14946
|
+
$call(callback) {
|
|
14947
|
+
callback(this);
|
|
14948
|
+
return this;
|
|
14949
|
+
},
|
|
14938
14950
|
union(other) {
|
|
14939
14951
|
appendSetOp("UNION", other);
|
|
14940
14952
|
return this;
|
|
@@ -26783,6 +26795,18 @@ class ModelQueryBuilder {
|
|
|
26783
26795
|
return "";
|
|
26784
26796
|
return this._trashed === "only" ? `${SOFT_DELETE_COLUMN} IS NOT NULL` : `${SOFT_DELETE_COLUMN} IS NULL`;
|
|
26785
26797
|
}
|
|
26798
|
+
assertNoUnappliedClauses(method) {
|
|
26799
|
+
const ignored = [];
|
|
26800
|
+
if (this._limit !== undefined)
|
|
26801
|
+
ignored.push("limit()");
|
|
26802
|
+
if (this._offset !== undefined)
|
|
26803
|
+
ignored.push("offset()");
|
|
26804
|
+
if (this._orderBy.length > 0)
|
|
26805
|
+
ignored.push("orderBy()");
|
|
26806
|
+
if (ignored.length > 0) {
|
|
26807
|
+
throw new TypeError(`[orm] ${method}() cannot apply ${ignored.join(", ")} \u2014 an UPDATE/DELETE takes no ORDER BY or LIMIT on every supported dialect. ` + `Previously these were ignored, so the statement affected every matching row. Narrow it with where() instead.`);
|
|
26808
|
+
}
|
|
26809
|
+
}
|
|
26786
26810
|
composeWhere(params) {
|
|
26787
26811
|
const userClause = this._wheres.length > 0 ? this.buildWhereClauses(params) : "";
|
|
26788
26812
|
const sd = this.softDeleteClause();
|
|
@@ -27032,6 +27056,7 @@ class ModelQueryBuilder {
|
|
|
27032
27056
|
}
|
|
27033
27057
|
async increment(column, amount = 1) {
|
|
27034
27058
|
assertValidIdentifier(column, "increment(column)");
|
|
27059
|
+
this.assertNoUnappliedClauses("increment");
|
|
27035
27060
|
const exec = getExecutor();
|
|
27036
27061
|
const params = [amount];
|
|
27037
27062
|
const incCol = sqlColumn(column);
|
|
@@ -27040,9 +27065,9 @@ class ModelQueryBuilder {
|
|
|
27040
27065
|
sql2 += `, updated_at = ?`;
|
|
27041
27066
|
params.push(formatNow());
|
|
27042
27067
|
}
|
|
27043
|
-
|
|
27044
|
-
|
|
27045
|
-
sql2 += ` WHERE ${
|
|
27068
|
+
const whereBody = this.composeWhere(params);
|
|
27069
|
+
if (whereBody) {
|
|
27070
|
+
sql2 += ` WHERE ${whereBody}`;
|
|
27046
27071
|
}
|
|
27047
27072
|
return (await exec.run(sql2, params)).changes;
|
|
27048
27073
|
}
|
|
@@ -27141,15 +27166,18 @@ class ModelQueryBuilder {
|
|
|
27141
27166
|
return Number(await this.aggregate("SUM", column) ?? 0) || 0;
|
|
27142
27167
|
}
|
|
27143
27168
|
async delete() {
|
|
27169
|
+
this.assertNoUnappliedClauses("delete");
|
|
27144
27170
|
const exec = getExecutor();
|
|
27145
27171
|
const params = [];
|
|
27146
27172
|
let sql2 = `DELETE FROM ${this._definition.table}`;
|
|
27147
|
-
|
|
27148
|
-
|
|
27173
|
+
const whereBody = this.composeWhere(params);
|
|
27174
|
+
if (whereBody) {
|
|
27175
|
+
sql2 += ` WHERE ${whereBody}`;
|
|
27149
27176
|
}
|
|
27150
27177
|
return (await exec.run(sql2, params)).changes;
|
|
27151
27178
|
}
|
|
27152
27179
|
async update(data) {
|
|
27180
|
+
this.assertNoUnappliedClauses("update");
|
|
27153
27181
|
const exec = getExecutor();
|
|
27154
27182
|
const entries = Object.entries(data);
|
|
27155
27183
|
const sets = entries.map(([k2]) => `${sqlColumn(k2)} = ?`).join(", ");
|
|
@@ -27158,8 +27186,9 @@ class ModelQueryBuilder {
|
|
|
27158
27186
|
params.push(formatNow());
|
|
27159
27187
|
}
|
|
27160
27188
|
let sql2 = `UPDATE ${this._definition.table} SET ${sets}${timestampsEnabled(this._definition) ? ", updated_at = ?" : ""}`;
|
|
27161
|
-
|
|
27162
|
-
|
|
27189
|
+
const whereBody = this.composeWhere(params);
|
|
27190
|
+
if (whereBody) {
|
|
27191
|
+
sql2 += ` WHERE ${whereBody}`;
|
|
27163
27192
|
}
|
|
27164
27193
|
return (await exec.run(sql2, params)).changes;
|
|
27165
27194
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -134,25 +134,25 @@ export declare interface SqlConfig {
|
|
|
134
134
|
sharedLockSyntax?: 'FOR SHARE' | 'LOCK IN SHARE MODE'
|
|
135
135
|
jsonContainsMode?: 'operator' | 'function'
|
|
136
136
|
}
|
|
137
|
-
/**
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
137
|
+
/** Common fields on every query lifecycle event. */
|
|
138
|
+
export declare interface QueryEvent {
|
|
139
|
+
sql: string
|
|
140
|
+
params?: QueryParam[]
|
|
141
|
+
kind?: QueryKind
|
|
142
|
+
}
|
|
143
143
|
export declare interface QueryHooks {
|
|
144
|
-
onQueryStart?: (event:
|
|
145
|
-
onQueryEnd?: (event:
|
|
146
|
-
onQueryError?: (event:
|
|
147
|
-
startSpan?: (event:
|
|
144
|
+
onQueryStart?: (event: QueryEvent) => void
|
|
145
|
+
onQueryEnd?: (event: QueryEvent & { durationMs: number, rowCount?: number }) => void
|
|
146
|
+
onQueryError?: (event: QueryEvent & { error: unknown, durationMs: number }) => void
|
|
147
|
+
startSpan?: (event: QueryEvent) => { end: (error?: unknown) => void }
|
|
148
148
|
slowQueryThresholdMs?: number
|
|
149
|
-
onSlowQuery?: (event:
|
|
150
|
-
beforeCreate?: (event: { table: string, data:
|
|
151
|
-
afterCreate?: (event: { table: string, data:
|
|
152
|
-
beforeUpdate?: (event: { table: string, data:
|
|
153
|
-
afterUpdate?: (event: { table: string, data:
|
|
154
|
-
beforeDelete?: (event: { table: string, where?:
|
|
155
|
-
afterDelete?: (event: { table: string, where?:
|
|
149
|
+
onSlowQuery?: (event: QueryEvent & { durationMs: number }) => void
|
|
150
|
+
beforeCreate?: (event: { table: string, data: QueryRecord }) => void | Promise<void>
|
|
151
|
+
afterCreate?: (event: { table: string, data: QueryRecord, result: unknown }) => void | Promise<void>
|
|
152
|
+
beforeUpdate?: (event: { table: string, data: QueryRecord, where?: QueryWhere }) => void | Promise<void>
|
|
153
|
+
afterUpdate?: (event: { table: string, data: QueryRecord, where?: QueryWhere, result: unknown }) => void | Promise<void>
|
|
154
|
+
beforeDelete?: (event: { table: string, where?: QueryWhere }) => void | Promise<void>
|
|
155
|
+
afterDelete?: (event: { table: string, where?: QueryWhere, result: unknown }) => void | Promise<void>
|
|
156
156
|
}
|
|
157
157
|
/**
|
|
158
158
|
* # `FeatureToggles`
|
|
@@ -208,7 +208,7 @@ export declare interface BrowserConfig {
|
|
|
208
208
|
onUnauthorized?: () => void
|
|
209
209
|
headers?: Record<string, string>
|
|
210
210
|
timeout?: number
|
|
211
|
-
transformResponse?: <T>(response:
|
|
211
|
+
transformResponse?: <T>(response: unknown) => T
|
|
212
212
|
transformRequest?: <T>(data: T) => any
|
|
213
213
|
}
|
|
214
214
|
/**
|
|
@@ -284,7 +284,7 @@ export declare interface GenerateMigrationResult {
|
|
|
284
284
|
sql: string
|
|
285
285
|
sqlStatements: string[]
|
|
286
286
|
hasChanges: boolean
|
|
287
|
-
plan:
|
|
287
|
+
plan: import('./migrations').MigrationPlan
|
|
288
288
|
operations?: import('./migrations').MigrationOperation[]
|
|
289
289
|
}
|
|
290
290
|
export declare interface UnsafeOptions {
|
|
@@ -309,6 +309,20 @@ export declare interface UnsafeOptions {
|
|
|
309
309
|
* - 'browser': Browser-compatible mode that uses fetch() API calls instead of direct database connections
|
|
310
310
|
*/
|
|
311
311
|
export type SupportedDialect = 'postgres' | 'mysql' | 'singlestore' | 'vitess' | 'sqlite' | 'browser';
|
|
312
|
+
/**
|
|
313
|
+
* # `QueryHooks`
|
|
314
|
+
*
|
|
315
|
+
* Optional lifecycle hooks around query execution. These are invoked for any
|
|
316
|
+
* statement executed through the builder (select/insert/update/delete/raw).
|
|
317
|
+
*/
|
|
318
|
+
/** A bound statement parameter: whatever a driver will accept as a value. */
|
|
319
|
+
export type QueryParam = string | number | bigint | boolean | Date | Uint8Array | null;
|
|
320
|
+
/** The kind of statement a hook is reporting on. */
|
|
321
|
+
export type QueryKind = 'select' | 'insert' | 'update' | 'delete' | 'raw';
|
|
322
|
+
/** The row shape a hook sees. Columns are unknown until the caller narrows. */
|
|
323
|
+
export type QueryRecord = Record<string, unknown>;
|
|
324
|
+
/** A `where` description as the mutation hooks receive it. */
|
|
325
|
+
export type QueryWhere = Record<string, unknown>;
|
|
312
326
|
/**
|
|
313
327
|
* # `DeepPartial`
|
|
314
328
|
*
|
|
@@ -340,7 +354,7 @@ export type SupportedDialect = 'postgres' | 'mysql' | 'singlestore' | 'vitess' |
|
|
|
340
354
|
* signature is not a property. `keyof (() => void)` is `never`, so the
|
|
341
355
|
* hook collapses to an empty object type: no longer callable, and loose
|
|
342
356
|
* enough to accept `42`. It also erases type parameters, which would turn
|
|
343
|
-
* `BrowserConfig.transformResponse` (`<T>(response:
|
|
357
|
+
* `BrowserConfig.transformResponse` (`<T>(response: unknown) => T`) into a
|
|
344
358
|
* shape with no signature at all. A hook or a token getter is a leaf.
|
|
345
359
|
*
|
|
346
360
|
* 2. ARRAYS SECOND, because the merge replaces them rather than merging them.
|
package/package.json
CHANGED