core-services-sdk 1.3.62 → 1.3.64
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/.claude/settings.local.json +22 -0
- package/package.json +1 -1
- package/src/core/normalize-phone-number.js +144 -25
- package/src/postgresql/apply-filter.js +141 -15
- package/tests/core/normalize-phone-number.unit.test.js +45 -0
- package/tests/postgresql/apply-filter-snake-case.integration.test.js +549 -0
- package/tests/postgresql/apply-filter.integration.test.js +56 -325
- package/tests/postgresql/paginate.integration.test.js +2 -2
- package/tests/postgresql/validate-schema.integration.test.js +2 -2
- package/types/core/normalize-phone-number.d.ts +97 -27
- package/types/postgresql/apply-filter.d.ts +231 -0
- package/types/postgresql/index.d.ts +1 -0
|
@@ -1,17 +1,19 @@
|
|
|
1
|
+
// apply-filter.integration.test.js
|
|
1
2
|
// @ts-nocheck
|
|
3
|
+
|
|
2
4
|
import { describe, it, beforeAll, afterAll, beforeEach, expect } from 'vitest'
|
|
3
5
|
import knex from 'knex'
|
|
4
6
|
|
|
5
7
|
import {
|
|
6
|
-
stopPostgres,
|
|
7
8
|
startPostgres,
|
|
9
|
+
stopPostgres,
|
|
8
10
|
buildPostgresUri,
|
|
9
11
|
} from '../../src/postgresql/start-stop-postgres-docker.js'
|
|
10
12
|
|
|
11
13
|
import { applyFilter } from '../../src/postgresql/apply-filter.js'
|
|
12
14
|
|
|
13
15
|
const PG_OPTIONS = {
|
|
14
|
-
port:
|
|
16
|
+
port: 5443,
|
|
15
17
|
containerName: 'postgres-apply-filter-test',
|
|
16
18
|
user: 'testuser',
|
|
17
19
|
pass: 'testpass',
|
|
@@ -69,7 +71,7 @@ beforeEach(async () => {
|
|
|
69
71
|
name: 'Asset One',
|
|
70
72
|
status: 'active',
|
|
71
73
|
type: 'invoice',
|
|
72
|
-
price: 100
|
|
74
|
+
price: 100,
|
|
73
75
|
created_at: new Date('2024-01-01'),
|
|
74
76
|
deleted_at: null,
|
|
75
77
|
},
|
|
@@ -78,7 +80,7 @@ beforeEach(async () => {
|
|
|
78
80
|
name: 'Asset Two',
|
|
79
81
|
status: 'active',
|
|
80
82
|
type: 'receipt',
|
|
81
|
-
price: 200
|
|
83
|
+
price: 200,
|
|
82
84
|
created_at: new Date('2024-01-02'),
|
|
83
85
|
deleted_at: null,
|
|
84
86
|
},
|
|
@@ -87,7 +89,7 @@ beforeEach(async () => {
|
|
|
87
89
|
name: 'Asset Three',
|
|
88
90
|
status: 'pending',
|
|
89
91
|
type: 'invoice',
|
|
90
|
-
price: 150
|
|
92
|
+
price: 150,
|
|
91
93
|
created_at: new Date('2024-01-03'),
|
|
92
94
|
deleted_at: null,
|
|
93
95
|
},
|
|
@@ -96,7 +98,7 @@ beforeEach(async () => {
|
|
|
96
98
|
name: 'Deleted Asset',
|
|
97
99
|
status: 'deleted',
|
|
98
100
|
type: 'receipt',
|
|
99
|
-
price: 50
|
|
101
|
+
price: 50,
|
|
100
102
|
created_at: new Date('2024-01-04'),
|
|
101
103
|
deleted_at: new Date('2024-01-05'),
|
|
102
104
|
},
|
|
@@ -105,7 +107,7 @@ beforeEach(async () => {
|
|
|
105
107
|
name: 'Expensive Asset',
|
|
106
108
|
status: 'active',
|
|
107
109
|
type: 'invoice',
|
|
108
|
-
price: 500
|
|
110
|
+
price: 500,
|
|
109
111
|
created_at: new Date('2024-01-05'),
|
|
110
112
|
deleted_at: null,
|
|
111
113
|
},
|
|
@@ -115,7 +117,7 @@ beforeEach(async () => {
|
|
|
115
117
|
{
|
|
116
118
|
id: '00000000-0000-0000-0000-000000000101',
|
|
117
119
|
invoice_number: 'INV-001',
|
|
118
|
-
amount: 1000
|
|
120
|
+
amount: 1000,
|
|
119
121
|
status: 'paid',
|
|
120
122
|
customer_id: '00000000-0000-0000-0000-000000000201',
|
|
121
123
|
created_at: new Date('2024-01-01'),
|
|
@@ -125,7 +127,7 @@ beforeEach(async () => {
|
|
|
125
127
|
{
|
|
126
128
|
id: '00000000-0000-0000-0000-000000000102',
|
|
127
129
|
invoice_number: 'INV-002',
|
|
128
|
-
amount: 2500
|
|
130
|
+
amount: 2500,
|
|
129
131
|
status: 'pending',
|
|
130
132
|
customer_id: '00000000-0000-0000-0000-000000000202',
|
|
131
133
|
created_at: new Date('2024-01-02'),
|
|
@@ -135,7 +137,7 @@ beforeEach(async () => {
|
|
|
135
137
|
{
|
|
136
138
|
id: '00000000-0000-0000-0000-000000000103',
|
|
137
139
|
invoice_number: 'INV-003',
|
|
138
|
-
amount: 500
|
|
140
|
+
amount: 500,
|
|
139
141
|
status: 'paid',
|
|
140
142
|
customer_id: '00000000-0000-0000-0000-000000000201',
|
|
141
143
|
created_at: new Date('2024-01-03'),
|
|
@@ -145,7 +147,7 @@ beforeEach(async () => {
|
|
|
145
147
|
{
|
|
146
148
|
id: '00000000-0000-0000-0000-000000000104',
|
|
147
149
|
invoice_number: 'INV-004',
|
|
148
|
-
amount: 3000
|
|
150
|
+
amount: 3000,
|
|
149
151
|
status: 'overdue',
|
|
150
152
|
customer_id: '00000000-0000-0000-0000-000000000203',
|
|
151
153
|
created_at: new Date('2024-01-04'),
|
|
@@ -155,7 +157,7 @@ beforeEach(async () => {
|
|
|
155
157
|
{
|
|
156
158
|
id: '00000000-0000-0000-0000-000000000105',
|
|
157
159
|
invoice_number: 'INV-005',
|
|
158
|
-
amount: 750
|
|
160
|
+
amount: 750,
|
|
159
161
|
status: 'cancelled',
|
|
160
162
|
customer_id: '00000000-0000-0000-0000-000000000201',
|
|
161
163
|
created_at: new Date('2024-01-05'),
|
|
@@ -165,277 +167,70 @@ beforeEach(async () => {
|
|
|
165
167
|
])
|
|
166
168
|
})
|
|
167
169
|
|
|
168
|
-
describe('applyFilter integration', () => {
|
|
169
|
-
it('applies
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
query,
|
|
170
|
+
describe('applyFilter integration (snake_case only)', () => {
|
|
171
|
+
it('applies equality filter', async () => {
|
|
172
|
+
const results = await applyFilter({
|
|
173
|
+
query: db('assets').select('*'),
|
|
173
174
|
filter: { status: 'active' },
|
|
174
175
|
tableName: 'assets',
|
|
175
176
|
})
|
|
176
177
|
|
|
177
|
-
const results = await filteredQuery
|
|
178
|
-
|
|
179
178
|
expect(results).toHaveLength(3)
|
|
180
|
-
expect(results.every((r) => r.status === 'active')).toBe(true)
|
|
181
|
-
})
|
|
182
|
-
|
|
183
|
-
it('converts camelCase keys to snake_case', async () => {
|
|
184
|
-
const query = db('assets').select('*')
|
|
185
|
-
const filteredQuery = applyFilter({
|
|
186
|
-
query,
|
|
187
|
-
filter: { deletedAt: { isNull: true }, name: 'Asset One' },
|
|
188
|
-
tableName: 'assets',
|
|
189
|
-
})
|
|
190
|
-
|
|
191
|
-
const results = await filteredQuery
|
|
192
|
-
|
|
193
|
-
expect(results).toHaveLength(1)
|
|
194
|
-
expect(results[0].name).toBe('Asset One')
|
|
195
179
|
})
|
|
196
180
|
|
|
197
|
-
it('applies
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
query,
|
|
201
|
-
filter: { status: { ne: 'deleted' } },
|
|
202
|
-
tableName: 'assets',
|
|
203
|
-
})
|
|
204
|
-
|
|
205
|
-
const results = await filteredQuery
|
|
206
|
-
|
|
207
|
-
expect(results).toHaveLength(4)
|
|
208
|
-
expect(results.every((r) => r.status !== 'deleted')).toBe(true)
|
|
209
|
-
})
|
|
210
|
-
|
|
211
|
-
it('applies not equal filter (neq alias)', async () => {
|
|
212
|
-
const query = db('assets').select('*')
|
|
213
|
-
const filteredQuery = applyFilter({
|
|
214
|
-
query,
|
|
215
|
-
filter: { status: { neq: 'deleted' } },
|
|
216
|
-
tableName: 'assets',
|
|
217
|
-
})
|
|
218
|
-
|
|
219
|
-
const results = await filteredQuery
|
|
220
|
-
|
|
221
|
-
expect(results).toHaveLength(4)
|
|
222
|
-
expect(results.every((r) => r.status !== 'deleted')).toBe(true)
|
|
223
|
-
})
|
|
224
|
-
|
|
225
|
-
it('applies IN filter with array directly', async () => {
|
|
226
|
-
const query = db('assets').select('*')
|
|
227
|
-
const filteredQuery = applyFilter({
|
|
228
|
-
query,
|
|
181
|
+
it('applies IN filter', async () => {
|
|
182
|
+
const results = await applyFilter({
|
|
183
|
+
query: db('assets').select('*'),
|
|
229
184
|
filter: { status: ['active', 'pending'] },
|
|
230
185
|
tableName: 'assets',
|
|
231
186
|
})
|
|
232
187
|
|
|
233
|
-
const results = await filteredQuery
|
|
234
|
-
|
|
235
188
|
expect(results).toHaveLength(4)
|
|
236
|
-
expect(
|
|
237
|
-
results.every((r) => r.status === 'active' || r.status === 'pending'),
|
|
238
|
-
).toBe(true)
|
|
239
189
|
})
|
|
240
190
|
|
|
241
|
-
it('applies IN filter
|
|
242
|
-
const
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
filter: { status: { in: ['active', 'pending'] } },
|
|
191
|
+
it('applies NOT IN filter', async () => {
|
|
192
|
+
const results = await applyFilter({
|
|
193
|
+
query: db('assets').select('*'),
|
|
194
|
+
filter: { status: { nin: ['deleted'] } },
|
|
246
195
|
tableName: 'assets',
|
|
247
196
|
})
|
|
248
197
|
|
|
249
|
-
const results = await filteredQuery
|
|
250
|
-
|
|
251
198
|
expect(results).toHaveLength(4)
|
|
252
|
-
expect(
|
|
253
|
-
results.every((r) => r.status === 'active' || r.status === 'pending'),
|
|
254
|
-
).toBe(true)
|
|
255
199
|
})
|
|
256
200
|
|
|
257
|
-
it('applies
|
|
258
|
-
const
|
|
259
|
-
|
|
260
|
-
query,
|
|
261
|
-
filter: { status: { nin: ['deleted', 'archived'] } },
|
|
262
|
-
tableName: 'assets',
|
|
263
|
-
})
|
|
264
|
-
|
|
265
|
-
const results = await filteredQuery
|
|
266
|
-
|
|
267
|
-
expect(results).toHaveLength(4)
|
|
268
|
-
expect(
|
|
269
|
-
results.every((r) => r.status !== 'deleted' && r.status !== 'archived'),
|
|
270
|
-
).toBe(true)
|
|
271
|
-
})
|
|
272
|
-
|
|
273
|
-
it('applies greater than filter (gt)', async () => {
|
|
274
|
-
const query = db('assets').select('*')
|
|
275
|
-
const filteredQuery = applyFilter({
|
|
276
|
-
query,
|
|
277
|
-
filter: { price: { gt: 150 } },
|
|
278
|
-
tableName: 'assets',
|
|
279
|
-
})
|
|
280
|
-
|
|
281
|
-
const results = await filteredQuery
|
|
282
|
-
|
|
283
|
-
expect(results).toHaveLength(2)
|
|
284
|
-
expect(results.every((r) => parseFloat(r.price) > 150)).toBe(true)
|
|
285
|
-
})
|
|
286
|
-
|
|
287
|
-
it('applies greater than or equal filter (gte)', async () => {
|
|
288
|
-
const query = db('assets').select('*')
|
|
289
|
-
const filteredQuery = applyFilter({
|
|
290
|
-
query,
|
|
291
|
-
filter: { price: { gte: 150 } },
|
|
292
|
-
tableName: 'assets',
|
|
293
|
-
})
|
|
294
|
-
|
|
295
|
-
const results = await filteredQuery
|
|
296
|
-
|
|
297
|
-
expect(results).toHaveLength(3)
|
|
298
|
-
expect(results.every((r) => parseFloat(r.price) >= 150)).toBe(true)
|
|
299
|
-
})
|
|
300
|
-
|
|
301
|
-
it('applies less than filter (lt)', async () => {
|
|
302
|
-
const query = db('assets').select('*')
|
|
303
|
-
const filteredQuery = applyFilter({
|
|
304
|
-
query,
|
|
305
|
-
filter: { price: { lt: 150 } },
|
|
306
|
-
tableName: 'assets',
|
|
307
|
-
})
|
|
308
|
-
|
|
309
|
-
const results = await filteredQuery
|
|
310
|
-
|
|
311
|
-
expect(results).toHaveLength(2)
|
|
312
|
-
expect(results.every((r) => parseFloat(r.price) < 150)).toBe(true)
|
|
313
|
-
})
|
|
314
|
-
|
|
315
|
-
it('applies less than or equal filter (lte)', async () => {
|
|
316
|
-
const query = db('assets').select('*')
|
|
317
|
-
const filteredQuery = applyFilter({
|
|
318
|
-
query,
|
|
319
|
-
filter: { price: { lte: 150 } },
|
|
320
|
-
tableName: 'assets',
|
|
321
|
-
})
|
|
322
|
-
|
|
323
|
-
const results = await filteredQuery
|
|
324
|
-
|
|
325
|
-
expect(results).toHaveLength(3)
|
|
326
|
-
expect(results.every((r) => parseFloat(r.price) <= 150)).toBe(true)
|
|
327
|
-
})
|
|
328
|
-
|
|
329
|
-
it('applies range filter with gte and lte', async () => {
|
|
330
|
-
const query = db('assets').select('*')
|
|
331
|
-
const filteredQuery = applyFilter({
|
|
332
|
-
query,
|
|
201
|
+
it('applies numeric range filter', async () => {
|
|
202
|
+
const results = await applyFilter({
|
|
203
|
+
query: db('assets').select('*'),
|
|
333
204
|
filter: { price: { gte: 100, lte: 200 } },
|
|
334
205
|
tableName: 'assets',
|
|
335
206
|
})
|
|
336
207
|
|
|
337
|
-
const results = await filteredQuery
|
|
338
|
-
|
|
339
208
|
expect(results).toHaveLength(3)
|
|
340
|
-
expect(
|
|
341
|
-
results.every(
|
|
342
|
-
(r) => parseFloat(r.price) >= 100 && parseFloat(r.price) <= 200,
|
|
343
|
-
),
|
|
344
|
-
).toBe(true)
|
|
345
|
-
})
|
|
346
|
-
|
|
347
|
-
it('applies case-sensitive LIKE filter', async () => {
|
|
348
|
-
const query = db('assets').select('*')
|
|
349
|
-
const filteredQuery = applyFilter({
|
|
350
|
-
query,
|
|
351
|
-
filter: { name: { like: '%Asset%' } },
|
|
352
|
-
tableName: 'assets',
|
|
353
|
-
})
|
|
354
|
-
|
|
355
|
-
const results = await filteredQuery
|
|
356
|
-
|
|
357
|
-
expect(results.length).toBeGreaterThan(0)
|
|
358
|
-
expect(results.every((r) => r.name.includes('Asset'))).toBe(true)
|
|
359
209
|
})
|
|
360
210
|
|
|
361
|
-
it('applies
|
|
362
|
-
const
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
filter: { name: { ilike: '%asset%' } },
|
|
211
|
+
it('applies isNull filter', async () => {
|
|
212
|
+
const results = await applyFilter({
|
|
213
|
+
query: db('assets').select('*'),
|
|
214
|
+
filter: { deleted_at: { isNull: true } },
|
|
366
215
|
tableName: 'assets',
|
|
367
216
|
})
|
|
368
217
|
|
|
369
|
-
const results = await filteredQuery
|
|
370
|
-
|
|
371
|
-
expect(results.length).toBeGreaterThan(0)
|
|
372
|
-
expect(
|
|
373
|
-
results.every((r) =>
|
|
374
|
-
r.name.toLowerCase().includes('asset'.toLowerCase()),
|
|
375
|
-
),
|
|
376
|
-
).toBe(true)
|
|
377
|
-
})
|
|
378
|
-
|
|
379
|
-
it('applies isNull filter when value is true', async () => {
|
|
380
|
-
const query = db('assets').select('*')
|
|
381
|
-
const filteredQuery = applyFilter({
|
|
382
|
-
query,
|
|
383
|
-
filter: { deletedAt: { isNull: true } },
|
|
384
|
-
tableName: 'assets',
|
|
385
|
-
})
|
|
386
|
-
|
|
387
|
-
const results = await filteredQuery
|
|
388
|
-
|
|
389
218
|
expect(results).toHaveLength(4)
|
|
390
|
-
expect(results.every((r) => r.deleted_at === null)).toBe(true)
|
|
391
219
|
})
|
|
392
220
|
|
|
393
|
-
it('applies isNotNull filter
|
|
394
|
-
const
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
filter: { deletedAt: { isNull: false } },
|
|
221
|
+
it('applies isNotNull filter', async () => {
|
|
222
|
+
const results = await applyFilter({
|
|
223
|
+
query: db('assets').select('*'),
|
|
224
|
+
filter: { deleted_at: { isNotNull: true } },
|
|
398
225
|
tableName: 'assets',
|
|
399
226
|
})
|
|
400
227
|
|
|
401
|
-
const results = await filteredQuery
|
|
402
|
-
|
|
403
|
-
expect(results).toHaveLength(1)
|
|
404
|
-
expect(results[0].deleted_at).not.toBe(null)
|
|
405
|
-
})
|
|
406
|
-
|
|
407
|
-
it('applies isNotNull filter when value is true', async () => {
|
|
408
|
-
const query = db('assets').select('*')
|
|
409
|
-
const filteredQuery = applyFilter({
|
|
410
|
-
query,
|
|
411
|
-
filter: { deletedAt: { isNotNull: true } },
|
|
412
|
-
tableName: 'assets',
|
|
413
|
-
})
|
|
414
|
-
|
|
415
|
-
const results = await filteredQuery
|
|
416
|
-
|
|
417
228
|
expect(results).toHaveLength(1)
|
|
418
|
-
expect(results[0].deleted_at).not.toBe(null)
|
|
419
|
-
})
|
|
420
|
-
|
|
421
|
-
it('applies isNull filter when isNotNull value is false', async () => {
|
|
422
|
-
const query = db('assets').select('*')
|
|
423
|
-
const filteredQuery = applyFilter({
|
|
424
|
-
query,
|
|
425
|
-
filter: { deletedAt: { isNotNull: false } },
|
|
426
|
-
tableName: 'assets',
|
|
427
|
-
})
|
|
428
|
-
|
|
429
|
-
const results = await filteredQuery
|
|
430
|
-
|
|
431
|
-
expect(results).toHaveLength(4)
|
|
432
|
-
expect(results.every((r) => r.deleted_at === null)).toBe(true)
|
|
433
229
|
})
|
|
434
230
|
|
|
435
231
|
it('applies multiple filters together', async () => {
|
|
436
|
-
const
|
|
437
|
-
|
|
438
|
-
query,
|
|
232
|
+
const results = await applyFilter({
|
|
233
|
+
query: db('assets').select('*'),
|
|
439
234
|
filter: {
|
|
440
235
|
status: 'active',
|
|
441
236
|
type: 'invoice',
|
|
@@ -444,106 +239,42 @@ describe('applyFilter integration', () => {
|
|
|
444
239
|
tableName: 'assets',
|
|
445
240
|
})
|
|
446
241
|
|
|
447
|
-
const results = await filteredQuery
|
|
448
|
-
|
|
449
242
|
expect(results).toHaveLength(2)
|
|
450
|
-
expect(results.every((r) => r.status === 'active')).toBe(true)
|
|
451
|
-
expect(results.every((r) => r.type === 'invoice')).toBe(true)
|
|
452
|
-
expect(results.every((r) => parseFloat(r.price) >= 100)).toBe(true)
|
|
453
|
-
})
|
|
454
|
-
|
|
455
|
-
it('returns empty results when filter matches nothing', async () => {
|
|
456
|
-
const query = db('assets').select('*')
|
|
457
|
-
const filteredQuery = applyFilter({
|
|
458
|
-
query,
|
|
459
|
-
filter: { status: 'non-existing' },
|
|
460
|
-
tableName: 'assets',
|
|
461
|
-
})
|
|
462
|
-
|
|
463
|
-
const results = await filteredQuery
|
|
464
|
-
|
|
465
|
-
expect(results).toHaveLength(0)
|
|
466
|
-
})
|
|
467
|
-
|
|
468
|
-
it('uses qualified column names with tableName', async () => {
|
|
469
|
-
const query = db('assets').select('assets.*')
|
|
470
|
-
const filteredQuery = applyFilter({
|
|
471
|
-
query,
|
|
472
|
-
filter: { status: 'active' },
|
|
473
|
-
tableName: 'assets',
|
|
474
|
-
})
|
|
475
|
-
|
|
476
|
-
const results = await filteredQuery
|
|
477
|
-
|
|
478
|
-
expect(results).toHaveLength(3)
|
|
479
|
-
expect(results.every((r) => r.status === 'active')).toBe(true)
|
|
480
|
-
})
|
|
481
|
-
|
|
482
|
-
it('ignores unknown operators', async () => {
|
|
483
|
-
const query = db('assets').select('*')
|
|
484
|
-
const filteredQuery = applyFilter({
|
|
485
|
-
query,
|
|
486
|
-
filter: { status: { unknownOperator: 'value' } },
|
|
487
|
-
tableName: 'assets',
|
|
488
|
-
})
|
|
489
|
-
|
|
490
|
-
const results = await filteredQuery
|
|
491
|
-
|
|
492
|
-
// Should return all records since unknown operator is ignored
|
|
493
|
-
expect(results).toHaveLength(5)
|
|
494
243
|
})
|
|
495
244
|
|
|
496
245
|
it('works with invoices table', async () => {
|
|
497
|
-
const
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
246
|
+
const results = await applyFilter({
|
|
247
|
+
query: db('invoices').select('*'),
|
|
248
|
+
filter: {
|
|
249
|
+
status: 'paid',
|
|
250
|
+
deleted_at: { isNull: true },
|
|
251
|
+
},
|
|
501
252
|
tableName: 'invoices',
|
|
502
253
|
})
|
|
503
254
|
|
|
504
|
-
const results = await filteredQuery
|
|
505
|
-
|
|
506
255
|
expect(results).toHaveLength(2)
|
|
507
|
-
expect(results.every((r) => r.status === 'paid')).toBe(true)
|
|
508
|
-
expect(results.every((r) => r.deleted_at === null)).toBe(true)
|
|
509
256
|
})
|
|
510
257
|
|
|
511
|
-
it('works with invoices
|
|
512
|
-
const
|
|
513
|
-
|
|
514
|
-
query,
|
|
258
|
+
it('works with invoices using snake_case foreign key', async () => {
|
|
259
|
+
const results = await applyFilter({
|
|
260
|
+
query: db('invoices').select('*'),
|
|
515
261
|
filter: {
|
|
516
|
-
|
|
262
|
+
customer_id: '00000000-0000-0000-0000-000000000201',
|
|
517
263
|
amount: { gte: 500 },
|
|
518
264
|
},
|
|
519
265
|
tableName: 'invoices',
|
|
520
266
|
})
|
|
521
267
|
|
|
522
|
-
const results = await filteredQuery
|
|
523
|
-
|
|
524
268
|
expect(results).toHaveLength(3)
|
|
525
|
-
expect(
|
|
526
|
-
results.every(
|
|
527
|
-
(r) =>
|
|
528
|
-
r.customer_id === '00000000-0000-0000-0000-000000000201' &&
|
|
529
|
-
parseFloat(r.amount) >= 500,
|
|
530
|
-
),
|
|
531
|
-
).toBe(true)
|
|
532
269
|
})
|
|
533
270
|
|
|
534
|
-
it('
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
const results = await filteredQuery
|
|
543
|
-
|
|
544
|
-
expect(results).toHaveLength(3)
|
|
545
|
-
expect(
|
|
546
|
-
results.every((r) => r.status === 'paid' || r.status === 'pending'),
|
|
547
|
-
).toBe(true)
|
|
271
|
+
it('throws when using camelCase keys (no automatic conversion)', async () => {
|
|
272
|
+
await expect(
|
|
273
|
+
applyFilter({
|
|
274
|
+
query: db('assets').select('*'),
|
|
275
|
+
filter: { deletedAt: { isNull: true } },
|
|
276
|
+
tableName: 'assets',
|
|
277
|
+
}),
|
|
278
|
+
).rejects.toThrow(/column .*deletedAt.* does not exist/i)
|
|
548
279
|
})
|
|
549
280
|
})
|
|
@@ -11,8 +11,8 @@ import {
|
|
|
11
11
|
import { sqlPaginate } from '../../src/postgresql/paginate.js'
|
|
12
12
|
|
|
13
13
|
const PG_OPTIONS = {
|
|
14
|
-
port:
|
|
15
|
-
containerName: 'postgres-paginate-test',
|
|
14
|
+
port: 5442,
|
|
15
|
+
containerName: 'postgres-paginate-test-5442',
|
|
16
16
|
user: 'testuser',
|
|
17
17
|
pass: 'testpass',
|
|
18
18
|
db: 'testdb',
|
|
@@ -9,8 +9,8 @@ import { connectToPg } from '../../src/postgresql/connect-to-pg.js'
|
|
|
9
9
|
import { validateSchema } from '../../src/postgresql/validate-schema.js'
|
|
10
10
|
|
|
11
11
|
const PG_OPTIONS = {
|
|
12
|
-
port:
|
|
13
|
-
containerName: 'postgres-validate-schema-test',
|
|
12
|
+
port: 5431,
|
|
13
|
+
containerName: 'postgres-validate-schema-test-5431',
|
|
14
14
|
user: 'testuser',
|
|
15
15
|
pass: 'testpass',
|
|
16
16
|
db: 'testdb',
|