orchid-orm 1.67.0 → 1.68.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.
package/dist/index.d.ts CHANGED
@@ -1,793 +1,753 @@
1
- import { Column, TableData, ColumnsShape, RelationConfigBase, QueryManyTake, QueryManyTakeOptional, EmptyObject, CreateData, UpdateData, WhereArg, SelectableFromShape, CreateManyMethodsNames, QueryHasWhere, CreateMethodsNames, MaybeArray, JoinQueryMethod, DeleteMethodsNames, IsolationLevel, TransactionOptions, AfterCommitStandaloneHook, AdapterBase, FromArg, FromResult, StorageOptions, DbSharedOptions, ColumnSchemaConfig, DbSqlMethod, TableDataItem, QueryData, IsQuery, TableDataFn, ComputedOptionsFactory, DbTableOptionScopes, QueryScopes, RecordUnknown, QueryBeforeHook, QueryAfterHook, QueryBeforeActionHook, AfterHook, ShallowSimplify, ShapeColumnPrimaryKeys, ShapeUniqueColumns, TableDataItemsUniqueColumns, TableDataItemsUniqueColumnTuples, UniqueConstraints, TableDataItemsUniqueConstraints, ComputedColumnsFromOptions, MapTableScopesOption, ComputedOptionsConfig, QueryOrExpression, DefaultSchemaConfig, DefaultColumnTypes, QueryReturnType, MergeQuery } from 'pqb/internal';
2
- import { Query, Db, QuerySchema } from 'pqb';
3
- export * from 'pqb';
4
-
1
+ import { Adapter, AfterCommitStandaloneHook, AfterHook, Column, ColumnSchemaConfig, ColumnsShape, ComputedColumnsFromOptions, ComputedOptionsConfig, ComputedOptionsFactory, CreateData, CreateManyMethodsNames, CreateMethodsNames, DbSharedOptions, DbSqlMethod, DbTableOptionScopes, DefaultColumnTypes, DefaultSchemaConfig, DeleteMethodsNames, EmptyObject, FromArg, FromResult, IsQuery, IsolationLevel, JoinQueryMethod, MapTableScopesOption, MaybeArray, MergeQuery, QueryAfterHook, QueryBeforeActionHook, QueryBeforeHook, QueryData, QueryHasWhere, QueryManyTake, QueryManyTakeOptional, QueryOrExpression, QueryReturnType, QuerySchema, QueryScopes, RecordUnknown, RelationConfigBase, SelectableFromShape, ShallowSimplify, ShapeColumnPrimaryKeys, ShapeUniqueColumns, StorageOptions, TableData, TableDataFn, TableDataItem, TableDataItemsUniqueColumnTuples, TableDataItemsUniqueColumns, TableDataItemsUniqueConstraints, TransactionOptions, UniqueConstraints, UpdateData, WhereArg } from "pqb/internal";
2
+ import { Db, Query } from "pqb";
3
+ export * from "pqb";
5
4
  interface RelationRefsOptions<Column extends PropertyKey = string, Shape extends Column.Shape.QueryInit = Column.Shape.QueryInit> {
6
- required?: boolean;
7
- columns: Column[];
8
- references: (keyof Shape)[];
9
- foreignKey?: boolean | TableData.References.Options;
10
- on?: ColumnsShape.InputPartial<Shape>;
5
+ required?: boolean;
6
+ columns: Column[];
7
+ references: (keyof Shape)[];
8
+ foreignKey?: boolean | TableData.References.Options;
9
+ on?: ColumnsShape.InputPartial<Shape>;
11
10
  }
12
11
  interface RelationThroughOptions<Through extends PropertyKey = string, Source extends PropertyKey = string> {
13
- through: Through;
14
- source: Source;
12
+ through: Through;
13
+ source: Source;
15
14
  }
16
-
17
15
  interface HasOne extends RelationThunkBase {
18
- type: 'hasOne';
19
- options: HasOneOptions;
16
+ type: 'hasOne';
17
+ options: HasOneOptions;
20
18
  }
21
19
  interface RelationHasOneThroughOptions<Through extends string, Source extends string> extends RelationThroughOptions<Through, Source> {
22
- required?: boolean;
20
+ required?: boolean;
23
21
  }
24
22
  type HasOneOptions<Columns extends Column.Shape.QueryInit = Column.Shape.QueryInit, Related extends ORMTableInput = ORMTableInput, Through extends string = string, Source extends string = string> = RelationRefsOptions<keyof Columns, Related['columns']['shape']> | RelationHasOneThroughOptions<Through, Source>;
25
- type HasOneParams<T extends RelationConfigSelf, Options> = Options extends RelationRefsOptions ? {
26
- [Name in Options['columns'][number]]: T['columns']['shape'][Name]['type'];
27
- } : Options extends RelationThroughOptions ? RelationConfigParams<T, T['relations'][Options['through']]> : never;
28
- type HasOneQueryThrough<Name extends string, TableQuery extends Query> = {
29
- [K in keyof TableQuery]: K extends '__selectable' ? SelectableFromShape<TableQuery['shape'], Name> : K extends '__as' ? Name : K extends CreateMethodsNames ? never : TableQuery[K];
30
- } & QueryHasWhere & HasRelJoin;
31
- type HasOneQuery<T extends RelationConfigSelf, Name extends string, TableQuery extends Query> = T['relations'][Name]['options'] extends RelationRefsOptions ? {
32
- [K in keyof TableQuery]: K extends '__defaults' ? {
33
- [K in keyof TableQuery['__defaults'] | T['relations'][Name]['options']['references'][number]]: true;
34
- } : K extends '__selectable' ? SelectableFromShape<TableQuery['shape'], Name> : K extends '__as' ? Name : K extends CreateManyMethodsNames ? never : TableQuery[K];
35
- } & QueryHasWhere & HasRelJoin : HasOneQueryThrough<Name, TableQuery>;
23
+ type HasOneParams<T extends RelationConfigSelf, Options> = Options extends RelationRefsOptions ? { [Name in Options['columns'][number]]: T['columns']['shape'][Name]['type'] } : Options extends RelationThroughOptions ? RelationConfigParams<T, T['relations'][Options['through']]> : never;
24
+ type HasOneQueryThrough<Name extends string, TableQuery extends Query> = { [K in keyof TableQuery]: K extends '__selectable' ? SelectableFromShape<TableQuery['shape'], Name> : K extends '__as' ? Name : K extends CreateMethodsNames ? never : TableQuery[K] } & QueryHasWhere & HasRelJoin;
25
+ type HasOneQuery<T extends RelationConfigSelf, Name extends string, TableQuery extends Query> = T['relations'][Name]['options'] extends RelationRefsOptions ? { [K in keyof TableQuery]: K extends '__defaults' ? { [K in keyof TableQuery['__defaults'] | T['relations'][Name]['options']['references'][number]]: true } : K extends '__selectable' ? SelectableFromShape<TableQuery['shape'], Name> : K extends '__as' ? Name : K extends CreateManyMethodsNames ? never : TableQuery[K] } & QueryHasWhere & HasRelJoin : HasOneQueryThrough<Name, TableQuery>;
36
26
  interface HasOneInfo<T extends RelationConfigSelf, Name extends string, Rel extends HasOne, Q extends Query> extends RelationConfigBase {
37
- returnsOne: true;
38
- query: Q;
39
- params: HasOneParams<T, Rel['options']>;
40
- maybeSingle: T['relations'][Name]['options']['required'] extends true ? QueryManyTake<Q> : QueryManyTakeOptional<Q>;
41
- omitForeignKeyInCreate: never;
42
- optionalDataForCreate: T['relations'][Name]['options'] extends RelationThroughOptions ? EmptyObject : {
43
- [P in Name]?: RelationToOneDataForCreate<{
44
- nestedCreateQuery: CreateData<Q>;
45
- table: Q;
46
- }>;
47
- };
48
- dataForCreate: never;
49
- dataForUpdate: {
50
- disconnect: boolean;
51
- } | {
52
- delete: boolean;
53
- } | {
54
- update: UpdateData<Q>;
55
- };
56
- dataForUpdateOne: {
57
- disconnect: boolean;
58
- } | {
59
- set: WhereArg<Q>;
60
- } | {
61
- delete: boolean;
62
- } | {
63
- update: UpdateData<Q>;
64
- } | {
65
- upsert: {
66
- update: UpdateData<Q>;
67
- create: CreateData<Q> | (() => CreateData<Q>);
68
- };
69
- } | {
70
- create: CreateData<Q>;
27
+ returnsOne: true;
28
+ query: Q;
29
+ params: HasOneParams<T, Rel['options']>;
30
+ maybeSingle: T['relations'][Name]['options']['required'] extends true ? QueryManyTake<Q> : QueryManyTakeOptional<Q>;
31
+ omitForeignKeyInCreate: never;
32
+ optionalDataForCreate: T['relations'][Name]['options'] extends RelationThroughOptions ? EmptyObject : { [P in Name]?: RelationToOneDataForCreate<{
33
+ nestedCreateQuery: CreateData<Q>;
34
+ table: Q;
35
+ }> };
36
+ dataForCreate: never;
37
+ dataForUpdate: {
38
+ disconnect: boolean;
39
+ } | {
40
+ delete: boolean;
41
+ } | {
42
+ update: UpdateData<Q>;
43
+ };
44
+ dataForUpdateOne: {
45
+ disconnect: boolean;
46
+ } | {
47
+ set: WhereArg<Q>;
48
+ } | {
49
+ delete: boolean;
50
+ } | {
51
+ update: UpdateData<Q>;
52
+ } | {
53
+ upsert: {
54
+ update: UpdateData<Q>;
55
+ create: CreateData<Q> | (() => CreateData<Q>);
71
56
  };
57
+ } | {
58
+ create: CreateData<Q>;
59
+ };
72
60
  }
73
-
74
61
  interface HasMany extends RelationThunkBase {
75
- type: 'hasMany';
76
- options: HasOneOptions;
62
+ type: 'hasMany';
63
+ options: HasOneOptions;
77
64
  }
78
- type HasManyQuery<T extends RelationConfigSelf, Name extends string, TableQuery extends Query> = T['relations'][Name]['options'] extends RelationRefsOptions ? {
79
- [K in keyof TableQuery]: K extends '__defaults' ? {
80
- [K in keyof TableQuery['__defaults'] | T['relations'][Name]['options']['references'][number]]: true;
81
- } : K extends '__selectable' ? SelectableFromShape<TableQuery['shape'], Name> : K extends '__as' ? Name : TableQuery[K];
82
- } & QueryHasWhere & HasRelJoin : HasOneQueryThrough<Name, TableQuery>;
65
+ type HasManyQuery<T extends RelationConfigSelf, Name extends string, TableQuery extends Query> = T['relations'][Name]['options'] extends RelationRefsOptions ? { [K in keyof TableQuery]: K extends '__defaults' ? { [K in keyof TableQuery['__defaults'] | T['relations'][Name]['options']['references'][number]]: true } : K extends '__selectable' ? SelectableFromShape<TableQuery['shape'], Name> : K extends '__as' ? Name : TableQuery[K] } & QueryHasWhere & HasRelJoin : HasOneQueryThrough<Name, TableQuery>;
83
66
  interface HasManyInfo<T extends RelationConfigSelf, Name extends string, Rel extends HasMany, Q extends Query> extends RelationConfigBase {
84
- returnsOne: false;
85
- query: Q;
86
- params: HasOneParams<T, Rel['options']>;
87
- maybeSingle: Q;
88
- omitForeignKeyInCreate: never;
89
- optionalDataForCreate: {
90
- [P in Name]?: T['relations'][Name]['options'] extends RelationThroughOptions ? EmptyObject : {
91
- create?: CreateData<Q>[];
92
- connect?: WhereArg<Q>[];
93
- connectOrCreate?: {
94
- where: WhereArg<Q>;
95
- create: CreateData<Q>;
96
- }[];
97
- };
98
- };
99
- dataForCreate: never;
100
- dataForUpdate: {
101
- disconnect?: MaybeArray<WhereArg<Q>>;
102
- delete?: MaybeArray<WhereArg<Q>>;
103
- update?: {
104
- where: MaybeArray<WhereArg<Q>>;
105
- data: UpdateData<Q>;
106
- };
67
+ returnsOne: false;
68
+ query: Q;
69
+ params: HasOneParams<T, Rel['options']>;
70
+ maybeSingle: Q;
71
+ omitForeignKeyInCreate: never;
72
+ optionalDataForCreate: { [P in Name]?: T['relations'][Name]['options'] extends RelationThroughOptions ? EmptyObject : {
73
+ create?: CreateData<Q>[];
74
+ connect?: WhereArg<Q>[];
75
+ connectOrCreate?: {
76
+ where: WhereArg<Q>;
77
+ create: CreateData<Q>;
78
+ }[];
79
+ } };
80
+ dataForCreate: never;
81
+ dataForUpdate: {
82
+ disconnect?: MaybeArray<WhereArg<Q>>;
83
+ delete?: MaybeArray<WhereArg<Q>>;
84
+ update?: {
85
+ where: MaybeArray<WhereArg<Q>>;
86
+ data: UpdateData<Q>;
107
87
  };
108
- dataForUpdateOne: {
109
- disconnect?: MaybeArray<WhereArg<Q>>;
110
- delete?: MaybeArray<WhereArg<Q>>;
111
- update?: {
112
- where: MaybeArray<WhereArg<Q>>;
113
- data: UpdateData<Q>;
114
- };
115
- set?: MaybeArray<WhereArg<Q>>;
116
- add?: MaybeArray<WhereArg<Q>>;
117
- create?: CreateData<Q>[];
88
+ };
89
+ dataForUpdateOne: {
90
+ disconnect?: MaybeArray<WhereArg<Q>>;
91
+ delete?: MaybeArray<WhereArg<Q>>;
92
+ update?: {
93
+ where: MaybeArray<WhereArg<Q>>;
94
+ data: UpdateData<Q>;
118
95
  };
96
+ set?: MaybeArray<WhereArg<Q>>;
97
+ add?: MaybeArray<WhereArg<Q>>;
98
+ create?: CreateData<Q>[];
99
+ };
119
100
  }
120
-
121
101
  interface RelJoin extends JoinQueryMethod {
122
- <T extends Query>(this: T): T;
102
+ <T extends Query>(this: T): T;
123
103
  }
124
104
  interface HasRelJoin {
125
- join: RelJoin;
105
+ join: RelJoin;
126
106
  }
127
-
128
107
  interface BelongsTo extends RelationThunkBase {
129
- type: 'belongsTo';
130
- options: BelongsToOptions;
108
+ type: 'belongsTo';
109
+ options: BelongsToOptions;
131
110
  }
132
111
  interface BelongsToOptions<Columns extends Column.Shape.QueryInit = Column.Shape.QueryInit, Related extends ORMTableInput = ORMTableInput> {
133
- required?: boolean;
134
- columns: (keyof Columns)[];
135
- references: (keyof Related['columns']['shape'])[];
136
- foreignKey?: boolean | TableData.References.Options;
137
- on?: ColumnsShape.InputPartial<Related['columns']['shape']>;
112
+ required?: boolean;
113
+ columns: (keyof Columns)[];
114
+ references: (keyof Related['columns']['shape'])[];
115
+ foreignKey?: boolean | TableData.References.Options;
116
+ on?: ColumnsShape.InputPartial<Related['columns']['shape']>;
138
117
  }
139
- type BelongsToParams<T extends RelationConfigSelf, FK extends string> = {
140
- [Name in FK]: T['columns']['shape'][Name]['type'];
141
- };
142
- type BelongsToQuery<T extends Query, Name extends string> = {
143
- [P in keyof T]: P extends '__selectable' ? SelectableFromShape<T['shape'], Name> : P extends '__as' ? Name : P extends CreateMethodsNames | DeleteMethodsNames ? never : T[P];
144
- } & QueryHasWhere & HasRelJoin;
118
+ type BelongsToParams<T extends RelationConfigSelf, FK extends string> = { [Name in FK]: T['columns']['shape'][Name]['type'] };
119
+ type BelongsToQuery<T extends Query, Name extends string> = { [P in keyof T]: P extends '__selectable' ? SelectableFromShape<T['shape'], Name> : P extends '__as' ? Name : P extends CreateMethodsNames | DeleteMethodsNames ? never : T[P] } & QueryHasWhere & HasRelJoin;
145
120
  interface BelongsToInfo<T extends RelationConfigSelf, Name extends string, FK extends string, Required, Q extends Query> extends RelationConfigBase {
146
- returnsOne: true;
147
- query: Q;
148
- params: BelongsToParams<T, FK>;
149
- maybeSingle: Required extends true ? QueryManyTake<Q> : QueryManyTakeOptional<Q>;
150
- omitForeignKeyInCreate: FK;
151
- dataForCreate: {
152
- columns: FK;
153
- nested: Required extends true ? {
154
- [Key in Name]: RelationToOneDataForCreateSameQuery<Q>;
155
- } : {
156
- [Key in Name]?: RelationToOneDataForCreateSameQuery<Q>;
157
- };
158
- };
159
- optionalDataForCreate: EmptyObject;
160
- dataForUpdate: {
161
- disconnect: boolean;
162
- } | {
163
- set: WhereArg<Q>;
164
- } | {
165
- delete: boolean;
166
- } | {
167
- update: UpdateData<Q>;
168
- } | {
169
- create: CreateData<Q>;
170
- };
171
- dataForUpdateOne: {
172
- disconnect: boolean;
173
- } | {
174
- set: WhereArg<Q>;
175
- } | {
176
- delete: boolean;
177
- } | {
178
- update: UpdateData<Q>;
179
- } | {
180
- create: CreateData<Q>;
181
- } | {
182
- upsert: {
183
- update: UpdateData<Q>;
184
- create: CreateData<Q> | (() => CreateData<Q>);
185
- };
121
+ returnsOne: true;
122
+ query: Q;
123
+ params: BelongsToParams<T, FK>;
124
+ maybeSingle: Required extends true ? QueryManyTake<Q> : QueryManyTakeOptional<Q>;
125
+ omitForeignKeyInCreate: FK;
126
+ dataForCreate: {
127
+ columns: FK;
128
+ nested: Required extends true ? { [Key in Name]: RelationToOneDataForCreateSameQuery<Q> } : { [Key in Name]?: RelationToOneDataForCreateSameQuery<Q> };
129
+ };
130
+ optionalDataForCreate: EmptyObject;
131
+ dataForUpdate: {
132
+ disconnect: boolean;
133
+ } | {
134
+ set: WhereArg<Q>;
135
+ } | {
136
+ delete: boolean;
137
+ } | {
138
+ update: UpdateData<Q>;
139
+ } | {
140
+ create: CreateData<Q>;
141
+ };
142
+ dataForUpdateOne: {
143
+ disconnect: boolean;
144
+ } | {
145
+ set: WhereArg<Q>;
146
+ } | {
147
+ delete: boolean;
148
+ } | {
149
+ update: UpdateData<Q>;
150
+ } | {
151
+ create: CreateData<Q>;
152
+ } | {
153
+ upsert: {
154
+ update: UpdateData<Q>;
155
+ create: CreateData<Q> | (() => CreateData<Q>);
186
156
  };
157
+ };
187
158
  }
188
-
189
159
  declare function transaction<Result>(this: {
190
- $qb: Db;
160
+ $qb: Db;
191
161
  }, fn: () => Promise<Result>): Promise<Result>;
192
162
  declare function transaction<Result>(this: {
193
- $qb: Db;
163
+ $qb: Db;
194
164
  }, options: IsolationLevel | TransactionOptions, fn: () => Promise<Result>): Promise<Result>;
195
165
  declare function ensureTransaction<Result>(this: {
196
- $qb: Db;
166
+ $qb: Db;
197
167
  }, cb: () => Promise<Result>): Promise<Result>;
198
168
  declare function isInTransaction(this: {
199
- $qb: Db;
169
+ $qb: Db;
200
170
  }): boolean;
201
171
  declare function afterCommit(this: {
202
- $qb: Db;
172
+ $qb: Db;
203
173
  }, hook: AfterCommitStandaloneHook): void;
204
-
205
174
  interface FromQuery extends Query {
206
- returnType: 'all';
175
+ returnType: 'all';
207
176
  }
208
- type OrchidORM<T extends TableClasses = TableClasses> = {
209
- [K in keyof T]: T[K] extends {
210
- new (): infer R extends ORMTableInput;
211
- } ? TableToDb<R> : never;
212
- } & OrchidORMMethods;
177
+ type OrchidORM<T extends TableClasses = TableClasses> = { [K in keyof T]: T[K] extends {
178
+ new (): infer R extends ORMTableInput;
179
+ } ? TableToDb<R> : never } & OrchidORMMethods;
213
180
  interface OrchidORMMethods {
214
- /**
215
- * @see import('pqb').QueryTransaction.prototype.transaction
216
- */
217
- $transaction: typeof transaction;
218
- /**
219
- * @see import('pqb').QueryTransaction.prototype.ensureTransaction
220
- */
221
- $ensureTransaction: typeof ensureTransaction;
222
- /**
223
- * @see import('pqb').QueryTransaction.prototype.isInTransaction
224
- */
225
- $isInTransaction: typeof isInTransaction;
226
- /**
227
- * @see import('pqb').QueryTransaction.prototype.afterCommit
228
- */
229
- $afterCommit: typeof afterCommit;
230
- $qb: Db;
231
- $adapterNotInTransaction: AdapterBase;
232
- /**
233
- * Adapter is a wrapper on top of `postgres-js`, `node-postgres`, or other db driver.
234
- *
235
- * When in transaction, returns a db adapter object for the transaction,
236
- * returns a default adapter object otherwise.
237
- *
238
- * Treat the adapter as implementation detail and avoid accessing it directly.
239
- */
240
- $getAdapter(): AdapterBase;
241
- /**
242
- * Use `$query` to perform raw SQL queries.
243
- *
244
- * ```ts
245
- * const value = 1;
246
- *
247
- * // it is safe to interpolate inside the backticks (``):
248
- * const result = await db.$query<{ one: number }>`SELECT ${value} one`;
249
- * // data is inside `rows` array:
250
- * result.rows[0].one;
251
- * ```
252
- *
253
- * If the query is executing inside a transaction, it will use the transaction connection automatically.
254
- *
255
- * ```ts
256
- * await db.transaction(async () => {
257
- * // both queries will execute in the same transaction
258
- * await db.$query`SELECT 1`;
259
- * await db.$query`SELECT 2`;
260
- * });
261
- * ```
262
- *
263
- * Alternatively, support a simple SQL string, with optional `values`:
264
- *
265
- * Note that the values is a simple array, and the SQL is referring to the values with `$1`, `$2` and so on.
266
- *
267
- * ```ts
268
- * const value = 1;
269
- *
270
- * // it is NOT safe to interpolate inside a simple string, use `values` to pass the values.
271
- * const result = await db.$query<{ one: number }>({
272
- * raw: 'SELECT $1 AS one',
273
- * values: [value],
274
- * });
275
- * // data is inside `rows` array:
276
- * result.rows[0].one;
277
- * ```
278
- *
279
- * @param args - SQL template literal, or an object { raw: string, values?: unknown[] }
280
- */
281
- $query: Db['query'];
282
- /**
283
- * The same as the {@link $query}, but returns an array of arrays instead of objects:
284
- *
285
- * ```ts
286
- * const value = 1;
287
- *
288
- * // it is safe to interpolate inside the backticks (``):
289
- * const result = await db.$queryArrays<[number]>`SELECT ${value} AS one`;
290
- * // `rows` is an array of arrays:
291
- * const row = result.rows[0];
292
- * row[0]; // our value
293
- * ```
294
- *
295
- * @param args - SQL template literal, or an object { raw: string, values?: unknown[] }
296
- */
297
- $queryArrays: Db['queryArrays'];
298
- /**
299
- * See {@link FromMethods.from}
300
- */
301
- $from<Arg extends MaybeArray<FromArg<Query>>>(arg: Arg): FromResult<FromQuery, Arg>;
302
- /**
303
- * `$withOptions` supports overriding `log`, `schema`, `role`, and `setConfig`.
304
- *
305
- * - `log`: boolean, enables or disables logging in the scope of the callback.
306
- * - `schema`: set a **default** schema, note that it does not override
307
- * if you already have a schema set in the ORM config or for a specific table.
308
- * - `role`: string, switches the Postgres role for the duration of the callback.
309
- * Used for row-level security policies.
310
- * - `setConfig`: object with string, number, or boolean values, sets Postgres custom
311
- * settings for the duration of the callback. Use dotted names like `app.tenant_id`.
312
- * Values are normalized to strings internally.
313
- *
314
- * SQL session options (`role` and `setConfig`) cannot be nested.
315
- * If an outer scope already has `role` or `setConfig`, attempting to set them again
316
- * in a nested `$withOptions` call will throw an error.
317
- * Nested scopes that only change `log` or `schema` will inherit the outer SQL session context.
318
- *
319
- * Explicit transactions inside the callback inherit the same SQL session context:
320
- *
321
- * ```ts
322
- * await db.$withOptions(
323
- * {
324
- * role: 'app_user',
325
- * setConfig: {
326
- * 'app.tenant_id': tenantId,
327
- * 'app.user_id': userId,
328
- * },
329
- * },
330
- * async () => {
331
- * const project = await db.project.find(projectId);
332
- *
333
- * await db.$transaction(async () => {
334
- * // This query runs in the transaction with the same role and config
335
- * await db.project.find(projectId).update({ lastViewedAt: new Date() });
336
- * });
337
- * },
338
- * );
339
- * ```
340
- *
341
- * Basic usage with `log` and `schema`:
342
- *
343
- * ```ts
344
- * await db.$withOptions({ log: true, schema: 'custom' }, async () => {
345
- * // will log this query, and will use the custom schema for this table,
346
- * // unless this table already has a configured schema.
347
- * await db.table.find(123);
348
- * });
349
- * ```
350
- */
351
- $withOptions<Result>(options: StorageOptions, cb: () => Promise<Result>): Promise<Result>;
352
- $close(): Promise<void>;
181
+ /**
182
+ * @see import('pqb').QueryTransaction.prototype.transaction
183
+ */
184
+ $transaction: typeof transaction;
185
+ /**
186
+ * @see import('pqb').QueryTransaction.prototype.ensureTransaction
187
+ */
188
+ $ensureTransaction: typeof ensureTransaction;
189
+ /**
190
+ * @see import('pqb').QueryTransaction.prototype.isInTransaction
191
+ */
192
+ $isInTransaction: typeof isInTransaction;
193
+ /**
194
+ * @see import('pqb').QueryTransaction.prototype.afterCommit
195
+ */
196
+ $afterCommit: typeof afterCommit;
197
+ $qb: Db;
198
+ $adapterNotInTransaction: Adapter;
199
+ /**
200
+ * Adapter is a wrapper on top of `postgres-js`, `node-postgres`, or other db driver.
201
+ *
202
+ * When in transaction, returns a db adapter object for the transaction,
203
+ * returns a default adapter object otherwise.
204
+ *
205
+ * Treat the adapter as implementation detail and avoid accessing it directly.
206
+ */
207
+ $getAdapter(): Adapter;
208
+ /**
209
+ * Use `$query` to perform raw SQL queries.
210
+ *
211
+ * ```ts
212
+ * const value = 1;
213
+ *
214
+ * // it is safe to interpolate inside the backticks (``):
215
+ * const result = await db.$query<{ one: number }>`SELECT ${value} one`;
216
+ * // data is inside `rows` array:
217
+ * result.rows[0].one;
218
+ * ```
219
+ *
220
+ * If the query is executing inside a transaction, it will use the transaction connection automatically.
221
+ *
222
+ * ```ts
223
+ * await db.transaction(async () => {
224
+ * // both queries will execute in the same transaction
225
+ * await db.$query`SELECT 1`;
226
+ * await db.$query`SELECT 2`;
227
+ * });
228
+ * ```
229
+ *
230
+ * Alternatively, support a simple SQL string, with optional `values`:
231
+ *
232
+ * Note that the values is a simple array, and the SQL is referring to the values with `$1`, `$2` and so on.
233
+ *
234
+ * ```ts
235
+ * const value = 1;
236
+ *
237
+ * // it is NOT safe to interpolate inside a simple string, use `values` to pass the values.
238
+ * const result = await db.$query<{ one: number }>({
239
+ * raw: 'SELECT $1 AS one',
240
+ * values: [value],
241
+ * });
242
+ * // data is inside `rows` array:
243
+ * result.rows[0].one;
244
+ * ```
245
+ *
246
+ * @param args - SQL template literal, or an object { raw: string, values?: unknown[] }
247
+ */
248
+ $query: Db['query'];
249
+ /**
250
+ * The same as the {@link $query}, but returns an array of arrays instead of objects:
251
+ *
252
+ * ```ts
253
+ * const value = 1;
254
+ *
255
+ * // it is safe to interpolate inside the backticks (``):
256
+ * const result = await db.$queryArrays<[number]>`SELECT ${value} AS one`;
257
+ * // `rows` is an array of arrays:
258
+ * const row = result.rows[0];
259
+ * row[0]; // our value
260
+ * ```
261
+ *
262
+ * @param args - SQL template literal, or an object { raw: string, values?: unknown[] }
263
+ */
264
+ $queryArrays: Db['queryArrays'];
265
+ /**
266
+ * See {@link FromMethods.from}
267
+ */
268
+ $from<Arg extends MaybeArray<FromArg<Query>>>(arg: Arg): FromResult<FromQuery, Arg>;
269
+ /**
270
+ * `$withOptions` supports overriding `log`, `schema`, `role`, and `setConfig`.
271
+ *
272
+ * - `log`: boolean, enables or disables logging in the scope of the callback.
273
+ * - `schema`: set a **default** schema, note that it does not override
274
+ * if you already have a schema set in the ORM config or for a specific table.
275
+ * - `role`: string, switches the Postgres role for the duration of the callback.
276
+ * Used for row-level security policies.
277
+ * - `setConfig`: object with string, number, or boolean values, sets Postgres custom
278
+ * settings for the duration of the callback. Use dotted names like `app.tenant_id`.
279
+ * Values are normalized to strings internally.
280
+ *
281
+ * SQL session options (`role` and `setConfig`) cannot be nested.
282
+ * If an outer scope already has `role` or `setConfig`, attempting to set them again
283
+ * in a nested `$withOptions` call will throw an error.
284
+ * Nested scopes that only change `log` or `schema` will inherit the outer SQL session context.
285
+ *
286
+ * Explicit transactions inside the callback inherit the same SQL session context:
287
+ *
288
+ * ```ts
289
+ * await db.$withOptions(
290
+ * {
291
+ * role: 'app_user',
292
+ * setConfig: {
293
+ * 'app.tenant_id': tenantId,
294
+ * 'app.user_id': userId,
295
+ * },
296
+ * },
297
+ * async () => {
298
+ * const project = await db.project.find(projectId);
299
+ *
300
+ * await db.$transaction(async () => {
301
+ * // This query runs in the transaction with the same role and config
302
+ * await db.project.find(projectId).update({ lastViewedAt: new Date() });
303
+ * });
304
+ * },
305
+ * );
306
+ * ```
307
+ *
308
+ * Basic usage with `log` and `schema`:
309
+ *
310
+ * ```ts
311
+ * await db.$withOptions({ log: true, schema: 'custom' }, async () => {
312
+ * // will log this query, and will use the custom schema for this table,
313
+ * // unless this table already has a configured schema.
314
+ * await db.table.find(123);
315
+ * });
316
+ * ```
317
+ */
318
+ $withOptions<Result>(options: StorageOptions, cb: () => Promise<Result>): Promise<Result>;
319
+ $close(): Promise<void>;
353
320
  }
354
321
  type OrchidOrmParam<Options> = true | null extends true ? 'Set strict: true to tsconfig' : Options;
355
- declare const orchidORMWithAdapter: <T extends TableClasses>({ log, logger, autoPreparedStatements, noPrimaryKey, schema, ...options }: OrchidOrmParam<({
356
- db: Query;
322
+ declare const orchidORMWithAdapter: <T extends TableClasses>({
323
+ log,
324
+ logger,
325
+ autoPreparedStatements,
326
+ noPrimaryKey,
327
+ schema,
328
+ ...options
329
+ }: OrchidOrmParam<({
330
+ db: Query;
357
331
  } | {
358
- adapter: AdapterBase;
332
+ adapter: Adapter;
359
333
  }) & DbSharedOptions>, tables: T) => OrchidORM<T>;
360
-
361
334
  interface HasAndBelongsToMany extends RelationThunkBase {
362
- type: 'hasAndBelongsToMany';
363
- options: HasAndBelongsToManyOptions;
335
+ type: 'hasAndBelongsToMany';
336
+ options: HasAndBelongsToManyOptions;
364
337
  }
365
338
  interface HasAndBelongsToManyOptions<Columns extends Column.Shape.QueryInit = Column.Shape.QueryInit, Related extends ORMTableInput = ORMTableInput> {
366
- required?: boolean;
367
- columns: (keyof Columns)[];
368
- references: string[];
339
+ required?: boolean;
340
+ columns: (keyof Columns)[];
341
+ references: string[];
342
+ foreignKey?: boolean | TableData.References.Options;
343
+ through: {
344
+ schema?: QuerySchema;
345
+ table: string;
346
+ columns: string[];
347
+ references: (keyof Related['columns']['shape'])[];
369
348
  foreignKey?: boolean | TableData.References.Options;
370
- through: {
371
- schema?: QuerySchema;
372
- table: string;
373
- columns: string[];
374
- references: (keyof Related['columns']['shape'])[];
375
- foreignKey?: boolean | TableData.References.Options;
376
- };
377
- on?: ColumnsShape.InputPartial<Related['columns']['shape']>;
349
+ };
350
+ on?: ColumnsShape.InputPartial<Related['columns']['shape']>;
378
351
  }
379
- type HasAndBelongsToManyParams<T extends RelationConfigSelf, FK extends string> = {
380
- [Name in FK]: T['columns']['shape'][Name]['type'];
381
- };
382
- type HasAndBelongsToManyQuery<Name extends string, TableQuery extends Query> = {
383
- [K in keyof TableQuery]: K extends '__selectable' ? SelectableFromShape<TableQuery['shape'], Name> : K extends '__as' ? Name : TableQuery[K];
384
- } & QueryHasWhere & HasRelJoin;
352
+ type HasAndBelongsToManyParams<T extends RelationConfigSelf, FK extends string> = { [Name in FK]: T['columns']['shape'][Name]['type'] };
353
+ type HasAndBelongsToManyQuery<Name extends string, TableQuery extends Query> = { [K in keyof TableQuery]: K extends '__selectable' ? SelectableFromShape<TableQuery['shape'], Name> : K extends '__as' ? Name : TableQuery[K] } & QueryHasWhere & HasRelJoin;
385
354
  interface HasAndBelongsToManyInfo<T extends RelationConfigSelf, Name extends string, FK extends string, Q extends Query> extends RelationConfigBase {
386
- returnsOne: false;
387
- query: Q;
388
- params: HasAndBelongsToManyParams<T, FK>;
389
- maybeSingle: Q;
390
- omitForeignKeyInCreate: never;
391
- optionalDataForCreate: {
392
- [P in Name]?: {
393
- create?: CreateData<Q>[];
394
- connect?: WhereArg<Q>[];
395
- connectOrCreate?: {
396
- where: WhereArg<Q>;
397
- create: CreateData<Q>;
398
- }[];
399
- };
355
+ returnsOne: false;
356
+ query: Q;
357
+ params: HasAndBelongsToManyParams<T, FK>;
358
+ maybeSingle: Q;
359
+ omitForeignKeyInCreate: never;
360
+ optionalDataForCreate: { [P in Name]?: {
361
+ create?: CreateData<Q>[];
362
+ connect?: WhereArg<Q>[];
363
+ connectOrCreate?: {
364
+ where: WhereArg<Q>;
365
+ create: CreateData<Q>;
366
+ }[];
367
+ } };
368
+ dataForCreate: never;
369
+ dataForUpdate: {
370
+ disconnect?: MaybeArray<WhereArg<Q>>;
371
+ set?: MaybeArray<WhereArg<Q>>;
372
+ add?: MaybeArray<WhereArg<Q>>;
373
+ delete?: MaybeArray<WhereArg<Q>>;
374
+ update?: {
375
+ where: MaybeArray<WhereArg<Q>>;
376
+ data: UpdateData<Q>;
400
377
  };
401
- dataForCreate: never;
402
- dataForUpdate: {
403
- disconnect?: MaybeArray<WhereArg<Q>>;
404
- set?: MaybeArray<WhereArg<Q>>;
405
- add?: MaybeArray<WhereArg<Q>>;
406
- delete?: MaybeArray<WhereArg<Q>>;
407
- update?: {
408
- where: MaybeArray<WhereArg<Q>>;
409
- data: UpdateData<Q>;
410
- };
411
- create?: CreateData<Q>[];
412
- };
413
- dataForUpdateOne: {
414
- disconnect?: MaybeArray<WhereArg<Q>>;
415
- set?: MaybeArray<WhereArg<Q>>;
416
- add?: MaybeArray<WhereArg<Q>>;
417
- delete?: MaybeArray<WhereArg<Q>>;
418
- update?: {
419
- where: MaybeArray<WhereArg<Q>>;
420
- data: UpdateData<Q>;
421
- };
422
- create?: CreateData<Q>[];
378
+ create?: CreateData<Q>[];
379
+ };
380
+ dataForUpdateOne: {
381
+ disconnect?: MaybeArray<WhereArg<Q>>;
382
+ set?: MaybeArray<WhereArg<Q>>;
383
+ add?: MaybeArray<WhereArg<Q>>;
384
+ delete?: MaybeArray<WhereArg<Q>>;
385
+ update?: {
386
+ where: MaybeArray<WhereArg<Q>>;
387
+ data: UpdateData<Q>;
423
388
  };
389
+ create?: CreateData<Q>[];
390
+ };
424
391
  }
425
-
426
392
  type RelationToOneDataForCreate<Rel extends {
427
- nestedCreateQuery: unknown;
428
- table: Query;
393
+ nestedCreateQuery: unknown;
394
+ table: Query;
429
395
  }> = {
430
- create: Rel['nestedCreateQuery'];
431
- connect?: never;
432
- connectOrCreate?: never;
396
+ create: Rel['nestedCreateQuery'];
397
+ connect?: never;
398
+ connectOrCreate?: never;
433
399
  } | {
434
- create?: never;
435
- connect: WhereArg<Rel['table']>;
436
- connectOrCreate?: never;
400
+ create?: never;
401
+ connect: WhereArg<Rel['table']>;
402
+ connectOrCreate?: never;
437
403
  } | {
438
- create?: never;
439
- connect?: never;
440
- connectOrCreate: {
441
- where: WhereArg<Rel['table']>;
442
- create: Rel['nestedCreateQuery'];
443
- };
404
+ create?: never;
405
+ connect?: never;
406
+ connectOrCreate: {
407
+ where: WhereArg<Rel['table']>;
408
+ create: Rel['nestedCreateQuery'];
409
+ };
444
410
  };
445
411
  type RelationToOneDataForCreateSameQuery<Q extends Query> = {
446
- create: CreateData<Q>;
447
- connect?: never;
448
- connectOrCreate?: never;
412
+ create: CreateData<Q>;
413
+ connect?: never;
414
+ connectOrCreate?: never;
449
415
  } | {
450
- create?: never;
451
- connect: WhereArg<Q>;
452
- connectOrCreate?: never;
416
+ create?: never;
417
+ connect: WhereArg<Q>;
418
+ connectOrCreate?: never;
453
419
  } | {
454
- create?: never;
455
- connect?: never;
456
- connectOrCreate: {
457
- where: WhereArg<Q>;
458
- create: CreateData<Q>;
459
- };
420
+ create?: never;
421
+ connect?: never;
422
+ connectOrCreate: {
423
+ where: WhereArg<Q>;
424
+ create: CreateData<Q>;
425
+ };
460
426
  };
461
427
  interface RelationThunkBase {
462
- type: string;
463
- related: ORMTableInput;
464
- options: unknown;
428
+ type: string;
429
+ related: ORMTableInput;
430
+ options: unknown;
465
431
  }
466
432
  type RelationThunk = BelongsTo | HasOne | HasMany | HasAndBelongsToMany;
467
433
  interface RelationThunks {
468
- [K: string]: RelationThunk;
434
+ [K: string]: RelationThunk;
469
435
  }
470
436
  type RelationTableToQuery<Relation> = Relation extends {
471
- related: infer R extends ORMTableInput;
437
+ related: infer R extends ORMTableInput;
472
438
  } ? TableToDb<R> : never;
473
439
  interface RelationConfigSelf {
474
- columns: {
475
- shape: Column.Shape.QueryInit;
476
- };
477
- relations: RelationThunks;
440
+ columns: {
441
+ shape: Column.Shape.QueryInit;
442
+ };
443
+ relations: RelationThunks;
478
444
  }
479
445
  type RelationConfigParams<T extends RelationConfigSelf, Relation extends RelationThunk> = Relation extends BelongsTo ? BelongsToParams<T, Relation['options']['columns'][number] & string> : Relation extends HasOne | HasMany ? HasOneParams<T, Relation['options']> : Relation extends HasAndBelongsToMany ? HasAndBelongsToManyParams<T, Relation['options']['columns'][number] & string> : never;
480
-
481
446
  interface TableClass<T extends ORMTableInput = ORMTableInput> {
482
- new (): T;
447
+ new (): T;
483
448
  }
484
449
  interface TableClasses {
485
- [K: string]: TableClass;
450
+ [K: string]: TableClass;
486
451
  }
487
452
  interface TableInfo {
488
- definedAs: string;
489
- db: OrchidORM;
490
- getFilePath(): string;
491
- name: string;
492
- }
493
- interface Table extends Query, TableInfo {
453
+ definedAs: string;
454
+ db: OrchidORM;
455
+ getFilePath(): string;
456
+ name: string;
494
457
  }
458
+ interface Table extends Query, TableInfo {}
495
459
  interface TableToDb<T extends ORMTableInput> extends TableInfo, Db<T['table'], T['columns']['shape'], keyof ShapeColumnPrimaryKeys<T['columns']['shape']> extends never ? never : ShapeColumnPrimaryKeys<T['columns']['shape']>, ShapeUniqueColumns<T['columns']['shape']> | TableDataItemsUniqueColumns<T['columns']['shape'], T['columns']['data']>, TableDataItemsUniqueColumnTuples<T['columns']['shape'], T['columns']['data']>, UniqueConstraints<T['columns']['shape']> | TableDataItemsUniqueConstraints<T['columns']['data']>, T['types'], T['columns']['shape'] & ComputedColumnsFromOptions<T['computed']>, MapTableScopesOption<T>, ColumnsShape.DefaultSelectKeys<T['columns']['shape']>> {
496
- relations: T extends RelationConfigSelf ? {
497
- [K in keyof T['relations'] & string]: T['relations'][K] extends BelongsTo ? BelongsToInfo<T, K, T['relations'][K]['options']['columns'][number] & string, T['relations'][K]['options']['required'], BelongsToQuery<RelationTableToQuery<T['relations'][K]>, K>> : T['relations'][K] extends HasOne ? HasOneInfo<T, K, T['relations'][K], HasOneQuery<T, K, RelationTableToQuery<T['relations'][K]>>> : T['relations'][K] extends HasMany ? HasManyInfo<T, K, T['relations'][K], HasManyQuery<T, K, RelationTableToQuery<T['relations'][K]>>> : T['relations'][K] extends HasAndBelongsToMany ? HasAndBelongsToManyInfo<T, K, T['relations'][K]['options']['columns'][number] & string, HasAndBelongsToManyQuery<K, RelationTableToQuery<T['relations'][K]>>> : never;
498
- } : EmptyObject;
460
+ relations: T extends RelationConfigSelf ? { [K in keyof T['relations'] & string]: T['relations'][K] extends BelongsTo ? BelongsToInfo<T, K, T['relations'][K]['options']['columns'][number] & string, T['relations'][K]['options']['required'], BelongsToQuery<RelationTableToQuery<T['relations'][K]>, K>> : T['relations'][K] extends HasOne ? HasOneInfo<T, K, T['relations'][K], HasOneQuery<T, K, RelationTableToQuery<T['relations'][K]>>> : T['relations'][K] extends HasMany ? HasManyInfo<T, K, T['relations'][K], HasManyQuery<T, K, RelationTableToQuery<T['relations'][K]>>> : T['relations'][K] extends HasAndBelongsToMany ? HasAndBelongsToManyInfo<T, K, T['relations'][K]['options']['columns'][number] & string, HasAndBelongsToManyQuery<K, RelationTableToQuery<T['relations'][K]>>> : never } : EmptyObject;
499
461
  }
500
462
  interface ORMTableInput {
501
- table: string;
502
- columns: {
503
- shape: Column.Shape.QueryInit;
504
- data: MaybeArray<TableDataItem>;
505
- };
506
- schema?: QuerySchema;
507
- types: unknown;
508
- noPrimaryKey?: boolean;
509
- filePath: string;
510
- language?: string;
511
- /**
512
- * collect computed columns returned by {@link BaseTable.setColumns}
513
- */
514
- computed?: ComputedOptionsFactory<never, never>;
515
- scopes?: RecordUnknown;
516
- readonly softDelete?: true | string;
517
- comment?: string;
518
- autoForeignKeys?: TableData.References.BaseOptions | boolean;
463
+ table: string;
464
+ columns: {
465
+ shape: Column.Shape.QueryInit;
466
+ data: MaybeArray<TableDataItem>;
467
+ };
468
+ schema?: QuerySchema;
469
+ types: unknown;
470
+ noPrimaryKey?: boolean;
471
+ filePath: string;
472
+ language?: string;
473
+ /**
474
+ * collect computed columns returned by {@link BaseTable.setColumns}
475
+ */
476
+ computed?: ComputedOptionsFactory<never, never>;
477
+ scopes?: RecordUnknown;
478
+ readonly softDelete?: true | string;
479
+ comment?: string;
480
+ autoForeignKeys?: TableData.References.BaseOptions | boolean;
519
481
  }
520
- type Queryable<T extends ORMTableInput> = ShallowSimplify<{
521
- [K in keyof T['columns']['shape']]?: T['columns']['shape'][K]['queryType'];
522
- }>;
482
+ type Queryable<T extends ORMTableInput> = ShallowSimplify<{ [K in keyof T['columns']['shape']]?: T['columns']['shape'][K]['queryType'] }>;
523
483
  type DefaultSelect<T extends ORMTableInput> = ShallowSimplify<ColumnsShape.DefaultOutput<T['columns']['shape']>>;
524
- type Selectable<T extends ORMTableInput> = T['computed'] extends ((t: never) => infer R extends ComputedOptionsConfig) ? ShallowSimplify<ColumnsShape.Output<T['columns']['shape']> & {
525
- [K in keyof R]: R[K] extends QueryOrExpression<unknown> ? R[K]['result']['value']['outputType'] : R[K] extends () => {
526
- result: {
527
- value: infer Value extends Column.Pick.QueryColumn;
528
- };
529
- } ? Value['outputType'] : never;
530
- }> : ShallowSimplify<ColumnsShape.Output<T['columns']['shape']>>;
484
+ type Selectable<T extends ORMTableInput> = T['computed'] extends ((t: never) => infer R extends ComputedOptionsConfig) ? ShallowSimplify<ColumnsShape.Output<T['columns']['shape']> & { [K in keyof R]: R[K] extends QueryOrExpression<unknown> ? R[K]['result']['value']['outputType'] : R[K] extends (() => {
485
+ result: {
486
+ value: infer Value extends Column.Pick.QueryColumn;
487
+ };
488
+ }) ? Value['outputType'] : never }> : ShallowSimplify<ColumnsShape.Output<T['columns']['shape']>>;
531
489
  type Insertable<T extends ORMTableInput> = ShallowSimplify<ColumnsShape.Input<T['columns']['shape']>>;
532
490
  type Updatable<T extends ORMTableInput> = ShallowSimplify<ColumnsShape.InputPartial<T['columns']['shape']>>;
533
491
  type BeforeHookMethod = (cb: QueryBeforeHook) => void;
534
492
  type BeforeActionHookMethod = (cb: QueryBeforeActionHook) => void;
535
493
  type AfterHookMethod = (cb: QueryAfterHook) => void;
536
494
  type AfterSelectableHookMethod = <Shape extends Column.QueryColumns, S extends (keyof Shape)[]>(this: {
537
- columns: {
538
- shape: Shape;
539
- };
495
+ columns: {
496
+ shape: Shape;
497
+ };
540
498
  }, select: S, cb: AfterHook<S, Shape>) => void;
541
499
  interface SetColumnsResult<Shape extends Column.Shape.QueryInit, Data extends MaybeArray<MaybeArray<TableDataItem>>> {
542
- shape: Shape;
543
- data: Data extends unknown[] ? Data : [Data];
500
+ shape: Shape;
501
+ data: Data extends unknown[] ? Data : [Data];
544
502
  }
545
503
  interface BaseTableInstance<ColumnTypes> {
546
- table: string;
504
+ table: string;
505
+ columns: {
506
+ shape: Column.Shape.QueryInit;
507
+ data: MaybeArray<TableDataItem>;
508
+ };
509
+ schema?: QuerySchema;
510
+ noPrimaryKey?: boolean;
511
+ snakeCase?: boolean;
512
+ types: ColumnTypes;
513
+ q: QueryData;
514
+ language?: string;
515
+ filePath: string;
516
+ result: Column.Shape.QueryInit;
517
+ clone<T extends IsQuery>(this: T): T;
518
+ getFilePath(): string;
519
+ setColumns<Shape extends Column.Shape.QueryInit, Data extends MaybeArray<TableDataItem>>(fn: (t: ColumnTypes) => Shape, tableData?: TableDataFn<Shape, Data>): SetColumnsResult<Shape, Data>;
520
+ /**
521
+ * You can add a generated column in the migration (see [generated](/guide/migration-column-methods.html#generated-column)),
522
+ * such column will persist in the database, it can be indexed.
523
+ *
524
+ * Or you can add a computed column on the ORM level, without adding it to the database, in such a way:
525
+ *
526
+ * ```ts
527
+ * import { BaseTable, sql } from './baseTable';
528
+ *
529
+ * export class UserTable extends BaseTable {
530
+ * readonly table = 'user';
531
+ * columns = this.setColumns((t) => ({
532
+ * id: t.identity().primaryKey(),
533
+ * firstName: t.string(),
534
+ * lastName: t.string(),
535
+ * }));
536
+ *
537
+ * computed = this.setComputed({
538
+ * fullName: (q) =>
539
+ * sql`${q.column('firstName')} || ' ' || ${q.column('lastName')}`.type(
540
+ * (t) => t.string(),
541
+ * ),
542
+ * });
543
+ * }
544
+ * ```
545
+ *
546
+ * `setComputed` takes an object where keys are computed column names, and values are functions returning raw SQL.
547
+ *
548
+ * Use `q.column` as shown above to reference a table column, it will be prefixed with a correct table name even if the table is joined under a different name.
549
+ *
550
+ * Computed columns are not selected by default, only on demand:
551
+ *
552
+ * ```ts
553
+ * const a = await db.user.take();
554
+ * a.fullName; // not selected
555
+ *
556
+ * const b = await db.user.select('*', 'fullName');
557
+ * b.fullName; // selected
558
+ *
559
+ * // Table post belongs to user as an author.
560
+ * // it's possible to select joined computed column:
561
+ * const posts = await db.post
562
+ * .join('author')
563
+ * .select('post.title', 'author.fullName');
564
+ * ```
565
+ *
566
+ * SQL query can be generated dynamically based on the current request context.
567
+ *
568
+ * Imagine we are using [AsyncLocalStorage](https://nodejs.org/api/async_context.html#asynchronous-context-tracking)
569
+ * to keep track of current user's language.
570
+ *
571
+ * And we have articles translated to different languages, each article has `title_en`, `title_uk`, `title_be` and so on.
572
+ *
573
+ * We can define a computed `title` by passing a function into `sql` method:
574
+ *
575
+ * ```ts
576
+ * import { sql } from './baseTable';
577
+ *
578
+ * type Locale = 'en' | 'uk' | 'be';
579
+ * const asyncLanguageStorage = new AsyncLocalStorage<Locale>();
580
+ * const defaultLocale: Locale = 'en';
581
+ *
582
+ * export class ArticleTable extends BaseTable {
583
+ * readonly table = 'article';
584
+ * columns = this.setColumns((t) => ({
585
+ * id: t.identity().primaryKey(),
586
+ * title_en: t.text(),
587
+ * title_uk: t.text().nullable(),
588
+ * title_be: t.text().nullable(),
589
+ * }));
590
+ *
591
+ * computed = this.setComputed({
592
+ * title: () =>
593
+ * // `sql` accepts a callback to generate a new query on every run
594
+ * sql(() => {
595
+ * // get locale dynamically based on current storage value
596
+ * const locale = asyncLanguageStorage.getStore() || defaultLocale;
597
+ *
598
+ * // use COALESCE in case when localized title is NULL, use title_en
599
+ * return sql`COALESCE(
600
+ * ${q.column(`title_${locale}`)},
601
+ * ${q.column(`title_${defaultLocale}`)}
602
+ * )`;
603
+ * }).type((t) => t.text()),
604
+ * });
605
+ * }
606
+ * ```
607
+ *
608
+ * @param computed - object where keys are column names and values are functions returning raw SQL
609
+ */
610
+ setComputed<Shape extends Column.Shape.QueryInit, Computed extends ComputedOptionsFactory<ColumnTypes, Shape>>(this: {
547
611
  columns: {
548
- shape: Column.Shape.QueryInit;
549
- data: MaybeArray<TableDataItem>;
612
+ shape: Shape;
550
613
  };
551
- schema?: QuerySchema;
552
- noPrimaryKey?: boolean;
553
- snakeCase?: boolean;
554
- types: ColumnTypes;
555
- q: QueryData;
556
- language?: string;
557
- filePath: string;
558
- result: Column.Shape.QueryInit;
559
- clone<T extends IsQuery>(this: T): T;
560
- getFilePath(): string;
561
- setColumns<Shape extends Column.Shape.QueryInit, Data extends MaybeArray<TableDataItem>>(fn: (t: ColumnTypes) => Shape, tableData?: TableDataFn<Shape, Data>): SetColumnsResult<Shape, Data>;
562
- /**
563
- * You can add a generated column in the migration (see [generated](/guide/migration-column-methods.html#generated-column)),
564
- * such column will persist in the database, it can be indexed.
565
- *
566
- * Or you can add a computed column on the ORM level, without adding it to the database, in such a way:
567
- *
568
- * ```ts
569
- * import { BaseTable, sql } from './baseTable';
570
- *
571
- * export class UserTable extends BaseTable {
572
- * readonly table = 'user';
573
- * columns = this.setColumns((t) => ({
574
- * id: t.identity().primaryKey(),
575
- * firstName: t.string(),
576
- * lastName: t.string(),
577
- * }));
578
- *
579
- * computed = this.setComputed({
580
- * fullName: (q) =>
581
- * sql`${q.column('firstName')} || ' ' || ${q.column('lastName')}`.type(
582
- * (t) => t.string(),
583
- * ),
584
- * });
585
- * }
586
- * ```
587
- *
588
- * `setComputed` takes an object where keys are computed column names, and values are functions returning raw SQL.
589
- *
590
- * Use `q.column` as shown above to reference a table column, it will be prefixed with a correct table name even if the table is joined under a different name.
591
- *
592
- * Computed columns are not selected by default, only on demand:
593
- *
594
- * ```ts
595
- * const a = await db.user.take();
596
- * a.fullName; // not selected
597
- *
598
- * const b = await db.user.select('*', 'fullName');
599
- * b.fullName; // selected
600
- *
601
- * // Table post belongs to user as an author.
602
- * // it's possible to select joined computed column:
603
- * const posts = await db.post
604
- * .join('author')
605
- * .select('post.title', 'author.fullName');
606
- * ```
607
- *
608
- * SQL query can be generated dynamically based on the current request context.
609
- *
610
- * Imagine we are using [AsyncLocalStorage](https://nodejs.org/api/async_context.html#asynchronous-context-tracking)
611
- * to keep track of current user's language.
612
- *
613
- * And we have articles translated to different languages, each article has `title_en`, `title_uk`, `title_be` and so on.
614
- *
615
- * We can define a computed `title` by passing a function into `sql` method:
616
- *
617
- * ```ts
618
- * import { sql } from './baseTable';
619
- *
620
- * type Locale = 'en' | 'uk' | 'be';
621
- * const asyncLanguageStorage = new AsyncLocalStorage<Locale>();
622
- * const defaultLocale: Locale = 'en';
623
- *
624
- * export class ArticleTable extends BaseTable {
625
- * readonly table = 'article';
626
- * columns = this.setColumns((t) => ({
627
- * id: t.identity().primaryKey(),
628
- * title_en: t.text(),
629
- * title_uk: t.text().nullable(),
630
- * title_be: t.text().nullable(),
631
- * }));
632
- *
633
- * computed = this.setComputed({
634
- * title: () =>
635
- * // `sql` accepts a callback to generate a new query on every run
636
- * sql(() => {
637
- * // get locale dynamically based on current storage value
638
- * const locale = asyncLanguageStorage.getStore() || defaultLocale;
639
- *
640
- * // use COALESCE in case when localized title is NULL, use title_en
641
- * return sql`COALESCE(
642
- * ${q.column(`title_${locale}`)},
643
- * ${q.column(`title_${defaultLocale}`)}
644
- * )`;
645
- * }).type((t) => t.text()),
646
- * });
647
- * }
648
- * ```
649
- *
650
- * @param computed - object where keys are column names and values are functions returning raw SQL
651
- */
652
- setComputed<Shape extends Column.Shape.QueryInit, Computed extends ComputedOptionsFactory<ColumnTypes, Shape>>(this: {
653
- columns: {
654
- shape: Shape;
655
- };
656
- }, computed: Computed): Computed;
657
- /**
658
- * See {@link ScopeMethods}
659
- */
660
- setScopes<Table extends string, Shape extends Column.Shape.QueryInit, Keys extends string>(this: {
661
- table: Table;
662
- columns: {
663
- shape: Shape;
664
- };
665
- }, scopes: DbTableOptionScopes<Table, Shape, Keys>): QueryScopes<Keys>;
666
- belongsTo<Columns extends Column.Shape.QueryInit, Related extends ORMTableInput, Options extends BelongsToOptions<Columns, Related>>(this: {
667
- columns: {
668
- shape: Columns;
669
- };
670
- }, fn: () => {
671
- new (): Related;
672
- }, options: Options): {
673
- type: 'belongsTo';
674
- related: Related;
675
- options: Options;
614
+ }, computed: Computed): Computed;
615
+ /**
616
+ * See {@link ScopeMethods}
617
+ */
618
+ setScopes<Table extends string, Shape extends Column.Shape.QueryInit, Keys extends string>(this: {
619
+ table: Table;
620
+ columns: {
621
+ shape: Shape;
676
622
  };
677
- hasOne<Columns extends Column.Shape.QueryInit, Related extends ORMTableInput, Through extends string, Source extends string, Options extends HasOneOptions<Columns, Related, Through, Source>>(this: {
678
- columns: {
679
- shape: Columns;
680
- };
681
- }, fn: () => {
682
- new (): Related;
683
- }, options: Options): {
684
- type: 'hasOne';
685
- related: Related;
686
- options: Options;
623
+ }, scopes: DbTableOptionScopes<Table, Shape, Keys>): QueryScopes<Keys>;
624
+ belongsTo<Columns extends Column.Shape.QueryInit, Related extends ORMTableInput, Options extends BelongsToOptions<Columns, Related>>(this: {
625
+ columns: {
626
+ shape: Columns;
687
627
  };
688
- hasMany<Columns extends Column.Shape.QueryInit, Related extends ORMTableInput, Through extends string, Source extends string, Options extends HasOneOptions<Columns, Related, Through, Source>>(this: {
689
- columns: {
690
- shape: Columns;
691
- };
692
- }, fn: () => {
693
- new (): Related;
694
- }, options: Options): {
695
- type: 'hasMany';
696
- related: Related;
697
- options: Options;
628
+ }, fn: () => {
629
+ new (): Related;
630
+ }, options: Options): {
631
+ type: 'belongsTo';
632
+ related: Related;
633
+ options: Options;
634
+ };
635
+ hasOne<Columns extends Column.Shape.QueryInit, Related extends ORMTableInput, Through extends string, Source extends string, Options extends HasOneOptions<Columns, Related, Through, Source>>(this: {
636
+ columns: {
637
+ shape: Columns;
698
638
  };
699
- hasAndBelongsToMany<Columns extends Column.Shape.QueryInit, Related extends ORMTableInput, Options extends HasAndBelongsToManyOptions<Columns, Related>>(this: {
700
- columns: {
701
- shape: Columns;
702
- };
703
- }, fn: () => {
704
- new (): Related;
705
- }, options: Options): {
706
- type: 'hasAndBelongsToMany';
707
- related: Related;
708
- options: Options;
639
+ }, fn: () => {
640
+ new (): Related;
641
+ }, options: Options): {
642
+ type: 'hasOne';
643
+ related: Related;
644
+ options: Options;
645
+ };
646
+ hasMany<Columns extends Column.Shape.QueryInit, Related extends ORMTableInput, Through extends string, Source extends string, Options extends HasOneOptions<Columns, Related, Through, Source>>(this: {
647
+ columns: {
648
+ shape: Columns;
709
649
  };
710
- beforeQuery: BeforeHookMethod;
711
- afterQuery: AfterHookMethod;
712
- beforeCreate: BeforeActionHookMethod;
713
- afterCreate: AfterSelectableHookMethod;
714
- afterCreateCommit: AfterSelectableHookMethod;
715
- beforeUpdate: BeforeActionHookMethod;
716
- afterUpdate: AfterSelectableHookMethod;
717
- afterUpdateCommit: AfterSelectableHookMethod;
718
- beforeSave: BeforeActionHookMethod;
719
- afterSave: AfterSelectableHookMethod;
720
- afterSaveCommit: AfterSelectableHookMethod;
721
- beforeDelete: BeforeHookMethod;
722
- afterDelete: AfterSelectableHookMethod;
723
- afterDeleteCommit: AfterSelectableHookMethod;
650
+ }, fn: () => {
651
+ new (): Related;
652
+ }, options: Options): {
653
+ type: 'hasMany';
654
+ related: Related;
655
+ options: Options;
656
+ };
657
+ hasAndBelongsToMany<Columns extends Column.Shape.QueryInit, Related extends ORMTableInput, Options extends HasAndBelongsToManyOptions<Columns, Related>>(this: {
658
+ columns: {
659
+ shape: Columns;
660
+ };
661
+ }, fn: () => {
662
+ new (): Related;
663
+ }, options: Options): {
664
+ type: 'hasAndBelongsToMany';
665
+ related: Related;
666
+ options: Options;
667
+ };
668
+ beforeQuery: BeforeHookMethod;
669
+ afterQuery: AfterHookMethod;
670
+ beforeCreate: BeforeActionHookMethod;
671
+ afterCreate: AfterSelectableHookMethod;
672
+ afterCreateCommit: AfterSelectableHookMethod;
673
+ beforeUpdate: BeforeActionHookMethod;
674
+ afterUpdate: AfterSelectableHookMethod;
675
+ afterUpdateCommit: AfterSelectableHookMethod;
676
+ beforeSave: BeforeActionHookMethod;
677
+ afterSave: AfterSelectableHookMethod;
678
+ afterSaveCommit: AfterSelectableHookMethod;
679
+ beforeDelete: BeforeHookMethod;
680
+ afterDelete: AfterSelectableHookMethod;
681
+ afterDeleteCommit: AfterSelectableHookMethod;
724
682
  }
725
683
  interface BaseTableClass<SchemaConfig extends ColumnSchemaConfig, ColumnTypes> {
726
- nowSQL: string | undefined;
727
- exportAs: string;
728
- columnTypes: ColumnTypes;
729
- getFilePath(): string;
730
- sql: DbSqlMethod<ColumnTypes>;
731
- new (): BaseTableInstance<ColumnTypes>;
732
- instance(): BaseTableInstance<ColumnTypes>;
733
- /**
734
- * All column types for inserting.
735
- */
736
- inputSchema: SchemaConfig['inputSchema'];
737
- /**
738
- * All column types as returned from a database.
739
- */
740
- outputSchema: SchemaConfig['outputSchema'];
741
- /**
742
- * All column types for query methods such as `where`.
743
- */
744
- querySchema: SchemaConfig['querySchema'];
745
- /**
746
- * Primary key column(s) type for query methods such as `where`.
747
- */
748
- pkeySchema: SchemaConfig['pkeySchema'];
749
- /**
750
- * Column types for inserting, excluding primary keys.
751
- * Equals to {@link inputSchema} without primary keys.
752
- */
753
- createSchema: SchemaConfig['createSchema'];
754
- /**
755
- * Column types for updating, excluding primary keys.
756
- * Equals to partial {@link createSchema}.
757
- */
758
- updateSchema: SchemaConfig['updateSchema'];
684
+ nowSQL: string | undefined;
685
+ exportAs: string;
686
+ columnTypes: ColumnTypes;
687
+ getFilePath(): string;
688
+ sql: DbSqlMethod<ColumnTypes>;
689
+ new (): BaseTableInstance<ColumnTypes>;
690
+ instance(): BaseTableInstance<ColumnTypes>;
691
+ /**
692
+ * All column types for inserting.
693
+ */
694
+ inputSchema: SchemaConfig['inputSchema'];
695
+ /**
696
+ * All column types as returned from a database.
697
+ */
698
+ outputSchema: SchemaConfig['outputSchema'];
699
+ /**
700
+ * All column types for query methods such as `where`.
701
+ */
702
+ querySchema: SchemaConfig['querySchema'];
703
+ /**
704
+ * Primary key column(s) type for query methods such as `where`.
705
+ */
706
+ pkeySchema: SchemaConfig['pkeySchema'];
707
+ /**
708
+ * Column types for inserting, excluding primary keys.
709
+ * Equals to {@link inputSchema} without primary keys.
710
+ */
711
+ createSchema: SchemaConfig['createSchema'];
712
+ /**
713
+ * Column types for updating, excluding primary keys.
714
+ * Equals to partial {@link createSchema}.
715
+ */
716
+ updateSchema: SchemaConfig['updateSchema'];
759
717
  }
760
- declare function createBaseTable<SchemaConfig extends ColumnSchemaConfig = DefaultSchemaConfig, ColumnTypes = DefaultColumnTypes<SchemaConfig>>({ schemaConfig, columnTypes: columnTypesArg, snakeCase, filePath: filePathArg, nowSQL, exportAs, language, autoForeignKeys, }?: {
761
- schemaConfig?: SchemaConfig;
762
- columnTypes?: ColumnTypes | ((t: DefaultColumnTypes<SchemaConfig>) => ColumnTypes);
763
- snakeCase?: boolean;
764
- filePath?: string;
765
- nowSQL?: string;
766
- exportAs?: string;
767
- language?: string;
768
- autoForeignKeys?: boolean | TableData.References.BaseOptions;
718
+ declare function createBaseTable<SchemaConfig extends ColumnSchemaConfig = DefaultSchemaConfig, ColumnTypes = DefaultColumnTypes<SchemaConfig>>({
719
+ schemaConfig,
720
+ columnTypes: columnTypesArg,
721
+ snakeCase,
722
+ filePath: filePathArg,
723
+ nowSQL,
724
+ exportAs,
725
+ language,
726
+ autoForeignKeys
727
+ }?: {
728
+ schemaConfig?: SchemaConfig;
729
+ columnTypes?: ColumnTypes | ((t: DefaultColumnTypes<SchemaConfig>) => ColumnTypes);
730
+ snakeCase?: boolean;
731
+ filePath?: string;
732
+ nowSQL?: string;
733
+ exportAs?: string;
734
+ language?: string;
735
+ autoForeignKeys?: boolean | TableData.References.BaseOptions;
769
736
  }): BaseTableClass<SchemaConfig, ColumnTypes>;
770
-
771
737
  type QueryMethods<T extends Query> = Record<string, (q: T, ...args: any[]) => any>;
772
- type QueryOne<T extends Query> = {
773
- [K in keyof T]: K extends 'returnType' ? Exclude<QueryReturnType, 'all' | undefined> : T[K];
774
- };
738
+ type QueryOne<T extends Query> = { [K in keyof T]: K extends 'returnType' ? Exclude<QueryReturnType, 'all' | undefined> : T[K] };
775
739
  interface MethodsBase<T extends Query> {
776
- queryMethods?: QueryMethods<T>;
777
- queryOneMethods?: QueryMethods<QueryOne<T>>;
778
- queryWithWhereMethods?: QueryMethods<T & QueryHasWhere>;
779
- queryOneWithWhereMethods?: QueryMethods<QueryOne<T & QueryHasWhere>>;
780
- methods?: RecordUnknown;
740
+ queryMethods?: QueryMethods<T>;
741
+ queryOneMethods?: QueryMethods<QueryOne<T>>;
742
+ queryWithWhereMethods?: QueryMethods<T & QueryHasWhere>;
743
+ queryOneWithWhereMethods?: QueryMethods<QueryOne<T & QueryHasWhere>>;
744
+ methods?: RecordUnknown;
781
745
  }
782
- type MapQueryMethods<BaseQuery extends Query, Method> = Method extends (q: any, ...args: infer Args) => infer Result ? <T extends BaseQuery>(this: T, ...args: Args) => Result extends Query ? MergeQuery<T, Result> : Result : never;
783
- type MapMethods<T extends Query, Methods extends MethodsBase<T>> = {
784
- [K in keyof Methods['queryMethods'] | keyof Methods['queryOneMethods'] | keyof Methods['queryWithWhereMethods'] | keyof Methods['queryOneWithWhereMethods'] | keyof Methods['methods']]: K extends keyof Methods['methods'] ? Methods['methods'][K] : K extends keyof Methods['queryOneWithWhereMethods'] ? MapQueryMethods<QueryOne<Query & QueryHasWhere>, Methods['queryOneWithWhereMethods'][K]> : K extends keyof Methods['queryWithWhereMethods'] ? MapQueryMethods<Query & QueryHasWhere, Methods['queryWithWhereMethods'][K]> : K extends keyof Methods['queryOneMethods'] ? MapQueryMethods<QueryOne<Query>, Methods['queryOneMethods'][K]> : K extends keyof Methods['queryMethods'] ? MapQueryMethods<Query, Methods['queryMethods'][K]> : never;
785
- };
746
+ type MapQueryMethods<BaseQuery extends Query, Method> = Method extends ((q: any, ...args: infer Args) => infer Result) ? <T extends BaseQuery>(this: T, ...args: Args) => Result extends Query ? MergeQuery<T, Result> : Result : never;
747
+ type MapMethods<T extends Query, Methods extends MethodsBase<T>> = { [K in keyof Methods['queryMethods'] | keyof Methods['queryOneMethods'] | keyof Methods['queryWithWhereMethods'] | keyof Methods['queryOneWithWhereMethods'] | keyof Methods['methods']]: K extends keyof Methods['methods'] ? Methods['methods'][K] : K extends keyof Methods['queryOneWithWhereMethods'] ? MapQueryMethods<QueryOne<Query & QueryHasWhere>, Methods['queryOneWithWhereMethods'][K]> : K extends keyof Methods['queryWithWhereMethods'] ? MapQueryMethods<Query & QueryHasWhere, Methods['queryWithWhereMethods'][K]> : K extends keyof Methods['queryOneMethods'] ? MapQueryMethods<QueryOne<Query>, Methods['queryOneMethods'][K]> : K extends keyof Methods['queryMethods'] ? MapQueryMethods<Query, Methods['queryMethods'][K]> : never };
786
748
  type Repo<T extends Query, Methods extends MethodsBase<T>> = T & MapMethods<T, Methods>;
787
749
  declare const createRepo: <T extends Query, Methods extends MethodsBase<T>>(table: T, methods: Methods) => Repo<(<Q extends {
788
- table: T["table"];
789
- shape: T["shape"];
750
+ table: T["table"];
751
+ shape: T["shape"];
790
752
  }>(q: Q) => Query & Q & MapMethods<T, Methods>) & T, Methods>;
791
-
792
- export { createBaseTable, createRepo, orchidORMWithAdapter };
793
- export type { BaseTableClass, BaseTableInstance, DefaultSelect, FromQuery, Insertable, MapMethods, MapQueryMethods, MethodsBase, ORMTableInput, OrchidORM, OrchidOrmParam, Queryable, Repo, Selectable, SetColumnsResult, Table, TableClass, TableClasses, TableInfo, TableToDb, Updatable };
753
+ export { BaseTableClass, BaseTableInstance, DefaultSelect, FromQuery, Insertable, MapMethods, MapQueryMethods, MethodsBase, ORMTableInput, OrchidORM, OrchidOrmParam, Queryable, Repo, Selectable, SetColumnsResult, Table, TableClass, TableClasses, TableInfo, TableToDb, Updatable, createBaseTable, createRepo, orchidORMWithAdapter };