pqb 0.1.0 → 0.1.2
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 +10 -6
- package/dist/index.esm.js +6 -4
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/columnSchema/columnTypes.ts +8 -4
- package/src/queryMethods/select.test.ts +104 -49
- package/src/test-utils.ts +9 -0
package/package.json
CHANGED
|
@@ -177,10 +177,14 @@ export const columnTypes = {
|
|
|
177
177
|
jsonText: () => new JSONTextColumn(),
|
|
178
178
|
array: <Item extends ColumnType>(item: Item) => new ArrayColumn(item),
|
|
179
179
|
|
|
180
|
-
timestamps
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
180
|
+
timestamps<T extends ColumnType>(this: {
|
|
181
|
+
timestamp(): T;
|
|
182
|
+
}): { createdAt: T; updatedAt: T } {
|
|
183
|
+
return {
|
|
184
|
+
createdAt: this.timestamp().default(raw('now()')),
|
|
185
|
+
updatedAt: this.timestamp().default(raw('now()')),
|
|
186
|
+
};
|
|
187
|
+
},
|
|
184
188
|
|
|
185
189
|
primaryKey(columns: string[], options?: { name?: string }) {
|
|
186
190
|
tableData.primaryKey = { columns, options };
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
assertType,
|
|
3
3
|
Chat,
|
|
4
4
|
chatData,
|
|
5
5
|
expectQueryNotMutated,
|
|
6
6
|
expectSql,
|
|
7
7
|
Message,
|
|
8
8
|
messageData,
|
|
9
|
+
MessageRecord,
|
|
9
10
|
now,
|
|
10
11
|
Profile,
|
|
11
12
|
profileData,
|
|
13
|
+
ProfileRecord,
|
|
12
14
|
User,
|
|
13
15
|
userData,
|
|
16
|
+
UserRecord,
|
|
14
17
|
useTestDatabase,
|
|
15
18
|
} from '../test-utils';
|
|
16
19
|
import { raw } from '../common';
|
|
@@ -29,25 +32,27 @@ describe('selectMethods', () => {
|
|
|
29
32
|
describe('select', () => {
|
|
30
33
|
it('should have no effect if no columns provided', () => {
|
|
31
34
|
const q = User.all();
|
|
35
|
+
const query = q.select();
|
|
36
|
+
|
|
37
|
+
assertType<Awaited<typeof q>, UserRecord[]>();
|
|
38
|
+
|
|
32
39
|
expectSql(
|
|
33
|
-
|
|
40
|
+
query.toSql(),
|
|
34
41
|
`
|
|
35
42
|
SELECT * FROM "user"
|
|
36
43
|
`,
|
|
37
44
|
);
|
|
38
|
-
expectSql(
|
|
39
|
-
q.select('id').select().toSql(),
|
|
40
|
-
`
|
|
41
|
-
SELECT "user"."id" FROM "user"
|
|
42
|
-
`,
|
|
43
|
-
);
|
|
44
45
|
expectQueryNotMutated(q);
|
|
45
46
|
});
|
|
46
47
|
|
|
47
48
|
it('should select provided columns', () => {
|
|
48
49
|
const q = User.all();
|
|
50
|
+
const query = q.select('id', 'name');
|
|
51
|
+
|
|
52
|
+
assertType<Awaited<typeof query>, Pick<UserRecord, 'id' | 'name'>[]>();
|
|
53
|
+
|
|
49
54
|
expectSql(
|
|
50
|
-
|
|
55
|
+
query.toSql(),
|
|
51
56
|
`
|
|
52
57
|
SELECT "user"."id", "user"."name" FROM "user"
|
|
53
58
|
`,
|
|
@@ -57,8 +62,12 @@ describe('selectMethods', () => {
|
|
|
57
62
|
|
|
58
63
|
it('should select table.column', () => {
|
|
59
64
|
const q = User.all();
|
|
65
|
+
const query = q.select('user.id', 'user.name');
|
|
66
|
+
|
|
67
|
+
assertType<Awaited<typeof query>, Pick<UserRecord, 'id' | 'name'>[]>();
|
|
68
|
+
|
|
60
69
|
expectSql(
|
|
61
|
-
|
|
70
|
+
query.toSql(),
|
|
62
71
|
`
|
|
63
72
|
SELECT "user"."id", "user"."name" FROM "user"
|
|
64
73
|
`,
|
|
@@ -68,12 +77,14 @@ describe('selectMethods', () => {
|
|
|
68
77
|
|
|
69
78
|
it('should select joined columns', () => {
|
|
70
79
|
const q = User.all();
|
|
80
|
+
const query = q
|
|
81
|
+
.join(Profile, 'profile.userId', '=', 'user.id')
|
|
82
|
+
.select('user.id', 'profile.userId');
|
|
83
|
+
|
|
84
|
+
assertType<Awaited<typeof query>, { id: number; userId: number }[]>();
|
|
71
85
|
|
|
72
86
|
expectSql(
|
|
73
|
-
|
|
74
|
-
.join(Profile, 'profile.userId', '=', 'user.id')
|
|
75
|
-
.select('user.id', 'profile.userId')
|
|
76
|
-
.toSql(),
|
|
87
|
+
query.toSql(),
|
|
77
88
|
`
|
|
78
89
|
SELECT "user"."id", "profile"."userId" FROM "user"
|
|
79
90
|
JOIN "profile" ON "profile"."userId" = "user"."id"
|
|
@@ -84,11 +95,14 @@ describe('selectMethods', () => {
|
|
|
84
95
|
|
|
85
96
|
it('should select joined columns with alias', () => {
|
|
86
97
|
const q = User.all();
|
|
98
|
+
const query = q
|
|
99
|
+
.join(Profile.as('p'), 'p.userId', '=', 'user.id')
|
|
100
|
+
.select('user.id', 'p.userId');
|
|
101
|
+
|
|
102
|
+
assertType<Awaited<typeof query>, { id: number; userId: number }[]>();
|
|
103
|
+
|
|
87
104
|
expectSql(
|
|
88
|
-
|
|
89
|
-
.join(Profile.as('p'), 'p.userId', '=', 'user.id')
|
|
90
|
-
.select('user.id', 'p.userId')
|
|
91
|
-
.toSql(),
|
|
105
|
+
query.toSql(),
|
|
92
106
|
`
|
|
93
107
|
SELECT "user"."id", "p"."userId" FROM "user"
|
|
94
108
|
JOIN "profile" AS "p" ON "p"."userId" = "user"."id"
|
|
@@ -125,11 +139,10 @@ describe('selectMethods', () => {
|
|
|
125
139
|
const q = User.all();
|
|
126
140
|
|
|
127
141
|
const query = q.select('id', profileRelation.where({ bio: 'bio' }));
|
|
128
|
-
|
|
142
|
+
assertType<
|
|
129
143
|
Awaited<typeof query>,
|
|
130
144
|
{ id: number; profile: typeof Profile['type'] | null }[]
|
|
131
|
-
>
|
|
132
|
-
expect(eq).toBe(true);
|
|
145
|
+
>();
|
|
133
146
|
|
|
134
147
|
expectSql(
|
|
135
148
|
query.toSql(),
|
|
@@ -167,11 +180,11 @@ describe('selectMethods', () => {
|
|
|
167
180
|
true
|
|
168
181
|
>,
|
|
169
182
|
);
|
|
170
|
-
|
|
183
|
+
|
|
184
|
+
assertType<
|
|
171
185
|
Awaited<typeof query>,
|
|
172
186
|
{ id: number; profile: typeof Profile['type'] }[]
|
|
173
|
-
>
|
|
174
|
-
expect(eq).toBe(true);
|
|
187
|
+
>();
|
|
175
188
|
});
|
|
176
189
|
|
|
177
190
|
it('should parse columns in single relation record result', async () => {
|
|
@@ -180,6 +193,12 @@ describe('selectMethods', () => {
|
|
|
180
193
|
await Profile.insert({ userId, updatedAt: now, createdAt: now });
|
|
181
194
|
|
|
182
195
|
const [record] = await User.select('id', profileRelation);
|
|
196
|
+
|
|
197
|
+
assertType<
|
|
198
|
+
typeof record,
|
|
199
|
+
{ id: number; profile: ProfileRecord | null }
|
|
200
|
+
>();
|
|
201
|
+
|
|
183
202
|
expect(record.profile).toMatchObject({
|
|
184
203
|
updatedAt: now,
|
|
185
204
|
createdAt: now,
|
|
@@ -213,11 +232,10 @@ describe('selectMethods', () => {
|
|
|
213
232
|
const q = User.all();
|
|
214
233
|
|
|
215
234
|
const query = q.select('id', messageRelation.where({ text: 'text' }));
|
|
216
|
-
|
|
235
|
+
assertType<
|
|
217
236
|
Awaited<typeof query>,
|
|
218
237
|
{ id: number; messages: typeof Message['type'][] }[]
|
|
219
|
-
>
|
|
220
|
-
expect(eq).toBe(true);
|
|
238
|
+
>();
|
|
221
239
|
|
|
222
240
|
expectSql(
|
|
223
241
|
query.toSql(),
|
|
@@ -251,6 +269,9 @@ describe('selectMethods', () => {
|
|
|
251
269
|
});
|
|
252
270
|
|
|
253
271
|
const [record] = await User.select('id', messageRelation);
|
|
272
|
+
|
|
273
|
+
assertType<typeof record, { id: number; messages: MessageRecord[] }>();
|
|
274
|
+
|
|
254
275
|
expect(record.messages[0]).toMatchObject({
|
|
255
276
|
updatedAt: now,
|
|
256
277
|
createdAt: now,
|
|
@@ -264,6 +285,8 @@ describe('selectMethods', () => {
|
|
|
264
285
|
it('should parse columns of the table', async () => {
|
|
265
286
|
const q = User.select('createdAt');
|
|
266
287
|
|
|
288
|
+
assertType<Awaited<typeof q>, { createdAt: Date }[]>();
|
|
289
|
+
|
|
267
290
|
expect((await q.all())[0].createdAt instanceof Date).toBe(true);
|
|
268
291
|
expect((await q.take()).createdAt instanceof Date).toBe(true);
|
|
269
292
|
expect((await q.rows())[0][0] instanceof Date).toBe(true);
|
|
@@ -273,6 +296,8 @@ describe('selectMethods', () => {
|
|
|
273
296
|
it('should parse columns of the table, selected by column name and table name', async () => {
|
|
274
297
|
const q = User.select('user.createdAt');
|
|
275
298
|
|
|
299
|
+
assertType<Awaited<typeof q>, { createdAt: Date }[]>();
|
|
300
|
+
|
|
276
301
|
expect((await q.all())[0].createdAt instanceof Date).toBe(true);
|
|
277
302
|
expect((await q.take()).createdAt instanceof Date).toBe(true);
|
|
278
303
|
expect((await q.rows())[0][0] instanceof Date).toBe(true);
|
|
@@ -284,6 +309,8 @@ describe('selectMethods', () => {
|
|
|
284
309
|
'user.createdAt',
|
|
285
310
|
);
|
|
286
311
|
|
|
312
|
+
assertType<Awaited<typeof q>, { createdAt: Date }[]>();
|
|
313
|
+
|
|
287
314
|
expect((await q.all())[0].createdAt instanceof Date).toBe(true);
|
|
288
315
|
expect((await q.take()).createdAt instanceof Date).toBe(true);
|
|
289
316
|
expect((await q.rows())[0][0] instanceof Date).toBe(true);
|
|
@@ -296,11 +323,10 @@ describe('selectMethods', () => {
|
|
|
296
323
|
|
|
297
324
|
const query = q.select({ aliasedId: 'id', aliasedName: 'name' });
|
|
298
325
|
|
|
299
|
-
|
|
326
|
+
assertType<
|
|
300
327
|
Awaited<typeof query>,
|
|
301
328
|
{ aliasedId: number; aliasedName: string }[]
|
|
302
|
-
>
|
|
303
|
-
expect(eq).toBe(true);
|
|
329
|
+
>();
|
|
304
330
|
|
|
305
331
|
expectSql(
|
|
306
332
|
query.toSql(),
|
|
@@ -320,11 +346,10 @@ describe('selectMethods', () => {
|
|
|
320
346
|
aliasedName: 'user.name',
|
|
321
347
|
});
|
|
322
348
|
|
|
323
|
-
|
|
349
|
+
assertType<
|
|
324
350
|
Awaited<typeof query>,
|
|
325
351
|
{ aliasedId: number; aliasedName: string }[]
|
|
326
|
-
>
|
|
327
|
-
expect(eq).toBe(true);
|
|
352
|
+
>();
|
|
328
353
|
|
|
329
354
|
expectSql(
|
|
330
355
|
query.toSql(),
|
|
@@ -338,14 +363,18 @@ describe('selectMethods', () => {
|
|
|
338
363
|
|
|
339
364
|
it('should select joined columns', () => {
|
|
340
365
|
const q = User.all();
|
|
366
|
+
const query = q.join(Profile, 'profile.userId', '=', 'user.id').select({
|
|
367
|
+
aliasedId: 'user.id',
|
|
368
|
+
aliasedUserId: 'profile.userId',
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
assertType<
|
|
372
|
+
Awaited<typeof query>,
|
|
373
|
+
{ aliasedId: number; aliasedUserId: number }[]
|
|
374
|
+
>();
|
|
375
|
+
|
|
341
376
|
expectSql(
|
|
342
|
-
|
|
343
|
-
.join(Profile, 'profile.userId', '=', 'user.id')
|
|
344
|
-
.select({
|
|
345
|
-
aliasedId: 'user.id',
|
|
346
|
-
aliasedUserId: 'profile.userId',
|
|
347
|
-
})
|
|
348
|
-
.toSql(),
|
|
377
|
+
query.toSql(),
|
|
349
378
|
`
|
|
350
379
|
SELECT "user"."id" AS "aliasedId", "profile"."userId" AS "aliasedUserId"
|
|
351
380
|
FROM "user"
|
|
@@ -357,14 +386,18 @@ describe('selectMethods', () => {
|
|
|
357
386
|
|
|
358
387
|
it('should select joined columns with alias', () => {
|
|
359
388
|
const q = User.all();
|
|
389
|
+
const query = q.join(Profile.as('p'), 'p.userId', '=', 'user.id').select({
|
|
390
|
+
aliasedId: 'user.id',
|
|
391
|
+
aliasedUserId: 'p.userId',
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
assertType<
|
|
395
|
+
Awaited<typeof query>,
|
|
396
|
+
{ aliasedId: number; aliasedUserId: number }[]
|
|
397
|
+
>();
|
|
398
|
+
|
|
360
399
|
expectSql(
|
|
361
|
-
|
|
362
|
-
.join(Profile.as('p'), 'p.userId', '=', 'user.id')
|
|
363
|
-
.select({
|
|
364
|
-
aliasedId: 'user.id',
|
|
365
|
-
aliasedUserId: 'p.userId',
|
|
366
|
-
})
|
|
367
|
-
.toSql(),
|
|
400
|
+
query.toSql(),
|
|
368
401
|
`
|
|
369
402
|
SELECT "user"."id" AS "aliasedId", "p"."userId" AS "aliasedUserId"
|
|
370
403
|
FROM "user"
|
|
@@ -376,8 +409,12 @@ describe('selectMethods', () => {
|
|
|
376
409
|
|
|
377
410
|
it('can select raw', () => {
|
|
378
411
|
const q = User.all();
|
|
412
|
+
const query = q.select({ one: raw('1') });
|
|
413
|
+
|
|
414
|
+
assertType<Awaited<typeof query>, { one: unknown }[]>();
|
|
415
|
+
|
|
379
416
|
expectSql(
|
|
380
|
-
|
|
417
|
+
query.toSql(),
|
|
381
418
|
`
|
|
382
419
|
SELECT 1 AS "one" FROM "user"
|
|
383
420
|
`,
|
|
@@ -387,8 +424,12 @@ describe('selectMethods', () => {
|
|
|
387
424
|
|
|
388
425
|
it('can select subquery', () => {
|
|
389
426
|
const q = User.all();
|
|
427
|
+
const query = q.select({ subquery: User.all() });
|
|
428
|
+
|
|
429
|
+
assertType<Awaited<typeof query>, { subquery: UserRecord[] }[]>();
|
|
430
|
+
|
|
390
431
|
expectSql(
|
|
391
|
-
|
|
432
|
+
query.toSql(),
|
|
392
433
|
`
|
|
393
434
|
SELECT
|
|
394
435
|
(
|
|
@@ -406,6 +447,8 @@ describe('selectMethods', () => {
|
|
|
406
447
|
it('should select all columns', () => {
|
|
407
448
|
const query = User.select('id', 'name').selectAll();
|
|
408
449
|
|
|
450
|
+
assertType<Awaited<typeof query>, UserRecord[]>();
|
|
451
|
+
|
|
409
452
|
expectSql(query.toSql(), `SELECT * FROM "user"`);
|
|
410
453
|
});
|
|
411
454
|
});
|
|
@@ -418,6 +461,8 @@ describe('selectMethods', () => {
|
|
|
418
461
|
date: 'createdAt',
|
|
419
462
|
});
|
|
420
463
|
|
|
464
|
+
assertType<Awaited<typeof q>, { date: Date }[]>();
|
|
465
|
+
|
|
421
466
|
expect((await q.all())[0].date instanceof Date).toBe(true);
|
|
422
467
|
expect((await q.take()).date instanceof Date).toBe(true);
|
|
423
468
|
expect((await q.rows())[0][0] instanceof Date).toBe(true);
|
|
@@ -428,6 +473,8 @@ describe('selectMethods', () => {
|
|
|
428
473
|
date: 'user.createdAt',
|
|
429
474
|
});
|
|
430
475
|
|
|
476
|
+
assertType<Awaited<typeof q>, { date: Date }[]>();
|
|
477
|
+
|
|
431
478
|
expect((await q.all())[0].date instanceof Date).toBe(true);
|
|
432
479
|
expect((await q.take()).date instanceof Date).toBe(true);
|
|
433
480
|
expect((await q.rows())[0][0] instanceof Date).toBe(true);
|
|
@@ -438,6 +485,8 @@ describe('selectMethods', () => {
|
|
|
438
485
|
date: 'user.createdAt',
|
|
439
486
|
});
|
|
440
487
|
|
|
488
|
+
assertType<Awaited<typeof q>, { date: Date }[]>();
|
|
489
|
+
|
|
441
490
|
expect((await q.all())[0].date instanceof Date).toBe(true);
|
|
442
491
|
expect((await q.take()).date instanceof Date).toBe(true);
|
|
443
492
|
expect((await q.rows())[0][0] instanceof Date).toBe(true);
|
|
@@ -448,6 +497,8 @@ describe('selectMethods', () => {
|
|
|
448
497
|
users: User.all(),
|
|
449
498
|
});
|
|
450
499
|
|
|
500
|
+
assertType<Awaited<typeof q>, { users: UserRecord[] }[]>();
|
|
501
|
+
|
|
451
502
|
expect((await q.all())[0].users[0].createdAt instanceof Date).toBe(true);
|
|
452
503
|
expect((await q.take()).users[0].createdAt instanceof Date).toBe(true);
|
|
453
504
|
expect((await q.rows())[0][0][0].createdAt instanceof Date).toBe(true);
|
|
@@ -458,6 +509,8 @@ describe('selectMethods', () => {
|
|
|
458
509
|
user: User.take(),
|
|
459
510
|
});
|
|
460
511
|
|
|
512
|
+
assertType<Awaited<typeof q>, { user: UserRecord }[]>();
|
|
513
|
+
|
|
461
514
|
expect((await q.all())[0].user.createdAt instanceof Date).toBe(true);
|
|
462
515
|
expect((await q.take()).user.createdAt instanceof Date).toBe(true);
|
|
463
516
|
expect((await q.rows())[0][0].createdAt instanceof Date).toBe(true);
|
|
@@ -471,6 +524,8 @@ describe('selectMethods', () => {
|
|
|
471
524
|
),
|
|
472
525
|
});
|
|
473
526
|
|
|
527
|
+
assertType<Awaited<typeof q>, { date: Date }[]>();
|
|
528
|
+
|
|
474
529
|
expect((await q.all())[0].date instanceof Date).toBe(true);
|
|
475
530
|
expect((await q.take()).date instanceof Date).toBe(true);
|
|
476
531
|
expect((await q.rows())[0][0] instanceof Date).toBe(true);
|
package/src/test-utils.ts
CHANGED
|
@@ -28,6 +28,7 @@ export const db = createDb({
|
|
|
28
28
|
},
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
+
export type UserRecord = typeof User['type'];
|
|
31
32
|
export const User = db('user', (t) => ({
|
|
32
33
|
id: t.serial().primaryKey(),
|
|
33
34
|
name: t.text(),
|
|
@@ -47,6 +48,7 @@ export const User = db('user', (t) => ({
|
|
|
47
48
|
updatedAt: t.timestamp(),
|
|
48
49
|
}));
|
|
49
50
|
|
|
51
|
+
export type ProfileRecord = typeof Profile['type'];
|
|
50
52
|
export const Profile = db('profile', (t) => ({
|
|
51
53
|
id: t.serial().primaryKey(),
|
|
52
54
|
userId: t.integer().foreignKey('user', 'id'),
|
|
@@ -62,6 +64,7 @@ export const Chat = db('chat', (t) => ({
|
|
|
62
64
|
updatedAt: t.timestamp(),
|
|
63
65
|
}));
|
|
64
66
|
|
|
67
|
+
export type MessageRecord = typeof Message['type'];
|
|
65
68
|
export const Message = db('message', (t) => ({
|
|
66
69
|
id: t.serial().primaryKey(),
|
|
67
70
|
chatId: t.integer().foreignKey('chat', 'id'),
|
|
@@ -110,6 +113,12 @@ export type AssertEqual<T, Expected> = [T] extends [Expected]
|
|
|
110
113
|
: false
|
|
111
114
|
: false;
|
|
112
115
|
|
|
116
|
+
export const assertType = <T, Expected>(
|
|
117
|
+
..._: AssertEqual<T, Expected> extends true ? [] : ['invalid type']
|
|
118
|
+
) => {
|
|
119
|
+
// noop
|
|
120
|
+
};
|
|
121
|
+
|
|
113
122
|
export const insert = async <
|
|
114
123
|
T extends Record<string, unknown> & { id: number },
|
|
115
124
|
>(
|