orchid-orm 1.74.0 → 1.76.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,67 +1,82 @@
1
- import { Adapter, AfterCommitStandaloneHook, AfterHook, Column, ColumnSchemaConfig, ColumnsShape, ComputedColumnsFromOptions, ComputedOptionsConfig, ComputedOptionsFactory, CreateData, CreateManyMethodsNames, CreateMethodsNames, CreateSelf, DbSharedOptions, DbSqlMethod, DbTableOptionScopes, DefaultColumnTypes, DefaultSchemaConfig, DeleteMethodsNames, EmptyObject, FromArg, FromResult, Grant, IsQuery, IsolationLevel, JoinQueryMethod, MapTableScopesOption, MaybeArray, MergeQuery, PickQuerySelectableRelations, QueryAfterHook, QueryBeforeActionHook, QueryBeforeHook, QueryData, QueryHasWhere, QueryReturnType, QuerySchema, QueryScopes, RawSqlBase, RecordUnknown, RelationConfigBase, Rls, SelectableFromShape, ShallowSimplify, ShapeColumnPrimaryKeys, ShapeUniqueColumns, StorageOptions, TableData, TableDataFn, TableDataItem, TableDataItemsUniqueColumnTuples, TableDataItemsUniqueColumns, TableDataItemsUniqueConstraints, TransactionOptions, UniqueConstraints, UpdateData, WhereArg } from "pqb/internal";
1
+ import { Adapter, AfterCommitStandaloneHook, AfterHook, Column, ColumnSchemaConfig, ColumnsShape, ComputedOptionsConfig, ComputedOptionsFactory, CreateData, CreateManyMethodsNames, CreateMethodsNames, CreateSelf, DbSharedOptions, DbSqlMethod, DbTableOptionScopes, DefaultColumnTypes, DefaultSchemaConfig, DeleteMethodsNames, EmptyObject, FromArg, FromResult, Grant, IsQuery, IsolationLevel, MaybeArray, MergeQuery, PickQuerySelectableRelations, QueryAfterHook, QueryBeforeActionHook, QueryBeforeHook, QueryData, QueryHasWhere, QueryReturnType, QuerySchema, QueryScopes, RawSqlBase, RecordUnknown, RelationConfigBase, Rls, SelectableFromShape, ShallowSimplify, StorageOptions, TableData, TableDataFn, TableDataItem, TransactionOptions, UpdateData, WhereArg } from "pqb/internal";
2
2
  import { Db, Query } from "pqb";
3
3
  export * from "pqb";
4
- interface RelationRefsOptions<Column extends PropertyKey = string, Shape extends Column.Shape.QueryInit = Column.Shape.QueryInit> {
4
+ interface BelongsTo extends RelationThunkBase {
5
+ type: 'belongsTo';
6
+ options: BelongsToOptions;
7
+ }
8
+ interface BelongsToOptions<Columns extends Column.Shape.QueryInit = Column.Shape.QueryInit, Related extends ORMTableInput = ORMTableInput> {
5
9
  required?: boolean;
6
- columns: Column[];
7
- references: (keyof Shape)[];
10
+ columns: (keyof Columns)[];
11
+ references: (keyof Related['columns']['shape'])[];
8
12
  foreignKey?: boolean | TableData.References.Options;
9
- on?: ColumnsShape.InputPartial<Shape>;
10
- }
11
- interface RelationThroughOptions<Through extends PropertyKey = string, Source extends PropertyKey = string> {
12
- through: Through;
13
- source: Source;
14
- }
15
- interface HasOne extends RelationThunkBase {
16
- type: 'hasOne';
17
- options: HasOneOptions;
13
+ on?: ColumnsShape.InputPartial<Related['columns']['shape']>;
18
14
  }
19
- interface RelationHasOneThroughOptions<Through extends string, Source extends string> extends RelationThroughOptions<Through, Source> {
20
- required?: boolean;
15
+ type BelongsToParams<T extends RelationConfigSelf, FK extends string> = { [Name in FK]: T['columns']['shape'][Name]['__type'] };
16
+ type BelongsToDefaultRequired<T extends RelationConfigSelf, Rel extends BelongsTo, Related> = Related extends {
17
+ softDelete: true;
18
+ } ? false : BelongsToDefaultRequiredFromColumns<T, Rel>;
19
+ type BelongsToDefaultRequiredFromColumns<T extends RelationConfigSelf, Rel extends BelongsTo> = BelongsToColumnRequired<T['columns']['shape'][Rel['options']['columns'][number] & string]> extends true ? true : false;
20
+ type BelongsToColumnRequired<Column> = Column extends {
21
+ data: {
22
+ isNullable: true;
23
+ };
24
+ } ? false : true;
25
+ 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;
26
+ interface BelongsToDataForCreate<Name extends string, FK extends string, Required, Q extends Query> {
27
+ columns: FK;
28
+ nested: Q extends Query.Pick.IsNotReadOnly ? Required extends true ? { [Key in Name]: RelationToOneDataForCreateSameQuery<Q> } : { [Key in Name]?: RelationToOneDataForCreateSameQuery<Q> } : { [Key in Name]?: never };
21
29
  }
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>;
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>;
26
- interface HasOneInfo<T extends RelationConfigSelf, Name extends string, Rel extends HasOne, Q extends Query> extends RelationConfigBase {
30
+ interface BelongsToInfo<T extends RelationConfigSelf, FK extends string, Required, Q extends Query> extends RelationConfigBase {
27
31
  returnsOne: true;
28
- required: T['relations'][Name]['options']['required'];
32
+ required: Required;
29
33
  query: Q;
30
- params: HasOneParams<T, Rel['options']>;
31
- omitForeignKeyInCreate: never;
32
- dataForCreate: { [K in Name]?: Q extends Query.Pick.IsNotReadOnly ? T['relations'][Name]['options'] extends RelationThroughOptions ? EmptyObject : RelationToOneDataForCreate<{
33
- nestedCreateQuery: CreateData<Q>;
34
- table: Q;
35
- }> : never };
36
- dataForUpdate: Q extends Query.Pick.IsNotReadOnly ? {
34
+ params: BelongsToParams<T, FK>;
35
+ omitForeignKeyInCreate: FK;
36
+ dataForUpdate: {
37
37
  disconnect: boolean;
38
38
  } | {
39
+ set: WhereArg<Q>;
40
+ } | (Q extends Query.Pick.IsNotReadOnly ? {
39
41
  delete: boolean;
40
42
  } | {
41
43
  update: UpdateData<Q>;
42
- } : never;
43
- dataForUpdateOne: Q extends Query.Pick.IsNotReadOnly ? {
44
+ } | {
45
+ create: CreateData<Q>;
46
+ } : never);
47
+ dataForUpdateOne: {
44
48
  disconnect: boolean;
45
49
  } | {
46
50
  set: WhereArg<Q>;
47
- } | {
51
+ } | (Q extends Query.Pick.IsNotReadOnly ? {
48
52
  delete: boolean;
49
53
  } | {
50
54
  update: UpdateData<Q>;
55
+ } | {
56
+ create: CreateData<Q>;
51
57
  } | {
52
58
  upsert: {
53
59
  update: UpdateData<Q>;
54
60
  create: CreateData<Q> | (() => CreateData<Q>);
55
61
  };
56
- } | {
57
- create: CreateData<Q>;
58
- } : never;
62
+ } : never);
63
+ }
64
+ interface RelationRefsOptions<Column extends PropertyKey = string, Shape extends Column.Shape.QueryInit = Column.Shape.QueryInit> {
65
+ required?: boolean;
66
+ columns: Column[];
67
+ references: (keyof Shape)[];
68
+ foreignKey?: boolean | TableData.References.Options;
69
+ on?: ColumnsShape.InputPartial<Shape>;
70
+ }
71
+ interface RelationThroughOptions<Through extends PropertyKey = string, Source extends PropertyKey = string> {
72
+ through: Through;
73
+ source: Source;
59
74
  }
60
75
  interface HasMany extends RelationThunkBase {
61
76
  type: 'hasMany';
62
77
  options: HasOneOptions;
63
78
  }
64
- 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>;
79
+ 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 : HasOneQueryThrough<Name, TableQuery>;
65
80
  interface HasManyInfo<T extends RelationConfigSelf, Name extends string, Rel extends HasMany, Q extends Query> extends RelationConfigBase {
66
81
  returnsOne: false;
67
82
  query: Q;
@@ -100,63 +115,50 @@ interface HasManyInfo<T extends RelationConfigSelf, Name extends string, Rel ext
100
115
  };
101
116
  } : never;
102
117
  }
103
- interface RelJoin extends JoinQueryMethod {
104
- <T extends Query>(this: T): T;
105
- }
106
- interface HasRelJoin {
107
- join: RelJoin;
108
- }
109
- interface BelongsTo extends RelationThunkBase {
110
- type: 'belongsTo';
111
- options: BelongsToOptions;
118
+ interface HasOne extends RelationThunkBase {
119
+ type: 'hasOne';
120
+ options: HasOneOptions;
112
121
  }
113
- interface BelongsToOptions<Columns extends Column.Shape.QueryInit = Column.Shape.QueryInit, Related extends ORMTableInput = ORMTableInput> {
122
+ interface RelationHasOneThroughOptions<Through extends string, Source extends string> extends RelationThroughOptions<Through, Source> {
114
123
  required?: boolean;
115
- columns: (keyof Columns)[];
116
- references: (keyof Related['columns']['shape'])[];
117
- foreignKey?: boolean | TableData.References.Options;
118
- on?: ColumnsShape.InputPartial<Related['columns']['shape']>;
119
- }
120
- type BelongsToParams<T extends RelationConfigSelf, FK extends string> = { [Name in FK]: T['columns']['shape'][Name]['__type'] };
121
- type BelongsToColumnsRequired<T extends RelationConfigSelf, FK extends string> = { [K in FK]: T['columns']['shape'][K]['data']['isNullable'] extends true ? false : true }[FK] extends true ? true : false;
122
- 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;
123
- interface BelongsToDataForCreate<Name extends string, FK extends string, Required, Q extends Query> {
124
- columns: FK;
125
- nested: Q extends Query.Pick.IsNotReadOnly ? Required extends true ? { [Key in Name]: RelationToOneDataForCreateSameQuery<Q> } : { [Key in Name]?: RelationToOneDataForCreateSameQuery<Q> } : { [Key in Name]?: never };
126
124
  }
127
- interface BelongsToInfo<T extends RelationConfigSelf, FK extends string, Required, Q extends Query> extends RelationConfigBase {
125
+ 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>;
126
+ 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;
127
+ 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;
128
+ 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 : HasOneQueryThrough<Name, TableQuery>;
129
+ interface HasOneInfo<T extends RelationConfigSelf, Name extends string, Rel extends HasOne, Q extends Query> extends RelationConfigBase {
128
130
  returnsOne: true;
129
- required: Required;
131
+ required: T['relations'][Name]['options']['required'];
130
132
  query: Q;
131
- params: BelongsToParams<T, FK>;
132
- omitForeignKeyInCreate: FK;
133
- dataForUpdate: {
133
+ params: HasOneParams<T, Rel['options']>;
134
+ omitForeignKeyInCreate: never;
135
+ dataForCreate: { [K in Name]?: Q extends Query.Pick.IsNotReadOnly ? T['relations'][Name]['options'] extends RelationThroughOptions ? EmptyObject : RelationToOneDataForCreate<{
136
+ nestedCreateQuery: CreateData<Q>;
137
+ table: Q;
138
+ }> : never };
139
+ dataForUpdate: Q extends Query.Pick.IsNotReadOnly ? {
134
140
  disconnect: boolean;
135
141
  } | {
136
- set: WhereArg<Q>;
137
- } | (Q extends Query.Pick.IsNotReadOnly ? {
138
142
  delete: boolean;
139
143
  } | {
140
144
  update: UpdateData<Q>;
141
- } | {
142
- create: CreateData<Q>;
143
- } : never);
144
- dataForUpdateOne: {
145
+ } : never;
146
+ dataForUpdateOne: Q extends Query.Pick.IsNotReadOnly ? {
145
147
  disconnect: boolean;
146
148
  } | {
147
149
  set: WhereArg<Q>;
148
- } | (Q extends Query.Pick.IsNotReadOnly ? {
150
+ } | {
149
151
  delete: boolean;
150
152
  } | {
151
153
  update: UpdateData<Q>;
152
- } | {
153
- create: CreateData<Q>;
154
154
  } | {
155
155
  upsert: {
156
156
  update: UpdateData<Q>;
157
157
  create: CreateData<Q> | (() => CreateData<Q>);
158
158
  };
159
- } : never);
159
+ } | {
160
+ create: CreateData<Q>;
161
+ } : never;
160
162
  }
161
163
  interface HasAndBelongsToMany extends RelationThunkBase {
162
164
  type: 'hasAndBelongsToMany';
@@ -177,7 +179,7 @@ interface HasAndBelongsToManyOptions<Columns extends Column.Shape.QueryInit = Co
177
179
  on?: ColumnsShape.InputPartial<Related['columns']['shape']>;
178
180
  }
179
181
  type HasAndBelongsToManyParams<T extends RelationConfigSelf, FK extends string> = { [Name in FK]: T['columns']['shape'][Name]['__type'] };
180
- 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;
182
+ 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;
181
183
  interface HasAndBelongsToManyInfo<T extends RelationConfigSelf, Name extends string, FK extends string, Q extends Query> extends RelationConfigBase {
182
184
  returnsOne: false;
183
185
  query: Q;
@@ -267,16 +269,27 @@ type RelationToOneDataForCreateSameQuery<Q extends RelationToOneDataForCreateSam
267
269
  };
268
270
  interface RelationThunkBase {
269
271
  type: string;
270
- related: ORMTableInput;
272
+ id: string;
271
273
  options: unknown;
272
274
  }
273
275
  type RelationThunk = BelongsTo | HasOne | HasMany | HasAndBelongsToMany;
274
276
  interface RelationThunks {
275
277
  [K: string]: RelationThunk;
276
278
  }
277
- type RelationTableToQuery<Relation> = Relation extends {
278
- related: infer R extends ORMTableInput;
279
- } ? TableToDb<R, R['table'] extends string ? R['table'] : R['name'], R['table'] extends string ? R['readOnly'] extends true ? true : undefined : R['readOnly'] extends false ? undefined : true> : never;
279
+ type TableClassInstances<T extends TableClasses> = InstanceType<T[keyof T]>;
280
+ type RelationToTableInputById<Tables, Id extends string> = Extract<Tables, {
281
+ id: Id;
282
+ }>;
283
+ type RelationToTableInputByKey<T extends TableClasses, Id extends string> = Id extends keyof T ? InstanceType<T[Id]> : never;
284
+ type RelationToTableInputByName<Tables, Id extends string> = Extract<Tables, {
285
+ table: Id;
286
+ } | {
287
+ name: Id;
288
+ }>;
289
+ type RelationToTableInputByKeyOrName<T extends TableClasses, Id extends string> = Id extends keyof T ? RelationToTableInputByKey<T, Id> : RelationToTableInputByName<TableClassInstances<T>, Id>;
290
+ type RelationToTableInputFromClasses<T extends TableClasses, Id extends string> = RelationToTableInputById<TableClassInstances<T>, Id> extends infer Result ? [Result] extends [never] ? RelationToTableInputByKeyOrName<T, Id> : Result : never;
291
+ type RelationToTableInput<TC extends TableClasses, VC extends TableClasses, Rel extends RelationThunkBase> = RelationToTableInputFromClasses<TC, Rel['id']> extends infer Result ? [Result] extends [never] ? RelationToTableInputFromClasses<VC, Rel['id']> extends infer Result ? [Result] extends [never] ? false : Result : never : Result : never;
292
+ type RelationTableToQuery<TC extends TableClasses, VC extends TableClasses, Rel extends RelationThunkBase> = RelationToTableInput<TC, VC, Rel> extends infer Result extends ORMTableInput ? TableQueryBuilder<TC, VC, Result> : never;
280
293
  interface RelationConfigSelf {
281
294
  columns: {
282
295
  shape: Column.Shape.QueryInit;
@@ -321,23 +334,17 @@ interface OrchidORMTableHelper<T extends Query> {
321
334
  */
322
335
  makeHelper<Args extends unknown[], Result>(fn: (q: T, ...args: Args) => Result): OrchidORMQueryHelper<T, Args, Result>;
323
336
  }
324
- type OrchidORMTables<T extends TableClasses = TableClasses> = { [K in keyof T]: T[K] extends {
325
- new (): infer R extends ORMTableInput;
326
- } ? OrchidORMTableHelper<TableToDb<R, R['table'], R['readOnly'] extends true ? true : undefined>> : never };
327
- type OrchidORMViews<T extends TableClasses = TableClasses> = { [K in keyof T]: T[K] extends {
337
+ type OrchidORMTables<TC extends TableClasses = TableClasses, VC extends TableClasses = TableClasses> = { [K in keyof TC]: TC[K] extends {
328
338
  new (): infer R extends ORMTableInput;
329
- } ? OrchidORMTableHelper<TableToDb<R, R['name'], R['readOnly'] extends false ? undefined : true, R['materialized'] extends true ? true : undefined>> : never };
330
- type OrchidORMBundle<T extends TableClasses = TableClasses, V extends TableClasses = TableClasses> = OrchidORMTables<T> & {
331
- $views: OrchidORMViews<V>;
339
+ } ? OrchidORMTableHelper<TableQueryBuilder<TC, VC, R>> : never };
340
+ type OrchidORMBundle<TC extends TableClasses = TableClasses, VC extends TableClasses = TableClasses> = OrchidORMTables<TC> & {
341
+ $views: OrchidORMTables<VC, TC>;
332
342
  };
333
- type OrchidORMDbTables<T extends TableClasses = TableClasses> = { [K in keyof T]: T[K] extends {
343
+ type OrchidORMDbTables<TC extends TableClasses = TableClasses, VC extends TableClasses = TableClasses> = { [K in keyof TC]: TC[K] extends {
334
344
  new (): infer R extends ORMTableInput;
335
- } ? TableToDb<R, R['table'], R['readOnly'] extends true ? true : undefined> : never };
336
- type OrchidORMDbViews<T extends TableClasses = TableClasses> = { [K in keyof T]: T[K] extends {
337
- new (): infer R extends ORMTableInput;
338
- } ? TableToDb<R, R['name'], R['readOnly'] extends false ? undefined : true, R['materialized'] extends true ? true : undefined> : never };
339
- type OrchidORM<T extends TableClasses = TableClasses, V extends TableClasses = TableClasses> = OrchidORMDbTables<T> & {
340
- $views: OrchidORMDbViews<V>;
345
+ } ? TableQueryBuilder<TC, VC, R> : never };
346
+ type OrchidORM<TC extends TableClasses = TableClasses, VC extends TableClasses = TableClasses> = OrchidORMDbTables<TC, VC> & {
347
+ $views: OrchidORMDbTables<VC, TC>;
341
348
  } & OrchidORMMethods;
342
349
  /**
343
350
  * Identity helper for table row-level security configuration.
@@ -531,23 +538,23 @@ interface TableInfo {
531
538
  name: string;
532
539
  }
533
540
  interface Table extends Query, TableInfo {}
534
- type BelongsToRequired<T extends RelationConfigSelf, Rel extends BelongsTo> = Rel['options'] extends {
541
+ type BelongsToRequired<T extends RelationConfigSelf, Rel extends BelongsTo, Related> = Rel['options'] extends {
535
542
  required: infer Required extends boolean;
536
543
  } ? Required : Rel['options'] extends {
537
544
  on: unknown;
538
- } ? false : BelongsToColumnsRequired<T, Rel['options']['columns'][number] & string>;
539
- type BelongsToRelationInfo<T extends RelationConfigSelf, Name extends string, Rel extends BelongsTo> = BelongsToInfo<T, Rel['options']['columns'][number] & string, BelongsToRequired<T, Rel>, BelongsToQuery<RelationTableToQuery<Rel>, Name>>;
540
- type BelongsToCreateData<T extends RelationConfigSelf, Name extends string, Rel extends BelongsTo> = BelongsToDataForCreate<Name, Rel['options']['columns'][number] & string, BelongsToRequired<T, Rel>, BelongsToQuery<RelationTableToQuery<Rel>, Name>>;
545
+ } ? false : BelongsToDefaultRequired<T, Rel, Related>;
546
+ type BelongsToRelationInfo<TC extends TableClasses, VC extends TableClasses, T extends RelationConfigSelf, Name extends string, Rel extends BelongsTo> = RelationToTableInput<TC, VC, Rel> extends infer Related extends ORMTableInput ? BelongsToInfo<T, Rel['options']['columns'][number] & string, BelongsToRequired<T, Rel, Related>, BelongsToQuery<TableQueryBuilder<TC, VC, Related>, Name>> : never;
547
+ type BelongsToCreateData<TC extends TableClasses, VC extends TableClasses, T extends RelationConfigSelf, Name extends string, Rel extends BelongsTo> = RelationToTableInput<TC, VC, Rel> extends infer Related extends ORMTableInput ? BelongsToDataForCreate<Name, Rel['options']['columns'][number] & string, BelongsToRequired<T, Rel, Related>, BelongsToQuery<TableQueryBuilder<TC, VC, Related>, Name>> : never;
541
548
  type BelongsToCreateDataColumns<T extends RelationConfigSelf> = { [K in keyof T['relations']]: T['relations'][K] extends BelongsTo ? T['relations'][K]['options']['columns'][number] & string : never }[keyof T['relations']];
542
- type BelongsToCreateDataForColumn<T extends RelationConfigSelf, Column extends string> = { [K in keyof T['relations']]: T['relations'][K] extends BelongsTo ? Column extends T['relations'][K]['options']['columns'][number] ? BelongsToCreateData<T, K & string, T['relations'][K]> : never : never }[keyof T['relations']];
543
- type RelationDataForCreate<T extends RelationConfigSelf, Name extends keyof T['relations'] & string> = T['relations'][Name] extends HasOne ? HasOneInfo<T, Name, T['relations'][Name], HasOneQuery<T, Name, RelationTableToQuery<T['relations'][Name]>>>['dataForCreate'] : T['relations'][Name] extends HasMany ? HasManyInfo<T, Name, T['relations'][Name], HasManyQuery<T, Name, RelationTableToQuery<T['relations'][Name]>>>['dataForCreate'] : T['relations'][Name] extends HasAndBelongsToMany ? HasAndBelongsToManyInfo<T, Name, T['relations'][Name]['options']['columns'][number] & string, HasAndBelongsToManyQuery<Name, RelationTableToQuery<T['relations'][Name]>>>['dataForCreate'] : never;
549
+ type BelongsToCreateDataForColumn<TC extends TableClasses, VC extends TableClasses, T extends RelationConfigSelf, Column extends string> = { [K in keyof T['relations']]: T['relations'][K] extends BelongsTo ? Column extends T['relations'][K]['options']['columns'][number] ? BelongsToCreateData<TC, VC, T, K & string, T['relations'][K]> : never : never }[keyof T['relations']];
550
+ type RelationDataForCreate<TC extends TableClasses, VC extends TableClasses, T extends RelationConfigSelf, Name extends keyof T['relations'] & string> = T['relations'][Name] extends HasOne ? HasOneInfo<T, Name, T['relations'][Name], HasOneQuery<T, Name, RelationTableToQuery<TC, VC, T['relations'][Name]>>>['dataForCreate'] : T['relations'][Name] extends HasMany ? HasManyInfo<T, Name, T['relations'][Name], HasManyQuery<T, Name, RelationTableToQuery<TC, VC, T['relations'][Name]>>>['dataForCreate'] : T['relations'][Name] extends HasAndBelongsToMany ? HasAndBelongsToManyInfo<T, Name, T['relations'][Name]['options']['columns'][number] & string, HasAndBelongsToManyQuery<Name, RelationTableToQuery<TC, VC, T['relations'][Name]>>>['dataForCreate'] : never;
544
551
  type RelationDataForCreateOptionalNames<T extends RelationConfigSelf> = { [K in keyof T['relations'] & string]: T['relations'][K] extends BelongsTo ? never : K }[keyof T['relations'] & string];
545
- type BelongsToRelationsDataForCreate<T extends RelationConfigSelf> = { [Column in BelongsToCreateDataColumns<T>]: BelongsToCreateDataForColumn<T, Column> };
546
- type RelationsDataForCreateOptional<T extends RelationConfigSelf> = RelationDataForCreateOptionalNames<T> extends never ? EmptyObject : { [K in RelationDataForCreateOptionalNames<T>]: (u: RelationDataForCreate<T, K>) => void }[RelationDataForCreateOptionalNames<T>] extends ((u: infer Obj) => void) ? Obj : EmptyObject;
547
- interface TableToDb<T extends ORMTableInput, Name extends string | undefined, ReadOnly extends true | undefined, Materialized extends true | undefined = undefined> extends TableInfo, Db<Name, 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']>, ReadOnly, Materialized> {
548
- relations: T extends RelationConfigSelf ? { [K in keyof T['relations'] & string]: T['relations'][K] extends BelongsTo ? BelongsToRelationInfo<T, K, T['relations'][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;
549
- relationsDataForCreate: T extends RelationConfigSelf ? BelongsToRelationsDataForCreate<T> : EmptyObject;
550
- relationsDataForCreateOptional: T extends RelationConfigSelf ? RelationsDataForCreateOptional<T> : EmptyObject;
552
+ type BelongsToRelationsDataForCreate<TC extends TableClasses, VC extends TableClasses, T extends RelationConfigSelf> = { [Column in BelongsToCreateDataColumns<T>]: BelongsToCreateDataForColumn<TC, VC, T, Column> };
553
+ type RelationsDataForCreateOptional<TC extends TableClasses, VC extends TableClasses, T extends RelationConfigSelf> = RelationDataForCreateOptionalNames<T> extends never ? EmptyObject : { [K in RelationDataForCreateOptionalNames<T>]: (u: RelationDataForCreate<TC, VC, T, K>) => void }[RelationDataForCreateOptionalNames<T>] extends ((u: infer Obj) => void) ? Obj : EmptyObject;
554
+ interface TableQueryBuilder<TC extends TableClasses, VC extends TableClasses, T extends ORMTableInput> extends TableInfo, Db<T['table'] extends string ? T['table'] : T['name'], T['columns']['shape'], T['columns']['data'], T['types'], T['table'] extends string ? T['readOnly'] extends true ? true : undefined : T['readOnly'] extends false ? undefined : true, T> {
555
+ relations: T extends RelationConfigSelf ? { [K in keyof T['relations'] & string]: T['relations'][K] extends BelongsTo ? BelongsToRelationInfo<TC, VC, T, K, T['relations'][K]> : T['relations'][K] extends HasOne ? HasOneInfo<T, K, T['relations'][K], HasOneQuery<T, K, RelationTableToQuery<TC, VC, T['relations'][K]>>> : T['relations'][K] extends HasMany ? HasManyInfo<T, K, T['relations'][K], HasManyQuery<T, K, RelationTableToQuery<TC, VC, T['relations'][K]>>> : T['relations'][K] extends HasAndBelongsToMany ? HasAndBelongsToManyInfo<T, K, T['relations'][K]['options']['columns'][number] & string, HasAndBelongsToManyQuery<K, RelationTableToQuery<TC, VC, T['relations'][K]>>> : never } : EmptyObject;
556
+ relationsDataForCreate: T extends RelationConfigSelf ? BelongsToRelationsDataForCreate<TC, VC, T> : EmptyObject;
557
+ relationsDataForCreateOptional: T extends RelationConfigSelf ? RelationsDataForCreateOptional<TC, VC, T> : EmptyObject;
551
558
  }
552
559
  interface PickORMTableInputColumns {
553
560
  columns: {
@@ -563,8 +570,10 @@ interface PickORMTableComputed {
563
570
  }
564
571
  interface PickORMTableInputColumnsAndComputed extends PickORMTableInputColumns, PickORMTableComputed {}
565
572
  interface ORMTableInput extends PickORMTableInputColumnsAndComputed {
573
+ id?: string;
566
574
  autoForeignKeys?: TableData.References.BaseOptions | boolean;
567
575
  schema?: QuerySchema;
576
+ nameInDb?: string;
568
577
  types: unknown;
569
578
  filePath: string;
570
579
  language?: string;
@@ -621,6 +630,10 @@ interface SetColumnsResult<Shape extends Column.Shape.QueryInit, Data extends Ma
621
630
  }
622
631
  interface BaseTableInstance<ColumnTypes> {
623
632
  table?: string;
633
+ /**
634
+ * Database relation name used in SQL and migration generation.
635
+ */
636
+ nameInDb?: string;
624
637
  columns: {
625
638
  shape: Column.Shape.QueryInit;
626
639
  data: MaybeArray<TableDataItem>;
@@ -632,6 +645,7 @@ interface BaseTableInstance<ColumnTypes> {
632
645
  q: QueryData;
633
646
  language?: string;
634
647
  filePath: string;
648
+ materialized?: true;
635
649
  /**
636
650
  * Keep this table-like definition available at runtime, but exclude it from
637
651
  * generated migration DDL reconciliation.
@@ -756,7 +770,7 @@ interface BaseTableInstance<ColumnTypes> {
756
770
  new (): Related;
757
771
  }, options: Options): {
758
772
  type: 'belongsTo';
759
- related: Related;
773
+ id: Related['id'] extends string ? Related['id'] : Related['table'] extends string ? Related['table'] : Related['name'];
760
774
  options: Options;
761
775
  };
762
776
  hasOne<Columns extends Column.Shape.QueryInit, Related extends ORMTableInput, Through extends string, Source extends string, Options extends HasOneOptions<Columns, Related, Through, Source>>(this: {
@@ -767,7 +781,7 @@ interface BaseTableInstance<ColumnTypes> {
767
781
  new (): Related;
768
782
  }, options: Options): {
769
783
  type: 'hasOne';
770
- related: Related;
784
+ id: Related['id'] extends string ? Related['id'] : Related['table'] extends string ? Related['table'] : Related['name'];
771
785
  options: Options;
772
786
  };
773
787
  hasMany<Columns extends Column.Shape.QueryInit, Related extends ORMTableInput, Through extends string, Source extends string, Options extends HasOneOptions<Columns, Related, Through, Source>>(this: {
@@ -778,7 +792,7 @@ interface BaseTableInstance<ColumnTypes> {
778
792
  new (): Related;
779
793
  }, options: Options): {
780
794
  type: 'hasMany';
781
- related: Related;
795
+ id: Related['id'] extends string ? Related['id'] : Related['table'] extends string ? Related['table'] : Related['name'];
782
796
  options: Options;
783
797
  };
784
798
  hasAndBelongsToMany<Columns extends Column.Shape.QueryInit, Related extends ORMTableInput, Options extends HasAndBelongsToManyOptions<Columns, Related>>(this: {
@@ -789,7 +803,7 @@ interface BaseTableInstance<ColumnTypes> {
789
803
  new (): Related;
790
804
  }, options: Options): {
791
805
  type: 'hasAndBelongsToMany';
792
- related: Related;
806
+ id: Related['id'] extends string ? Related['id'] : Related['table'] extends string ? Related['table'] : Related['name'];
793
807
  options: Options;
794
808
  };
795
809
  beforeQuery: BeforeHookMethod;
@@ -897,4 +911,4 @@ declare const createRepo: <T extends Query, Methods extends MethodsBase<T>>(tabl
897
911
  table: T["table"];
898
912
  shape: T["shape"];
899
913
  }>(q: Q) => Query & Q & MapMethods<T, Methods>) & T, Methods>;
900
- export { BaseMaterializedViewInstance, BaseTableClass, BaseTableInstance, BaseViewInstance, DefaultSelect, FromQuery, Insertable, MapMethods, MapQueryMethods, MethodsBase, ORMTableInput, OrchidORM, OrchidORMBundle, OrchidORMDbTables, OrchidORMDbViews, OrchidORMTableHelper, OrchidORMTables, OrchidORMViews, OrchidOrmParam, PickORMTableComputed, PickORMTableInputColumns, PickORMTableInputColumnsAndComputed, Queryable, Repo, Selectable, SetColumnsResult, Table, TableClass, TableClasses, TableInfo, TableToDb, Updatable, bundleOrchidORM, bundleOrchidORMTables, createBaseTable, createRepo, defineRls, makeOrchidOrmDbWithAdapter, orchidORMWithAdapter, setGrants };
914
+ export { BaseMaterializedViewInstance, BaseTableClass, BaseTableInstance, BaseViewInstance, DefaultSelect, FromQuery, Insertable, MapMethods, MapQueryMethods, MethodsBase, ORMTableInput, OrchidORM, OrchidORMBundle, OrchidORMDbTables, OrchidORMTables, OrchidOrmParam, PickORMTableComputed, PickORMTableInputColumns, PickORMTableInputColumnsAndComputed, Queryable, Repo, Selectable, SetColumnsResult, Table, TableClass, TableClasses, TableInfo, TableQueryBuilder, Updatable, bundleOrchidORM, bundleOrchidORMTables, createBaseTable, createRepo, defineRls, makeOrchidOrmDbWithAdapter, orchidORMWithAdapter, setGrants };
package/dist/index.js CHANGED
@@ -67,6 +67,8 @@ function createBaseTable({ schemaConfig = pqb_internal.defaultSchemaConfig, colu
67
67
  let instance = instances.get(this);
68
68
  if (!instance) {
69
69
  instance = new this();
70
+ const name = instance.table || instance.name;
71
+ if (instance.nameInDb === void 0 && name) instance.nameInDb = instance.snakeCase ? (0, pqb_internal.toSnakeCase)(name) : name;
70
72
  instances.set(this, instance);
71
73
  }
72
74
  return instance;
@@ -214,7 +216,7 @@ function joinHasRelation(baseQuery, joiningQuery, primaryKeys, foreignKeys, len)
214
216
  return q;
215
217
  }
216
218
  const addAutoForeignKey = (tableConfig, from, to, primaryKeys, foreignKeys, options, originalForeignKeys) => {
217
- const toTable = to.table;
219
+ const toTable = to.q.nameInDb || to.table;
218
220
  let fkeyOptions = options.foreignKey !== void 0 ? options.foreignKey : tableConfig.autoForeignKeys;
219
221
  if (!fkeyOptions) return;
220
222
  if (fkeyOptions === true) fkeyOptions = tableConfig.autoForeignKeys || pqb_internal.emptyObject;
@@ -228,7 +230,10 @@ const addAutoForeignKey = (tableConfig, from, to, primaryKeys, foreignKeys, opti
228
230
  if (typeof fkey.fnOrTable === "string") {
229
231
  fkeyTable = fkey.fnOrTable;
230
232
  fkeyColumn = getColumnKeyFromDbName(to, fkeyColumn);
231
- } else fkeyTable = fkey.fnOrTable().instance().table;
233
+ } else {
234
+ const instance = fkey.fnOrTable().instance();
235
+ fkeyTable = instance.nameInDb || instance.table;
236
+ }
232
237
  if (toTable === fkeyTable && pkey === fkeyColumn) return;
233
238
  }
234
239
  }
@@ -239,7 +244,13 @@ const addAutoForeignKey = (tableConfig, from, to, primaryKeys, foreignKeys, opti
239
244
  const sortedFkeys = [...foreignKeys].sort();
240
245
  for (const { references: refs } of constraints) {
241
246
  if (!refs) continue;
242
- if (refs.columns.length === sortedFkeys.length && refs.columns.every((column, i) => column === sortedFkeys[i]) && refs.foreignColumns.length === sortedPkeys.length && (typeof refs.fnOrTable === "string" ? refs.fnOrTable === toTable && refs.foreignColumns.every((column, i) => getColumnKeyFromDbName(to, column) === sortedPkeys[i]) : refs.fnOrTable().instance().table === toTable && refs.foreignColumns.every((column, i) => column === sortedPkeys[i]))) return;
247
+ let sameForeignTable = false;
248
+ if (typeof refs.fnOrTable === "string") sameForeignTable = refs.fnOrTable === toTable && refs.foreignColumns.every((column, i) => getColumnKeyFromDbName(to, column) === sortedPkeys[i]);
249
+ else {
250
+ const instance = refs.fnOrTable().instance();
251
+ sameForeignTable = (instance.nameInDb || instance.table) === toTable && refs.foreignColumns.every((column, i) => column === sortedPkeys[i]);
252
+ }
253
+ if (refs.columns.length === sortedFkeys.length && refs.columns.every((column, i) => column === sortedFkeys[i]) && refs.foreignColumns.length === sortedPkeys.length && sameForeignTable) return;
243
254
  }
244
255
  }
245
256
  (from.internal.tableData.constraints ??= []).push({
@@ -410,9 +421,10 @@ var BelongsToVirtualColumn = class extends pqb_internal.VirtualColumn {
410
421
  this.nestedUpdate(queryForUpdate, set, data);
411
422
  }
412
423
  };
413
- const getBelongsToRequired = (tableConfig, relation) => {
424
+ const getBelongsToRequired = (tableConfig, relatedTableConfig, relation) => {
414
425
  const { required } = relation.options;
415
426
  if (typeof required === "boolean") return required;
427
+ if (relatedTableConfig.softDelete) return false;
416
428
  return relation.options.columns.every((key) => {
417
429
  return !tableConfig.columns.shape[key].data.isNullable;
418
430
  });
@@ -1359,6 +1371,7 @@ const applyRelations = (qb, tables, result, schema) => {
1359
1371
  const data = {
1360
1372
  relationName,
1361
1373
  relation,
1374
+ otherTable: otherTable[1],
1362
1375
  dbTable,
1363
1376
  otherDbTable
1364
1377
  };
@@ -1402,7 +1415,7 @@ const delayRelation = (delayedRelations, table, relationName, data) => {
1402
1415
  if (tableRelations[relationName]) tableRelations[relationName].push(data);
1403
1416
  else tableRelations[relationName] = [data];
1404
1417
  };
1405
- const applyRelation = (table, qb, { relationName, relation, dbTable, otherDbTable }, delayedRelations, schema) => {
1418
+ const applyRelation = (table, qb, { relationName, relation, otherTable, dbTable, otherDbTable }, delayedRelations, schema) => {
1406
1419
  const baseQuery = Object.create(otherDbTable);
1407
1420
  baseQuery.baseQuery = baseQuery;
1408
1421
  const query = baseQuery.as(relationName);
@@ -1415,21 +1428,12 @@ const applyRelation = (table, qb, { relationName, relation, dbTable, otherDbTabl
1415
1428
  else if (type === "hasAndBelongsToMany") data = makeHasAndBelongsToManyMethod(table, dbTable, qb, relation, relationName, query, schema);
1416
1429
  else throw new Error(`Unknown relation type ${type}`);
1417
1430
  if (data.returns === "one") {
1418
- if (type === "belongsTo" ? getBelongsToRequired(table, relation) : relation.options.required) (0, pqb_internal._queryTake)(query);
1431
+ if (type === "belongsTo" ? getBelongsToRequired(table, otherTable, relation) : relation.options.required) (0, pqb_internal._queryTake)(query);
1419
1432
  else (0, pqb_internal._queryTakeOptional)(query);
1420
1433
  query.q.returnsOne = true;
1421
1434
  }
1422
1435
  if (data.virtualColumn) dbTable.shape[relationName] = dbTable.q.selectShape[relationName] = data.virtualColumn;
1423
1436
  baseQuery.joinQuery = data.joinQuery;
1424
- const { join: originalJoin } = baseQuery;
1425
- baseQuery.join = function(...args) {
1426
- if (args.length) return originalJoin.apply(this, args);
1427
- else {
1428
- const q = this.clone();
1429
- q.q.innerJoinLateral = true;
1430
- return q;
1431
- }
1432
- };
1433
1437
  dbTable.relations[relationName] = {
1434
1438
  table: otherDbTable,
1435
1439
  query,
@@ -1486,6 +1490,7 @@ const assignTablesToOrm = (isTable, tables, result, adapter, qb, asyncStorage, c
1486
1490
  scopes: table.scopes,
1487
1491
  softDelete: table.softDelete,
1488
1492
  snakeCase: table.snakeCase,
1493
+ nameInDb: table.nameInDb,
1489
1494
  comment: table.comment,
1490
1495
  readOnly: isTable ? table.readOnly ? true : void 0 : table.materialized || table.readOnly !== false ? true : void 0,
1491
1496
  materialized: !isTable && table.materialized ? true : void 0,
@@ -1615,12 +1620,12 @@ const privateOrchidORMWithAdapter = ({ log, logger, autoPreparedStatements, noPr
1615
1620
  viewInstances = assignTablesToOrm(false, views, result.$views, adapter, qb, asyncStorage, commonOptions, schema);
1616
1621
  const tableDbNames = Object.values(tableInstances).map((table) => {
1617
1622
  const s = typeof table.schema === "function" ? table.schema() : table.schema;
1618
- return `${s ? s + "." : ""}${table.table}`;
1623
+ return `${s ? s + "." : ""}${table.nameInDb}`;
1619
1624
  });
1620
1625
  for (const key in views) {
1621
1626
  const view = viewInstances[key];
1622
1627
  const s = typeof view.schema === "function" ? view.schema() : view.schema;
1623
- const name = `${s ? s + "." : ""}${view.name}`;
1628
+ const name = `${s ? s + "." : ""}${view.nameInDb}`;
1624
1629
  if (tableDbNames.includes(name)) throw new Error(`Cannot configure both a table and a view for database relation ${name}`);
1625
1630
  }
1626
1631
  }