orchid-orm 1.3.16 → 1.4.16
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/CHANGELOG.md +12 -0
- package/dist/index.d.ts +39 -32
- package/dist/index.esm.js +102 -100
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +102 -100
- package/dist/index.js.map +1 -1
- package/jest-setup.ts +4 -0
- package/package.json +8 -4
- package/src/appCodeUpdater/appCodeUpdater.ts +19 -0
- package/src/appCodeUpdater/fileChanges.ts +41 -0
- package/src/appCodeUpdater/testUtils.ts +31 -0
- package/src/appCodeUpdater/tsUtils.ts +137 -0
- package/src/appCodeUpdater/updateMainFile.test.ts +230 -0
- package/src/appCodeUpdater/updateMainFile.ts +163 -0
- package/src/appCodeUpdater/updateTableFile.ts +19 -0
- package/src/index.ts +5 -1
- package/src/orm.test.ts +13 -13
- package/src/orm.ts +21 -21
- package/src/relations/belongsTo.test.ts +1 -1
- package/src/relations/belongsTo.ts +2 -2
- package/src/relations/hasAndBelongsToMany.test.ts +1 -1
- package/src/relations/hasAndBelongsToMany.ts +9 -9
- package/src/relations/hasMany.test.ts +16 -10
- package/src/relations/hasMany.ts +6 -6
- package/src/relations/hasOne.test.ts +10 -10
- package/src/relations/hasOne.ts +6 -6
- package/src/relations/relations.ts +73 -71
- package/src/relations/utils.ts +3 -3
- package/src/repo.test.ts +29 -29
- package/src/repo.ts +6 -6
- package/src/{model.test.ts → table.test.ts} +15 -15
- package/src/{model.ts → table.ts} +17 -17
- package/src/test-utils/test-db.ts +15 -15
- package/src/test-utils/{test-models.ts → test-tables.ts} +42 -42
- package/src/transaction.test.ts +1 -1
- package/src/transaction.ts +4 -4
- package/src/utils.ts +9 -0
- package/tsconfig.json +1 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BelongsTo, BelongsToInfo, makeBelongsToMethod } from './belongsTo';
|
|
2
2
|
import { HasOne, HasOneInfo, makeHasOneMethod } from './hasOne';
|
|
3
|
-
import {
|
|
3
|
+
import { DbTable, Table, TableClass, TableClasses } from '../table';
|
|
4
4
|
import { OrchidORM } from '../orm';
|
|
5
5
|
import {
|
|
6
6
|
Query,
|
|
@@ -26,7 +26,7 @@ import { getSourceRelation, getThroughRelation } from './utils';
|
|
|
26
26
|
export interface RelationThunkBase {
|
|
27
27
|
type: string;
|
|
28
28
|
returns: 'one' | 'many';
|
|
29
|
-
fn():
|
|
29
|
+
fn(): TableClass;
|
|
30
30
|
options: BaseRelation['options'];
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -45,16 +45,16 @@ export type RelationData = {
|
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
export type Relation<
|
|
48
|
-
T extends
|
|
48
|
+
T extends Table,
|
|
49
49
|
Relations extends RelationThunks,
|
|
50
50
|
K extends keyof Relations,
|
|
51
|
-
M extends Query =
|
|
51
|
+
M extends Query = DbTable<ReturnType<Relations[K]['fn']>>,
|
|
52
52
|
Info extends RelationInfo = RelationInfo<T, Relations, Relations[K]>,
|
|
53
53
|
> = {
|
|
54
54
|
type: Relations[K]['type'];
|
|
55
55
|
returns: Relations[K]['returns'];
|
|
56
56
|
key: K;
|
|
57
|
-
|
|
57
|
+
table: M;
|
|
58
58
|
query: M;
|
|
59
59
|
joinQuery(fromQuery: Query, toQuery: Query): Query;
|
|
60
60
|
defaults: Info['populate'];
|
|
@@ -67,13 +67,13 @@ export type Relation<
|
|
|
67
67
|
options: Relations[K]['options'];
|
|
68
68
|
};
|
|
69
69
|
|
|
70
|
-
export type
|
|
70
|
+
export type RelationScopeOrTable<Relation extends RelationThunkBase> =
|
|
71
71
|
Relation['options']['scope'] extends (q: Query) => Query
|
|
72
72
|
? ReturnType<Relation['options']['scope']>
|
|
73
|
-
:
|
|
73
|
+
: DbTable<ReturnType<Relation['fn']>>;
|
|
74
74
|
|
|
75
75
|
export type RelationInfo<
|
|
76
|
-
T extends
|
|
76
|
+
T extends Table = Table,
|
|
77
77
|
Relations extends RelationThunks = RelationThunks,
|
|
78
78
|
Relation extends RelationThunk = RelationThunk,
|
|
79
79
|
> = Relation extends BelongsTo
|
|
@@ -87,11 +87,11 @@ export type RelationInfo<
|
|
|
87
87
|
: never;
|
|
88
88
|
|
|
89
89
|
export type MapRelation<
|
|
90
|
-
T extends
|
|
90
|
+
T extends Table,
|
|
91
91
|
Relations extends RelationThunks,
|
|
92
92
|
RelationName extends keyof Relations,
|
|
93
93
|
Relation extends RelationThunk = Relations[RelationName],
|
|
94
|
-
RelatedQuery extends Query =
|
|
94
|
+
RelatedQuery extends Query = RelationScopeOrTable<Relation>,
|
|
95
95
|
Info extends {
|
|
96
96
|
params: Record<string, unknown>;
|
|
97
97
|
populate: string;
|
|
@@ -114,7 +114,7 @@ export type MapRelation<
|
|
|
114
114
|
Info['chainedDelete']
|
|
115
115
|
>;
|
|
116
116
|
|
|
117
|
-
export type MapRelations<T extends
|
|
117
|
+
export type MapRelations<T extends Table> = 'relations' extends keyof T
|
|
118
118
|
? T['relations'] extends RelationThunks
|
|
119
119
|
? {
|
|
120
120
|
[K in keyof T['relations']]: MapRelation<T, T['relations'], K>;
|
|
@@ -125,48 +125,50 @@ export type MapRelations<T extends Model> = 'relations' extends keyof T
|
|
|
125
125
|
type ApplyRelationData = {
|
|
126
126
|
relationName: string;
|
|
127
127
|
relation: RelationThunk;
|
|
128
|
-
|
|
129
|
-
|
|
128
|
+
dbTable: DbTable<TableClass>;
|
|
129
|
+
otherDbTable: DbTable<TableClass>;
|
|
130
130
|
};
|
|
131
131
|
|
|
132
132
|
type DelayedRelations = Map<Query, Record<string, ApplyRelationData[]>>;
|
|
133
133
|
|
|
134
134
|
export const applyRelations = (
|
|
135
135
|
qb: Query,
|
|
136
|
-
|
|
137
|
-
result: OrchidORM<
|
|
136
|
+
tables: Record<string, Table>,
|
|
137
|
+
result: OrchidORM<TableClasses>,
|
|
138
138
|
) => {
|
|
139
|
-
const
|
|
139
|
+
const tableEntries = Object.entries(tables);
|
|
140
140
|
|
|
141
141
|
const delayedRelations: DelayedRelations = new Map();
|
|
142
142
|
|
|
143
|
-
for (const
|
|
144
|
-
const
|
|
143
|
+
for (const name in tables) {
|
|
144
|
+
const table = tables[name] as Table & {
|
|
145
145
|
relations?: RelationThunks;
|
|
146
146
|
};
|
|
147
|
-
if (!('relations' in
|
|
147
|
+
if (!('relations' in table) || typeof table.relations !== 'object')
|
|
148
148
|
continue;
|
|
149
149
|
|
|
150
|
-
const
|
|
151
|
-
for (const relationName in
|
|
152
|
-
const relation =
|
|
153
|
-
const
|
|
154
|
-
const
|
|
155
|
-
(pair) => pair[1] instanceof
|
|
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
156
|
);
|
|
157
|
-
if (!
|
|
158
|
-
throw new Error(
|
|
157
|
+
if (!otherTable) {
|
|
158
|
+
throw new Error(
|
|
159
|
+
`Cannot find table class for class ${otherTableClass.name}`,
|
|
160
|
+
);
|
|
159
161
|
}
|
|
160
|
-
const
|
|
161
|
-
const
|
|
162
|
-
if (!
|
|
163
|
-
throw new Error(`Cannot find
|
|
162
|
+
const otherTableName = otherTable[0];
|
|
163
|
+
const otherDbTable = result[otherTableName];
|
|
164
|
+
if (!otherDbTable)
|
|
165
|
+
throw new Error(`Cannot find table class by name ${otherTableName}`);
|
|
164
166
|
|
|
165
167
|
const data: ApplyRelationData = {
|
|
166
168
|
relationName,
|
|
167
169
|
relation,
|
|
168
|
-
|
|
169
|
-
|
|
170
|
+
dbTable,
|
|
171
|
+
otherDbTable,
|
|
170
172
|
};
|
|
171
173
|
|
|
172
174
|
const options = relation.options as { through?: string; source?: string };
|
|
@@ -174,9 +176,9 @@ export const applyRelations = (
|
|
|
174
176
|
typeof options.through === 'string' &&
|
|
175
177
|
typeof options.source === 'string'
|
|
176
178
|
) {
|
|
177
|
-
const throughRelation = getThroughRelation(
|
|
179
|
+
const throughRelation = getThroughRelation(dbTable, options.through);
|
|
178
180
|
if (!throughRelation) {
|
|
179
|
-
delayRelation(delayedRelations,
|
|
181
|
+
delayRelation(delayedRelations, dbTable, options.through, data);
|
|
180
182
|
continue;
|
|
181
183
|
}
|
|
182
184
|
|
|
@@ -187,7 +189,7 @@ export const applyRelations = (
|
|
|
187
189
|
if (!sourceRelation) {
|
|
188
190
|
delayRelation(
|
|
189
191
|
delayedRelations,
|
|
190
|
-
throughRelation.
|
|
192
|
+
throughRelation.table,
|
|
191
193
|
options.source,
|
|
192
194
|
data,
|
|
193
195
|
);
|
|
@@ -207,17 +209,17 @@ export const applyRelations = (
|
|
|
207
209
|
for (const item of value[key]) {
|
|
208
210
|
const { relation } = item;
|
|
209
211
|
|
|
210
|
-
if (item.
|
|
212
|
+
if (item.dbTable.relations[item.relationName as never]) continue;
|
|
211
213
|
|
|
212
|
-
const as = item.
|
|
214
|
+
const as = item.dbTable.definedAs;
|
|
213
215
|
let message = `Cannot define a \`${item.relationName}\` relation on \`${as}\``;
|
|
214
|
-
const
|
|
216
|
+
const table = result[as];
|
|
215
217
|
|
|
216
218
|
const { through, source } = relation.options as {
|
|
217
219
|
through: string;
|
|
218
220
|
source: string;
|
|
219
221
|
};
|
|
220
|
-
const throughRel =
|
|
222
|
+
const throughRel = table.relations[
|
|
221
223
|
through as never
|
|
222
224
|
] as unknown as BaseRelation;
|
|
223
225
|
|
|
@@ -226,10 +228,10 @@ export const applyRelations = (
|
|
|
226
228
|
} else if (
|
|
227
229
|
source &&
|
|
228
230
|
throughRel &&
|
|
229
|
-
!throughRel.
|
|
231
|
+
!throughRel.table.relations[source as never]
|
|
230
232
|
) {
|
|
231
233
|
message += `: cannot find \`${source}\` relation in \`${
|
|
232
|
-
(throughRel.
|
|
234
|
+
(throughRel.table as DbTable<TableClass>).definedAs
|
|
233
235
|
}\` required by the \`source\` option`;
|
|
234
236
|
}
|
|
235
237
|
|
|
@@ -241,37 +243,37 @@ export const applyRelations = (
|
|
|
241
243
|
|
|
242
244
|
const delayRelation = (
|
|
243
245
|
delayedRelations: DelayedRelations,
|
|
244
|
-
|
|
246
|
+
table: Query,
|
|
245
247
|
relationName: string,
|
|
246
248
|
data: ApplyRelationData,
|
|
247
249
|
) => {
|
|
248
|
-
let
|
|
249
|
-
if (!
|
|
250
|
-
|
|
251
|
-
delayedRelations.set(
|
|
250
|
+
let tableRelations = delayedRelations.get(table);
|
|
251
|
+
if (!tableRelations) {
|
|
252
|
+
tableRelations = {};
|
|
253
|
+
delayedRelations.set(table, tableRelations);
|
|
252
254
|
}
|
|
253
|
-
if (
|
|
254
|
-
|
|
255
|
+
if (tableRelations[relationName]) {
|
|
256
|
+
tableRelations[relationName].push(data);
|
|
255
257
|
} else {
|
|
256
|
-
|
|
258
|
+
tableRelations[relationName] = [data];
|
|
257
259
|
}
|
|
258
260
|
};
|
|
259
261
|
|
|
260
262
|
const applyRelation = (
|
|
261
263
|
qb: Query,
|
|
262
|
-
{ relationName, relation,
|
|
264
|
+
{ relationName, relation, dbTable, otherDbTable }: ApplyRelationData,
|
|
263
265
|
delayedRelations: DelayedRelations,
|
|
264
266
|
) => {
|
|
265
267
|
const query = (
|
|
266
268
|
relation.options.scope
|
|
267
|
-
? relation.options.scope(
|
|
268
|
-
: (
|
|
269
|
+
? relation.options.scope(otherDbTable)
|
|
270
|
+
: (otherDbTable as unknown as QueryWithTable)
|
|
269
271
|
).as(relationName);
|
|
270
272
|
|
|
271
273
|
const definedAs = (query as unknown as { definedAs?: string }).definedAs;
|
|
272
274
|
if (!definedAs) {
|
|
273
275
|
throw new Error(
|
|
274
|
-
`
|
|
276
|
+
`Table class for table ${query.table} is not attached to db instance`,
|
|
275
277
|
);
|
|
276
278
|
}
|
|
277
279
|
|
|
@@ -280,12 +282,12 @@ const applyRelation = (
|
|
|
280
282
|
if (type === 'belongsTo') {
|
|
281
283
|
data = makeBelongsToMethod(relation, relationName, query);
|
|
282
284
|
} else if (type === 'hasOne') {
|
|
283
|
-
data = makeHasOneMethod(
|
|
285
|
+
data = makeHasOneMethod(dbTable, relation, relationName, query);
|
|
284
286
|
} else if (type === 'hasMany') {
|
|
285
|
-
data = makeHasManyMethod(
|
|
287
|
+
data = makeHasManyMethod(dbTable, relation, relationName, query);
|
|
286
288
|
} else if (type === 'hasAndBelongsToMany') {
|
|
287
289
|
data = makeHasAndBelongsToManyMethod(
|
|
288
|
-
|
|
290
|
+
dbTable,
|
|
289
291
|
qb,
|
|
290
292
|
relation,
|
|
291
293
|
relationName,
|
|
@@ -300,51 +302,51 @@ const applyRelation = (
|
|
|
300
302
|
}
|
|
301
303
|
|
|
302
304
|
if (data.virtualColumn) {
|
|
303
|
-
|
|
305
|
+
dbTable.shape[relationName] = data.virtualColumn;
|
|
304
306
|
}
|
|
305
307
|
|
|
306
|
-
makeRelationQuery(
|
|
308
|
+
makeRelationQuery(dbTable, definedAs, relationName, data);
|
|
307
309
|
|
|
308
|
-
(
|
|
310
|
+
(dbTable.relations as Record<string, unknown>)[relationName] = {
|
|
309
311
|
type,
|
|
310
312
|
key: relationName,
|
|
311
|
-
|
|
313
|
+
table: otherDbTable,
|
|
312
314
|
query,
|
|
313
315
|
joinQuery: data.joinQuery,
|
|
314
316
|
primaryKey: data.primaryKey,
|
|
315
317
|
options: relation.options,
|
|
316
318
|
};
|
|
317
319
|
|
|
318
|
-
const
|
|
319
|
-
if (!
|
|
320
|
+
const tableRelations = delayedRelations.get(dbTable);
|
|
321
|
+
if (!tableRelations) return;
|
|
320
322
|
|
|
321
|
-
|
|
323
|
+
tableRelations[relationName]?.forEach((data) => {
|
|
322
324
|
applyRelation(qb, data, delayedRelations);
|
|
323
325
|
});
|
|
324
326
|
};
|
|
325
327
|
|
|
326
328
|
const makeRelationQuery = (
|
|
327
|
-
|
|
329
|
+
table: Query,
|
|
328
330
|
definedAs: string,
|
|
329
331
|
relationName: string,
|
|
330
332
|
data: RelationData,
|
|
331
333
|
) => {
|
|
332
|
-
Object.defineProperty(
|
|
334
|
+
Object.defineProperty(table, relationName, {
|
|
333
335
|
get() {
|
|
334
|
-
const
|
|
336
|
+
const toTable = this.db[definedAs].as(relationName) as Query;
|
|
335
337
|
|
|
336
338
|
if (data.returns === 'one') {
|
|
337
|
-
|
|
339
|
+
toTable._take();
|
|
338
340
|
}
|
|
339
341
|
|
|
340
342
|
const query = this.isSubQuery
|
|
341
|
-
?
|
|
342
|
-
:
|
|
343
|
+
? toTable
|
|
344
|
+
: toTable._whereExists(data.reverseJoin(this, toTable), (q) => q);
|
|
343
345
|
|
|
344
346
|
query.query[relationQueryKey] = {
|
|
345
347
|
relationName,
|
|
346
348
|
sourceQuery: this,
|
|
347
|
-
relationQuery:
|
|
349
|
+
relationQuery: toTable,
|
|
348
350
|
joinQuery: data.joinQuery,
|
|
349
351
|
};
|
|
350
352
|
|
package/src/relations/utils.ts
CHANGED
|
@@ -57,15 +57,15 @@ export type NestedUpdateManyItems = {
|
|
|
57
57
|
|
|
58
58
|
export type NestedUpdateItem = NestedUpdateOneItem | NestedUpdateManyItems;
|
|
59
59
|
|
|
60
|
-
export const getThroughRelation = (
|
|
61
|
-
return (
|
|
60
|
+
export const getThroughRelation = (table: Query, through: string) => {
|
|
61
|
+
return (table.relations as Record<string, Relation>)[through];
|
|
62
62
|
};
|
|
63
63
|
|
|
64
64
|
export const getSourceRelation = (
|
|
65
65
|
throughRelation: Relation,
|
|
66
66
|
source: string,
|
|
67
67
|
) => {
|
|
68
|
-
return (throughRelation.
|
|
68
|
+
return (throughRelation.table.relations as Record<string, Relation>)[source];
|
|
69
69
|
};
|
|
70
70
|
|
|
71
71
|
export const hasRelationHandleCreate = (
|
package/src/repo.test.ts
CHANGED
|
@@ -1,63 +1,63 @@
|
|
|
1
1
|
import { orchidORM } from './orm';
|
|
2
2
|
import { pgConfig } from './test-utils/test-db';
|
|
3
|
-
import {
|
|
3
|
+
import { createBaseTable } from './table';
|
|
4
4
|
import { assertType, expectSql } from './test-utils/test-utils';
|
|
5
5
|
import { columnTypes, QueryReturnType } from 'pqb';
|
|
6
6
|
import { createRepo } from './repo';
|
|
7
7
|
|
|
8
|
-
const
|
|
8
|
+
const BaseTable = createBaseTable({ columnTypes });
|
|
9
9
|
|
|
10
|
-
class
|
|
10
|
+
class SomeTable extends BaseTable {
|
|
11
11
|
table = 'someTable';
|
|
12
12
|
columns = this.setColumns((t) => ({
|
|
13
13
|
id: t.serial().primaryKey(),
|
|
14
|
-
name: t.text(),
|
|
14
|
+
name: t.text(0, 100),
|
|
15
15
|
}));
|
|
16
16
|
|
|
17
17
|
relations = {
|
|
18
|
-
|
|
18
|
+
other: this.hasMany(() => OtherTable, {
|
|
19
19
|
primaryKey: 'id',
|
|
20
20
|
foreignKey: 'someId',
|
|
21
21
|
}),
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
class
|
|
25
|
+
class OtherTable extends BaseTable {
|
|
26
26
|
table = 'otherTable';
|
|
27
27
|
columns = this.setColumns((t) => ({
|
|
28
28
|
id: t.serial().primaryKey(),
|
|
29
|
-
someId: t.integer().foreignKey(() =>
|
|
30
|
-
anotherId: t.integer().foreignKey(() =>
|
|
29
|
+
someId: t.integer().foreignKey(() => SomeTable, 'id'),
|
|
30
|
+
anotherId: t.integer().foreignKey(() => AnotherTable, 'id'),
|
|
31
31
|
}));
|
|
32
32
|
|
|
33
33
|
relations = {
|
|
34
|
-
|
|
34
|
+
some: this.belongsTo(() => SomeTable, {
|
|
35
35
|
primaryKey: 'id',
|
|
36
36
|
foreignKey: 'someId',
|
|
37
37
|
}),
|
|
38
|
-
|
|
38
|
+
another: this.belongsTo(() => AnotherTable, {
|
|
39
39
|
primaryKey: 'id',
|
|
40
40
|
foreignKey: 'anotherId',
|
|
41
41
|
}),
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
class
|
|
46
|
-
table = '
|
|
45
|
+
class AnotherTable extends BaseTable {
|
|
46
|
+
table = 'another';
|
|
47
47
|
columns = this.setColumns((t) => ({
|
|
48
48
|
id: t.serial().primaryKey(),
|
|
49
49
|
}));
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
const db = orchidORM(pgConfig, {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
some: SomeTable,
|
|
54
|
+
other: OtherTable,
|
|
55
|
+
another: AnotherTable,
|
|
56
56
|
});
|
|
57
57
|
|
|
58
58
|
describe('createRepo', () => {
|
|
59
59
|
describe('queryMethods', () => {
|
|
60
|
-
const repo = createRepo(db.
|
|
60
|
+
const repo = createRepo(db.some, {
|
|
61
61
|
queryMethods: {
|
|
62
62
|
one(q) {
|
|
63
63
|
return q.select('id');
|
|
@@ -71,7 +71,7 @@ describe('createRepo', () => {
|
|
|
71
71
|
},
|
|
72
72
|
});
|
|
73
73
|
|
|
74
|
-
it('should accept user defined methods and allow to use them on the
|
|
74
|
+
it('should accept user defined methods and allow to use them on the table with chaining', async () => {
|
|
75
75
|
const q = repo.one().two().three(123).take();
|
|
76
76
|
|
|
77
77
|
assertType<Awaited<typeof q>, { id: number; name: string }>();
|
|
@@ -89,13 +89,13 @@ describe('createRepo', () => {
|
|
|
89
89
|
});
|
|
90
90
|
|
|
91
91
|
it('should have custom methods on relation queries inside of select', async () => {
|
|
92
|
-
const q = db.
|
|
93
|
-
|
|
92
|
+
const q = db.other.select('id', {
|
|
93
|
+
some: (q) => repo(q.some).one().two().three(123),
|
|
94
94
|
});
|
|
95
95
|
|
|
96
96
|
assertType<
|
|
97
97
|
Awaited<typeof q>,
|
|
98
|
-
{ id: number;
|
|
98
|
+
{ id: number; some: { id: number; name: string } | null }[]
|
|
99
99
|
>();
|
|
100
100
|
|
|
101
101
|
expectSql(
|
|
@@ -106,13 +106,13 @@ describe('createRepo', () => {
|
|
|
106
106
|
(
|
|
107
107
|
SELECT row_to_json("t".*)
|
|
108
108
|
FROM (
|
|
109
|
-
SELECT "
|
|
110
|
-
FROM "someTable" AS "
|
|
111
|
-
WHERE "
|
|
112
|
-
AND "
|
|
109
|
+
SELECT "some"."id", "some"."name"
|
|
110
|
+
FROM "someTable" AS "some"
|
|
111
|
+
WHERE "some"."id" = $1
|
|
112
|
+
AND "some"."id" = "otherTable"."someId"
|
|
113
113
|
LIMIT $2
|
|
114
114
|
) AS "t"
|
|
115
|
-
) AS "
|
|
115
|
+
) AS "some"
|
|
116
116
|
FROM "otherTable"
|
|
117
117
|
`,
|
|
118
118
|
[123, 1],
|
|
@@ -121,7 +121,7 @@ describe('createRepo', () => {
|
|
|
121
121
|
});
|
|
122
122
|
|
|
123
123
|
describe('queryOneMethods', () => {
|
|
124
|
-
const repo = createRepo(db.
|
|
124
|
+
const repo = createRepo(db.some, {
|
|
125
125
|
queryOneMethods: {
|
|
126
126
|
one(q) {
|
|
127
127
|
const type: Exclude<QueryReturnType, 'all'> = q.returnType;
|
|
@@ -140,7 +140,7 @@ describe('createRepo', () => {
|
|
|
140
140
|
});
|
|
141
141
|
|
|
142
142
|
describe('queryWithWhereMethods', () => {
|
|
143
|
-
const repo = createRepo(db.
|
|
143
|
+
const repo = createRepo(db.some, {
|
|
144
144
|
queryWithWhereMethods: {
|
|
145
145
|
one(q) {
|
|
146
146
|
const hasWhere: true = q.hasWhere;
|
|
@@ -161,7 +161,7 @@ describe('createRepo', () => {
|
|
|
161
161
|
});
|
|
162
162
|
|
|
163
163
|
describe('queryOneWithWhere', () => {
|
|
164
|
-
const repo = createRepo(db.
|
|
164
|
+
const repo = createRepo(db.some, {
|
|
165
165
|
queryOneWithWhereMethods: {
|
|
166
166
|
one(q) {
|
|
167
167
|
const type: Exclude<QueryReturnType, 'all'> = q.returnType;
|
|
@@ -185,7 +185,7 @@ describe('createRepo', () => {
|
|
|
185
185
|
});
|
|
186
186
|
|
|
187
187
|
describe('methods', () => {
|
|
188
|
-
const repo = createRepo(db.
|
|
188
|
+
const repo = createRepo(db.some, {
|
|
189
189
|
methods: {
|
|
190
190
|
one(a: number, b: string) {
|
|
191
191
|
return a + b;
|
package/src/repo.ts
CHANGED
|
@@ -75,7 +75,7 @@ export type Repo<
|
|
|
75
75
|
Mapped;
|
|
76
76
|
|
|
77
77
|
export const createRepo = <T extends Query, Methods extends MethodsBase<T>>(
|
|
78
|
-
|
|
78
|
+
table: T,
|
|
79
79
|
methods: Methods,
|
|
80
80
|
): Repo<T, Methods> => {
|
|
81
81
|
const queryMethods = {
|
|
@@ -88,18 +88,18 @@ export const createRepo = <T extends Query, Methods extends MethodsBase<T>>(
|
|
|
88
88
|
const plainMethods = methods.methods;
|
|
89
89
|
|
|
90
90
|
const repo = (q: Query) => {
|
|
91
|
-
const proto = Object.create(q.
|
|
92
|
-
proto.
|
|
91
|
+
const proto = Object.create(q.__table);
|
|
92
|
+
proto.__table = proto;
|
|
93
93
|
const result = Object.create(proto);
|
|
94
94
|
result.query = getClonedQueryData(q.query);
|
|
95
95
|
|
|
96
96
|
if (plainMethods) {
|
|
97
|
-
Object.assign(proto.
|
|
97
|
+
Object.assign(proto.__table, plainMethods);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
for (const key in queryMethods) {
|
|
101
101
|
const method = queryMethods[key] as (...args: unknown[]) => unknown;
|
|
102
|
-
(proto.
|
|
102
|
+
(proto.__table as unknown as Record<string, unknown>)[key] = function (
|
|
103
103
|
...args: unknown[]
|
|
104
104
|
) {
|
|
105
105
|
return method(this, ...args);
|
|
@@ -109,7 +109,7 @@ export const createRepo = <T extends Query, Methods extends MethodsBase<T>>(
|
|
|
109
109
|
return result;
|
|
110
110
|
};
|
|
111
111
|
|
|
112
|
-
const q = repo(
|
|
112
|
+
const q = repo(table);
|
|
113
113
|
|
|
114
114
|
return new Proxy(repo, {
|
|
115
115
|
get(_, key) {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createBaseTable } from './table';
|
|
2
2
|
import { orchidORM } from './orm';
|
|
3
3
|
import { adapter, db } from './test-utils/test-db';
|
|
4
4
|
import { assertType, userData, useTestDatabase } from './test-utils/test-utils';
|
|
5
5
|
import { ColumnType, columnTypes, Operators } from 'pqb';
|
|
6
|
-
import {
|
|
6
|
+
import { BaseTable } from './test-utils/test-tables';
|
|
7
7
|
|
|
8
|
-
describe('
|
|
8
|
+
describe('table', () => {
|
|
9
9
|
useTestDatabase();
|
|
10
10
|
|
|
11
11
|
describe('overriding column types', () => {
|
|
@@ -15,8 +15,8 @@ describe('model', () => {
|
|
|
15
15
|
operators = Operators.any;
|
|
16
16
|
}
|
|
17
17
|
const type = new Type();
|
|
18
|
-
const
|
|
19
|
-
class
|
|
18
|
+
const BaseTable = createBaseTable({ columnTypes: { type: () => type } });
|
|
19
|
+
class UserTable extends BaseTable {
|
|
20
20
|
table = 'user';
|
|
21
21
|
columns = this.setColumns((t) => ({
|
|
22
22
|
id: t.type().primaryKey(),
|
|
@@ -27,7 +27,7 @@ describe('model', () => {
|
|
|
27
27
|
const { user } = orchidORM(
|
|
28
28
|
{ adapter },
|
|
29
29
|
{
|
|
30
|
-
user:
|
|
30
|
+
user: UserTable,
|
|
31
31
|
},
|
|
32
32
|
);
|
|
33
33
|
|
|
@@ -39,8 +39,8 @@ describe('model', () => {
|
|
|
39
39
|
it('should return date as string by default', async () => {
|
|
40
40
|
await db.user.create(userData);
|
|
41
41
|
|
|
42
|
-
const
|
|
43
|
-
class
|
|
42
|
+
const BaseTable = createBaseTable({ columnTypes });
|
|
43
|
+
class UserTable extends BaseTable {
|
|
44
44
|
table = 'user';
|
|
45
45
|
columns = this.setColumns((t) => ({
|
|
46
46
|
id: t.serial().primaryKey(),
|
|
@@ -51,7 +51,7 @@ describe('model', () => {
|
|
|
51
51
|
const { user } = orchidORM(
|
|
52
52
|
{ adapter },
|
|
53
53
|
{
|
|
54
|
-
user:
|
|
54
|
+
user: UserTable,
|
|
55
55
|
},
|
|
56
56
|
);
|
|
57
57
|
|
|
@@ -64,7 +64,7 @@ describe('model', () => {
|
|
|
64
64
|
it('should return date as Date when overridden', async () => {
|
|
65
65
|
await db.user.create(userData);
|
|
66
66
|
|
|
67
|
-
const
|
|
67
|
+
const BaseTable = createBaseTable({
|
|
68
68
|
columnTypes: {
|
|
69
69
|
serial: columnTypes.serial,
|
|
70
70
|
timestamp() {
|
|
@@ -73,7 +73,7 @@ describe('model', () => {
|
|
|
73
73
|
},
|
|
74
74
|
});
|
|
75
75
|
|
|
76
|
-
class
|
|
76
|
+
class UserTable extends BaseTable {
|
|
77
77
|
table = 'user';
|
|
78
78
|
columns = this.setColumns((t) => ({
|
|
79
79
|
id: t.serial().primaryKey(),
|
|
@@ -84,7 +84,7 @@ describe('model', () => {
|
|
|
84
84
|
const { user } = orchidORM(
|
|
85
85
|
{ adapter },
|
|
86
86
|
{
|
|
87
|
-
user:
|
|
87
|
+
user: UserTable,
|
|
88
88
|
},
|
|
89
89
|
);
|
|
90
90
|
|
|
@@ -96,8 +96,8 @@ describe('model', () => {
|
|
|
96
96
|
});
|
|
97
97
|
|
|
98
98
|
describe('noPrimaryKey', () => {
|
|
99
|
-
it('should allow to the
|
|
100
|
-
class
|
|
99
|
+
it('should allow to the table to not have a primary key', () => {
|
|
100
|
+
class UserTable extends BaseTable {
|
|
101
101
|
table = 'user';
|
|
102
102
|
noPrimaryKey = true;
|
|
103
103
|
columns = this.setColumns((t) => ({
|
|
@@ -110,7 +110,7 @@ describe('model', () => {
|
|
|
110
110
|
adapter,
|
|
111
111
|
},
|
|
112
112
|
{
|
|
113
|
-
user:
|
|
113
|
+
user: UserTable,
|
|
114
114
|
},
|
|
115
115
|
);
|
|
116
116
|
});
|