pqb 0.57.1 → 0.57.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1829 -47
- package/dist/index.js +1851 -526
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1324 -96
- package/dist/index.mjs.map +1 -1
- package/dist/node-postgres.d.ts +1074 -4
- package/dist/node-postgres.js +37 -5
- package/dist/node-postgres.js.map +1 -1
- package/dist/node-postgres.mjs +33 -1
- package/dist/node-postgres.mjs.map +1 -1
- package/dist/postgres-js.d.ts +1076 -6
- package/dist/postgres-js.js +40 -8
- package/dist/postgres-js.js.map +1 -1
- package/dist/postgres-js.mjs +33 -1
- package/dist/postgres-js.mjs.map +1 -1
- package/package.json +3 -11
package/dist/postgres-js.d.ts
CHANGED
|
@@ -1,11 +1,1081 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import { ColumnSchemaConfig, AdapterConfigBase, AdapterBase, QueryResultRow, QueryResult, QueryArraysResult, QueryError } from 'orchid-core';
|
|
3
|
-
import postgres, { Error } from 'postgres';
|
|
1
|
+
import * as pqb from 'pqb';
|
|
4
2
|
import { DbOptions, DefaultSchemaConfig, DefaultColumnTypes, DbResult } from 'pqb';
|
|
3
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
4
|
+
import postgres, { Error as Error$1 } from 'postgres';
|
|
5
|
+
|
|
6
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
7
|
+
interface FnUnknownToUnknown {
|
|
8
|
+
(a: unknown): unknown;
|
|
9
|
+
}
|
|
10
|
+
interface RecordKeyTrue {
|
|
11
|
+
[K: string]: true;
|
|
12
|
+
}
|
|
13
|
+
interface RecordString {
|
|
14
|
+
[K: string]: string;
|
|
15
|
+
}
|
|
16
|
+
interface RecordUnknown {
|
|
17
|
+
[K: string]: unknown;
|
|
18
|
+
}
|
|
19
|
+
type EmptyObject = {};
|
|
20
|
+
|
|
21
|
+
type ExpressionChain = (OperatorToSQL<unknown, unknown> | unknown)[];
|
|
22
|
+
interface ExpressionData {
|
|
23
|
+
chain?: ExpressionChain;
|
|
24
|
+
expr?: Expression;
|
|
25
|
+
}
|
|
26
|
+
declare abstract class Expression<T extends QueryColumn = QueryColumn> {
|
|
27
|
+
abstract result: {
|
|
28
|
+
value: T;
|
|
29
|
+
};
|
|
30
|
+
abstract q: ExpressionData;
|
|
31
|
+
meta: {
|
|
32
|
+
kind: 'select';
|
|
33
|
+
};
|
|
34
|
+
toSQL(ctx: {
|
|
35
|
+
values: unknown[];
|
|
36
|
+
}, quotedAs?: string): string;
|
|
37
|
+
abstract makeSQL(ctx: {
|
|
38
|
+
values: unknown[];
|
|
39
|
+
}, quotedAs?: string): string;
|
|
40
|
+
}
|
|
41
|
+
type TemplateLiteralArgs = [
|
|
42
|
+
strings: TemplateStringsArray,
|
|
43
|
+
...values: unknown[]
|
|
44
|
+
];
|
|
45
|
+
type RawSQLValues = RecordUnknown;
|
|
46
|
+
declare abstract class ExpressionTypeMethod {
|
|
47
|
+
type<T extends {
|
|
48
|
+
q: {
|
|
49
|
+
expr?: Expression;
|
|
50
|
+
};
|
|
51
|
+
columnTypes: unknown;
|
|
52
|
+
}, C extends QueryColumn>(this: T, fn: (types: T['columnTypes']) => C): // Omit is optimal
|
|
53
|
+
Omit<T, 'result'> & {
|
|
54
|
+
result: {
|
|
55
|
+
value: C;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
interface RawSQLBase<T extends QueryColumn = QueryColumn, ColumnTypes = unknown> extends Expression<T>, ExpressionTypeMethod {
|
|
60
|
+
}
|
|
61
|
+
declare abstract class RawSQLBase<T extends QueryColumn = QueryColumn, ColumnTypes = unknown> extends Expression<T> {
|
|
62
|
+
_sql: string | TemplateLiteralArgs;
|
|
63
|
+
_values?: RecordUnknown | undefined;
|
|
64
|
+
result: {
|
|
65
|
+
value: T;
|
|
66
|
+
};
|
|
67
|
+
q: ExpressionData;
|
|
68
|
+
abstract columnTypes: ColumnTypes;
|
|
69
|
+
abstract makeSQL(ctx: {
|
|
70
|
+
values: unknown[];
|
|
71
|
+
}): string;
|
|
72
|
+
constructor(_sql: string | TemplateLiteralArgs, _values?: RecordUnknown | undefined);
|
|
73
|
+
values<Self extends RawSQLBase>(this: Self, values: RawSQLValues): Self;
|
|
74
|
+
toCode(t: string): string;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
interface OperatorBase<Value> {
|
|
78
|
+
(this: any, arg: Value): any;
|
|
79
|
+
_opType: Value;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Function to turn the operator expression into SQL.
|
|
83
|
+
*
|
|
84
|
+
* @param key - SQL of the target to apply operator for, can be a quoted column name or an SQL expression wrapped with parens.
|
|
85
|
+
* @param args - arguments of operator function.
|
|
86
|
+
* @param ctx - context object for SQL conversions, for collecting query variables.
|
|
87
|
+
* @param quotedAs - quoted table name.
|
|
88
|
+
*/
|
|
89
|
+
interface OperatorToSQL<Value, Ctx> {
|
|
90
|
+
(key: string, args: [Value], ctx: Ctx, quotedAs?: string): string;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
interface ColumnSchemaGetterTableClass {
|
|
94
|
+
prototype: {
|
|
95
|
+
columns: {
|
|
96
|
+
shape: ColumnTypesBase;
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
inputSchema(): unknown;
|
|
100
|
+
querySchema(): unknown;
|
|
101
|
+
pkeySchema(): unknown;
|
|
102
|
+
createSchema(): unknown;
|
|
103
|
+
}
|
|
104
|
+
interface ColumnTypeSchemaArg {
|
|
105
|
+
type: unknown;
|
|
106
|
+
nullable<T extends ColumnTypeBase>(this: T): NullableColumn<T, unknown, unknown, unknown>;
|
|
107
|
+
encode: unknown;
|
|
108
|
+
parse: unknown;
|
|
109
|
+
parseNull: unknown;
|
|
110
|
+
asType: unknown;
|
|
111
|
+
narrowType: unknown;
|
|
112
|
+
narrowAllTypes: unknown;
|
|
113
|
+
error?: unknown;
|
|
114
|
+
}
|
|
115
|
+
interface ColumnSchemaConfig<T extends ColumnTypeBase = ColumnTypeBase> extends ColumnTypeSchemaArg {
|
|
116
|
+
dateAsNumber: unknown;
|
|
117
|
+
dateAsDate: unknown;
|
|
118
|
+
enum: unknown;
|
|
119
|
+
array: unknown;
|
|
120
|
+
boolean(): unknown;
|
|
121
|
+
buffer(): unknown;
|
|
122
|
+
unknown(): unknown;
|
|
123
|
+
never(): unknown;
|
|
124
|
+
stringSchema(): unknown;
|
|
125
|
+
stringMin(max: number): unknown;
|
|
126
|
+
stringMax(max: number): unknown;
|
|
127
|
+
stringMinMax(min: number, max: number): unknown;
|
|
128
|
+
number(): unknown;
|
|
129
|
+
int(): unknown;
|
|
130
|
+
stringNumberDate(): unknown;
|
|
131
|
+
timeInterval(): unknown;
|
|
132
|
+
bit(max?: number): unknown;
|
|
133
|
+
uuid(): unknown;
|
|
134
|
+
json(): T;
|
|
135
|
+
inputSchema(this: ColumnSchemaGetterTableClass): unknown;
|
|
136
|
+
outputSchema(this: ColumnSchemaGetterTableClass): unknown;
|
|
137
|
+
querySchema(this: ColumnSchemaGetterTableClass): unknown;
|
|
138
|
+
createSchema(this: ColumnSchemaGetterTableClass): unknown;
|
|
139
|
+
updateSchema(this: ColumnSchemaGetterTableClass): unknown;
|
|
140
|
+
pkeySchema(this: ColumnSchemaGetterTableClass): unknown;
|
|
141
|
+
smallint(): T;
|
|
142
|
+
integer(): T;
|
|
143
|
+
real(): T;
|
|
144
|
+
smallSerial(): T;
|
|
145
|
+
serial(): T;
|
|
146
|
+
bigint(): T;
|
|
147
|
+
decimal(precision?: number, scale?: number): T;
|
|
148
|
+
doublePrecision(): T;
|
|
149
|
+
bigSerial(): T;
|
|
150
|
+
money(): T;
|
|
151
|
+
varchar(limit?: number): T;
|
|
152
|
+
text(): T;
|
|
153
|
+
string(limit?: number): T;
|
|
154
|
+
citext(): T;
|
|
155
|
+
date(): T;
|
|
156
|
+
timestampNoTZ(precision?: number): T;
|
|
157
|
+
timestamp(precision?: number): T;
|
|
158
|
+
geographyPointSchema(): unknown;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
interface PickQueryShape {
|
|
162
|
+
shape: QueryColumns;
|
|
163
|
+
}
|
|
164
|
+
interface PickQueryInputType {
|
|
165
|
+
inputType: unknown;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
declare class QueryHookUtils<T extends PickQueryInputType> {
|
|
169
|
+
query: IsQuery;
|
|
170
|
+
columns: string[];
|
|
171
|
+
private key;
|
|
172
|
+
constructor(query: IsQuery, columns: string[], key: 'hookCreateSet' | 'hookUpdateSet');
|
|
173
|
+
set: (data: { [K in keyof T["inputType"]]?: T["inputType"][K] | (() => QueryOrExpression<T["inputType"][K]>) | undefined; }) => void;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
interface ColumnsShapeBase {
|
|
177
|
+
[K: string]: ColumnTypeBase;
|
|
178
|
+
}
|
|
179
|
+
type NullableColumn<T extends ColumnTypeBase, InputSchema, OutputSchema, QuerySchema> = {
|
|
180
|
+
[K in keyof T]: K extends 'type' ? T['type'] | null : K extends 'inputType' ? T['inputType'] | null : K extends 'inputSchema' ? InputSchema : K extends 'outputType' ? T['outputType'] | (unknown extends T['nullType'] ? null : T['nullType']) : K extends 'outputSchema' ? OutputSchema : K extends 'queryType' ? T['queryType'] | null : K extends 'querySchema' ? QuerySchema : K extends 'data' ? T['data'] & DataNullable : K extends 'operators' ? // `Omit` here is faster than ternaries
|
|
181
|
+
Omit<T['operators'], 'equals' | 'not'> & OperatorsNullable<T['queryType']> : T[K];
|
|
182
|
+
};
|
|
183
|
+
interface DataNullable {
|
|
184
|
+
isNullable: true;
|
|
185
|
+
optional: true;
|
|
186
|
+
}
|
|
187
|
+
interface OperatorsNullable<T> {
|
|
188
|
+
equals: OperatorBase<T | null>;
|
|
189
|
+
not: OperatorBase<T | null>;
|
|
190
|
+
}
|
|
191
|
+
interface PickColumnBaseData {
|
|
192
|
+
data: ColumnDataBase;
|
|
193
|
+
}
|
|
194
|
+
type ColumnWithDefault<T extends PickColumnBaseData, Value> = {
|
|
195
|
+
[K in keyof T]: K extends 'data' ? {
|
|
196
|
+
[K in keyof T['data']]: K extends 'default' ? Value extends null ? never : Value : K extends 'optional' ? true : T['data'][K];
|
|
197
|
+
} : T[K];
|
|
198
|
+
};
|
|
199
|
+
type ColumnDefaultSelect<T extends PickColumnBaseData, Value extends boolean> = {
|
|
200
|
+
[K in keyof T]: K extends 'data' ? {
|
|
201
|
+
[K in keyof T['data']]: K extends 'explicitSelect' ? Value extends true ? false : true : T['data'][K];
|
|
202
|
+
} : T[K];
|
|
203
|
+
};
|
|
204
|
+
interface ColumnDataAppReadOnly {
|
|
205
|
+
data: {
|
|
206
|
+
appReadOnly: true;
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
type ColumnTypesBase = {
|
|
210
|
+
[K in string]: ColumnTypeBase;
|
|
211
|
+
};
|
|
212
|
+
interface ColumnDataBase {
|
|
213
|
+
key: string;
|
|
214
|
+
name?: string;
|
|
215
|
+
optional: true | undefined;
|
|
216
|
+
isNullable?: true;
|
|
217
|
+
primaryKey?: string;
|
|
218
|
+
default: unknown;
|
|
219
|
+
defaultDefault: unknown;
|
|
220
|
+
runtimeDefault?(): unknown;
|
|
221
|
+
explicitSelect?: boolean;
|
|
222
|
+
as?: ColumnTypeBase;
|
|
223
|
+
unique?: string;
|
|
224
|
+
modifyQuery?(q: QueryBaseCommon, column: ColumnTypeBase): void;
|
|
225
|
+
checks?: ColumnDataCheckBase[];
|
|
226
|
+
isOfCustomType?: boolean;
|
|
227
|
+
errors?: RecordString;
|
|
228
|
+
defaultTimestamp?: 'createdAt' | 'updatedAt';
|
|
229
|
+
alias?: string;
|
|
230
|
+
extension?: string;
|
|
231
|
+
encode?(input: any): unknown;
|
|
232
|
+
parse?(input: any): unknown;
|
|
233
|
+
parseItem?(input: string): unknown;
|
|
234
|
+
parseNull?(): unknown;
|
|
235
|
+
jsonCast?: string;
|
|
236
|
+
readOnly?: boolean;
|
|
237
|
+
appReadOnly: true | undefined;
|
|
238
|
+
setOnCreate?(arg: QueryHookUtils<PickQueryInputType>): unknown;
|
|
239
|
+
setOnUpdate?(arg: QueryHookUtils<PickQueryInputType>): unknown;
|
|
240
|
+
setOnSave?(arg: QueryHookUtils<PickQueryInputType>): unknown;
|
|
241
|
+
typmod?: number;
|
|
242
|
+
virtual?: true;
|
|
243
|
+
}
|
|
244
|
+
interface ColumnDataCheckBase {
|
|
245
|
+
sql: RawSQLBase;
|
|
246
|
+
name?: string;
|
|
247
|
+
}
|
|
248
|
+
interface QueryColumn<T = unknown, Op = any> {
|
|
249
|
+
dataType: string;
|
|
250
|
+
type: T;
|
|
251
|
+
outputType: T;
|
|
252
|
+
queryType: T;
|
|
253
|
+
operators: Op;
|
|
254
|
+
}
|
|
255
|
+
interface QueryColumns {
|
|
256
|
+
[K: string]: QueryColumn;
|
|
257
|
+
}
|
|
258
|
+
interface QueryColumnData {
|
|
259
|
+
explicitSelect?: boolean;
|
|
260
|
+
primaryKey?: string;
|
|
261
|
+
unique?: string;
|
|
262
|
+
optional?: true;
|
|
263
|
+
isNullable?: true;
|
|
264
|
+
default?: unknown;
|
|
265
|
+
name?: string;
|
|
266
|
+
readOnly?: boolean;
|
|
267
|
+
appReadOnly: true | undefined;
|
|
268
|
+
}
|
|
269
|
+
interface QueryColumnInit extends QueryColumn {
|
|
270
|
+
inputType: unknown;
|
|
271
|
+
data: QueryColumnData;
|
|
272
|
+
}
|
|
273
|
+
interface QueryColumnsInit {
|
|
274
|
+
[K: string]: QueryColumnInit;
|
|
275
|
+
}
|
|
276
|
+
interface ColumnToCodeCtx {
|
|
277
|
+
t: string;
|
|
278
|
+
table: string;
|
|
279
|
+
currentSchema: string;
|
|
280
|
+
migration?: boolean;
|
|
281
|
+
snakeCase?: boolean;
|
|
282
|
+
}
|
|
283
|
+
declare abstract class ColumnTypeBase<Schema extends ColumnTypeSchemaArg = ColumnTypeSchemaArg, Type = unknown, InputSchema = any, Ops = any, InputType = Type, OutputType = Type, OutputSchema = InputSchema, QueryType = InputType, QuerySchema = InputSchema, Data extends ColumnDataBase = ColumnDataBase> {
|
|
284
|
+
inputSchema: InputSchema;
|
|
285
|
+
outputSchema: OutputSchema;
|
|
286
|
+
querySchema: QuerySchema;
|
|
287
|
+
abstract dataType: string;
|
|
288
|
+
abstract operators: Ops;
|
|
289
|
+
abstract toCode(ctx: ColumnToCodeCtx, key: string): Code;
|
|
290
|
+
abstract toSQL(): string;
|
|
291
|
+
type: Type;
|
|
292
|
+
inputType: InputType;
|
|
293
|
+
outputType: OutputType;
|
|
294
|
+
queryType: QueryType;
|
|
295
|
+
nullType: unknown;
|
|
296
|
+
nullSchema: unknown;
|
|
297
|
+
isNullable: boolean;
|
|
298
|
+
data: Data;
|
|
299
|
+
error: Schema['error'];
|
|
300
|
+
_parse?: (input: unknown) => unknown;
|
|
301
|
+
constructor(schema: ColumnTypeSchemaArg, inputSchema: InputSchema, outputSchema?: OutputSchema, querySchema?: QuerySchema);
|
|
302
|
+
/**
|
|
303
|
+
* Set a default value to a column. Columns that have defaults become optional when creating a record.
|
|
304
|
+
*
|
|
305
|
+
* If you provide a value or a raw SQL, such default should be set on the column in migration to be applied on a database level.
|
|
306
|
+
*
|
|
307
|
+
* Or you can specify a callback that returns a value. This function will be called for each creating record. Such a default won't be applied to a database.
|
|
308
|
+
*
|
|
309
|
+
* ```ts
|
|
310
|
+
* export class Table extends BaseTable {
|
|
311
|
+
* readonly table = 'table';
|
|
312
|
+
* columns = this.setColumns((t) => ({
|
|
313
|
+
* // values as defaults:
|
|
314
|
+
* int: t.integer().default(123),
|
|
315
|
+
* text: t.text().default('text'),
|
|
316
|
+
*
|
|
317
|
+
* // raw SQL default:
|
|
318
|
+
* timestamp: t.timestamp().default(t.sql`now()`),
|
|
319
|
+
*
|
|
320
|
+
* // runtime default, each new records gets a new random value:
|
|
321
|
+
* random: t.numeric().default(() => Math.random()),
|
|
322
|
+
* }));
|
|
323
|
+
* }
|
|
324
|
+
* ```
|
|
325
|
+
*
|
|
326
|
+
* @param value - default value or a function returning a value
|
|
327
|
+
*/
|
|
328
|
+
default<T extends Pick<ColumnTypeBase, 'type' | 'inputType' | 'data'>, Value extends T['inputType'] | null | RawSQLBase | (() => T['inputType'])>(this: T, value: Value): ColumnWithDefault<T, Value>;
|
|
329
|
+
/**
|
|
330
|
+
* Use `hasDefault` to let the column be omitted when creating records.
|
|
331
|
+
*
|
|
332
|
+
* It's better to use {@link default} instead so the value is explicit and serves as a hint.
|
|
333
|
+
*/
|
|
334
|
+
hasDefault<T extends PickColumnBaseData>(this: T): ColumnWithDefault<T, RawSQLBase>;
|
|
335
|
+
/**
|
|
336
|
+
* Set a database-level validation check to a column. `check` accepts a raw SQL.
|
|
337
|
+
*
|
|
338
|
+
* ```ts
|
|
339
|
+
* import { change } from '../dbScript';
|
|
340
|
+
*
|
|
341
|
+
* change(async (db) => {
|
|
342
|
+
* await db.createTable('table', (t) => ({
|
|
343
|
+
* // validate rank to be from 1 to 10
|
|
344
|
+
* rank: t.integer().check(t.sql`1 >= "rank" AND "rank" <= 10`),
|
|
345
|
+
* // constraint name can be passed as a second argument
|
|
346
|
+
* column: t.integer().check(t.sql`...`, 'check_name'),
|
|
347
|
+
* // a single column can have multiple checks
|
|
348
|
+
* multiChecksColumn: t
|
|
349
|
+
* .integer()
|
|
350
|
+
* .check(t.sql`...`)
|
|
351
|
+
* .check(t.sql`...`, 'optional_name'),
|
|
352
|
+
* }));
|
|
353
|
+
* });
|
|
354
|
+
* ```
|
|
355
|
+
*
|
|
356
|
+
* @param sql - raw SQL expression
|
|
357
|
+
* @param name - to specify a constraint name
|
|
358
|
+
*/
|
|
359
|
+
check<T extends PickColumnBaseData>(this: T, sql: RawSQLBase, name?: string): T;
|
|
360
|
+
/**
|
|
361
|
+
* Use `nullable` to mark the column as nullable. By default, all columns are required.
|
|
362
|
+
*
|
|
363
|
+
* Nullable columns are optional when creating records.
|
|
364
|
+
*
|
|
365
|
+
* ```ts
|
|
366
|
+
* export class Table extends BaseTable {
|
|
367
|
+
* readonly table = 'table';
|
|
368
|
+
* columns = this.setColumns((t) => ({
|
|
369
|
+
* name: t.integer().nullable(),
|
|
370
|
+
* }));
|
|
371
|
+
* }
|
|
372
|
+
* ```
|
|
373
|
+
*/
|
|
374
|
+
nullable: Schema['nullable'];
|
|
375
|
+
/**
|
|
376
|
+
* Set a custom function to process value for the column when creating or updating a record.
|
|
377
|
+
*
|
|
378
|
+
* The type of `input` argument will be used as the type of the column when creating and updating.
|
|
379
|
+
*
|
|
380
|
+
* If you have a validation library [installed and configured](/guide/columns-validation-methods.html),
|
|
381
|
+
* first argument is a schema to validate the input.
|
|
382
|
+
*
|
|
383
|
+
* ```ts
|
|
384
|
+
* import { z } from 'zod';
|
|
385
|
+
*
|
|
386
|
+
* export class Table extends BaseTable {
|
|
387
|
+
* readonly table = 'table';
|
|
388
|
+
* columns = this.setColumns((t) => ({
|
|
389
|
+
* // encode boolean, number, or string to text before saving
|
|
390
|
+
* column: t
|
|
391
|
+
* .string()
|
|
392
|
+
* // when having validation library, the first argument is a validation schema
|
|
393
|
+
* .encode(
|
|
394
|
+
* z.boolean().or(z.number()).or(z.string()),
|
|
395
|
+
* (input: boolean | number | string) => String(input),
|
|
396
|
+
* )
|
|
397
|
+
* // no schema argument otherwise
|
|
398
|
+
* .encode((input: boolean | number | string) => String(input)),
|
|
399
|
+
* }));
|
|
400
|
+
* }
|
|
401
|
+
*
|
|
402
|
+
* // numbers and booleans will be converted to a string:
|
|
403
|
+
* await db.table.create({ column: 123 });
|
|
404
|
+
* await db.table.create({ column: true });
|
|
405
|
+
* await db.table.where({ column: 'true' }).update({ column: false });
|
|
406
|
+
* ```
|
|
407
|
+
*
|
|
408
|
+
* @param fn - function to encode value for a database, argument type is specified by you, return type must be compatible with a database
|
|
409
|
+
*/
|
|
410
|
+
encode: Schema['encode'];
|
|
411
|
+
/**
|
|
412
|
+
* Set a custom function to process value after loading it from a database.
|
|
413
|
+
*
|
|
414
|
+
* The type of input is the type of column before `.parse`, the resulting type will replace the type of column.
|
|
415
|
+
*
|
|
416
|
+
* If you have a validation library [installed and configured](/guide/columns-validation-methods.html),
|
|
417
|
+
* first argument is a schema for validating the output.
|
|
418
|
+
*
|
|
419
|
+
* For handling `null` values use {@link parseNull} instead or in addition.
|
|
420
|
+
*
|
|
421
|
+
* ```ts
|
|
422
|
+
* import { z } from 'zod';
|
|
423
|
+
* import { number, integer } from 'valibot';
|
|
424
|
+
*
|
|
425
|
+
* export class Table extends BaseTable {
|
|
426
|
+
* readonly table = 'table';
|
|
427
|
+
* columns = this.setColumns((t) => ({
|
|
428
|
+
* columnZod: t
|
|
429
|
+
* .string()
|
|
430
|
+
* // when having validation library, the first argument is a schema
|
|
431
|
+
* .parse(z.number().int(), (input) => parseInt(input))
|
|
432
|
+
* // no schema argument otherwise
|
|
433
|
+
* .parse((input) => parseInt(input)),
|
|
434
|
+
*
|
|
435
|
+
* columnValibot: t
|
|
436
|
+
* .string()
|
|
437
|
+
* .parse(number([integer()]), (input) => parseInt(input))
|
|
438
|
+
* .parse((input) => parseInt(input)),
|
|
439
|
+
* }));
|
|
440
|
+
* }
|
|
441
|
+
*
|
|
442
|
+
* // column will be parsed to a number
|
|
443
|
+
* const value: number = await db.table.get('column');
|
|
444
|
+
* ```
|
|
445
|
+
*
|
|
446
|
+
* @param fn - function to parse a value from the database, argument is the type of this column, return type is up to you
|
|
447
|
+
*/
|
|
448
|
+
parse: Schema['parse'];
|
|
449
|
+
/**
|
|
450
|
+
* Use `parseNull` to specify runtime defaults at selection time.
|
|
451
|
+
*
|
|
452
|
+
* The `parseNull` function is only triggered for `nullable` columns.
|
|
453
|
+
*
|
|
454
|
+
* ```ts
|
|
455
|
+
* export class Table extends BaseTable {
|
|
456
|
+
* readonly table = 'table';
|
|
457
|
+
* columns = this.setColumns((t) => ({
|
|
458
|
+
* column: t
|
|
459
|
+
* .integer()
|
|
460
|
+
* .parse(String) // parse non-nulls to string
|
|
461
|
+
* .parseNull(() => false), // replace nulls with false
|
|
462
|
+
* .nullable(),
|
|
463
|
+
* }));
|
|
464
|
+
* }
|
|
465
|
+
*
|
|
466
|
+
* const record = await db.table.take()
|
|
467
|
+
* record.column // can be a string or boolean, not null
|
|
468
|
+
* ```
|
|
469
|
+
*
|
|
470
|
+
* If you have a validation library [installed and configured](/guide/columns-validation-methods),
|
|
471
|
+
* first argument is a schema for validating the output.
|
|
472
|
+
*
|
|
473
|
+
* ```ts
|
|
474
|
+
* export class Table extends BaseTable {
|
|
475
|
+
* readonly table = 'table';
|
|
476
|
+
* columns = this.setColumns((t) => ({
|
|
477
|
+
* column: t
|
|
478
|
+
* .integer()
|
|
479
|
+
* .parse(z.string(), String) // parse non-nulls to string
|
|
480
|
+
* .parseNull(z.literal(false), () => false), // replace nulls with false
|
|
481
|
+
* .nullable(),
|
|
482
|
+
* }));
|
|
483
|
+
* }
|
|
484
|
+
*
|
|
485
|
+
* const record = await db.table.take()
|
|
486
|
+
* record.column // can be a string or boolean, not null
|
|
487
|
+
*
|
|
488
|
+
* Table.outputSchema().parse({
|
|
489
|
+
* column: false, // the schema expects strings or `false` literals, not nulls
|
|
490
|
+
* })
|
|
491
|
+
* ```
|
|
492
|
+
*/
|
|
493
|
+
parseNull: Schema['parseNull'];
|
|
494
|
+
/**
|
|
495
|
+
* This method changes a column type without modifying its behavior.
|
|
496
|
+
* This is needed when converting columns to a validation schema, the converter will pick a different type specified by `.as`.
|
|
497
|
+
*
|
|
498
|
+
* Before calling `.as` need to use `.encode` with the input of the same type as the input of the target column,
|
|
499
|
+
* and `.parse` which returns the correct type.
|
|
500
|
+
*
|
|
501
|
+
* ```ts
|
|
502
|
+
* // column has the same type as t.integer()
|
|
503
|
+
* const column = t
|
|
504
|
+
* .string()
|
|
505
|
+
* .encode((input: number) => input)
|
|
506
|
+
* .parse((text) => parseInt(text))
|
|
507
|
+
* .as(t.integer());
|
|
508
|
+
* ```
|
|
509
|
+
*
|
|
510
|
+
* @param column - other column type to inherit from
|
|
511
|
+
*/
|
|
512
|
+
as<T extends {
|
|
513
|
+
inputType: unknown;
|
|
514
|
+
outputType: unknown;
|
|
515
|
+
data: ColumnDataBase;
|
|
516
|
+
}, C extends Omit<ColumnTypeBase, 'inputType' | 'outputType'> & {
|
|
517
|
+
inputType: T['inputType'];
|
|
518
|
+
outputType: T['outputType'];
|
|
519
|
+
}>(this: T, column: C): C;
|
|
520
|
+
/**
|
|
521
|
+
* @deprecated use narrowType instead
|
|
522
|
+
*/
|
|
523
|
+
asType: Schema['asType'];
|
|
524
|
+
/**
|
|
525
|
+
* `narrowType` narrows TypeScript types of a column. It sets input, output, query type altogether.
|
|
526
|
+
*
|
|
527
|
+
* For example, to narrow a `string` type to a union of string literals.
|
|
528
|
+
*
|
|
529
|
+
* When _not_ integrating with [validation libraries](/guide/columns-validation-methods), `narrowType` has the following syntax:
|
|
530
|
+
*
|
|
531
|
+
* ```ts
|
|
532
|
+
* export class Table extends BaseTable {
|
|
533
|
+
* readonly table = 'table';
|
|
534
|
+
* columns = this.setColumns((t) => ({
|
|
535
|
+
* size: t.string().narrowType((t) => t<'small' | 'medium' | 'large'>()),
|
|
536
|
+
* }));
|
|
537
|
+
* }
|
|
538
|
+
*
|
|
539
|
+
* // size will be typed as 'small' | 'medium' | 'large'
|
|
540
|
+
* const size = await db.table.get('size');
|
|
541
|
+
* ```
|
|
542
|
+
*
|
|
543
|
+
* - `input` is for `create`, `update` methods.
|
|
544
|
+
* - `output` is for the data that is loaded from a database and parsed if the column has `parse`.
|
|
545
|
+
* - `query` is used in `where` and other query methods, it should be compatible with the actual database column type.
|
|
546
|
+
*
|
|
547
|
+
* When integrating with a [validation library](/guide/columns-validation-methods), also provide validation schemas:
|
|
548
|
+
*
|
|
549
|
+
* ```ts
|
|
550
|
+
* const sizeSchema = z.union([
|
|
551
|
+
* z.literal('small'),
|
|
552
|
+
* z.literal('medium'),
|
|
553
|
+
* z.literal('large'),
|
|
554
|
+
* ]);
|
|
555
|
+
*
|
|
556
|
+
* export class Table extends BaseTable {
|
|
557
|
+
* readonly table = 'table';
|
|
558
|
+
* columns = this.setColumns((t) => ({
|
|
559
|
+
* size: t.text().narrowType(sizeSchema),
|
|
560
|
+
* }));
|
|
561
|
+
* }
|
|
562
|
+
*
|
|
563
|
+
* // size will be typed as 'small' | 'medium' | 'large'
|
|
564
|
+
* const size = await db.table.get('size');
|
|
565
|
+
* ```
|
|
566
|
+
*/
|
|
567
|
+
narrowType: Schema['narrowType'];
|
|
568
|
+
/**
|
|
569
|
+
* Allows to narrow different TypeScript types of a column granularly.
|
|
570
|
+
*
|
|
571
|
+
* Use it when the column's input is different from output.
|
|
572
|
+
*
|
|
573
|
+
* When _not_ integrating with [validation libraries](/guide/columns-validation-methods), `narrowAllTypes` has the following syntax:
|
|
574
|
+
*
|
|
575
|
+
* ```ts
|
|
576
|
+
* export class Table extends BaseTable {
|
|
577
|
+
* readonly table = 'table';
|
|
578
|
+
* columns = this.setColumns((t) => ({
|
|
579
|
+
* size: t.string().narrowAllTypes((t) =>
|
|
580
|
+
* t<{
|
|
581
|
+
* // what types are accepted when creating/updating
|
|
582
|
+
* input: 'small' | 'medium' | 'large';
|
|
583
|
+
* // how types are retured from a database
|
|
584
|
+
* output: 'small' | 'medium' | 'large';
|
|
585
|
+
* // what types the column accepts in `where` and similar
|
|
586
|
+
* query: 'small' | 'medium' | 'large';
|
|
587
|
+
* }>(),
|
|
588
|
+
* ),
|
|
589
|
+
* }));
|
|
590
|
+
* }
|
|
591
|
+
*
|
|
592
|
+
* // size will be typed as 'small' | 'medium' | 'large'
|
|
593
|
+
* const size = await db.table.get('size');
|
|
594
|
+
* ```
|
|
595
|
+
*
|
|
596
|
+
* - `input` is for `create`, `update` methods.
|
|
597
|
+
* - `output` is for the data that is loaded from a database and parsed if the column has `parse`.
|
|
598
|
+
* - `query` is used in `where` and other query methods, it should be compatible with the actual database column type.
|
|
599
|
+
*
|
|
600
|
+
* When integrating with a [validation library](/guide/columns-validation-methods), also provide validation schemas:
|
|
601
|
+
*
|
|
602
|
+
* ```ts
|
|
603
|
+
* const sizeSchema = z.union([
|
|
604
|
+
* z.literal('small'),
|
|
605
|
+
* z.literal('medium'),
|
|
606
|
+
* z.literal('large'),
|
|
607
|
+
* ]);
|
|
608
|
+
*
|
|
609
|
+
* export class Table extends BaseTable {
|
|
610
|
+
* readonly table = 'table';
|
|
611
|
+
* columns = this.setColumns((t) => ({
|
|
612
|
+
* size: t.text().narrowAllTypes({
|
|
613
|
+
* input: sizeSchema,
|
|
614
|
+
* output: sizeSchema,
|
|
615
|
+
* query: sizeSchema,
|
|
616
|
+
* }),
|
|
617
|
+
* }));
|
|
618
|
+
* }
|
|
619
|
+
*
|
|
620
|
+
* // size will be typed as 'small' | 'medium' | 'large'
|
|
621
|
+
* const size = await db.table.get('size');
|
|
622
|
+
* ```
|
|
623
|
+
*/
|
|
624
|
+
narrowAllTypes: Schema['narrowAllTypes'];
|
|
625
|
+
input<T extends {
|
|
626
|
+
inputSchema: unknown;
|
|
627
|
+
}, InputSchema extends Schema['type']>(this: T, fn: (schema: T['inputSchema']) => InputSchema): {
|
|
628
|
+
[K in keyof T]: K extends 'inputSchema' ? InputSchema : T[K];
|
|
629
|
+
};
|
|
630
|
+
output<T extends {
|
|
631
|
+
outputSchema: unknown;
|
|
632
|
+
}, OutputSchema extends Schema['type']>(this: T, fn: (schema: T['outputSchema']) => OutputSchema): {
|
|
633
|
+
[K in keyof T]: K extends 'outputSchema' ? OutputSchema : T[K];
|
|
634
|
+
};
|
|
635
|
+
query<T extends {
|
|
636
|
+
querySchema: unknown;
|
|
637
|
+
}, QuerySchema extends Schema['type']>(this: T, fn: (schema: T['querySchema']) => QuerySchema): {
|
|
638
|
+
[K in keyof T]: K extends 'querySchema' ? QuerySchema : T[K];
|
|
639
|
+
};
|
|
640
|
+
/**
|
|
641
|
+
* Set a database column name.
|
|
642
|
+
*
|
|
643
|
+
* @param name - name of the column in database.
|
|
644
|
+
*/
|
|
645
|
+
name<T extends PickColumnBaseData>(this: T, name: string): T;
|
|
646
|
+
/**
|
|
647
|
+
* Append `select(false)` to a column to exclude it from the default selection.
|
|
648
|
+
* It won't be selected with `selectAll` or `select('*')` as well.
|
|
649
|
+
*
|
|
650
|
+
* ```ts
|
|
651
|
+
* export class UserTable extends BaseTable {
|
|
652
|
+
* readonly table = 'user';
|
|
653
|
+
* columns = this.setColumns((t) => ({
|
|
654
|
+
* id: t.identity().primaryKey(),
|
|
655
|
+
* name: t.string(),
|
|
656
|
+
* password: t.string().select(false),
|
|
657
|
+
* }));
|
|
658
|
+
* }
|
|
659
|
+
*
|
|
660
|
+
* // only id and name are selected, without password
|
|
661
|
+
* const user = await db.user.find(123);
|
|
662
|
+
*
|
|
663
|
+
* // password is still omitted, even with the wildcard
|
|
664
|
+
* const same = await db.user.find(123).select('*');
|
|
665
|
+
*
|
|
666
|
+
* const comment = await db.comment.find(123).select({
|
|
667
|
+
* // password is omitted in the sub-selects as well
|
|
668
|
+
* author: (q) => q.author,
|
|
669
|
+
* });
|
|
670
|
+
*
|
|
671
|
+
* // password is omitted here as well
|
|
672
|
+
* const created = await db.user.create(userData);
|
|
673
|
+
* ```
|
|
674
|
+
*
|
|
675
|
+
* Such a column can only be selected explicitly.
|
|
676
|
+
*
|
|
677
|
+
* ```ts
|
|
678
|
+
* const userWithPassword = await db.user.find(123).select('*', 'password');
|
|
679
|
+
* ```
|
|
680
|
+
*/
|
|
681
|
+
select<T extends PickColumnBaseData, Value extends boolean>(this: T, value: Value): ColumnDefaultSelect<T, Value>;
|
|
682
|
+
/**
|
|
683
|
+
* Forbid the column to be used in [create](/guide/create-update-delete.html#create-insert) and [update](/guide/create-update-delete.html#update) methods.
|
|
684
|
+
*
|
|
685
|
+
* `readOnly` column is still can be set from a [hook](http://localhost:5173/guide/hooks.html#set-values-before-create-or-update).
|
|
686
|
+
*
|
|
687
|
+
* `readOnly` column can be used together with a `default`.
|
|
688
|
+
*
|
|
689
|
+
* ```ts
|
|
690
|
+
* export class Table extends BaseTable {
|
|
691
|
+
* readonly table = 'table';
|
|
692
|
+
* columns = this.setColumns((t) => ({
|
|
693
|
+
* id: t.identity().primaryKey(),
|
|
694
|
+
* column: t.string().default(() => 'default value'),
|
|
695
|
+
* another: t.string().readOnly(),
|
|
696
|
+
* }));
|
|
697
|
+
*
|
|
698
|
+
* init(orm: typeof db) {
|
|
699
|
+
* this.beforeSave(({ set }) => {
|
|
700
|
+
* set({ another: 'value' });
|
|
701
|
+
* });
|
|
702
|
+
* }
|
|
703
|
+
* }
|
|
704
|
+
*
|
|
705
|
+
* // later in the code
|
|
706
|
+
* db.table.create({ column: 'value' }); // TS error, runtime error
|
|
707
|
+
* ```
|
|
708
|
+
*/
|
|
709
|
+
readOnly<T>(this: T): T & ColumnDataAppReadOnly;
|
|
710
|
+
/**
|
|
711
|
+
* Set a column value when creating a record.
|
|
712
|
+
* This works for [readOnly](#readonly) columns as well.
|
|
713
|
+
*
|
|
714
|
+
* If no value or undefined is returned, the hook won't have any effect.
|
|
715
|
+
*
|
|
716
|
+
* ```ts
|
|
717
|
+
* export class Table extends BaseTable {
|
|
718
|
+
* readonly table = 'table';
|
|
719
|
+
* columns = this.setColumns((t) => ({
|
|
720
|
+
* id: t.identity().primaryKey(),
|
|
721
|
+
* column: t.string().setOnCreate(() => 'value'),
|
|
722
|
+
* }));
|
|
723
|
+
* }
|
|
724
|
+
* ```
|
|
725
|
+
*/
|
|
726
|
+
setOnCreate<T extends QueryColumnInit>(this: T, fn: (arg: QueryHookUtils<PickQueryInputType>) => T['inputType'] | void): T;
|
|
727
|
+
/**
|
|
728
|
+
* Set a column value when updating a record.
|
|
729
|
+
* This works for [readOnly](#readonly) columns as well.
|
|
730
|
+
*
|
|
731
|
+
* If no value or undefined is returned, the hook won't have any effect.
|
|
732
|
+
*
|
|
733
|
+
* ```ts
|
|
734
|
+
* export class Table extends BaseTable {
|
|
735
|
+
* readonly table = 'table';
|
|
736
|
+
* columns = this.setColumns((t) => ({
|
|
737
|
+
* id: t.identity().primaryKey(),
|
|
738
|
+
* column: t.string().setOnUpdate(() => 'value'),
|
|
739
|
+
* }));
|
|
740
|
+
* }
|
|
741
|
+
* ```
|
|
742
|
+
*/
|
|
743
|
+
setOnUpdate<T extends QueryColumnInit>(this: T, fn: (arg: QueryHookUtils<PickQueryInputType>) => T['inputType'] | void): T;
|
|
744
|
+
/**
|
|
745
|
+
* Set a column value when creating or updating a record.
|
|
746
|
+
* This works for [readOnly](#readonly) columns as well.
|
|
747
|
+
*
|
|
748
|
+
* If no value or undefined is returned, the hook won't have any effect.
|
|
749
|
+
*
|
|
750
|
+
* ```ts
|
|
751
|
+
* export class Table extends BaseTable {
|
|
752
|
+
* readonly table = 'table';
|
|
753
|
+
* columns = this.setColumns((t) => ({
|
|
754
|
+
* id: t.identity().primaryKey(),
|
|
755
|
+
* column: t.string().setOnSave(() => 'value'),
|
|
756
|
+
* }));
|
|
757
|
+
* }
|
|
758
|
+
* ```
|
|
759
|
+
*/
|
|
760
|
+
setOnSave<T extends QueryColumnInit>(this: T, fn: (arg: QueryHookUtils<PickQueryInputType>) => T['inputType'] | void): T;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
type Code = string | Codes;
|
|
764
|
+
type Codes = Code[];
|
|
765
|
+
|
|
766
|
+
type DelayedRelationSelect = {
|
|
767
|
+
query: QueryBase;
|
|
768
|
+
value?: {
|
|
769
|
+
[K: string]: IsQuery;
|
|
770
|
+
};
|
|
771
|
+
};
|
|
772
|
+
|
|
773
|
+
interface QueryInternalColumnNameToKey {
|
|
774
|
+
columnNameToKeyMap?: Map<string, string>;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
interface PickQueryDataAliases {
|
|
778
|
+
aliases?: RecordString;
|
|
779
|
+
}
|
|
780
|
+
interface QueryDataAliases extends PickQueryDataAliases {
|
|
781
|
+
as?: string;
|
|
782
|
+
outerAliases?: RecordString;
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
interface HasCteHooks {
|
|
786
|
+
cteHooks?: CteHooks;
|
|
787
|
+
}
|
|
788
|
+
interface CteHooks {
|
|
789
|
+
hasSelect: boolean;
|
|
790
|
+
tableHooks: CteTableHooks;
|
|
791
|
+
}
|
|
792
|
+
interface CteTableHooks {
|
|
793
|
+
[K: string]: CteTableHook;
|
|
794
|
+
}
|
|
795
|
+
interface CteTableHook {
|
|
796
|
+
shape: ColumnsShapeBase;
|
|
797
|
+
tableHook: TableHook;
|
|
798
|
+
}
|
|
799
|
+
interface TableHook {
|
|
800
|
+
select?: HookSelect;
|
|
801
|
+
after?: ((data: unknown, query: any) => unknown | Promise<unknown>)[];
|
|
802
|
+
afterCommit?: ((data: unknown, query: any) => unknown | Promise<unknown>)[];
|
|
803
|
+
}
|
|
804
|
+
type HookSelect = Map<string, HookSelectValue>;
|
|
805
|
+
interface HookSelectValue {
|
|
806
|
+
select: string | {
|
|
807
|
+
sql: string;
|
|
808
|
+
};
|
|
809
|
+
as?: string;
|
|
810
|
+
temp?: string;
|
|
811
|
+
}
|
|
812
|
+
interface HasTableHook {
|
|
813
|
+
tableHook?: TableHook;
|
|
814
|
+
}
|
|
815
|
+
interface HasHookSelect {
|
|
816
|
+
hookSelect?: HookSelect;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
interface PickQueryDataParsers {
|
|
820
|
+
defaultParsers?: ColumnsParsers;
|
|
821
|
+
parsers?: ColumnsParsers;
|
|
822
|
+
batchParsers?: BatchParsers;
|
|
823
|
+
}
|
|
824
|
+
type ColumnParser = FnUnknownToUnknown;
|
|
825
|
+
interface BatchParser {
|
|
826
|
+
path: string[];
|
|
827
|
+
fn: (path: string[], queryResult: {
|
|
828
|
+
rows: unknown[];
|
|
829
|
+
}) => MaybePromise<void>;
|
|
830
|
+
}
|
|
831
|
+
type ColumnsParsers = {
|
|
832
|
+
[K in string | getValueKey]?: ColumnParser;
|
|
833
|
+
};
|
|
834
|
+
type BatchParsers = BatchParser[];
|
|
835
|
+
|
|
836
|
+
interface QueryDataBase extends QueryDataAliases, PickQueryDataParsers, HasHookSelect {
|
|
837
|
+
shape: QueryColumnsInit;
|
|
838
|
+
select?: unknown;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
interface SqlCommonOptions extends HasTableHook, HasCteHooks {
|
|
842
|
+
delayedRelationSelect?: DelayedRelationSelect;
|
|
843
|
+
}
|
|
844
|
+
interface SingleSqlItem {
|
|
845
|
+
text: string;
|
|
846
|
+
values?: unknown[];
|
|
847
|
+
}
|
|
848
|
+
interface SingleSql extends SingleSqlItem, SqlCommonOptions {
|
|
849
|
+
}
|
|
850
|
+
interface QueryMetaBase<Scopes extends RecordKeyTrue = RecordKeyTrue> {
|
|
851
|
+
kind: string;
|
|
852
|
+
as?: string;
|
|
853
|
+
subQuery: boolean;
|
|
854
|
+
hasSelect?: true;
|
|
855
|
+
hasWhere?: true;
|
|
856
|
+
defaults: EmptyObject;
|
|
857
|
+
tsQuery?: string;
|
|
858
|
+
scopes: Scopes;
|
|
859
|
+
selectable: SelectableBase;
|
|
860
|
+
defaultSelect: PropertyKey;
|
|
861
|
+
}
|
|
862
|
+
interface QueryInternalTableDataPrimaryKey {
|
|
863
|
+
columns: string[];
|
|
864
|
+
name?: string;
|
|
865
|
+
}
|
|
866
|
+
interface QueryInternalTableDataBase {
|
|
867
|
+
primaryKey?: QueryInternalTableDataPrimaryKey;
|
|
868
|
+
}
|
|
869
|
+
interface QueryInternalBase extends QueryInternalColumnNameToKey {
|
|
870
|
+
runtimeDefaultColumns?: string[];
|
|
871
|
+
transactionStorage: AsyncLocalStorage<TransactionState>;
|
|
872
|
+
scopes?: RecordUnknown;
|
|
873
|
+
snakeCase?: boolean;
|
|
874
|
+
noPrimaryKey: boolean;
|
|
875
|
+
comment?: string;
|
|
876
|
+
primaryKeys?: string[];
|
|
877
|
+
tableData: QueryInternalTableDataBase;
|
|
878
|
+
}
|
|
879
|
+
interface IsQuery {
|
|
880
|
+
__isQuery: true;
|
|
881
|
+
}
|
|
882
|
+
interface QueryBase extends IsQuery {
|
|
883
|
+
internal: QueryInternalBase;
|
|
884
|
+
shape: QueryColumns;
|
|
885
|
+
q: QueryDataBase;
|
|
886
|
+
table?: string;
|
|
887
|
+
}
|
|
888
|
+
interface QueryBaseCommon<Scopes extends RecordKeyTrue = RecordKeyTrue> extends QueryBase {
|
|
889
|
+
meta: QueryMetaBase<Scopes>;
|
|
890
|
+
}
|
|
891
|
+
interface SelectableBase {
|
|
892
|
+
[K: PropertyKey]: {
|
|
893
|
+
as: string;
|
|
894
|
+
column: QueryColumn;
|
|
895
|
+
};
|
|
896
|
+
}
|
|
897
|
+
type getValueKey = typeof getValueKey;
|
|
898
|
+
declare const getValueKey: unique symbol;
|
|
899
|
+
interface QueryOrExpression<T> {
|
|
900
|
+
result: {
|
|
901
|
+
value: QueryColumn<T>;
|
|
902
|
+
};
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
interface QueryLogObject {
|
|
906
|
+
colors: boolean;
|
|
907
|
+
beforeQuery(sql: SingleSql): unknown;
|
|
908
|
+
afterQuery(sql: SingleSql, logData: unknown): void;
|
|
909
|
+
onError(error: Error, sql: SingleSql, logData: unknown): void;
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
declare class OrchidOrmInternalError extends Error {
|
|
913
|
+
#private;
|
|
914
|
+
data?: RecordUnknown | undefined;
|
|
915
|
+
constructor(query: QueryBase, message?: string, data?: RecordUnknown | undefined);
|
|
916
|
+
get query(): QueryBase;
|
|
917
|
+
}
|
|
918
|
+
type QueryErrorName = 'parseComplete' | 'bindComplete' | 'closeComplete' | 'noData' | 'portalSuspended' | 'replicationStart' | 'emptyQuery' | 'copyDone' | 'copyData' | 'rowDescription' | 'parameterDescription' | 'parameterStatus' | 'backendKeyData' | 'notification' | 'readyForQuery' | 'commandComplete' | 'dataRow' | 'copyInResponse' | 'copyOutResponse' | 'authenticationOk' | 'authenticationMD5Password' | 'authenticationCleartextPassword' | 'authenticationSASL' | 'authenticationSASLContinue' | 'authenticationSASLFinal' | 'error' | 'notice';
|
|
919
|
+
declare abstract class QueryError<T extends PickQueryShape = PickQueryShape> extends OrchidOrmInternalError {
|
|
920
|
+
message: string;
|
|
921
|
+
name: QueryErrorName;
|
|
922
|
+
stack: string | undefined;
|
|
923
|
+
code: string | undefined;
|
|
924
|
+
detail: string | undefined;
|
|
925
|
+
severity: string | undefined;
|
|
926
|
+
hint: string | undefined;
|
|
927
|
+
position: string | undefined;
|
|
928
|
+
internalPosition: string | undefined;
|
|
929
|
+
internalQuery: string | undefined;
|
|
930
|
+
where: string | undefined;
|
|
931
|
+
schema: string | undefined;
|
|
932
|
+
table: string | undefined;
|
|
933
|
+
column: string | undefined;
|
|
934
|
+
dataType: string | undefined;
|
|
935
|
+
constraint: string | undefined;
|
|
936
|
+
file: string | undefined;
|
|
937
|
+
line: string | undefined;
|
|
938
|
+
routine: string | undefined;
|
|
939
|
+
get isUnique(): boolean;
|
|
940
|
+
columnsCache?: {
|
|
941
|
+
[K in keyof T['shape']]?: true;
|
|
942
|
+
};
|
|
943
|
+
get columns(): { [K in keyof T["shape"]]?: true | undefined; };
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
/**
|
|
947
|
+
* Generic result returning from query methods.
|
|
948
|
+
*/
|
|
949
|
+
interface QueryResultRow {
|
|
950
|
+
[K: string]: any;
|
|
951
|
+
}
|
|
952
|
+
interface QueryResult<T extends QueryResultRow = any> {
|
|
953
|
+
rowCount: number;
|
|
954
|
+
rows: T[];
|
|
955
|
+
fields: {
|
|
956
|
+
name: string;
|
|
957
|
+
}[];
|
|
958
|
+
}
|
|
959
|
+
interface QueryArraysResult<R extends any[] = any[]> {
|
|
960
|
+
rowCount: number;
|
|
961
|
+
rows: R[];
|
|
962
|
+
fields: {
|
|
963
|
+
name: string;
|
|
964
|
+
}[];
|
|
965
|
+
}
|
|
966
|
+
interface AdapterConfigBase {
|
|
967
|
+
databaseURL?: string;
|
|
968
|
+
/**
|
|
969
|
+
* This option may be useful in CI when database container has started, CI starts performing next steps,
|
|
970
|
+
* migrations begin to apply though database may be not fully ready for connections yet.
|
|
971
|
+
*
|
|
972
|
+
* Set `connectRetry: true` for the default backoff strategy. It performs 10 attempts starting with 50ms delay and increases delay exponentially according to this formula:
|
|
973
|
+
*
|
|
974
|
+
* ```
|
|
975
|
+
* (factor, defaults to 1.5) ** (currentAttempt - 1) * (delay, defaults to 50)
|
|
976
|
+
* ```
|
|
977
|
+
*
|
|
978
|
+
* So the 2nd attempt will happen in 50ms from start, 3rd attempt in 125ms, 3rd in 237ms, and so on.
|
|
979
|
+
*
|
|
980
|
+
* You can customize max attempts to be made, `factor` multiplier and the starting delay by passing:
|
|
981
|
+
*
|
|
982
|
+
* ```ts
|
|
983
|
+
* const options = {
|
|
984
|
+
* databaseURL: process.env.DATABASE_URL,
|
|
985
|
+
* connectRetry: {
|
|
986
|
+
* attempts: 15, // max attempts
|
|
987
|
+
* strategy: {
|
|
988
|
+
* delay: 100, // initial delay
|
|
989
|
+
* factor: 2, // multiplier for the formula above
|
|
990
|
+
* }
|
|
991
|
+
* }
|
|
992
|
+
* };
|
|
993
|
+
*
|
|
994
|
+
* rakeDb(options, { ... });
|
|
995
|
+
* ```
|
|
996
|
+
*
|
|
997
|
+
* You can pass a custom function to `strategy` to customize delay behavior:
|
|
998
|
+
*
|
|
999
|
+
* ```ts
|
|
1000
|
+
* import { setTimeout } from 'timers/promises';
|
|
1001
|
+
*
|
|
1002
|
+
* const options = {
|
|
1003
|
+
* databaseURL: process.env.DATABASE_URL,
|
|
1004
|
+
* connectRetry: {
|
|
1005
|
+
* attempts: 5,
|
|
1006
|
+
* stragegy(currentAttempt: number, maxAttempts: number) {
|
|
1007
|
+
* // linear: wait 100ms after 1st attempt, then 200m after 2nd, and so on.
|
|
1008
|
+
* return setTimeout(currentAttempt * 100);
|
|
1009
|
+
* },
|
|
1010
|
+
* },
|
|
1011
|
+
* };
|
|
1012
|
+
* ```
|
|
1013
|
+
*/
|
|
1014
|
+
connectRetry?: AdapterConfigConnectRetryParam | true;
|
|
1015
|
+
}
|
|
1016
|
+
interface AdapterConfigConnectRetryParam {
|
|
1017
|
+
attempts?: number;
|
|
1018
|
+
strategy?: AdapterConfigConnectRetryStrategyParam | AdapterConfigConnectRetryStrategy;
|
|
1019
|
+
}
|
|
1020
|
+
interface AdapterConfigConnectRetryStrategyParam {
|
|
1021
|
+
delay?: number;
|
|
1022
|
+
factor?: number;
|
|
1023
|
+
}
|
|
1024
|
+
interface AdapterConfigConnectRetry {
|
|
1025
|
+
attempts: number;
|
|
1026
|
+
strategy: AdapterConfigConnectRetryStrategy;
|
|
1027
|
+
}
|
|
1028
|
+
interface AdapterConfigConnectRetryStrategy {
|
|
1029
|
+
(attempt: number, attempts: number): Promise<void> | void;
|
|
1030
|
+
}
|
|
1031
|
+
interface AdapterBase {
|
|
1032
|
+
connectRetryConfig?: AdapterConfigConnectRetry;
|
|
1033
|
+
schema?: string;
|
|
1034
|
+
errorClass: new (...args: any[]) => Error;
|
|
1035
|
+
assignError(to: QueryError, from: Error): void;
|
|
1036
|
+
reconfigure(params: {
|
|
1037
|
+
database?: string;
|
|
1038
|
+
user?: string;
|
|
1039
|
+
password?: string;
|
|
1040
|
+
schema?: string;
|
|
1041
|
+
}): AdapterBase;
|
|
1042
|
+
getDatabase(): string;
|
|
1043
|
+
getUser(): string;
|
|
1044
|
+
getSchema(): string | undefined;
|
|
1045
|
+
getHost(): string;
|
|
1046
|
+
connect?(): Promise<unknown>;
|
|
1047
|
+
query<T extends QueryResultRow = QueryResultRow>(text: string, values?: unknown[]): Promise<QueryResult<T>>;
|
|
1048
|
+
arrays<R extends any[] = any[]>(text: string, values?: unknown[]): Promise<QueryArraysResult<R>>;
|
|
1049
|
+
/**
|
|
1050
|
+
* Run a transaction
|
|
1051
|
+
*
|
|
1052
|
+
* @param options - optional transaction parameters
|
|
1053
|
+
* @param cb - callback will be called with a db client with a dedicated connection.
|
|
1054
|
+
*/
|
|
1055
|
+
transaction<T>(options: string | undefined, cb: (adapter: AdapterBase) => Promise<T>): Promise<T>;
|
|
1056
|
+
close(): Promise<void>;
|
|
1057
|
+
}
|
|
1058
|
+
interface TransactionState {
|
|
1059
|
+
adapter: AdapterBase;
|
|
1060
|
+
transactionId: number;
|
|
1061
|
+
afterCommit?: TransactionAfterCommitHook[];
|
|
1062
|
+
log?: QueryLogObject;
|
|
1063
|
+
testTransactionCount?: number;
|
|
1064
|
+
}
|
|
1065
|
+
/**
|
|
1066
|
+
* Element of `afterCommit` transaction array. See {@link TransactionState.afterCommit}.
|
|
1067
|
+
*/
|
|
1068
|
+
type TransactionAfterCommitHook = unknown[] | QueryBaseCommon | AfterCommitHook[] | AfterCommitStandaloneHook;
|
|
1069
|
+
interface AfterCommitHook {
|
|
1070
|
+
(data: unknown[], q: QueryBaseCommon): unknown | Promise<unknown>;
|
|
1071
|
+
}
|
|
1072
|
+
interface AfterCommitStandaloneHook {
|
|
1073
|
+
(): unknown | Promise<unknown>;
|
|
1074
|
+
}
|
|
5
1075
|
|
|
6
1076
|
interface CreatePostgresJsDbOptions<SchemaConfig extends ColumnSchemaConfig, ColumnTypes> extends PostgresJsAdapterOptions, DbOptions<SchemaConfig, ColumnTypes> {
|
|
7
1077
|
}
|
|
8
|
-
declare const createDb: <SchemaConfig extends ColumnSchemaConfig<
|
|
1078
|
+
declare const createDb: <SchemaConfig extends ColumnSchemaConfig<pqb.ColumnTypeBase<pqb.ColumnTypeSchemaArg, unknown, any, any, unknown, unknown, any, unknown, any, pqb.ColumnDataBase>> = DefaultSchemaConfig, ColumnTypes = DefaultColumnTypes<SchemaConfig>>(options: CreatePostgresJsDbOptions<SchemaConfig, ColumnTypes>) => DbResult<ColumnTypes>;
|
|
9
1079
|
interface PostgresJsAdapterOptions extends postgres.Options<any>, AdapterConfigBase {
|
|
10
1080
|
databaseURL?: string;
|
|
11
1081
|
schema?: string;
|
|
@@ -31,7 +1101,7 @@ declare class PostgresJsAdapter implements AdapterBase {
|
|
|
31
1101
|
arrays<R extends any[] = any[]>(text: string, values?: unknown[]): Promise<QueryArraysResult<R>>;
|
|
32
1102
|
transaction<Result>(options: string | undefined, cb: (adapter: AdapterBase) => Promise<Result>): Promise<Result>;
|
|
33
1103
|
close(): Promise<void>;
|
|
34
|
-
assignError(to: QueryError, dbError: Error): void;
|
|
1104
|
+
assignError(to: QueryError, dbError: Error$1): void;
|
|
35
1105
|
}
|
|
36
1106
|
declare class PostgresJsTransactionAdapter implements AdapterBase {
|
|
37
1107
|
adapter: PostgresJsAdapter;
|
|
@@ -52,7 +1122,7 @@ declare class PostgresJsTransactionAdapter implements AdapterBase {
|
|
|
52
1122
|
arrays<R extends any[] = any[]>(text: string, values?: unknown[]): Promise<QueryArraysResult<R>>;
|
|
53
1123
|
transaction<Result>(_options: string | undefined, cb: (adapter: PostgresJsTransactionAdapter) => Promise<Result>): Promise<Result>;
|
|
54
1124
|
close(): Promise<void>;
|
|
55
|
-
assignError(to: QueryError, from: Error): void;
|
|
1125
|
+
assignError(to: QueryError, from: Error$1): void;
|
|
56
1126
|
}
|
|
57
1127
|
|
|
58
1128
|
export { type CreatePostgresJsDbOptions, PostgresJsAdapter, type PostgresJsAdapterOptions, PostgresJsTransactionAdapter, createDb };
|