pqb 0.57.6 → 0.58.0

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.
@@ -1,1082 +1,10 @@
1
1
  import * as pqb from 'pqb';
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[], catchingSavepoint?: string): Promise<QueryResult<T>>;
1048
- arrays<R extends any[] = any[]>(text: string, values?: unknown[], catchingSavepoint?: string): 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
- catchI?: number;
1065
- }
1066
- /**
1067
- * Element of `afterCommit` transaction array. See {@link TransactionState.afterCommit}.
1068
- */
1069
- type TransactionAfterCommitHook = unknown[] | QueryBaseCommon | AfterCommitHook[] | AfterCommitStandaloneHook;
1070
- interface AfterCommitHook {
1071
- (data: unknown[], q: QueryBaseCommon): unknown | Promise<unknown>;
1072
- }
1073
- interface AfterCommitStandaloneHook {
1074
- (): unknown | Promise<unknown>;
1075
- }
2
+ import { ColumnSchemaConfig, DbOptions, DefaultSchemaConfig, DefaultColumnTypes, DbResult, AdapterConfigBase, AdapterBase, QueryResultRow, QueryResult, QueryArraysResult, QueryError } from 'pqb';
3
+ import postgres, { Error } from 'postgres';
1076
4
 
1077
5
  interface CreatePostgresJsDbOptions<SchemaConfig extends ColumnSchemaConfig, ColumnTypes> extends PostgresJsAdapterOptions, DbOptions<SchemaConfig, ColumnTypes> {
1078
6
  }
1079
- 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>;
7
+ declare const createDb: <SchemaConfig extends ColumnSchemaConfig<pqb.Column.Pick.Data> = DefaultSchemaConfig, ColumnTypes = DefaultColumnTypes<SchemaConfig>>(options: CreatePostgresJsDbOptions<SchemaConfig, ColumnTypes>) => DbResult<ColumnTypes>;
1080
8
  interface PostgresJsAdapterOptions extends postgres.Options<any>, AdapterConfigBase {
1081
9
  databaseURL?: string;
1082
10
  schema?: string;
@@ -1087,7 +15,9 @@ declare class PostgresJsAdapter implements AdapterBase {
1087
15
  config: PostgresJsAdapterOptions;
1088
16
  errorClass: typeof postgres.PostgresError;
1089
17
  constructor(config: PostgresJsAdapterOptions);
18
+ private configure;
1090
19
  private getURL;
20
+ updateConfig(config: PostgresJsAdapterOptions): Promise<void>;
1091
21
  reconfigure(params: {
1092
22
  database?: string;
1093
23
  user?: string;
@@ -1098,17 +28,18 @@ declare class PostgresJsAdapter implements AdapterBase {
1098
28
  getUser(): string;
1099
29
  getSchema(): string | undefined;
1100
30
  getHost(): string;
1101
- query<T extends QueryResultRow = QueryResultRow>(text: string, values?: unknown[], catchingSavepoint?: string): Promise<QueryResult<T>>;
1102
- arrays<R extends any[] = any[]>(text: string, values?: unknown[], catchingSavepoint?: string): Promise<QueryArraysResult<R>>;
31
+ query<T extends QueryResultRow = QueryResultRow>(text: string, values?: unknown[]): Promise<QueryResult<T>>;
32
+ arrays<R extends any[] = any[]>(text: string, values?: unknown[]): Promise<QueryArraysResult<R>>;
1103
33
  transaction<Result>(options: string | undefined, cb: (adapter: AdapterBase) => Promise<Result>): Promise<Result>;
1104
34
  close(): Promise<void>;
1105
- assignError(to: QueryError, dbError: Error$1): void;
35
+ assignError(to: QueryError, dbError: Error): void;
1106
36
  }
1107
37
  declare class PostgresJsTransactionAdapter implements AdapterBase {
1108
38
  adapter: PostgresJsAdapter;
1109
39
  sql: postgres.Sql;
1110
40
  errorClass: typeof postgres.PostgresError;
1111
41
  constructor(adapter: PostgresJsAdapter, sql: postgres.Sql);
42
+ updateConfig(config: PostgresJsAdapterOptions): Promise<void>;
1112
43
  reconfigure(params: {
1113
44
  database?: string;
1114
45
  user?: string;
@@ -1123,7 +54,7 @@ declare class PostgresJsTransactionAdapter implements AdapterBase {
1123
54
  arrays<R extends any[] = any[]>(text: string, values?: unknown[], catchingSavepoint?: string): Promise<QueryArraysResult<R>>;
1124
55
  transaction<Result>(_options: string | undefined, cb: (adapter: PostgresJsTransactionAdapter) => Promise<Result>): Promise<Result>;
1125
56
  close(): Promise<void>;
1126
- assignError(to: QueryError, from: Error$1): void;
57
+ assignError(to: QueryError, from: Error): void;
1127
58
  }
1128
59
 
1129
60
  export { type CreatePostgresJsDbOptions, PostgresJsAdapter, type PostgresJsAdapterOptions, PostgresJsTransactionAdapter, createDb };