drizzle-orm 0.38.3-e6823b4 → 0.38.3-efed06b
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/libsql/session.cjs +4 -8
- package/libsql/session.cjs.map +1 -1
- package/libsql/session.js +4 -8
- package/libsql/session.js.map +1 -1
- package/mysql-core/dialect.cjs +29 -11
- package/mysql-core/dialect.cjs.map +1 -1
- package/mysql-core/dialect.d.cts +3 -1
- package/mysql-core/dialect.d.ts +3 -1
- package/mysql-core/dialect.js +29 -11
- package/mysql-core/dialect.js.map +1 -1
- package/mysql-proxy/driver.cjs.map +1 -1
- package/mysql-proxy/driver.d.cts +1 -1
- package/mysql-proxy/driver.d.ts +1 -1
- package/mysql-proxy/driver.js.map +1 -1
- package/mysql-proxy/session.cjs +3 -23
- package/mysql-proxy/session.cjs.map +1 -1
- package/mysql-proxy/session.js +3 -23
- package/mysql-proxy/session.js.map +1 -1
- package/mysql2/session.cjs +1 -22
- package/mysql2/session.cjs.map +1 -1
- package/mysql2/session.js +1 -22
- package/mysql2/session.js.map +1 -1
- package/package.json +1 -1
- package/pg-core/dialect.cjs +20 -11
- package/pg-core/dialect.cjs.map +1 -1
- package/pg-core/dialect.d.cts +2 -1
- package/pg-core/dialect.d.ts +2 -1
- package/pg-core/dialect.js +20 -11
- package/pg-core/dialect.js.map +1 -1
- package/planetscale-serverless/session.cjs +1 -24
- package/planetscale-serverless/session.cjs.map +1 -1
- package/planetscale-serverless/session.js +1 -24
- package/planetscale-serverless/session.js.map +1 -1
- package/relations.cjs +141 -22
- package/relations.cjs.map +1 -1
- package/relations.d.cts +39 -26
- package/relations.d.ts +39 -26
- package/relations.js +149 -24
- package/relations.js.map +1 -1
- package/sql/sql.cjs +1 -1
- package/sql/sql.cjs.map +1 -1
- package/sql/sql.js +1 -1
- package/sql/sql.js.map +1 -1
- package/sql-js/driver.cjs.map +1 -1
- package/sql-js/driver.d.cts +1 -1
- package/sql-js/driver.d.ts +1 -1
- package/sql-js/driver.js.map +1 -1
- package/sql-js/session.cjs +18 -0
- package/sql-js/session.cjs.map +1 -1
- package/sql-js/session.d.cts +1 -0
- package/sql-js/session.d.ts +1 -0
- package/sql-js/session.js +18 -0
- package/sql-js/session.js.map +1 -1
- package/sqlite-core/db.cjs +4 -2
- package/sqlite-core/db.cjs.map +1 -1
- package/sqlite-core/db.d.cts +2 -1
- package/sqlite-core/db.d.ts +2 -1
- package/sqlite-core/db.js +4 -2
- package/sqlite-core/db.js.map +1 -1
- package/sqlite-core/dialect.cjs +19 -7
- package/sqlite-core/dialect.cjs.map +1 -1
- package/sqlite-core/dialect.d.cts +2 -1
- package/sqlite-core/dialect.d.ts +2 -1
- package/sqlite-core/dialect.js +19 -7
- package/sqlite-core/dialect.js.map +1 -1
- package/sqlite-core/query-builders/query.cjs +27 -9
- package/sqlite-core/query-builders/query.cjs.map +1 -1
- package/sqlite-core/query-builders/query.d.cts +5 -3
- package/sqlite-core/query-builders/query.d.ts +5 -3
- package/sqlite-core/query-builders/query.js +27 -9
- package/sqlite-core/query-builders/query.js.map +1 -1
- package/sqlite-core/session.cjs +2 -2
- package/sqlite-core/session.cjs.map +1 -1
- package/sqlite-core/session.d.cts +1 -1
- package/sqlite-core/session.d.ts +1 -1
- package/sqlite-core/session.js +2 -2
- package/sqlite-core/session.js.map +1 -1
- package/sqlite-proxy/driver.cjs +3 -2
- package/sqlite-proxy/driver.cjs.map +1 -1
- package/sqlite-proxy/driver.d.cts +2 -2
- package/sqlite-proxy/driver.d.ts +2 -2
- package/sqlite-proxy/driver.js +3 -2
- package/sqlite-proxy/driver.js.map +1 -1
- package/sqlite-proxy/session.cjs +15 -14
- package/sqlite-proxy/session.cjs.map +1 -1
- package/sqlite-proxy/session.js +15 -14
- package/sqlite-proxy/session.js.map +1 -1
- package/version.cjs +1 -1
- package/version.d.cts +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
package/relations.d.cts
CHANGED
|
@@ -2,7 +2,7 @@ import { type AnyTable, type InferModelFromColumns, Table } from "./table.cjs";
|
|
|
2
2
|
import { type AnyColumn, Column } from "./column.cjs";
|
|
3
3
|
import { entityKind } from "./entity.cjs";
|
|
4
4
|
import { and, asc, between, desc, exists, ilike, inArray, isNotNull, isNull, like, not, notBetween, notExists, notIlike, notInArray, notLike, or } from "./sql/expressions/index.cjs";
|
|
5
|
-
import { Placeholder, SQL, sql, type SQLWrapper } from "./sql/sql.cjs";
|
|
5
|
+
import { type Placeholder, SQL, sql, type SQLWrapper } from "./sql/sql.cjs";
|
|
6
6
|
import { type Assume, type Equal, type Simplify, type ValueOrArray, type Writable } from "./utils.cjs";
|
|
7
7
|
export declare class Relations<TSchema extends Record<string, unknown> = Record<string, unknown>, TTables extends Record<string, Table> = Record<string, Table>, TConfig extends RelationsBuilderConfig<TTables> = RelationsBuilderConfig<TTables>> {
|
|
8
8
|
readonly schema: TSchema;
|
|
@@ -35,6 +35,12 @@ export declare abstract class Relation<TSourceTableName extends string = string,
|
|
|
35
35
|
sourceTable: AnyTable<{
|
|
36
36
|
name: TSourceTableName;
|
|
37
37
|
}>;
|
|
38
|
+
through?: {
|
|
39
|
+
source: AnyColumn[];
|
|
40
|
+
target: AnyColumn[];
|
|
41
|
+
};
|
|
42
|
+
throughTable?: Table;
|
|
43
|
+
isReversed?: boolean;
|
|
38
44
|
constructor(targetTable: AnyTable<{
|
|
39
45
|
name: TTargetTableName;
|
|
40
46
|
}>);
|
|
@@ -122,7 +128,7 @@ export type DBQueryConfig<TRelationType extends 'one' | 'many' = 'one' | 'many',
|
|
|
122
128
|
[K in keyof TTableConfig['columns']]?: boolean | undefined;
|
|
123
129
|
} | undefined;
|
|
124
130
|
with?: {
|
|
125
|
-
[K in keyof TTableConfig['relations']]?:
|
|
131
|
+
[K in keyof TTableConfig['relations']]?: boolean | (TTableConfig['relations'][K] extends Relation ? DBQueryConfig<TTableConfig['relations'][K] extends One<string, string> ? 'one' : 'many', TSchema, FindTableInRelationalConfig<TSchema, TTableConfig['relations'][K]['targetTable']>> : never) | undefined;
|
|
126
132
|
} | undefined;
|
|
127
133
|
extras?: Record<string, SQLWrapper> | ((table: Simplify<AnyTable<TTableConfig> & TTableConfig['columns']>, operators: SQLOperator) => Record<string, SQLWrapper>) | undefined;
|
|
128
134
|
offset?: number | Placeholder | undefined;
|
|
@@ -164,11 +170,14 @@ export type ExtractTablesWithRelations<TRelations extends Relations, TTables ext
|
|
|
164
170
|
};
|
|
165
171
|
export type ReturnTypeOrValue<T> = T extends (...args: any[]) => infer R ? R : T;
|
|
166
172
|
export type BuildRelationResult<TConfig extends TablesRelationalConfig, TInclude, TRelations extends Record<string, RelationsBuilderEntry>> = {
|
|
167
|
-
[K in
|
|
173
|
+
[K in TruthyKeysOnly<TInclude> & keyof TRelations]: TRelations[K] extends infer TRel extends Relation ? BuildQueryResult<TConfig, FindTableInRelationalConfig<TConfig, TRel['targetTable']>, Assume<TInclude[K], true | Record<string, unknown>>> extends infer TResult ? TRel extends One<string, string> ? TResult | (Equal<TRel['optional'], true> extends true ? null : TInclude[K] extends Record<string, unknown> ? TInclude[K]['where'] extends Record<string, any> ? null : never : never) : TResult[] : never : TRelations[K] extends AggregatedField<infer TData> ? TData : never;
|
|
168
174
|
};
|
|
169
175
|
export type NonUndefinedKeysOnly<T> = ExtractObjectValues<{
|
|
170
176
|
[K in keyof T as T[K] extends undefined ? never : K]: K;
|
|
171
177
|
}> & keyof T;
|
|
178
|
+
export type TruthyKeysOnly<T> = ExtractObjectValues<{
|
|
179
|
+
[K in keyof T as T[K] extends undefined | false ? never : K]: K;
|
|
180
|
+
}> & keyof T;
|
|
172
181
|
export type BuildQueryResult<TSchema extends TablesRelationalConfig, TTableConfig extends TableRelationalConfig, TFullSelection extends true | Record<string, unknown>> = Equal<TFullSelection, true> extends true ? InferModelFromColumns<TTableConfig['columns']> : TFullSelection extends Record<string, unknown> ? Simplify<(TFullSelection['columns'] extends Record<string, unknown> ? InferModelFromColumns<{
|
|
173
182
|
[K in Equal<Exclude<TFullSelection['columns'][keyof TFullSelection['columns'] & keyof TTableConfig['columns']], undefined>, false> extends true ? Exclude<keyof TTableConfig['columns'], NonUndefinedKeysOnly<TFullSelection['columns']>> : {
|
|
174
183
|
[K in keyof TFullSelection['columns']]: Equal<TFullSelection['columns'][K], true> extends true ? K : never;
|
|
@@ -186,12 +195,13 @@ export interface BuildRelationalQueryResult {
|
|
|
186
195
|
field: Column | Table | SQL | SQL.Aliased | SQLWrapper | AggregatedField;
|
|
187
196
|
isArray?: boolean;
|
|
188
197
|
selection?: BuildRelationalQueryResult['selection'];
|
|
198
|
+
isOptional?: boolean;
|
|
189
199
|
}[];
|
|
190
200
|
sql: SQL;
|
|
191
201
|
}
|
|
192
202
|
export declare function mapRelationalRow(row: Record<string, unknown>, buildQueryResultSelection: BuildRelationalQueryResult['selection'], mapColumnValue?: (value: unknown) => unknown,
|
|
193
203
|
/** Needed for SQLite as it returns JSON values as strings */
|
|
194
|
-
parseJson?: boolean): Record<string, unknown>;
|
|
204
|
+
parseJson?: boolean, path?: string): Record<string, unknown>;
|
|
195
205
|
export declare class RelationsBuilderTable<TTableName extends string = string> implements SQLWrapper {
|
|
196
206
|
static readonly [entityKind]: string;
|
|
197
207
|
readonly _: {
|
|
@@ -211,7 +221,7 @@ export type RelationsBuilderColumnConfig<TTableName extends string = string, TDa
|
|
|
211
221
|
readonly column: AnyColumn<{
|
|
212
222
|
tableName: TTableName;
|
|
213
223
|
}>;
|
|
214
|
-
through?: RelationsBuilderColumnBase;
|
|
224
|
+
readonly through?: RelationsBuilderColumnBase;
|
|
215
225
|
};
|
|
216
226
|
export type RelationsBuilderColumnBase<TTableName extends string = string, TData = unknown> = {
|
|
217
227
|
_: RelationsBuilderColumnConfig<TTableName, TData>;
|
|
@@ -224,33 +234,33 @@ export declare class RelationsBuilderColumn<TTableName extends string = string,
|
|
|
224
234
|
readonly column: AnyColumn<{
|
|
225
235
|
tableName: TTableName;
|
|
226
236
|
}>;
|
|
227
|
-
through?: RelationsBuilderColumnBase;
|
|
237
|
+
readonly through?: RelationsBuilderColumnBase;
|
|
228
238
|
};
|
|
229
239
|
constructor(column: AnyColumn<{
|
|
230
240
|
tableName: TTableName;
|
|
231
|
-
}
|
|
232
|
-
through(column:
|
|
241
|
+
}>, through?: RelationsBuilderColumn);
|
|
242
|
+
through(column: RelationsBuilderColumn): RelationsBuilderColumnBase<TTableName, TData>;
|
|
233
243
|
getSQL(): SQL;
|
|
234
244
|
}
|
|
235
245
|
export type RelationFieldsFilterInternals<T> = {
|
|
236
|
-
eq?: T;
|
|
237
|
-
ne?: T;
|
|
238
|
-
gt?: T;
|
|
239
|
-
gte?: T;
|
|
240
|
-
lt?: T;
|
|
241
|
-
lte?: T;
|
|
242
|
-
in?: T[];
|
|
243
|
-
notIn?: T[];
|
|
244
|
-
like?: string;
|
|
245
|
-
ilike?: string;
|
|
246
|
-
notLike?: string;
|
|
247
|
-
notIlike?: string;
|
|
246
|
+
eq?: T | Placeholder;
|
|
247
|
+
ne?: T | Placeholder;
|
|
248
|
+
gt?: T | Placeholder;
|
|
249
|
+
gte?: T | Placeholder;
|
|
250
|
+
lt?: T | Placeholder;
|
|
251
|
+
lte?: T | Placeholder;
|
|
252
|
+
in?: (T | Placeholder)[] | Placeholder;
|
|
253
|
+
notIn?: (T | Placeholder)[] | Placeholder;
|
|
254
|
+
like?: string | Placeholder;
|
|
255
|
+
ilike?: string | Placeholder;
|
|
256
|
+
notLike?: string | Placeholder;
|
|
257
|
+
notIlike?: string | Placeholder;
|
|
248
258
|
isNull?: true;
|
|
249
259
|
isNotNull?: true;
|
|
250
260
|
NOT?: RelationsFieldFilter<T>;
|
|
251
261
|
OR?: RelationsFieldFilter<T>[];
|
|
252
262
|
};
|
|
253
|
-
export type RelationsFieldFilter<T> = T |
|
|
263
|
+
export type RelationsFieldFilter<T> = RelationFieldsFilterInternals<T> | (T extends Record<string, any> ? never : T);
|
|
254
264
|
export type RelationsFilter<TColumns extends Record<string, Column>> = {
|
|
255
265
|
[K in keyof TColumns]?: RelationsFieldFilter<TColumns[K]['_']['data']>;
|
|
256
266
|
} & {
|
|
@@ -258,9 +268,7 @@ export type RelationsFilter<TColumns extends Record<string, Column>> = {
|
|
|
258
268
|
NOT?: RelationsFilter<TColumns>;
|
|
259
269
|
RAW?: (table: Simplify<AnyTable<{
|
|
260
270
|
columns: TColumns;
|
|
261
|
-
}> &
|
|
262
|
-
[K in keyof TColumns]: TColumns[K];
|
|
263
|
-
}>, operators: Operators) => SQL;
|
|
271
|
+
}> & TColumns>, operators: Operators) => SQL;
|
|
264
272
|
};
|
|
265
273
|
export interface OneConfig<TSchema extends Record<string, Table>, TSourceColumns extends Readonly<[RelationsBuilderColumnBase, ...RelationsBuilderColumnBase[]]> | Readonly<RelationsBuilderColumnBase>, TTargetTableName extends string, TOptional extends boolean> {
|
|
266
274
|
from?: TSourceColumns | Writable<TSourceColumns>;
|
|
@@ -282,7 +290,7 @@ export interface ManyConfig<TSchema extends Record<string, Table>, TSourceColumn
|
|
|
282
290
|
}
|
|
283
291
|
export type AnyManyConfig = ManyConfig<Record<string, Table>, Readonly<[RelationsBuilderColumnBase, ...RelationsBuilderColumnBase[]]> | Readonly<RelationsBuilderColumnBase>, string>;
|
|
284
292
|
export interface OneFn<TTables extends Record<string, Table>, TTargetTableName extends string> {
|
|
285
|
-
<TSourceColumns extends Readonly<[RelationsBuilderColumnBase, ...RelationsBuilderColumnBase[]]> | RelationsBuilderColumnBase = any, TOptional extends boolean =
|
|
293
|
+
<TSourceColumns extends Readonly<[RelationsBuilderColumnBase, ...RelationsBuilderColumnBase[]]> | RelationsBuilderColumnBase = any, TOptional extends boolean = true>(config?: OneConfig<TTables, TSourceColumns, TTargetTableName, TOptional>): One<TSourceColumns extends [RelationsBuilderColumnBase, ...RelationsBuilderColumnBase[]] ? TSourceColumns[number]['_']['tableName'] : Assume<TSourceColumns, RelationsBuilderColumnBase>['_']['tableName'], TTargetTableName, TOptional>;
|
|
286
294
|
}
|
|
287
295
|
export interface ManyFn<TTables extends Record<string, Table>, TTargetTableName extends string> {
|
|
288
296
|
<TSourceColumns extends Readonly<[RelationsBuilderColumnBase, ...RelationsBuilderColumnBase[]]> | RelationsBuilderColumnBase = any>(config?: ManyConfig<TTables, TSourceColumns, TTargetTableName>): Many<TSourceColumns extends [RelationsBuilderColumnBase, ...RelationsBuilderColumnBase[]] ? TSourceColumns[number]['_']['tableName'] : Assume<TSourceColumns, RelationsBuilderColumnBase>['_']['tableName'], TTargetTableName>;
|
|
@@ -341,7 +349,12 @@ export declare function relationExtrasToSQL(table: Table, extras: Extras): {
|
|
|
341
349
|
field: Column | Table | SQL | SQL.Aliased | SQLWrapper | AggregatedField;
|
|
342
350
|
isArray?: boolean;
|
|
343
351
|
selection?: BuildRelationalQueryResult["selection"];
|
|
352
|
+
isOptional?: boolean;
|
|
344
353
|
}[];
|
|
345
354
|
};
|
|
346
|
-
export
|
|
355
|
+
export type BuiltRelationFilters = {
|
|
356
|
+
filter?: SQL;
|
|
357
|
+
joinCondition?: SQL;
|
|
358
|
+
};
|
|
359
|
+
export declare function relationToSQL(relation: Relation, sourceTable: Table, targetTable: Table, throughTable?: Table): BuiltRelationFilters;
|
|
347
360
|
export {};
|
package/relations.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { type AnyTable, type InferModelFromColumns, Table } from "./table.js";
|
|
|
2
2
|
import { type AnyColumn, Column } from "./column.js";
|
|
3
3
|
import { entityKind } from "./entity.js";
|
|
4
4
|
import { and, asc, between, desc, exists, ilike, inArray, isNotNull, isNull, like, not, notBetween, notExists, notIlike, notInArray, notLike, or } from "./sql/expressions/index.js";
|
|
5
|
-
import { Placeholder, SQL, sql, type SQLWrapper } from "./sql/sql.js";
|
|
5
|
+
import { type Placeholder, SQL, sql, type SQLWrapper } from "./sql/sql.js";
|
|
6
6
|
import { type Assume, type Equal, type Simplify, type ValueOrArray, type Writable } from "./utils.js";
|
|
7
7
|
export declare class Relations<TSchema extends Record<string, unknown> = Record<string, unknown>, TTables extends Record<string, Table> = Record<string, Table>, TConfig extends RelationsBuilderConfig<TTables> = RelationsBuilderConfig<TTables>> {
|
|
8
8
|
readonly schema: TSchema;
|
|
@@ -35,6 +35,12 @@ export declare abstract class Relation<TSourceTableName extends string = string,
|
|
|
35
35
|
sourceTable: AnyTable<{
|
|
36
36
|
name: TSourceTableName;
|
|
37
37
|
}>;
|
|
38
|
+
through?: {
|
|
39
|
+
source: AnyColumn[];
|
|
40
|
+
target: AnyColumn[];
|
|
41
|
+
};
|
|
42
|
+
throughTable?: Table;
|
|
43
|
+
isReversed?: boolean;
|
|
38
44
|
constructor(targetTable: AnyTable<{
|
|
39
45
|
name: TTargetTableName;
|
|
40
46
|
}>);
|
|
@@ -122,7 +128,7 @@ export type DBQueryConfig<TRelationType extends 'one' | 'many' = 'one' | 'many',
|
|
|
122
128
|
[K in keyof TTableConfig['columns']]?: boolean | undefined;
|
|
123
129
|
} | undefined;
|
|
124
130
|
with?: {
|
|
125
|
-
[K in keyof TTableConfig['relations']]?:
|
|
131
|
+
[K in keyof TTableConfig['relations']]?: boolean | (TTableConfig['relations'][K] extends Relation ? DBQueryConfig<TTableConfig['relations'][K] extends One<string, string> ? 'one' : 'many', TSchema, FindTableInRelationalConfig<TSchema, TTableConfig['relations'][K]['targetTable']>> : never) | undefined;
|
|
126
132
|
} | undefined;
|
|
127
133
|
extras?: Record<string, SQLWrapper> | ((table: Simplify<AnyTable<TTableConfig> & TTableConfig['columns']>, operators: SQLOperator) => Record<string, SQLWrapper>) | undefined;
|
|
128
134
|
offset?: number | Placeholder | undefined;
|
|
@@ -164,11 +170,14 @@ export type ExtractTablesWithRelations<TRelations extends Relations, TTables ext
|
|
|
164
170
|
};
|
|
165
171
|
export type ReturnTypeOrValue<T> = T extends (...args: any[]) => infer R ? R : T;
|
|
166
172
|
export type BuildRelationResult<TConfig extends TablesRelationalConfig, TInclude, TRelations extends Record<string, RelationsBuilderEntry>> = {
|
|
167
|
-
[K in
|
|
173
|
+
[K in TruthyKeysOnly<TInclude> & keyof TRelations]: TRelations[K] extends infer TRel extends Relation ? BuildQueryResult<TConfig, FindTableInRelationalConfig<TConfig, TRel['targetTable']>, Assume<TInclude[K], true | Record<string, unknown>>> extends infer TResult ? TRel extends One<string, string> ? TResult | (Equal<TRel['optional'], true> extends true ? null : TInclude[K] extends Record<string, unknown> ? TInclude[K]['where'] extends Record<string, any> ? null : never : never) : TResult[] : never : TRelations[K] extends AggregatedField<infer TData> ? TData : never;
|
|
168
174
|
};
|
|
169
175
|
export type NonUndefinedKeysOnly<T> = ExtractObjectValues<{
|
|
170
176
|
[K in keyof T as T[K] extends undefined ? never : K]: K;
|
|
171
177
|
}> & keyof T;
|
|
178
|
+
export type TruthyKeysOnly<T> = ExtractObjectValues<{
|
|
179
|
+
[K in keyof T as T[K] extends undefined | false ? never : K]: K;
|
|
180
|
+
}> & keyof T;
|
|
172
181
|
export type BuildQueryResult<TSchema extends TablesRelationalConfig, TTableConfig extends TableRelationalConfig, TFullSelection extends true | Record<string, unknown>> = Equal<TFullSelection, true> extends true ? InferModelFromColumns<TTableConfig['columns']> : TFullSelection extends Record<string, unknown> ? Simplify<(TFullSelection['columns'] extends Record<string, unknown> ? InferModelFromColumns<{
|
|
173
182
|
[K in Equal<Exclude<TFullSelection['columns'][keyof TFullSelection['columns'] & keyof TTableConfig['columns']], undefined>, false> extends true ? Exclude<keyof TTableConfig['columns'], NonUndefinedKeysOnly<TFullSelection['columns']>> : {
|
|
174
183
|
[K in keyof TFullSelection['columns']]: Equal<TFullSelection['columns'][K], true> extends true ? K : never;
|
|
@@ -186,12 +195,13 @@ export interface BuildRelationalQueryResult {
|
|
|
186
195
|
field: Column | Table | SQL | SQL.Aliased | SQLWrapper | AggregatedField;
|
|
187
196
|
isArray?: boolean;
|
|
188
197
|
selection?: BuildRelationalQueryResult['selection'];
|
|
198
|
+
isOptional?: boolean;
|
|
189
199
|
}[];
|
|
190
200
|
sql: SQL;
|
|
191
201
|
}
|
|
192
202
|
export declare function mapRelationalRow(row: Record<string, unknown>, buildQueryResultSelection: BuildRelationalQueryResult['selection'], mapColumnValue?: (value: unknown) => unknown,
|
|
193
203
|
/** Needed for SQLite as it returns JSON values as strings */
|
|
194
|
-
parseJson?: boolean): Record<string, unknown>;
|
|
204
|
+
parseJson?: boolean, path?: string): Record<string, unknown>;
|
|
195
205
|
export declare class RelationsBuilderTable<TTableName extends string = string> implements SQLWrapper {
|
|
196
206
|
static readonly [entityKind]: string;
|
|
197
207
|
readonly _: {
|
|
@@ -211,7 +221,7 @@ export type RelationsBuilderColumnConfig<TTableName extends string = string, TDa
|
|
|
211
221
|
readonly column: AnyColumn<{
|
|
212
222
|
tableName: TTableName;
|
|
213
223
|
}>;
|
|
214
|
-
through?: RelationsBuilderColumnBase;
|
|
224
|
+
readonly through?: RelationsBuilderColumnBase;
|
|
215
225
|
};
|
|
216
226
|
export type RelationsBuilderColumnBase<TTableName extends string = string, TData = unknown> = {
|
|
217
227
|
_: RelationsBuilderColumnConfig<TTableName, TData>;
|
|
@@ -224,33 +234,33 @@ export declare class RelationsBuilderColumn<TTableName extends string = string,
|
|
|
224
234
|
readonly column: AnyColumn<{
|
|
225
235
|
tableName: TTableName;
|
|
226
236
|
}>;
|
|
227
|
-
through?: RelationsBuilderColumnBase;
|
|
237
|
+
readonly through?: RelationsBuilderColumnBase;
|
|
228
238
|
};
|
|
229
239
|
constructor(column: AnyColumn<{
|
|
230
240
|
tableName: TTableName;
|
|
231
|
-
}
|
|
232
|
-
through(column:
|
|
241
|
+
}>, through?: RelationsBuilderColumn);
|
|
242
|
+
through(column: RelationsBuilderColumn): RelationsBuilderColumnBase<TTableName, TData>;
|
|
233
243
|
getSQL(): SQL;
|
|
234
244
|
}
|
|
235
245
|
export type RelationFieldsFilterInternals<T> = {
|
|
236
|
-
eq?: T;
|
|
237
|
-
ne?: T;
|
|
238
|
-
gt?: T;
|
|
239
|
-
gte?: T;
|
|
240
|
-
lt?: T;
|
|
241
|
-
lte?: T;
|
|
242
|
-
in?: T[];
|
|
243
|
-
notIn?: T[];
|
|
244
|
-
like?: string;
|
|
245
|
-
ilike?: string;
|
|
246
|
-
notLike?: string;
|
|
247
|
-
notIlike?: string;
|
|
246
|
+
eq?: T | Placeholder;
|
|
247
|
+
ne?: T | Placeholder;
|
|
248
|
+
gt?: T | Placeholder;
|
|
249
|
+
gte?: T | Placeholder;
|
|
250
|
+
lt?: T | Placeholder;
|
|
251
|
+
lte?: T | Placeholder;
|
|
252
|
+
in?: (T | Placeholder)[] | Placeholder;
|
|
253
|
+
notIn?: (T | Placeholder)[] | Placeholder;
|
|
254
|
+
like?: string | Placeholder;
|
|
255
|
+
ilike?: string | Placeholder;
|
|
256
|
+
notLike?: string | Placeholder;
|
|
257
|
+
notIlike?: string | Placeholder;
|
|
248
258
|
isNull?: true;
|
|
249
259
|
isNotNull?: true;
|
|
250
260
|
NOT?: RelationsFieldFilter<T>;
|
|
251
261
|
OR?: RelationsFieldFilter<T>[];
|
|
252
262
|
};
|
|
253
|
-
export type RelationsFieldFilter<T> = T |
|
|
263
|
+
export type RelationsFieldFilter<T> = RelationFieldsFilterInternals<T> | (T extends Record<string, any> ? never : T);
|
|
254
264
|
export type RelationsFilter<TColumns extends Record<string, Column>> = {
|
|
255
265
|
[K in keyof TColumns]?: RelationsFieldFilter<TColumns[K]['_']['data']>;
|
|
256
266
|
} & {
|
|
@@ -258,9 +268,7 @@ export type RelationsFilter<TColumns extends Record<string, Column>> = {
|
|
|
258
268
|
NOT?: RelationsFilter<TColumns>;
|
|
259
269
|
RAW?: (table: Simplify<AnyTable<{
|
|
260
270
|
columns: TColumns;
|
|
261
|
-
}> &
|
|
262
|
-
[K in keyof TColumns]: TColumns[K];
|
|
263
|
-
}>, operators: Operators) => SQL;
|
|
271
|
+
}> & TColumns>, operators: Operators) => SQL;
|
|
264
272
|
};
|
|
265
273
|
export interface OneConfig<TSchema extends Record<string, Table>, TSourceColumns extends Readonly<[RelationsBuilderColumnBase, ...RelationsBuilderColumnBase[]]> | Readonly<RelationsBuilderColumnBase>, TTargetTableName extends string, TOptional extends boolean> {
|
|
266
274
|
from?: TSourceColumns | Writable<TSourceColumns>;
|
|
@@ -282,7 +290,7 @@ export interface ManyConfig<TSchema extends Record<string, Table>, TSourceColumn
|
|
|
282
290
|
}
|
|
283
291
|
export type AnyManyConfig = ManyConfig<Record<string, Table>, Readonly<[RelationsBuilderColumnBase, ...RelationsBuilderColumnBase[]]> | Readonly<RelationsBuilderColumnBase>, string>;
|
|
284
292
|
export interface OneFn<TTables extends Record<string, Table>, TTargetTableName extends string> {
|
|
285
|
-
<TSourceColumns extends Readonly<[RelationsBuilderColumnBase, ...RelationsBuilderColumnBase[]]> | RelationsBuilderColumnBase = any, TOptional extends boolean =
|
|
293
|
+
<TSourceColumns extends Readonly<[RelationsBuilderColumnBase, ...RelationsBuilderColumnBase[]]> | RelationsBuilderColumnBase = any, TOptional extends boolean = true>(config?: OneConfig<TTables, TSourceColumns, TTargetTableName, TOptional>): One<TSourceColumns extends [RelationsBuilderColumnBase, ...RelationsBuilderColumnBase[]] ? TSourceColumns[number]['_']['tableName'] : Assume<TSourceColumns, RelationsBuilderColumnBase>['_']['tableName'], TTargetTableName, TOptional>;
|
|
286
294
|
}
|
|
287
295
|
export interface ManyFn<TTables extends Record<string, Table>, TTargetTableName extends string> {
|
|
288
296
|
<TSourceColumns extends Readonly<[RelationsBuilderColumnBase, ...RelationsBuilderColumnBase[]]> | RelationsBuilderColumnBase = any>(config?: ManyConfig<TTables, TSourceColumns, TTargetTableName>): Many<TSourceColumns extends [RelationsBuilderColumnBase, ...RelationsBuilderColumnBase[]] ? TSourceColumns[number]['_']['tableName'] : Assume<TSourceColumns, RelationsBuilderColumnBase>['_']['tableName'], TTargetTableName>;
|
|
@@ -341,7 +349,12 @@ export declare function relationExtrasToSQL(table: Table, extras: Extras): {
|
|
|
341
349
|
field: Column | Table | SQL | SQL.Aliased | SQLWrapper | AggregatedField;
|
|
342
350
|
isArray?: boolean;
|
|
343
351
|
selection?: BuildRelationalQueryResult["selection"];
|
|
352
|
+
isOptional?: boolean;
|
|
344
353
|
}[];
|
|
345
354
|
};
|
|
346
|
-
export
|
|
355
|
+
export type BuiltRelationFilters = {
|
|
356
|
+
filter?: SQL;
|
|
357
|
+
joinCondition?: SQL;
|
|
358
|
+
};
|
|
359
|
+
export declare function relationToSQL(relation: Relation, sourceTable: Table, targetTable: Table, throughTable?: Table): BuiltRelationFilters;
|
|
347
360
|
export {};
|
package/relations.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
getTableUniqueName,
|
|
3
|
+
IsAlias,
|
|
4
|
+
OriginalName,
|
|
5
|
+
Schema,
|
|
6
|
+
Table
|
|
7
|
+
} from "./table.js";
|
|
2
8
|
import { Columns, getTableName } from "./table.js";
|
|
3
9
|
import { Column } from "./column.js";
|
|
4
10
|
import { entityKind, is } from "./entity.js";
|
|
@@ -28,7 +34,7 @@ import {
|
|
|
28
34
|
notLike,
|
|
29
35
|
or
|
|
30
36
|
} from "./sql/expressions/index.js";
|
|
31
|
-
import {
|
|
37
|
+
import { SQL, sql } from "./sql/sql.js";
|
|
32
38
|
import { getTableColumns } from "./utils.js";
|
|
33
39
|
class Relations {
|
|
34
40
|
constructor(schema, tables, config) {
|
|
@@ -89,9 +95,30 @@ class Relations {
|
|
|
89
95
|
if (relation.sourceColumns && relation.targetColumns) {
|
|
90
96
|
if (relation.sourceColumns.length !== relation.targetColumns.length) {
|
|
91
97
|
throw new Error(
|
|
92
|
-
`${relationPrintName}: "from" and "to"
|
|
98
|
+
`${relationPrintName}: "from" and "to" fields must have the same length`
|
|
93
99
|
);
|
|
94
100
|
}
|
|
101
|
+
if (relation.through) {
|
|
102
|
+
if (relation.through.source.length !== relation.through.target.length || relation.through.source.length !== relation.sourceColumns.length || relation.through.target.length !== relation.targetColumns.length) {
|
|
103
|
+
throw new Error(
|
|
104
|
+
`${relationPrintName}: ".through(column)" must be used either on all columns in "from" and "to" or not defined on any of them`
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
for (const column of relation.through.source) {
|
|
108
|
+
if (column.table !== relation.throughTable) {
|
|
109
|
+
throw new Error(
|
|
110
|
+
`${relationPrintName}: ".through(column)" must be used on the same table by all columns of the relation`
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
for (const column of relation.through.target) {
|
|
115
|
+
if (column.table !== relation.throughTable) {
|
|
116
|
+
throw new Error(
|
|
117
|
+
`${relationPrintName}: ".through(column)" must be used on the same table by all columns of the relation`
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
95
122
|
continue;
|
|
96
123
|
}
|
|
97
124
|
if (relation.sourceColumns || relation.targetColumns) {
|
|
@@ -151,7 +178,13 @@ Hint: you can specify "alias" on both sides of the relation with the same value`
|
|
|
151
178
|
}
|
|
152
179
|
relation.sourceColumns = reverseRelation.targetColumns;
|
|
153
180
|
relation.targetColumns = reverseRelation.sourceColumns;
|
|
154
|
-
relation.
|
|
181
|
+
relation.through = reverseRelation.through ? {
|
|
182
|
+
source: reverseRelation.through.target,
|
|
183
|
+
target: reverseRelation.through.source
|
|
184
|
+
} : void 0;
|
|
185
|
+
relation.throughTable = reverseRelation.throughTable;
|
|
186
|
+
relation.isReversed = !relation.where;
|
|
187
|
+
relation.where = relation.where ?? reverseRelation.where;
|
|
155
188
|
}
|
|
156
189
|
}
|
|
157
190
|
}
|
|
@@ -171,6 +204,9 @@ class Relation {
|
|
|
171
204
|
alias;
|
|
172
205
|
where;
|
|
173
206
|
sourceTable;
|
|
207
|
+
through;
|
|
208
|
+
throughTable;
|
|
209
|
+
isReversed;
|
|
174
210
|
}
|
|
175
211
|
class One extends Relation {
|
|
176
212
|
static [entityKind] = "OneV2";
|
|
@@ -180,12 +216,30 @@ class One extends Relation {
|
|
|
180
216
|
this.alias = config?.alias;
|
|
181
217
|
this.where = config?.where;
|
|
182
218
|
if (config?.from) {
|
|
183
|
-
this.sourceColumns = Array.isArray(config.from) ? config.from.map((it) =>
|
|
219
|
+
this.sourceColumns = (Array.isArray(config.from) ? config.from : [config.from]).map((it) => {
|
|
220
|
+
this.throughTable ??= it._.through?._.column.table;
|
|
221
|
+
return it._.column;
|
|
222
|
+
});
|
|
184
223
|
}
|
|
185
224
|
if (config?.to) {
|
|
186
|
-
this.targetColumns = Array.isArray(config.to) ? config.to.map((it) =>
|
|
225
|
+
this.targetColumns = (Array.isArray(config.to) ? config.to : [config.to]).map((it) => {
|
|
226
|
+
this.throughTable ??= it._.through?._.column.table;
|
|
227
|
+
return it._.column;
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
if (this.throughTable) {
|
|
231
|
+
this.through = Array.isArray(config?.from) ? {
|
|
232
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain -- in case it's undefined, error will be thrown in Relations constructor
|
|
233
|
+
source: config.from.map((e) => e._.through?._.column),
|
|
234
|
+
target: (config.to ?? []).map((e) => e._.column)
|
|
235
|
+
} : {
|
|
236
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain -- in case it's undefined, error will be thrown in Relations constructor
|
|
237
|
+
source: [config?.from?._.through?._.column],
|
|
238
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
|
|
239
|
+
target: [config?.to?._.through?._.column]
|
|
240
|
+
};
|
|
187
241
|
}
|
|
188
|
-
this.optional = config?.optional ??
|
|
242
|
+
this.optional = config?.optional ?? true;
|
|
189
243
|
}
|
|
190
244
|
}
|
|
191
245
|
class Many extends Relation {
|
|
@@ -195,10 +249,28 @@ class Many extends Relation {
|
|
|
195
249
|
this.alias = config?.alias;
|
|
196
250
|
this.where = config?.where;
|
|
197
251
|
if (config?.from) {
|
|
198
|
-
this.sourceColumns = Array.isArray(config.from) ? config.from.map((it) =>
|
|
252
|
+
this.sourceColumns = (Array.isArray(config.from) ? config.from : [config.from]).map((it) => {
|
|
253
|
+
this.throughTable ??= it._.through?._.column.table;
|
|
254
|
+
return it._.column;
|
|
255
|
+
});
|
|
199
256
|
}
|
|
200
257
|
if (config?.to) {
|
|
201
|
-
this.targetColumns = Array.isArray(config.to) ? config.to.map((it) =>
|
|
258
|
+
this.targetColumns = (Array.isArray(config.to) ? config.to : [config.to]).map((it) => {
|
|
259
|
+
this.throughTable ??= it._.through?._.column.table;
|
|
260
|
+
return it._.column;
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
if (this.throughTable) {
|
|
264
|
+
this.through = Array.isArray(config?.from) ? {
|
|
265
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain -- in case it's undefined, error will be thrown in Relations constructor
|
|
266
|
+
source: config.from.map((e) => e._.through?._.column),
|
|
267
|
+
target: (config.to ?? []).map((e) => e._.column)
|
|
268
|
+
} : {
|
|
269
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain -- in case it's undefined, error will be thrown in Relations constructor
|
|
270
|
+
source: [config?.from?._.through?._.column],
|
|
271
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
|
|
272
|
+
target: [config?.to?._.through?._.column]
|
|
273
|
+
};
|
|
202
274
|
}
|
|
203
275
|
}
|
|
204
276
|
static [entityKind] = "ManyV2";
|
|
@@ -218,7 +290,8 @@ class Count extends AggregatedField {
|
|
|
218
290
|
if (!this.query) {
|
|
219
291
|
if (!this.table)
|
|
220
292
|
throw new Error("Table must be set before building aggregate field");
|
|
221
|
-
|
|
293
|
+
const table = this.table;
|
|
294
|
+
this.query = sql`select count(*) as ${sql.identifier("r")} from ${table[IsAlias] ? sql`${sql`${sql.identifier(table[Schema] ?? "")}.`.if(table[Schema])}${sql.identifier(table[OriginalName])} as ${table}` : table}`.mapWith(Number);
|
|
222
295
|
}
|
|
223
296
|
return this.query;
|
|
224
297
|
}
|
|
@@ -255,24 +328,33 @@ const orderByOperators = {
|
|
|
255
328
|
function getOrderByOperators() {
|
|
256
329
|
return orderByOperators;
|
|
257
330
|
}
|
|
258
|
-
function mapRelationalRow(row, buildQueryResultSelection, mapColumnValue = (value) => value, parseJson = false) {
|
|
331
|
+
function mapRelationalRow(row, buildQueryResultSelection, mapColumnValue = (value) => value, parseJson = false, path) {
|
|
259
332
|
for (const selectionItem of buildQueryResultSelection) {
|
|
260
333
|
const field = selectionItem.field;
|
|
261
334
|
if (is(field, Table)) {
|
|
335
|
+
const currentPath = `${path ? `${path}.` : ""}${selectionItem.key}`;
|
|
262
336
|
if (row[selectionItem.key] === null)
|
|
263
337
|
continue;
|
|
264
338
|
if (parseJson)
|
|
265
339
|
row[selectionItem.key] = JSON.parse(row[selectionItem.key]);
|
|
266
340
|
if (selectionItem.isArray) {
|
|
267
341
|
for (const item of row[selectionItem.key]) {
|
|
268
|
-
mapRelationalRow(
|
|
342
|
+
mapRelationalRow(
|
|
343
|
+
item,
|
|
344
|
+
selectionItem.selection,
|
|
345
|
+
mapColumnValue,
|
|
346
|
+
false,
|
|
347
|
+
currentPath
|
|
348
|
+
);
|
|
269
349
|
}
|
|
270
350
|
continue;
|
|
271
351
|
}
|
|
272
352
|
mapRelationalRow(
|
|
273
353
|
row[selectionItem.key],
|
|
274
354
|
selectionItem.selection,
|
|
275
|
-
mapColumnValue
|
|
355
|
+
mapColumnValue,
|
|
356
|
+
false,
|
|
357
|
+
currentPath
|
|
276
358
|
);
|
|
277
359
|
continue;
|
|
278
360
|
}
|
|
@@ -309,16 +391,16 @@ class RelationsBuilderTable {
|
|
|
309
391
|
class RelationsBuilderColumn {
|
|
310
392
|
static [entityKind] = "RelationsBuilderColumn";
|
|
311
393
|
_;
|
|
312
|
-
constructor(column) {
|
|
394
|
+
constructor(column, through) {
|
|
313
395
|
this._ = {
|
|
314
396
|
tableName: getTableName(column.table),
|
|
315
397
|
data: void 0,
|
|
316
|
-
column
|
|
398
|
+
column,
|
|
399
|
+
through
|
|
317
400
|
};
|
|
318
401
|
}
|
|
319
402
|
through(column) {
|
|
320
|
-
this._.
|
|
321
|
-
return this;
|
|
403
|
+
return new RelationsBuilderColumn(this._.column, column);
|
|
322
404
|
}
|
|
323
405
|
getSQL() {
|
|
324
406
|
return this._.column.getSQL();
|
|
@@ -382,7 +464,7 @@ function defineRelations(schema, relations) {
|
|
|
382
464
|
);
|
|
383
465
|
}
|
|
384
466
|
function relationsFieldFilterToSQL(column, filter) {
|
|
385
|
-
if (typeof filter !== "object"
|
|
467
|
+
if (typeof filter !== "object")
|
|
386
468
|
return eq(column, filter);
|
|
387
469
|
const entries = Object.entries(filter);
|
|
388
470
|
if (!entries.length)
|
|
@@ -409,6 +491,21 @@ function relationsFieldFilterToSQL(column, filter) {
|
|
|
409
491
|
);
|
|
410
492
|
continue;
|
|
411
493
|
}
|
|
494
|
+
case "isNotNull":
|
|
495
|
+
case "isNull": {
|
|
496
|
+
if (!value)
|
|
497
|
+
continue;
|
|
498
|
+
parts.push(operators[target](column));
|
|
499
|
+
continue;
|
|
500
|
+
}
|
|
501
|
+
case "in": {
|
|
502
|
+
parts.push(operators.inArray(column, value));
|
|
503
|
+
continue;
|
|
504
|
+
}
|
|
505
|
+
case "notIn": {
|
|
506
|
+
parts.push(operators.notInArray(column, value));
|
|
507
|
+
continue;
|
|
508
|
+
}
|
|
412
509
|
default: {
|
|
413
510
|
parts.push(
|
|
414
511
|
operators[target](
|
|
@@ -436,7 +533,7 @@ function relationsFilterToSQL(table, filter) {
|
|
|
436
533
|
case "RAW": {
|
|
437
534
|
if (value) {
|
|
438
535
|
parts.push(
|
|
439
|
-
value(table
|
|
536
|
+
value(table, operators)
|
|
440
537
|
);
|
|
441
538
|
}
|
|
442
539
|
continue;
|
|
@@ -506,16 +603,44 @@ function relationExtrasToSQL(table, extras) {
|
|
|
506
603
|
selection
|
|
507
604
|
};
|
|
508
605
|
}
|
|
509
|
-
function relationToSQL(relation, sourceTable, targetTable) {
|
|
606
|
+
function relationToSQL(relation, sourceTable, targetTable, throughTable) {
|
|
607
|
+
if (relation.through) {
|
|
608
|
+
const outerColumnWhere = relation.sourceColumns.map((s, i) => {
|
|
609
|
+
const t = relation.through.source[i];
|
|
610
|
+
return eq(
|
|
611
|
+
sql`${sourceTable}.${sql.identifier(s.name)}`,
|
|
612
|
+
sql`${throughTable}.${sql.identifier(t.name)}`
|
|
613
|
+
);
|
|
614
|
+
});
|
|
615
|
+
const innerColumnWhere = relation.targetColumns.map((s, i) => {
|
|
616
|
+
const t = relation.through.target[i];
|
|
617
|
+
return eq(
|
|
618
|
+
sql`${throughTable}.${sql.identifier(t.name)}`,
|
|
619
|
+
sql`${targetTable}.${sql.identifier(s.name)}`
|
|
620
|
+
);
|
|
621
|
+
});
|
|
622
|
+
return {
|
|
623
|
+
filter: and(
|
|
624
|
+
relation.where ? relation.isReversed ? relationsFilterToSQL(targetTable, relation.where) : relationsFilterToSQL(sourceTable, relation.where) : void 0
|
|
625
|
+
),
|
|
626
|
+
joinCondition: and(
|
|
627
|
+
...outerColumnWhere,
|
|
628
|
+
...innerColumnWhere
|
|
629
|
+
)
|
|
630
|
+
};
|
|
631
|
+
}
|
|
510
632
|
const columnWhere = relation.sourceColumns.map((s, i) => {
|
|
511
633
|
const t = relation.targetColumns[i];
|
|
512
634
|
return eq(
|
|
513
|
-
sql`${
|
|
514
|
-
sql`${
|
|
635
|
+
sql`${sourceTable}.${sql.identifier(s.name)}`,
|
|
636
|
+
sql`${targetTable}.${sql.identifier(t.name)}`
|
|
515
637
|
);
|
|
516
638
|
});
|
|
517
|
-
const
|
|
518
|
-
|
|
639
|
+
const fullWhere = and(
|
|
640
|
+
...columnWhere,
|
|
641
|
+
relation.where ? relation.isReversed ? relationsFilterToSQL(targetTable, relation.where) : relationsFilterToSQL(sourceTable, relation.where) : void 0
|
|
642
|
+
);
|
|
643
|
+
return { filter: fullWhere };
|
|
519
644
|
}
|
|
520
645
|
export {
|
|
521
646
|
AggregatedField,
|