orchid-orm 1.5.29 → 1.5.30

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.
Files changed (58) hide show
  1. package/dist/index.js +10 -10
  2. package/dist/index.js.map +1 -1
  3. package/dist/index.mjs +10 -10
  4. package/dist/index.mjs.map +1 -1
  5. package/package.json +13 -22
  6. package/.env.example +0 -1
  7. package/.turbo/turbo-check.log +0 -26
  8. package/.turbo/turbo-test.log +0 -26
  9. package/.turbo/turbo-test:ci.log +0 -26
  10. package/CHANGELOG.md +0 -382
  11. package/coverage/coverage-summary.json +0 -28
  12. package/jest-setup.ts +0 -11
  13. package/rollup.config.js +0 -18
  14. package/src/bin/bin.ts +0 -3
  15. package/src/bin/init.test.ts +0 -810
  16. package/src/bin/init.ts +0 -529
  17. package/src/codegen/appCodeUpdater.test.ts +0 -75
  18. package/src/codegen/appCodeUpdater.ts +0 -53
  19. package/src/codegen/createBaseTableFile.test.ts +0 -53
  20. package/src/codegen/createBaseTableFile.ts +0 -31
  21. package/src/codegen/fileChanges.ts +0 -41
  22. package/src/codegen/testUtils.ts +0 -56
  23. package/src/codegen/tsUtils.ts +0 -180
  24. package/src/codegen/updateMainFile.test.ts +0 -253
  25. package/src/codegen/updateMainFile.ts +0 -210
  26. package/src/codegen/updateTableFile/changeTable.test.ts +0 -804
  27. package/src/codegen/updateTableFile/changeTable.ts +0 -536
  28. package/src/codegen/updateTableFile/createTable.test.ts +0 -139
  29. package/src/codegen/updateTableFile/createTable.ts +0 -51
  30. package/src/codegen/updateTableFile/renameTable.test.ts +0 -124
  31. package/src/codegen/updateTableFile/renameTable.ts +0 -67
  32. package/src/codegen/updateTableFile/updateTableFile.ts +0 -22
  33. package/src/codegen/utils.ts +0 -13
  34. package/src/index.ts +0 -5
  35. package/src/orm.test.ts +0 -92
  36. package/src/orm.ts +0 -98
  37. package/src/relations/belongsTo.test.ts +0 -1122
  38. package/src/relations/belongsTo.ts +0 -352
  39. package/src/relations/hasAndBelongsToMany.test.ts +0 -1335
  40. package/src/relations/hasAndBelongsToMany.ts +0 -472
  41. package/src/relations/hasMany.test.ts +0 -2616
  42. package/src/relations/hasMany.ts +0 -401
  43. package/src/relations/hasOne.test.ts +0 -1701
  44. package/src/relations/hasOne.ts +0 -351
  45. package/src/relations/relations.test.ts +0 -37
  46. package/src/relations/relations.ts +0 -363
  47. package/src/relations/utils.ts +0 -162
  48. package/src/repo.test.ts +0 -200
  49. package/src/repo.ts +0 -119
  50. package/src/table.test.ts +0 -121
  51. package/src/table.ts +0 -184
  52. package/src/test-utils/test-db.ts +0 -32
  53. package/src/test-utils/test-tables.ts +0 -194
  54. package/src/test-utils/test-utils.ts +0 -119
  55. package/src/transaction.test.ts +0 -47
  56. package/src/transaction.ts +0 -27
  57. package/src/utils.ts +0 -9
  58. package/tsconfig.json +0 -14
@@ -1,363 +0,0 @@
1
- import { BelongsTo, BelongsToInfo, makeBelongsToMethod } from './belongsTo';
2
- import { HasOne, HasOneInfo, makeHasOneMethod } from './hasOne';
3
- import { DbTable, Table, TableClass, TableClasses } from '../table';
4
- import { OrchidORM } from '../orm';
5
- import {
6
- Query,
7
- QueryWithTable,
8
- RelationQuery,
9
- SetQueryReturnsAll,
10
- SetQueryReturnsOne,
11
- SetQueryReturnsOneOptional,
12
- BaseRelation,
13
- defaultsKey,
14
- relationQueryKey,
15
- EmptyObject,
16
- VirtualColumn,
17
- } from 'pqb';
18
- import { HasMany, HasManyInfo, makeHasManyMethod } from './hasMany';
19
- import {
20
- HasAndBelongsToMany,
21
- HasAndBelongsToManyInfo,
22
- makeHasAndBelongsToManyMethod,
23
- } from './hasAndBelongsToMany';
24
- import { getSourceRelation, getThroughRelation } from './utils';
25
-
26
- export interface RelationThunkBase {
27
- type: string;
28
- returns: 'one' | 'many';
29
- fn(): TableClass;
30
- options: BaseRelation['options'];
31
- }
32
-
33
- export type RelationThunk = BelongsTo | HasOne | HasMany | HasAndBelongsToMany;
34
-
35
- export type RelationThunks = Record<string, RelationThunk>;
36
-
37
- export type RelationData = {
38
- returns: 'one' | 'many';
39
- method(params: Record<string, unknown>): Query;
40
- virtualColumn?: VirtualColumn;
41
- joinQuery(fromQuery: Query, toQuery: Query): Query;
42
- reverseJoin(fromQuery: Query, toQuery: Query): Query;
43
- primaryKey: string;
44
- modifyRelatedQuery?(relatedQuery: Query): (query: Query) => void;
45
- };
46
-
47
- export type Relation<
48
- T extends Table,
49
- Relations extends RelationThunks,
50
- K extends keyof Relations,
51
- M extends Query = DbTable<ReturnType<Relations[K]['fn']>>,
52
- Info extends RelationInfo = RelationInfo<T, Relations, Relations[K]>,
53
- > = {
54
- type: Relations[K]['type'];
55
- returns: Relations[K]['returns'];
56
- key: K;
57
- table: M;
58
- query: M;
59
- joinQuery(fromQuery: Query, toQuery: Query): Query;
60
- defaults: Info['populate'];
61
- nestedCreateQuery: [Info['populate']] extends [never]
62
- ? M
63
- : M & {
64
- [defaultsKey]: Record<Info['populate'], true>;
65
- };
66
- primaryKey: string;
67
- options: Relations[K]['options'];
68
- };
69
-
70
- export type RelationScopeOrTable<Relation extends RelationThunkBase> =
71
- Relation['options']['scope'] extends (q: Query) => Query
72
- ? ReturnType<Relation['options']['scope']>
73
- : DbTable<ReturnType<Relation['fn']>>;
74
-
75
- export type RelationInfo<
76
- T extends Table = Table,
77
- Relations extends RelationThunks = RelationThunks,
78
- Relation extends RelationThunk = RelationThunk,
79
- > = Relation extends BelongsTo
80
- ? BelongsToInfo<T, Relation>
81
- : Relation extends HasOne
82
- ? HasOneInfo<T, Relations, Relation>
83
- : Relation extends HasMany
84
- ? HasManyInfo<T, Relations, Relation>
85
- : Relation extends HasAndBelongsToMany
86
- ? HasAndBelongsToManyInfo<T, Relation>
87
- : never;
88
-
89
- export type MapRelation<
90
- T extends Table,
91
- Relations extends RelationThunks,
92
- RelationName extends keyof Relations,
93
- Relation extends RelationThunk = Relations[RelationName],
94
- RelatedQuery extends Query = RelationScopeOrTable<Relation>,
95
- Info extends {
96
- params: Record<string, unknown>;
97
- populate: string;
98
- chainedCreate: boolean;
99
- chainedDelete: boolean;
100
- } = RelationInfo<T, Relations, Relation>,
101
- > = RelationQuery<
102
- RelationName,
103
- Info['params'],
104
- Info['populate'],
105
- Relation['returns'] extends 'one'
106
- ? Relation['options']['required'] extends true
107
- ? SetQueryReturnsOne<RelatedQuery>
108
- : SetQueryReturnsOneOptional<RelatedQuery>
109
- : SetQueryReturnsAll<RelatedQuery>,
110
- Relation['options']['required'] extends boolean
111
- ? Relation['options']['required']
112
- : false,
113
- Info['chainedCreate'],
114
- Info['chainedDelete']
115
- >;
116
-
117
- export type MapRelations<T extends Table> = 'relations' extends keyof T
118
- ? T['relations'] extends RelationThunks
119
- ? {
120
- [K in keyof T['relations']]: MapRelation<T, T['relations'], K>;
121
- }
122
- : EmptyObject
123
- : EmptyObject;
124
-
125
- type ApplyRelationData = {
126
- relationName: string;
127
- relation: RelationThunk;
128
- dbTable: DbTable<TableClass>;
129
- otherDbTable: DbTable<TableClass>;
130
- };
131
-
132
- type DelayedRelations = Map<Query, Record<string, ApplyRelationData[]>>;
133
-
134
- export const applyRelations = (
135
- qb: Query,
136
- tables: Record<string, Table>,
137
- result: OrchidORM<TableClasses>,
138
- ) => {
139
- const tableEntries = Object.entries(tables);
140
-
141
- const delayedRelations: DelayedRelations = new Map();
142
-
143
- for (const name in tables) {
144
- const table = tables[name] as Table & {
145
- relations?: RelationThunks;
146
- };
147
- if (!('relations' in table) || typeof table.relations !== 'object')
148
- continue;
149
-
150
- const dbTable = result[name];
151
- for (const relationName in table.relations) {
152
- const relation = table.relations[relationName];
153
- const otherTableClass = relation.fn();
154
- const otherTable = tableEntries.find(
155
- (pair) => pair[1] instanceof otherTableClass,
156
- );
157
- if (!otherTable) {
158
- throw new Error(
159
- `Cannot find table class for class ${otherTableClass.name}`,
160
- );
161
- }
162
- const otherTableName = otherTable[0];
163
- const otherDbTable = result[otherTableName];
164
- if (!otherDbTable)
165
- throw new Error(`Cannot find table class by name ${otherTableName}`);
166
-
167
- const data: ApplyRelationData = {
168
- relationName,
169
- relation,
170
- dbTable,
171
- otherDbTable,
172
- };
173
-
174
- const options = relation.options as { through?: string; source?: string };
175
- if (
176
- typeof options.through === 'string' &&
177
- typeof options.source === 'string'
178
- ) {
179
- const throughRelation = getThroughRelation(dbTable, options.through);
180
- if (!throughRelation) {
181
- delayRelation(delayedRelations, dbTable, options.through, data);
182
- continue;
183
- }
184
-
185
- const sourceRelation = getSourceRelation(
186
- throughRelation,
187
- options.source,
188
- );
189
- if (!sourceRelation) {
190
- delayRelation(
191
- delayedRelations,
192
- throughRelation.table,
193
- options.source,
194
- data,
195
- );
196
- continue;
197
- }
198
- }
199
-
200
- applyRelation(qb, data, delayedRelations);
201
- }
202
- }
203
-
204
- if (delayedRelations.size) {
205
- const { value } = delayedRelations.values().next() as {
206
- value: Record<string, ApplyRelationData[]>;
207
- };
208
- for (const key in value) {
209
- for (const item of value[key]) {
210
- const { relation } = item;
211
-
212
- if (item.dbTable.relations[item.relationName as never]) continue;
213
-
214
- const as = item.dbTable.definedAs;
215
- let message = `Cannot define a \`${item.relationName}\` relation on \`${as}\``;
216
- const table = result[as];
217
-
218
- const { through, source } = relation.options as {
219
- through: string;
220
- source: string;
221
- };
222
- const throughRel = table.relations[
223
- through as never
224
- ] as unknown as BaseRelation;
225
-
226
- if (through && !throughRel) {
227
- message += `: cannot find \`${through}\` relation required by the \`through\` option`;
228
- } else if (
229
- source &&
230
- throughRel &&
231
- !throughRel.table.relations[source as never]
232
- ) {
233
- message += `: cannot find \`${source}\` relation in \`${
234
- (throughRel.table as DbTable<TableClass>).definedAs
235
- }\` required by the \`source\` option`;
236
- }
237
-
238
- throw new Error(message);
239
- }
240
- }
241
- }
242
- };
243
-
244
- const delayRelation = (
245
- delayedRelations: DelayedRelations,
246
- table: Query,
247
- relationName: string,
248
- data: ApplyRelationData,
249
- ) => {
250
- let tableRelations = delayedRelations.get(table);
251
- if (!tableRelations) {
252
- tableRelations = {};
253
- delayedRelations.set(table, tableRelations);
254
- }
255
- if (tableRelations[relationName]) {
256
- tableRelations[relationName].push(data);
257
- } else {
258
- tableRelations[relationName] = [data];
259
- }
260
- };
261
-
262
- const applyRelation = (
263
- qb: Query,
264
- { relationName, relation, dbTable, otherDbTable }: ApplyRelationData,
265
- delayedRelations: DelayedRelations,
266
- ) => {
267
- const query = (
268
- relation.options.scope
269
- ? relation.options.scope(otherDbTable)
270
- : (otherDbTable as unknown as QueryWithTable)
271
- ).as(relationName);
272
-
273
- const definedAs = (query as unknown as { definedAs?: string }).definedAs;
274
- if (!definedAs) {
275
- throw new Error(
276
- `Table class for table ${query.table} is not attached to db instance`,
277
- );
278
- }
279
-
280
- const { type } = relation;
281
- let data;
282
- if (type === 'belongsTo') {
283
- data = makeBelongsToMethod(relation, relationName, query);
284
- } else if (type === 'hasOne') {
285
- data = makeHasOneMethod(dbTable, relation, relationName, query);
286
- } else if (type === 'hasMany') {
287
- data = makeHasManyMethod(dbTable, relation, relationName, query);
288
- } else if (type === 'hasAndBelongsToMany') {
289
- data = makeHasAndBelongsToManyMethod(
290
- dbTable,
291
- qb,
292
- relation,
293
- relationName,
294
- query,
295
- );
296
- } else {
297
- throw new Error(`Unknown relation type ${type}`);
298
- }
299
-
300
- if (data.returns === 'one') {
301
- query._take();
302
- }
303
-
304
- if (data.virtualColumn) {
305
- dbTable.shape[relationName] = data.virtualColumn;
306
- }
307
-
308
- makeRelationQuery(dbTable, definedAs, relationName, data);
309
-
310
- (dbTable.relations as Record<string, unknown>)[relationName] = {
311
- type,
312
- key: relationName,
313
- table: otherDbTable,
314
- query,
315
- joinQuery: data.joinQuery,
316
- primaryKey: data.primaryKey,
317
- options: relation.options,
318
- };
319
-
320
- const tableRelations = delayedRelations.get(dbTable);
321
- if (!tableRelations) return;
322
-
323
- tableRelations[relationName]?.forEach((data) => {
324
- applyRelation(qb, data, delayedRelations);
325
- });
326
- };
327
-
328
- const makeRelationQuery = (
329
- table: Query,
330
- definedAs: string,
331
- relationName: string,
332
- data: RelationData,
333
- ) => {
334
- Object.defineProperty(table, relationName, {
335
- get() {
336
- const toTable = this.db[definedAs].as(relationName) as Query;
337
-
338
- if (data.returns === 'one') {
339
- toTable._take();
340
- }
341
-
342
- const query = this.isSubQuery
343
- ? toTable
344
- : toTable._whereExists(data.reverseJoin(this, toTable), (q) => q);
345
-
346
- query.query[relationQueryKey] = {
347
- relationName,
348
- sourceQuery: this,
349
- relationQuery: toTable,
350
- joinQuery: data.joinQuery,
351
- };
352
-
353
- const setQuery = data.modifyRelatedQuery?.(query);
354
- setQuery?.(this);
355
-
356
- return new Proxy(data.method, {
357
- get(_, prop) {
358
- return (query as unknown as Record<string, unknown>)[prop as string];
359
- },
360
- }) as unknown as RelationQuery;
361
- },
362
- });
363
- };
@@ -1,162 +0,0 @@
1
- import {
2
- CreateCtx,
3
- MaybeArray,
4
- pushQueryValue,
5
- Query,
6
- QueryBase,
7
- Relation,
8
- UpdateCtx,
9
- UpdateData,
10
- WhereArg,
11
- } from 'pqb';
12
- import { HasOneNestedInsert, HasOneNestedUpdate } from './hasOne';
13
- import { HasManyNestedInsert, HasManyNestedUpdate } from './hasMany';
14
-
15
- export type NestedInsertOneItem = {
16
- create?: Record<string, unknown>;
17
- connect?: WhereArg<QueryBase>;
18
- connectOrCreate?: {
19
- where: WhereArg<QueryBase>;
20
- create: Record<string, unknown>;
21
- };
22
- };
23
-
24
- export type NestedInsertManyItems = {
25
- create?: Record<string, unknown>[];
26
- connect?: WhereArg<QueryBase>[];
27
- connectOrCreate?: {
28
- where: WhereArg<QueryBase>;
29
- create: Record<string, unknown>;
30
- }[];
31
- };
32
-
33
- export type NestedInsertItem = NestedInsertOneItem | NestedInsertManyItems;
34
-
35
- export type NestedUpdateOneItem = {
36
- disconnect?: boolean;
37
- set?: WhereArg<QueryBase>;
38
- delete?: boolean;
39
- update?: UpdateData<Query>;
40
- upsert?: {
41
- update: UpdateData<Query>;
42
- create: Record<string, unknown>;
43
- };
44
- create: Record<string, unknown>;
45
- };
46
-
47
- export type NestedUpdateManyItems = {
48
- disconnect?: MaybeArray<WhereArg<QueryBase>>;
49
- set?: MaybeArray<WhereArg<QueryBase>>;
50
- delete?: MaybeArray<WhereArg<QueryBase>>;
51
- update?: {
52
- where: MaybeArray<WhereArg<QueryBase>>;
53
- data: UpdateData<Query>;
54
- };
55
- create: Record<string, unknown>[];
56
- };
57
-
58
- export type NestedUpdateItem = NestedUpdateOneItem | NestedUpdateManyItems;
59
-
60
- export const getThroughRelation = (table: Query, through: string) => {
61
- return (table.relations as Record<string, Relation>)[through];
62
- };
63
-
64
- export const getSourceRelation = (
65
- throughRelation: Relation,
66
- source: string,
67
- ) => {
68
- return (throughRelation.table.relations as Record<string, Relation>)[source];
69
- };
70
-
71
- export const hasRelationHandleCreate = (
72
- q: Query,
73
- ctx: CreateCtx,
74
- item: Record<string, unknown>,
75
- rowIndex: number,
76
- key: string,
77
- primaryKey: string,
78
- nestedInsert: HasOneNestedInsert | HasManyNestedInsert,
79
- ) => {
80
- const value = item[key] as NestedInsertItem;
81
- if (
82
- (!value.create ||
83
- (Array.isArray(value.create) && value.create.length === 0)) &&
84
- (!value.connect ||
85
- (Array.isArray(value.connect) && value.connect.length === 0)) &&
86
- (!value.connectOrCreate ||
87
- (Array.isArray(value.connectOrCreate) &&
88
- value.connectOrCreate.length === 0))
89
- )
90
- return;
91
-
92
- const store = ctx as unknown as {
93
- hasRelation?: Record<string, [number, NestedInsertItem][]>;
94
- };
95
-
96
- if (!store.hasRelation) store.hasRelation = {};
97
-
98
- const values = [rowIndex, value] as [number, NestedInsertItem];
99
-
100
- if (store.hasRelation[key]) {
101
- store.hasRelation[key].push(values);
102
- return;
103
- }
104
-
105
- q.query.wrapInTransaction = true;
106
- ctx.returnTypeAll = true;
107
- ctx.requiredReturning[primaryKey] = true;
108
-
109
- const relationData = [values];
110
- store.hasRelation[key] = relationData;
111
-
112
- pushQueryValue(q, 'afterCreate', async (q: Query) => {
113
- const { resultAll } = ctx;
114
- return (nestedInsert as HasOneNestedInsert)(
115
- q,
116
- relationData.map(([rowIndex, data]) => [
117
- resultAll[rowIndex],
118
- data as NestedInsertOneItem,
119
- ]),
120
- );
121
- });
122
- };
123
-
124
- export const hasRelationHandleUpdate = (
125
- q: Query,
126
- ctx: UpdateCtx,
127
- set: Record<string, unknown>,
128
- key: string,
129
- primaryKey: string,
130
- nestedUpdate: HasOneNestedUpdate | HasManyNestedUpdate,
131
- ) => {
132
- const value = set[key] as NestedUpdateItem;
133
-
134
- if (
135
- !value.set &&
136
- !('upsert' in value) &&
137
- (!value.disconnect ||
138
- (Array.isArray(value.disconnect) && value.disconnect.length === 0)) &&
139
- (!value.delete ||
140
- (Array.isArray(value.delete) && value.delete.length === 0)) &&
141
- (!value.update ||
142
- (Array.isArray(value.update.where) && value.update.where.length === 0)) &&
143
- (!value.create ||
144
- (Array.isArray(value.create) && value.create.length === 0))
145
- )
146
- return;
147
-
148
- if (!q.query.select?.includes('*') && !q.query.select?.includes(primaryKey)) {
149
- q._select(primaryKey);
150
- }
151
-
152
- q.query.wrapInTransaction = true;
153
- ctx.returnTypeAll = true;
154
-
155
- pushQueryValue(q, 'afterUpdate', (q: Query) => {
156
- return (nestedUpdate as HasOneNestedUpdate)(
157
- q,
158
- ctx.resultAll,
159
- value as NestedUpdateOneItem,
160
- );
161
- });
162
- };