pqb 0.7.4 → 0.7.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pqb",
3
- "version": "0.7.4",
3
+ "version": "0.7.6",
4
4
  "description": "Postgres query builder",
5
5
  "homepage": "https://orchid-orm.netlify.app/guide/query-builder-setup.html",
6
6
  "repository": {
@@ -277,7 +277,7 @@ describe('operators', () => {
277
277
  User.where({ name: { contains: 'ko' } }).toSql(),
278
278
  `
279
279
  SELECT * FROM "user"
280
- WHERE "user"."name" LIKE '%' || $1 || '%'
280
+ WHERE "user"."name" ILIKE '%' || $1 || '%'
281
281
  `,
282
282
  ['ko'],
283
283
  );
@@ -288,7 +288,7 @@ describe('operators', () => {
288
288
  User.where({ name: { contains: User.select('name').take() } }).toSql(),
289
289
  `
290
290
  SELECT * FROM "user"
291
- WHERE "user"."name" LIKE '%' || (SELECT "user"."name" FROM "user" LIMIT $1) || '%'
291
+ WHERE "user"."name" ILIKE '%' || (SELECT "user"."name" FROM "user" LIMIT $1) || '%'
292
292
  `,
293
293
  [1],
294
294
  );
@@ -299,19 +299,19 @@ describe('operators', () => {
299
299
  User.where({ name: { contains: db.raw("'ko'") } }).toSql(),
300
300
  `
301
301
  SELECT * FROM "user"
302
- WHERE "user"."name" LIKE '%' || 'ko' || '%'
302
+ WHERE "user"."name" ILIKE '%' || 'ko' || '%'
303
303
  `,
304
304
  );
305
305
  });
306
306
  });
307
307
 
308
- describe('containsInsensitive', () => {
308
+ describe('containsSensitive', () => {
309
309
  it('should handle value', () => {
310
310
  expectSql(
311
- User.where({ name: { containsInsensitive: 'ko' } }).toSql(),
311
+ User.where({ name: { containsSensitive: 'ko' } }).toSql(),
312
312
  `
313
313
  SELECT * FROM "user"
314
- WHERE "user"."name" ILIKE '%' || $1 || '%'
314
+ WHERE "user"."name" LIKE '%' || $1 || '%'
315
315
  `,
316
316
  ['ko'],
317
317
  );
@@ -320,11 +320,11 @@ describe('operators', () => {
320
320
  it('should handle sub query', () => {
321
321
  expectSql(
322
322
  User.where({
323
- name: { containsInsensitive: User.select('name').take() },
323
+ name: { containsSensitive: User.select('name').take() },
324
324
  }).toSql(),
325
325
  `
326
326
  SELECT * FROM "user"
327
- WHERE "user"."name" ILIKE '%' || (SELECT "user"."name" FROM "user" LIMIT $1) || '%'
327
+ WHERE "user"."name" LIKE '%' || (SELECT "user"."name" FROM "user" LIMIT $1) || '%'
328
328
  `,
329
329
  [1],
330
330
  );
@@ -332,10 +332,10 @@ describe('operators', () => {
332
332
 
333
333
  it('should handle raw query', () => {
334
334
  expectSql(
335
- User.where({ name: { containsInsensitive: db.raw("'ko'") } }).toSql(),
335
+ User.where({ name: { containsSensitive: db.raw("'ko'") } }).toSql(),
336
336
  `
337
337
  SELECT * FROM "user"
338
- WHERE "user"."name" ILIKE '%' || 'ko' || '%'
338
+ WHERE "user"."name" LIKE '%' || 'ko' || '%'
339
339
  `,
340
340
  );
341
341
  });
@@ -347,7 +347,7 @@ describe('operators', () => {
347
347
  User.where({ name: { startsWith: 'ko' } }).toSql(),
348
348
  `
349
349
  SELECT * FROM "user"
350
- WHERE "user"."name" LIKE $1 || '%'
350
+ WHERE "user"."name" ILIKE $1 || '%'
351
351
  `,
352
352
  ['ko'],
353
353
  );
@@ -360,7 +360,7 @@ describe('operators', () => {
360
360
  }).toSql(),
361
361
  `
362
362
  SELECT * FROM "user"
363
- WHERE "user"."name" LIKE (SELECT "user"."name" FROM "user" LIMIT $1) || '%'
363
+ WHERE "user"."name" ILIKE (SELECT "user"."name" FROM "user" LIMIT $1) || '%'
364
364
  `,
365
365
  [1],
366
366
  );
@@ -371,19 +371,19 @@ describe('operators', () => {
371
371
  User.where({ name: { startsWith: db.raw("'ko'") } }).toSql(),
372
372
  `
373
373
  SELECT * FROM "user"
374
- WHERE "user"."name" LIKE 'ko' || '%'
374
+ WHERE "user"."name" ILIKE 'ko' || '%'
375
375
  `,
376
376
  );
377
377
  });
378
378
  });
379
379
 
380
- describe('startsWithInsensitive', () => {
380
+ describe('startsWithSensitive', () => {
381
381
  it('should handle value', () => {
382
382
  expectSql(
383
- User.where({ name: { startsWithInsensitive: 'ko' } }).toSql(),
383
+ User.where({ name: { startsWithSensitive: 'ko' } }).toSql(),
384
384
  `
385
385
  SELECT * FROM "user"
386
- WHERE "user"."name" ILIKE $1 || '%'
386
+ WHERE "user"."name" LIKE $1 || '%'
387
387
  `,
388
388
  ['ko'],
389
389
  );
@@ -392,11 +392,11 @@ describe('operators', () => {
392
392
  it('should handle sub query', () => {
393
393
  expectSql(
394
394
  User.where({
395
- name: { startsWithInsensitive: User.select('name').take() },
395
+ name: { startsWithSensitive: User.select('name').take() },
396
396
  }).toSql(),
397
397
  `
398
398
  SELECT * FROM "user"
399
- WHERE "user"."name" ILIKE (SELECT "user"."name" FROM "user" LIMIT $1) || '%'
399
+ WHERE "user"."name" LIKE (SELECT "user"."name" FROM "user" LIMIT $1) || '%'
400
400
  `,
401
401
  [1],
402
402
  );
@@ -404,10 +404,10 @@ describe('operators', () => {
404
404
 
405
405
  it('should handle raw query', () => {
406
406
  expectSql(
407
- User.where({ name: { startsWithInsensitive: db.raw("'ko'") } }).toSql(),
407
+ User.where({ name: { startsWithSensitive: db.raw("'ko'") } }).toSql(),
408
408
  `
409
409
  SELECT * FROM "user"
410
- WHERE "user"."name" ILIKE 'ko' || '%'
410
+ WHERE "user"."name" LIKE 'ko' || '%'
411
411
  `,
412
412
  );
413
413
  });
@@ -419,7 +419,7 @@ describe('operators', () => {
419
419
  User.where({ name: { endsWith: 'ko' } }).toSql(),
420
420
  `
421
421
  SELECT * FROM "user"
422
- WHERE "user"."name" LIKE '%' || $1
422
+ WHERE "user"."name" ILIKE '%' || $1
423
423
  `,
424
424
  ['ko'],
425
425
  );
@@ -432,7 +432,7 @@ describe('operators', () => {
432
432
  }).toSql(),
433
433
  `
434
434
  SELECT * FROM "user"
435
- WHERE "user"."name" LIKE '%' || (SELECT "user"."name" FROM "user" LIMIT $1)
435
+ WHERE "user"."name" ILIKE '%' || (SELECT "user"."name" FROM "user" LIMIT $1)
436
436
  `,
437
437
  [1],
438
438
  );
@@ -443,19 +443,19 @@ describe('operators', () => {
443
443
  User.where({ name: { endsWith: db.raw("'ko'") } }).toSql(),
444
444
  `
445
445
  SELECT * FROM "user"
446
- WHERE "user"."name" LIKE '%' || 'ko'
446
+ WHERE "user"."name" ILIKE '%' || 'ko'
447
447
  `,
448
448
  );
449
449
  });
450
450
  });
451
451
 
452
- describe('endsWithInsensitive', () => {
452
+ describe('endsWithSensitive', () => {
453
453
  it('should handle value', () => {
454
454
  expectSql(
455
- User.where({ name: { endsWithInsensitive: 'ko' } }).toSql(),
455
+ User.where({ name: { endsWithSensitive: 'ko' } }).toSql(),
456
456
  `
457
457
  SELECT * FROM "user"
458
- WHERE "user"."name" ILIKE '%' || $1
458
+ WHERE "user"."name" LIKE '%' || $1
459
459
  `,
460
460
  ['ko'],
461
461
  );
@@ -464,11 +464,11 @@ describe('operators', () => {
464
464
  it('should handle sub query', () => {
465
465
  expectSql(
466
466
  User.where({
467
- name: { endsWithInsensitive: User.select('name').take() },
467
+ name: { endsWithSensitive: User.select('name').take() },
468
468
  }).toSql(),
469
469
  `
470
470
  SELECT * FROM "user"
471
- WHERE "user"."name" ILIKE '%' || (SELECT "user"."name" FROM "user" LIMIT $1)
471
+ WHERE "user"."name" LIKE '%' || (SELECT "user"."name" FROM "user" LIMIT $1)
472
472
  `,
473
473
  [1],
474
474
  );
@@ -476,10 +476,10 @@ describe('operators', () => {
476
476
 
477
477
  it('should handle raw query', () => {
478
478
  expectSql(
479
- User.where({ name: { endsWithInsensitive: db.raw("'ko'") } }).toSql(),
479
+ User.where({ name: { endsWithSensitive: db.raw("'ko'") } }).toSql(),
480
480
  `
481
481
  SELECT * FROM "user"
482
- WHERE "user"."name" ILIKE '%' || 'ko'
482
+ WHERE "user"."name" LIKE '%' || 'ko'
483
483
  `,
484
484
  );
485
485
  });
@@ -77,31 +77,31 @@ const all = {
77
77
  contains: <T>() =>
78
78
  createOperator<T | Query | RawExpression>(
79
79
  (key, value, values) =>
80
- `${key} LIKE '%' || ${quoteValue(value, values)} || '%'`,
80
+ `${key} ILIKE '%' || ${quoteValue(value, values)} || '%'`,
81
81
  ),
82
- containsInsensitive: <T>() =>
82
+ containsSensitive: <T>() =>
83
83
  createOperator<T | Query | RawExpression>(
84
84
  (key, value, values) =>
85
- `${key} ILIKE '%' || ${quoteValue(value, values)} || '%'`,
85
+ `${key} LIKE '%' || ${quoteValue(value, values)} || '%'`,
86
86
  ),
87
87
  startsWith: <T>() =>
88
- createOperator<T | Query | RawExpression>(
89
- (key, value, values) => `${key} LIKE ${quoteValue(value, values)} || '%'`,
90
- ),
91
- startsWithInsensitive: <T>() =>
92
88
  createOperator<T | Query | RawExpression>(
93
89
  (key, value, values) =>
94
90
  `${key} ILIKE ${quoteValue(value, values)} || '%'`,
95
91
  ),
96
- endsWith: <T>() =>
92
+ startsWithSensitive: <T>() =>
97
93
  createOperator<T | Query | RawExpression>(
98
- (key, value, values) => `${key} LIKE '%' || ${quoteValue(value, values)}`,
94
+ (key, value, values) => `${key} LIKE ${quoteValue(value, values)} || '%'`,
99
95
  ),
100
- endsWithInsensitive: <T>() =>
96
+ endsWith: <T>() =>
101
97
  createOperator<T | Query | RawExpression>(
102
98
  (key, value, values) =>
103
99
  `${key} ILIKE '%' || ${quoteValue(value, values)}`,
104
100
  ),
101
+ endsWithSensitive: <T>() =>
102
+ createOperator<T | Query | RawExpression>(
103
+ (key, value, values) => `${key} LIKE '%' || ${quoteValue(value, values)}`,
104
+ ),
105
105
  between: <T>() =>
106
106
  createOperator<[T | Query | RawExpression, T | Query | RawExpression]>(
107
107
  (key, [from, to], values) =>
@@ -148,11 +148,11 @@ const numeric = <T>() => ({
148
148
  const text = <T>() => ({
149
149
  ...base<T>(),
150
150
  contains: all.contains<T>(),
151
- containsInsensitive: all.containsInsensitive<T>(),
151
+ containsSensitive: all.containsSensitive<T>(),
152
152
  startsWith: all.startsWith<T>(),
153
- startsWithInsensitive: all.startsWithInsensitive<T>(),
153
+ startsWithSensitive: all.startsWithSensitive<T>(),
154
154
  endsWith: all.endsWith<T>(),
155
- endsWithInsensitive: all.endsWithInsensitive<T>(),
155
+ endsWithSensitive: all.endsWithSensitive<T>(),
156
156
  });
157
157
 
158
158
  const json = <T>() => ({
@@ -12,13 +12,13 @@ import { DeleteQueryData } from '../sql';
12
12
  describe('delete', () => {
13
13
  useTestDatabase();
14
14
 
15
- it('should throw when updating without where condition', () => {
15
+ it('should prevent deleting all with TS error', () => {
16
16
  // @ts-expect-error update should have where condition or forceAll flag
17
- expect(() => User.delete()).toThrow();
17
+ User.delete();
18
18
  });
19
19
 
20
- it('should run without where condition when forceAll flag provided', async () => {
21
- await expect(User.delete(true)).resolves.not.toThrow();
20
+ it('should allow deleting all with empty where', () => {
21
+ User.where().delete();
22
22
  });
23
23
 
24
24
  it('should be aliased as `del`', () => {
@@ -2,29 +2,17 @@ import { Query, SetQueryReturnsRowCount } from '../query';
2
2
 
3
3
  export type DeleteMethodsNames = 'del' | '_del' | 'delete' | '_delete';
4
4
 
5
- type DeleteArgs<T extends Query> = T['hasWhere'] extends true
6
- ? [forceAll?: boolean]
7
- : [true];
5
+ type DeleteArgs<T extends Query> = T['hasWhere'] extends true ? [] : [never];
8
6
 
9
7
  type DeleteResult<T extends Query> = T['hasSelect'] extends true
10
8
  ? T
11
9
  : SetQueryReturnsRowCount<T>;
12
10
 
13
- const del = <T extends Query>(
14
- self: T,
15
- ...args: DeleteArgs<T>
16
- ): DeleteResult<T> => {
17
- return self.clone()._del(...args) as unknown as DeleteResult<T>;
11
+ const del = <T extends Query>(self: T): DeleteResult<T> => {
12
+ return _del(self.clone()) as unknown as DeleteResult<T>;
18
13
  };
19
14
 
20
- const _del = <T extends Query>(
21
- q: T,
22
- ...args: DeleteArgs<T>
23
- ): DeleteResult<T> => {
24
- if (!q.query.and?.length && !q.query.or?.length && !args[0]) {
25
- throw new Error('No where conditions or forceAll flag provided to delete');
26
- }
27
-
15
+ const _del = <T extends Query>(q: T): DeleteResult<T> => {
28
16
  if (!q.query.select) {
29
17
  q.query.returnType = 'rowCount';
30
18
  }
@@ -34,19 +22,23 @@ const _del = <T extends Query>(
34
22
  };
35
23
 
36
24
  export class Delete {
37
- del<T extends Query>(this: T, ...args: DeleteArgs<T>): DeleteResult<T> {
38
- return del(this, ...args);
25
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
26
+ del<T extends Query>(this: T, ..._args: DeleteArgs<T>): DeleteResult<T> {
27
+ return del(this);
39
28
  }
40
29
 
41
- _del<T extends Query>(this: T, ...args: DeleteArgs<T>): DeleteResult<T> {
42
- return _del(this, ...args);
30
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
31
+ _del<T extends Query>(this: T, ..._args: DeleteArgs<T>): DeleteResult<T> {
32
+ return _del(this);
43
33
  }
44
34
 
45
- delete<T extends Query>(this: T, ...args: DeleteArgs<T>): DeleteResult<T> {
46
- return del(this, ...args);
35
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
36
+ delete<T extends Query>(this: T, ..._args: DeleteArgs<T>): DeleteResult<T> {
37
+ return del(this);
47
38
  }
48
39
 
49
- _delete<T extends Query>(this: T, ...args: DeleteArgs<T>): DeleteResult<T> {
50
- return _del(this, ...args);
40
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
41
+ _delete<T extends Query>(this: T, ..._args: DeleteArgs<T>): DeleteResult<T> {
42
+ return _del(this);
51
43
  }
52
44
  }
@@ -23,15 +23,13 @@ describe('update', () => {
23
23
  expectQueryNotMutated(q);
24
24
  });
25
25
 
26
- it('should throw when updating without where condition', () => {
26
+ it('should prevent from updating without conditions with TS error', () => {
27
27
  // @ts-expect-error update should have where condition or forceAll flag
28
- expect(() => User.update({ name: 'new name' })).toThrow();
28
+ User.update({ name: 'new name' });
29
29
  });
30
30
 
31
- it('should run without where condition when forceAll flag provided', async () => {
32
- await expect(
33
- User.update({ name: 'new name' }, true),
34
- ).resolves.not.toThrow();
31
+ it('should let update all with empty where', () => {
32
+ User.where().update({ name: 'new name' });
35
33
  });
36
34
 
37
35
  it('should update record with raw sql, returning updated rows count', async () => {
@@ -98,17 +98,13 @@ type UpdateHasAndBelongsToManyData<Rel extends HasAndBelongsToManyRelation> = {
98
98
  create?: CreateData<Rel['nestedCreateQuery']>[];
99
99
  };
100
100
 
101
- type UpdateArgs<T extends Query, ForceAll extends boolean> = (
102
- T['hasWhere'] extends true ? true : ForceAll
103
- ) extends true
104
- ? [update: UpdateData<T>]
105
- : [update: UpdateData<T>, forceAll: true];
106
-
107
- type UpdateRawArgs<T extends Query, ForceAll extends boolean> = (
108
- T['hasWhere'] extends true ? true : ForceAll
109
- ) extends true
110
- ? [update: RawExpression]
111
- : [update: RawExpression, forceAll: true];
101
+ type UpdateArg<T extends Query> = T['hasWhere'] extends true
102
+ ? UpdateData<T>
103
+ : never;
104
+
105
+ type UpdateRawArg<T extends Query> = T['hasWhere'] extends true
106
+ ? RawExpression
107
+ : never;
112
108
 
113
109
  type UpdateResult<T extends Query> = T['hasSelect'] extends true
114
110
  ? T
@@ -143,14 +139,10 @@ const checkIfUpdateIsEmpty = (q: UpdateQueryData) => {
143
139
  return !q.updateData?.some((item) => isRaw(item) || Object.keys(item).length);
144
140
  };
145
141
 
146
- const update = <T extends Query>(q: T, forceAll: boolean): UpdateResult<T> => {
142
+ const update = <T extends Query>(q: T): UpdateResult<T> => {
147
143
  const { query } = q;
148
144
  query.type = 'update';
149
145
 
150
- if (!query.and?.length && !query.or?.length && !forceAll) {
151
- throw new Error('No where conditions or forceAll flag provided to update');
152
- }
153
-
154
146
  if (!query.select) {
155
147
  query.returnType = 'rowCount';
156
148
  }
@@ -159,22 +151,14 @@ const update = <T extends Query>(q: T, forceAll: boolean): UpdateResult<T> => {
159
151
  };
160
152
 
161
153
  export class Update {
162
- update<T extends Query, ForceAll extends boolean = false>(
163
- this: T,
164
- ...args: UpdateArgs<T, ForceAll>
165
- ): UpdateResult<T> {
154
+ update<T extends Query>(this: T, arg: UpdateArg<T>): UpdateResult<T> {
166
155
  const q = this.clone() as T;
167
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
168
- return q._update(...(args as any));
156
+ return q._update(arg);
169
157
  }
170
- _update<T extends Query, ForceAll extends boolean = false>(
171
- this: T,
172
- ...args: UpdateArgs<T, ForceAll>
173
- ): UpdateResult<T> {
158
+ _update<T extends Query>(this: T, arg: UpdateArg<T>): UpdateResult<T> {
174
159
  const { query } = this;
175
- const data = args[0];
176
160
 
177
- const set: Record<string, unknown> = { ...data };
161
+ const set: Record<string, unknown> = { ...arg };
178
162
  pushQueryValue(this, 'updateData', set);
179
163
 
180
164
  const { relations, shape } = this as {
@@ -187,13 +171,13 @@ export class Update {
187
171
 
188
172
  const originalReturnType = query.returnType || 'all';
189
173
 
190
- for (const key in data) {
174
+ for (const key in arg) {
191
175
  if (relations[key]) {
192
176
  delete set[key];
193
177
  if (relations[key].type === 'belongsTo') {
194
- prependRelations[key] = data[key] as Record<string, unknown>;
178
+ prependRelations[key] = arg[key] as Record<string, unknown>;
195
179
  } else {
196
- const value = data[key] as NestedUpdateItem;
180
+ const value = arg[key] as NestedUpdateItem;
197
181
 
198
182
  if (
199
183
  !value.set &&
@@ -217,7 +201,7 @@ export class Update {
217
201
  this._select(primaryKey as StringKey<keyof T['selectable']>);
218
202
  }
219
203
  }
220
- appendRelations[key] = data[key] as Record<string, unknown>;
204
+ appendRelations[key] = arg[key] as Record<string, unknown>;
221
205
  }
222
206
  } else if (!shape[key] && shape !== anyShape) {
223
207
  delete set[key];
@@ -335,41 +319,26 @@ export class Update {
335
319
  query.wrapInTransaction = true;
336
320
  }
337
321
 
338
- return update(this, (args as [unknown, boolean])[1]);
322
+ return update(this);
339
323
  }
340
324
 
341
- updateRaw<T extends Query, ForceAll extends boolean = false>(
342
- this: T,
343
- ...args: UpdateRawArgs<T, ForceAll>
344
- ): UpdateResult<T> {
325
+ updateRaw<T extends Query>(this: T, arg: UpdateRawArg<T>): UpdateResult<T> {
345
326
  const q = this.clone() as T;
346
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
347
- return q._updateRaw(...(args as any));
327
+ return q._updateRaw(arg);
348
328
  }
349
- _updateRaw<T extends Query, ForceAll extends boolean = false>(
350
- this: T,
351
- ...args: UpdateRawArgs<T, ForceAll>
352
- ): UpdateResult<T> {
353
- pushQueryValue(this, 'updateData', args[0]);
354
- return update(this, (args as [unknown, boolean])[1]);
329
+ _updateRaw<T extends Query>(this: T, arg: UpdateRawArg<T>): UpdateResult<T> {
330
+ pushQueryValue(this, 'updateData', arg);
331
+ return update(this);
355
332
  }
356
333
 
357
- updateOrThrow<T extends Query, ForceAll extends boolean = false>(
358
- this: T,
359
- ...args: UpdateArgs<T, ForceAll>
360
- ): UpdateResult<T> {
334
+ updateOrThrow<T extends Query>(this: T, arg: UpdateArg<T>): UpdateResult<T> {
361
335
  const q = this.clone() as T;
362
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
363
- return q._updateOrThrow(...(args as any));
336
+ return q._updateOrThrow(arg);
364
337
  }
365
338
 
366
- _updateOrThrow<T extends Query, ForceAll extends boolean = false>(
367
- this: T,
368
- ...args: UpdateArgs<T, ForceAll>
369
- ): UpdateResult<T> {
339
+ _updateOrThrow<T extends Query>(this: T, arg: UpdateArg<T>): UpdateResult<T> {
370
340
  this.query.throwOnNotFound = true;
371
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
372
- return this._update(...(args as any)) as unknown as UpdateResult<T>;
341
+ return this._update(arg);
373
342
  }
374
343
 
375
344
  increment<T extends Query>(