@balena/abstract-sql-compiler 10.2.5-build-tests-ts-c00e9270589111b882d4894fc437dd8b0343ecce-1 → 10.2.6-build-ts-tests-3f2373a4482584aa493652784bd2041a8b7b9314-1

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.
@@ -1,3 +1,87 @@
1
+ - commits:
2
+ - subject: "Tests: convert test/sbvr/reference-type to typescript"
3
+ hash: c41377f6f468c2c4006399e19117153837b503e6
4
+ body: ""
5
+ footer:
6
+ Change-type: patch
7
+ change-type: patch
8
+ author: Pagan Gazzard
9
+ nested: []
10
+ - subject: "Tests: convert test/sbvr/pilots to typescript"
11
+ hash: a275ef78d116e2768f95c402b1bcbcf79b1e0079
12
+ body: ""
13
+ footer:
14
+ Change-type: patch
15
+ change-type: patch
16
+ author: Pagan Gazzard
17
+ nested: []
18
+ - subject: "Tests: convert test/sbvr/test to typescript"
19
+ hash: 18ec8de28eb80b2d1d3ec46cc7550dbbe8b4b9e6
20
+ body: ""
21
+ footer:
22
+ Change-type: patch
23
+ change-type: patch
24
+ author: Pagan Gazzard
25
+ nested: []
26
+ - subject: "Tests: convert test/odata/expand to typescript"
27
+ hash: 031750d479e9c67293c489ccd93436d33aa668f9
28
+ body: ""
29
+ footer:
30
+ Change-type: patch
31
+ change-type: patch
32
+ author: Pagan Gazzard
33
+ nested: []
34
+ - subject: "Tests: convert test/odata/filterby to typescript"
35
+ hash: 206aaf4363007e81f5d54d4bf957835b184fcf94
36
+ body: ""
37
+ footer:
38
+ Change-type: patch
39
+ change-type: patch
40
+ author: Pagan Gazzard
41
+ nested: []
42
+ - subject: "Tests: convert test/odata/orderby to typescript"
43
+ hash: 1bd82f39836a28017436090307fb6d2646396d69
44
+ body: ""
45
+ footer:
46
+ Change-type: patch
47
+ change-type: patch
48
+ author: Pagan Gazzard
49
+ nested: []
50
+ - subject: "Tests: convert test/odata/paging to typescript"
51
+ hash: fec1912620feecf5c6ab596680cec2909bfdcb1b
52
+ body: ""
53
+ footer:
54
+ Change-type: patch
55
+ change-type: patch
56
+ author: Pagan Gazzard
57
+ nested: []
58
+ - subject: "Tests: convert test/odata/resource_parsing to typescript"
59
+ hash: 601c5256a8ac7acd00ae3f978365eab44782448e
60
+ body: ""
61
+ footer:
62
+ Change-type: patch
63
+ change-type: patch
64
+ author: Pagan Gazzard
65
+ nested: []
66
+ - subject: "Tests: convert test/odata/select to typescript"
67
+ hash: 75492ad8a054b7178cb2579c61cfa98a191d49b8
68
+ body: ""
69
+ footer:
70
+ Change-type: patch
71
+ change-type: patch
72
+ author: Pagan Gazzard
73
+ nested: []
74
+ - subject: "Tests: convert test/odata/stress to typescript"
75
+ hash: 35caa5820914c0ca082f7784ff4c54c5245cefcc
76
+ body: ""
77
+ footer:
78
+ Change-type: patch
79
+ change-type: patch
80
+ author: Pagan Gazzard
81
+ nested: []
82
+ version: 10.2.6
83
+ title: ""
84
+ date: 2025-04-07T11:05:19.400Z
1
85
  - commits:
2
86
  - subject: "Tests: convert test/odata/test to typescript"
3
87
  hash: c00e9270589111b882d4894fc437dd8b0343ecce
@@ -9,7 +93,7 @@
9
93
  nested: []
10
94
  version: 10.2.5
11
95
  title: ""
12
- date: 2025-04-06T22:37:16.638Z
96
+ date: 2025-04-06T22:40:57.152Z
13
97
  - commits:
14
98
  - subject: Update dev dependencies
15
99
  hash: 703263fa73aff2253d1a931a5946a027d20c9ff6
package/CHANGELOG.md CHANGED
@@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file
4
4
  automatically by Versionist. DO NOT EDIT THIS FILE MANUALLY!
5
5
  This project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
+ ## 10.2.6 - 2025-04-07
8
+
9
+ * Tests: convert test/sbvr/reference-type to typescript [Pagan Gazzard]
10
+ * Tests: convert test/sbvr/pilots to typescript [Pagan Gazzard]
11
+ * Tests: convert test/sbvr/test to typescript [Pagan Gazzard]
12
+ * Tests: convert test/odata/expand to typescript [Pagan Gazzard]
13
+ * Tests: convert test/odata/filterby to typescript [Pagan Gazzard]
14
+ * Tests: convert test/odata/orderby to typescript [Pagan Gazzard]
15
+ * Tests: convert test/odata/paging to typescript [Pagan Gazzard]
16
+ * Tests: convert test/odata/resource_parsing to typescript [Pagan Gazzard]
17
+ * Tests: convert test/odata/select to typescript [Pagan Gazzard]
18
+ * Tests: convert test/odata/stress to typescript [Pagan Gazzard]
19
+
7
20
  ## 10.2.5 - 2025-04-06
8
21
 
9
22
  * Tests: convert test/odata/test to typescript [Pagan Gazzard]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@balena/abstract-sql-compiler",
3
- "version": "10.2.5-build-tests-ts-c00e9270589111b882d4894fc437dd8b0343ecce-1",
3
+ "version": "10.2.6-build-ts-tests-3f2373a4482584aa493652784bd2041a8b7b9314-1",
4
4
  "description": "A translator for abstract sql into sql.",
5
5
  "type": "commonjs",
6
6
  "main": "out/AbstractSQLCompiler.js",
@@ -11,8 +11,8 @@
11
11
  "test": "mocha",
12
12
  "posttest": "npm run lint",
13
13
  "prepare": "node -e \"try { (await import('husky')).default() } catch (e) { if (e.code !== 'ERR_MODULE_NOT_FOUND') throw e }\" --input-type module && npm run build",
14
- "lint-fix": "balena-lint --fix -e js -e ts src/ test/",
15
- "lint": "balena-lint -e js -e ts src/ test/ && tsc --noEmit && tsc --noEmit --project tsconfig.js.json"
14
+ "lint-fix": "balena-lint --fix src/ test/",
15
+ "lint": "balena-lint src/ test/ && tsc --noEmit"
16
16
  },
17
17
  "repository": "https://github.com/balena-io-modules/abstract-sql-compiler.git",
18
18
  "author": "",
@@ -42,9 +42,6 @@
42
42
  "typescript": "^5.8.2"
43
43
  },
44
44
  "lint-staged": {
45
- "*.js": [
46
- "balena-lint --fix"
47
- ],
48
45
  "*.ts": [
49
46
  "balena-lint --fix"
50
47
  ]
@@ -54,16 +51,13 @@
54
51
  "recursive": true,
55
52
  "require": "ts-node/register/transpile-only",
56
53
  "bail": true,
57
- "_": [
58
- "test/**/*.ts",
59
- "test/**/*.js"
60
- ]
54
+ "_": "test/**/*.ts"
61
55
  },
62
56
  "engines": {
63
57
  "node": ">=20.14.0",
64
58
  "npm": ">=10.7.0"
65
59
  },
66
60
  "versionist": {
67
- "publishedAt": "2025-04-06T22:37:17.012Z"
61
+ "publishedAt": "2025-04-07T11:05:19.874Z"
68
62
  }
69
63
  }
@@ -1,3 +1,4 @@
1
+ import type { ExpectationFailFn, ExpectationSuccessFn } from './test';
1
2
  import test from './test';
2
3
  import {
3
4
  pilotFields,
@@ -8,8 +9,15 @@ import {
8
9
  } from './fields';
9
10
  import _ from 'lodash';
10
11
 
11
- const postgresAgg = (field) => 'COALESCE(JSON_AGG(' + field + "), '[]')";
12
- const mysqlAgg = (field) => "'[' || group_concat(" + field + ", ',') || ']'";
12
+ type TestFn = (
13
+ aggFunc: (field: string) => string,
14
+ fields?: string,
15
+ ) => ExpectationSuccessFn;
16
+
17
+ const postgresAgg = (field: string) =>
18
+ 'COALESCE(JSON_AGG(' + field + "), '[]')";
19
+ const mysqlAgg = (field: string) =>
20
+ "'[' || group_concat(" + field + ", ',') || ']'";
13
21
  const websqlAgg = mysqlAgg;
14
22
 
15
23
  (function () {
@@ -17,7 +25,7 @@ const websqlAgg = mysqlAgg;
17
25
  pilotFields,
18
26
  (field) => field === '"pilot"."licence"',
19
27
  ).join(', ');
20
- const testFunc = (aggFunc, fields) => (result, sqlEquals) => {
28
+ const testFunc: TestFn = (aggFunc, fields) => (result, sqlEquals) => {
21
29
  it('should select from pilot.*, aggregated licence', () => {
22
30
  sqlEquals?.(
23
31
  result,
@@ -38,10 +46,28 @@ FROM "pilot"`,
38
46
  const urlCount = '/pilot?$expand=licence/$count';
39
47
  test.postgres(url, testFunc(postgresAgg, aliasLicenceFields.join(', ')));
40
48
  test.postgres(urlCount, testFunc(postgresAgg, 'COUNT(*) AS "$count"'));
41
- test.mysql.fail(url, testFunc(mysqlAgg, aliasLicenceFields.join(', ')));
42
- test.mysql.fail(urlCount, testFunc(mysqlAgg, 'COUNT(*) AS "$count"'));
43
- test.websql.fail(url, testFunc(websqlAgg, aliasLicenceFields.join(', ')));
44
- test.websql.fail(urlCount, testFunc(websqlAgg, 'COUNT(*) AS "$count"'));
49
+ test.mysql.fail(
50
+ url,
51
+ testFunc(
52
+ mysqlAgg,
53
+ aliasLicenceFields.join(', '),
54
+ ) as any as ExpectationFailFn,
55
+ );
56
+ test.mysql.fail(
57
+ urlCount,
58
+ testFunc(mysqlAgg, 'COUNT(*) AS "$count"') as any as ExpectationFailFn,
59
+ );
60
+ test.websql.fail(
61
+ url,
62
+ testFunc(
63
+ websqlAgg,
64
+ aliasLicenceFields.join(', '),
65
+ ) as any as ExpectationFailFn,
66
+ );
67
+ test.websql.fail(
68
+ urlCount,
69
+ testFunc(websqlAgg, 'COUNT(*) AS "$count"') as any as ExpectationFailFn,
70
+ );
45
71
  })();
46
72
 
47
73
  (function () {
@@ -49,7 +75,7 @@ FROM "pilot"`,
49
75
  aliasPilotCanFlyPlaneFields,
50
76
  (field) => field === '"pilot.pilot-can fly-plane"."can fly-plane"',
51
77
  ).join(', ');
52
- const testFunc = (aggFunc) => (result, sqlEquals) => {
78
+ const testFunc: TestFn = (aggFunc) => (result, sqlEquals) => {
53
79
  it('should select from pilot.*, aggregated(pilot-can fly-plane, aggregated plane)', () => {
54
80
  sqlEquals?.(
55
81
  result,
@@ -79,8 +105,8 @@ FROM "pilot"`,
79
105
  '/pilot?$expand=can_fly__plane($expand=plane)',
80
106
  ]) {
81
107
  test.postgres(url, testFunc(postgresAgg));
82
- test.mysql.fail(url, testFunc(mysqlAgg));
83
- test.websql.fail(url, testFunc(websqlAgg));
108
+ test.mysql.fail(url, testFunc(mysqlAgg) as any as ExpectationFailFn);
109
+ test.websql.fail(url, testFunc(websqlAgg) as any as ExpectationFailFn);
84
110
  }
85
111
  })();
86
112
 
@@ -93,7 +119,7 @@ FROM "pilot"`,
93
119
  pilotFields,
94
120
  (field) => field === '"pilot"."licence"',
95
121
  ).join(', ');
96
- const testFunc = (aggFunc) => (result, sqlEquals) => {
122
+ const testFunc: TestFn = (aggFunc) => (result, sqlEquals) => {
97
123
  it('should select from pilot.*, aggregated(pilot-can fly-plane, aggregated plane), aggregated licence', () => {
98
124
  sqlEquals?.(
99
125
  result,
@@ -130,13 +156,13 @@ FROM "pilot"`,
130
156
  '/pilot?$expand=can_fly__plane($expand=plane),licence',
131
157
  ]) {
132
158
  test.postgres(url, testFunc(postgresAgg));
133
- test.mysql.fail(url, testFunc(mysqlAgg));
134
- test.websql.fail(url, testFunc(websqlAgg));
159
+ test.mysql.fail(url, testFunc(mysqlAgg) as any as ExpectationFailFn);
160
+ test.websql.fail(url, testFunc(websqlAgg) as any as ExpectationFailFn);
135
161
  }
136
162
  })();
137
163
 
138
164
  (function () {
139
- const testFunc = (aggFunc) => (result, sqlEquals) => {
165
+ const testFunc: TestFn = (aggFunc) => (result, sqlEquals) => {
140
166
  it('should select from pilot.*, aggregated(pilot-can fly-plane, aggregated plane), aggregated licence', () => {
141
167
  sqlEquals?.(
142
168
  result,
@@ -155,8 +181,8 @@ FROM "pilot"`,
155
181
  };
156
182
  const url = '/pilot?$select=licence&$expand=licence';
157
183
  test.postgres(url, testFunc(postgresAgg));
158
- test.mysql.fail(url, testFunc(mysqlAgg));
159
- test.websql.fail(url, testFunc(websqlAgg));
184
+ test.mysql.fail(url, testFunc(mysqlAgg) as any as ExpectationFailFn);
185
+ test.websql.fail(url, testFunc(websqlAgg) as any as ExpectationFailFn);
160
186
  })();
161
187
 
162
188
  (function () {
@@ -164,7 +190,7 @@ FROM "pilot"`,
164
190
  aliasPilotCanFlyPlaneFields,
165
191
  (field) => field === '"pilot.pilot-can fly-plane"."can fly-plane"',
166
192
  ).join(', ');
167
- const testFunc = (aggFunc) => (result, sqlEquals) => {
193
+ const testFunc: TestFn = (aggFunc) => (result, sqlEquals) => {
168
194
  it('should select from pilot.*, aggregated(pilot-can fly-plane, aggregated plane)', () => {
169
195
  sqlEquals?.(
170
196
  result,
@@ -194,8 +220,8 @@ FROM "pilot"`,
194
220
  '/pilot?$select=id&$expand=can_fly__plane($expand=plane)',
195
221
  ]) {
196
222
  test.postgres(url, testFunc(postgresAgg));
197
- test.mysql.fail(url, testFunc(mysqlAgg));
198
- test.websql.fail(url, testFunc(websqlAgg));
223
+ test.mysql.fail(url, testFunc(mysqlAgg) as any as ExpectationFailFn);
224
+ test.websql.fail(url, testFunc(websqlAgg) as any as ExpectationFailFn);
199
225
  }
200
226
  })();
201
227
 
@@ -204,7 +230,7 @@ FROM "pilot"`,
204
230
  aliasPilotCanFlyPlaneFields,
205
231
  (field) => field === '"pilot.pilot-can fly-plane"."can fly-plane"',
206
232
  ).join(', ');
207
- const testFunc = (aggFunc) => (result, sqlEquals) => {
233
+ const testFunc: TestFn = (aggFunc) => (result, sqlEquals) => {
208
234
  it('should select from pilot.*, aggregated(pilot-can fly-plane, aggregated plane), aggregated licence', () => {
209
235
  sqlEquals?.(
210
236
  result,
@@ -241,13 +267,13 @@ FROM "pilot"`,
241
267
  '/pilot?$select=id,licence&$expand=can_fly__plane($expand=plane),licence',
242
268
  ]) {
243
269
  test.postgres(url, testFunc(postgresAgg));
244
- test.mysql.fail(url, testFunc(mysqlAgg));
245
- test.websql.fail(url, testFunc(websqlAgg));
270
+ test.mysql.fail(url, testFunc(mysqlAgg) as any as ExpectationFailFn);
271
+ test.websql.fail(url, testFunc(websqlAgg) as any as ExpectationFailFn);
246
272
  }
247
273
  })();
248
274
 
249
275
  (function () {
250
- const testFunc = (aggFunc) => (result, sqlEquals) => {
276
+ const testFunc: TestFn = (aggFunc) => (result, sqlEquals) => {
251
277
  it('should select from pilot.*, aggregated(pilot-can fly-plane, aggregated plane)', () => {
252
278
  sqlEquals?.(
253
279
  result,
@@ -266,8 +292,8 @@ FROM "pilot"`,
266
292
  };
267
293
  const url = '/pilot?$expand=can_fly__plane($select=id)';
268
294
  test.postgres(url, testFunc(postgresAgg));
269
- test.mysql.fail(url, testFunc(mysqlAgg));
270
- test.websql.fail(url, testFunc(websqlAgg));
295
+ test.mysql.fail(url, testFunc(mysqlAgg) as any as ExpectationFailFn);
296
+ test.websql.fail(url, testFunc(websqlAgg) as any as ExpectationFailFn);
271
297
  })();
272
298
 
273
299
  (function () {
@@ -275,7 +301,7 @@ FROM "pilot"`,
275
301
  pilotFields,
276
302
  (field) => field === '"pilot"."licence"',
277
303
  ).join(', ');
278
- const testFunc = (aggFunc, fields) => (result, sqlEquals) => {
304
+ const testFunc: TestFn = (aggFunc, fields) => (result, sqlEquals) => {
279
305
  it('should select from pilot.*, aggregated licence', () => {
280
306
  sqlEquals?.(
281
307
  result,
@@ -311,25 +337,31 @@ FROM "pilot"`,
311
337
  url,
312
338
  'GET',
313
339
  [['Bind', 0]],
314
- testFunc(mysqlAgg, aliasLicenceFields.join(', ')),
340
+ testFunc(
341
+ mysqlAgg,
342
+ aliasLicenceFields.join(', '),
343
+ ) as any as ExpectationFailFn,
315
344
  );
316
345
  test.mysql.fail(
317
346
  urlCount,
318
347
  'GET',
319
348
  [['Bind', 0]],
320
- testFunc(mysqlAgg, 'COUNT(*) AS "$count"'),
349
+ testFunc(mysqlAgg, 'COUNT(*) AS "$count"') as any as ExpectationFailFn,
321
350
  );
322
351
  test.websql.fail(
323
352
  url,
324
353
  'GET',
325
354
  [['Bind', 0]],
326
- testFunc(websqlAgg, aliasLicenceFields.join(', ')),
355
+ testFunc(
356
+ websqlAgg,
357
+ aliasLicenceFields.join(', '),
358
+ ) as any as ExpectationFailFn,
327
359
  );
328
360
  test.websql.fail(
329
361
  urlCount,
330
362
  'GET',
331
363
  [['Bind', 0]],
332
- testFunc(websqlAgg, 'COUNT(*) AS "$count'),
364
+ testFunc(websqlAgg, 'COUNT(*) AS "$count') as any as ExpectationFailFn,
333
365
  );
334
366
  })();
335
367
 
@@ -338,7 +370,7 @@ FROM "pilot"`,
338
370
  pilotFields,
339
371
  (field) => field === '"pilot"."licence"',
340
372
  ).join(', ');
341
- const testFunc = (aggFunc) => (result, sqlEquals) => {
373
+ const testFunc: TestFn = (aggFunc) => (result, sqlEquals) => {
342
374
  it('should select from pilot.*, aggregated licence', () => {
343
375
  sqlEquals?.(
344
376
  result,
@@ -359,8 +391,18 @@ FROM "pilot"`,
359
391
  };
360
392
  const url = '/pilot?$expand=licence($filter=is_of__pilot/id eq 1)';
361
393
  test.postgres(url, 'GET', [['Bind', 0]], testFunc(postgresAgg));
362
- test.mysql.fail(url, 'GET', [['Bind', 0]], testFunc(mysqlAgg));
363
- test.websql.fail(url, 'GET', [['Bind', 0]], testFunc(websqlAgg));
394
+ test.mysql.fail(
395
+ url,
396
+ 'GET',
397
+ [['Bind', 0]],
398
+ testFunc(mysqlAgg) as any as ExpectationFailFn,
399
+ );
400
+ test.websql.fail(
401
+ url,
402
+ 'GET',
403
+ [['Bind', 0]],
404
+ testFunc(websqlAgg) as any as ExpectationFailFn,
405
+ );
364
406
  })();
365
407
 
366
408
  (function () {
@@ -368,7 +410,7 @@ FROM "pilot"`,
368
410
  pilotFields,
369
411
  (field) => field === '"pilot"."licence"',
370
412
  ).join(', ');
371
- const testFunc = (aggFunc) => (result, sqlEquals) => {
413
+ const testFunc: TestFn = (aggFunc) => (result, sqlEquals) => {
372
414
  it('should select from pilot.*, aggregated licence', () => {
373
415
  sqlEquals?.(
374
416
  result,
@@ -388,8 +430,8 @@ FROM "pilot"`,
388
430
  };
389
431
  const url = '/pilot?$expand=licence($orderby=id)';
390
432
  test.postgres(url, testFunc(postgresAgg));
391
- test.mysql.fail(url, testFunc(mysqlAgg));
392
- test.websql.fail(url, testFunc(websqlAgg));
433
+ test.mysql.fail(url, testFunc(mysqlAgg) as any as ExpectationFailFn);
434
+ test.websql.fail(url, testFunc(websqlAgg) as any as ExpectationFailFn);
393
435
  })();
394
436
 
395
437
  (function () {
@@ -397,7 +439,7 @@ FROM "pilot"`,
397
439
  pilotFields,
398
440
  (field) => field === '"pilot"."licence"',
399
441
  ).join(', ');
400
- const testFunc = (aggFunc) => (result, sqlEquals) => {
442
+ const testFunc: TestFn = (aggFunc) => (result, sqlEquals) => {
401
443
  it('should select from pilot.*, aggregated count(*) licence and ignore orderby', () => {
402
444
  sqlEquals?.(
403
445
  result,
@@ -416,8 +458,8 @@ FROM "pilot"`,
416
458
  };
417
459
  const urlCount = '/pilot?$expand=licence/$count($orderby=id)';
418
460
  test.postgres(urlCount, testFunc(postgresAgg));
419
- test.mysql.fail(urlCount, testFunc(mysqlAgg));
420
- test.websql.fail(urlCount, testFunc(websqlAgg));
461
+ test.mysql.fail(urlCount, testFunc(mysqlAgg) as any as ExpectationFailFn);
462
+ test.websql.fail(urlCount, testFunc(websqlAgg) as any as ExpectationFailFn);
421
463
  })();
422
464
 
423
465
  (function () {
@@ -425,7 +467,7 @@ FROM "pilot"`,
425
467
  pilotFields,
426
468
  (field) => field === '"pilot"."licence"',
427
469
  ).join(', ');
428
- const testFunc = (aggFunc) => (result, sqlEquals) => {
470
+ const testFunc: TestFn = (aggFunc) => (result, sqlEquals) => {
429
471
  it('should select from pilot.*, aggregated licence', () => {
430
472
  sqlEquals?.(
431
473
  result,
@@ -445,8 +487,18 @@ FROM "pilot"`,
445
487
  };
446
488
  const url = '/pilot?$expand=licence($top=10)';
447
489
  test.postgres(url, 'GET', [['Bind', 0]], testFunc(postgresAgg));
448
- test.mysql.fail(url, 'GET', [['Bind', 0]], testFunc(mysqlAgg));
449
- test.websql.fail(url, 'GET', [['Bind', 0]], testFunc(websqlAgg));
490
+ test.mysql.fail(
491
+ url,
492
+ 'GET',
493
+ [['Bind', 0]],
494
+ testFunc(mysqlAgg) as any as ExpectationFailFn,
495
+ );
496
+ test.websql.fail(
497
+ url,
498
+ 'GET',
499
+ [['Bind', 0]],
500
+ testFunc(websqlAgg) as any as ExpectationFailFn,
501
+ );
450
502
  })();
451
503
 
452
504
  (function () {
@@ -454,7 +506,7 @@ FROM "pilot"`,
454
506
  pilotFields,
455
507
  (field) => field === '"pilot"."licence"',
456
508
  ).join(', ');
457
- const testFunc = (aggFunc) => (result, sqlEquals) => {
509
+ const testFunc: TestFn = (aggFunc) => (result, sqlEquals) => {
458
510
  it('should select from pilot.*, aggregated count(*) licence and ignore top', () => {
459
511
  sqlEquals?.(
460
512
  result,
@@ -473,8 +525,8 @@ FROM "pilot"`,
473
525
  };
474
526
  const urlCount = '/pilot?$expand=licence/$count($top=10)';
475
527
  test.postgres(urlCount, testFunc(postgresAgg));
476
- test.mysql.fail(urlCount, testFunc(mysqlAgg));
477
- test.websql.fail(urlCount, testFunc(websqlAgg));
528
+ test.mysql.fail(urlCount, testFunc(mysqlAgg) as any as ExpectationFailFn);
529
+ test.websql.fail(urlCount, testFunc(websqlAgg) as any as ExpectationFailFn);
478
530
  })();
479
531
 
480
532
  (function () {
@@ -482,7 +534,7 @@ FROM "pilot"`,
482
534
  pilotFields,
483
535
  (field) => field === '"pilot"."licence"',
484
536
  ).join(', ');
485
- const testFunc = (aggFunc) => (result, sqlEquals) => {
537
+ const testFunc: TestFn = (aggFunc) => (result, sqlEquals) => {
486
538
  it('should select from pilot.*, aggregated licence', () => {
487
539
  sqlEquals?.(
488
540
  result,
@@ -502,8 +554,18 @@ FROM "pilot"`,
502
554
  };
503
555
  const url = '/pilot?$expand=licence($skip=10)';
504
556
  test.postgres(url, 'GET', [['Bind', 0]], testFunc(postgresAgg));
505
- test.mysql.fail(url, 'GET', [['Bind', 0]], testFunc(mysqlAgg));
506
- test.websql.fail(url, 'GET', [['Bind', 0]], testFunc(websqlAgg));
557
+ test.mysql.fail(
558
+ url,
559
+ 'GET',
560
+ [['Bind', 0]],
561
+ testFunc(mysqlAgg) as any as ExpectationFailFn,
562
+ );
563
+ test.websql.fail(
564
+ url,
565
+ 'GET',
566
+ [['Bind', 0]],
567
+ testFunc(websqlAgg) as any as ExpectationFailFn,
568
+ );
507
569
  })();
508
570
 
509
571
  (function () {
@@ -511,7 +573,7 @@ FROM "pilot"`,
511
573
  pilotFields,
512
574
  (field) => field === '"pilot"."licence"',
513
575
  ).join(', ');
514
- const testFunc = (aggFunc) => (result, sqlEquals) => {
576
+ const testFunc: TestFn = (aggFunc) => (result, sqlEquals) => {
515
577
  it('should select from pilot.*, aggregated count(*) licence and ignore skip', () => {
516
578
  sqlEquals?.(
517
579
  result,
@@ -530,12 +592,12 @@ FROM "pilot"`,
530
592
  };
531
593
  const urlCount = '/pilot?$expand=licence/$count($skip=10)';
532
594
  test.postgres(urlCount, testFunc(postgresAgg));
533
- test.mysql.fail(urlCount, testFunc(mysqlAgg));
534
- test.websql.fail(urlCount, testFunc(websqlAgg));
595
+ test.mysql.fail(urlCount, testFunc(mysqlAgg) as any as ExpectationFailFn);
596
+ test.websql.fail(urlCount, testFunc(websqlAgg) as any as ExpectationFailFn);
535
597
  })();
536
598
 
537
599
  (function () {
538
- const testFunc = (aggFunc) => (result, sqlEquals) => {
600
+ const testFunc: TestFn = (aggFunc) => (result, sqlEquals) => {
539
601
  it('should select from pilot.*, aggregated(pilot-can fly-plane, aggregated plane)', () => {
540
602
  sqlEquals?.(
541
603
  result,
@@ -554,12 +616,12 @@ FROM "pilot"`,
554
616
  };
555
617
  const url = '/pilot?$expand=can_fly__plane($select=plane)';
556
618
  test.postgres(url, testFunc(postgresAgg));
557
- test.mysql.fail(url, testFunc(mysqlAgg));
558
- test.websql.fail(url, testFunc(websqlAgg));
619
+ test.mysql.fail(url, testFunc(mysqlAgg) as any as ExpectationFailFn);
620
+ test.websql.fail(url, testFunc(websqlAgg) as any as ExpectationFailFn);
559
621
  })();
560
622
 
561
623
  (function () {
562
- const testFunc = (aggFunc) => (result, sqlEquals) => {
624
+ const testFunc: TestFn = (aggFunc) => (result, sqlEquals) => {
563
625
  it('should select from pilot.*, aggregated count(*) pilot-can fly-plane and ignore select', () => {
564
626
  sqlEquals?.(
565
627
  result,
@@ -578,8 +640,8 @@ FROM "pilot"`,
578
640
  };
579
641
  const urlCount = '/pilot?$expand=can_fly__plane/$count($select=plane)';
580
642
  test.postgres(urlCount, testFunc(postgresAgg));
581
- test.mysql.fail(urlCount, testFunc(mysqlAgg));
582
- test.websql.fail(urlCount, testFunc(websqlAgg));
643
+ test.mysql.fail(urlCount, testFunc(mysqlAgg) as any as ExpectationFailFn);
644
+ test.websql.fail(urlCount, testFunc(websqlAgg) as any as ExpectationFailFn);
583
645
  })();
584
646
 
585
647
  (function () {
@@ -588,7 +650,7 @@ FROM "pilot"`,
588
650
  pilotFields,
589
651
  (field) => field === '"pilot"."trained-pilot"',
590
652
  ).join(', ');
591
- const testFunc = (aggFunc) => (result, sqlEquals) => {
653
+ const testFunc: TestFn = (aggFunc) => (result, sqlEquals) => {
592
654
  it('should select from pilot.*, aggregated pilot', () => {
593
655
  sqlEquals?.(
594
656
  result,
@@ -607,6 +669,6 @@ FROM "pilot"`,
607
669
  };
608
670
  const url = '/pilot?$expand=trained__pilot';
609
671
  test.postgres(url, testFunc(postgresAgg));
610
- test.mysql.fail(url, testFunc(mysqlAgg));
611
- test.websql.fail(url, testFunc(websqlAgg));
672
+ test.mysql.fail(url, testFunc(mysqlAgg) as any as ExpectationFailFn);
673
+ test.websql.fail(url, testFunc(websqlAgg) as any as ExpectationFailFn);
612
674
  })();
@@ -4,29 +4,46 @@
4
4
  * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
5
5
  */
6
6
  import { expect } from 'chai';
7
+ import type { ExpectationSuccessFn } from './test';
7
8
  import test, { clientModel } from './test';
8
9
  import _ from 'lodash';
9
10
  import { odataNameToSqlName } from '@balena/odata-to-abstract-sql';
10
11
  import { pilotFields, teamFields, aliasPilotCanFlyPlaneFields } from './fields';
12
+ import type {
13
+ Binding,
14
+ DurationNode,
15
+ SqlResult,
16
+ } from '../../src/AbstractSQLCompiler';
11
17
 
12
18
  const pilotFieldsStr = pilotFields.join(', ');
13
19
  const aliasPilotCanFlyPlaneFieldsStr = aliasPilotCanFlyPlaneFields.join(', ');
14
20
  const teamFieldsStr = teamFields.join(', ');
15
21
 
16
- let parseOperandFactory = function (defaultResource) {
17
- if (defaultResource == null) {
18
- defaultResource = 'pilot';
19
- }
22
+ type ParsedOperand = {
23
+ odata: string | number | boolean;
24
+ bindings: Binding[];
25
+ sql: string;
26
+ };
27
+ type Operand =
28
+ | string
29
+ | number
30
+ | boolean
31
+ | Date
32
+ | DurationNode[1]
33
+ | ParsedOperand;
34
+
35
+ let parseOperandFactory = function (defaultResource = 'pilot') {
20
36
  let bindNo = 0;
21
- const operandToOData = function (operand) {
22
- if (operand.odata != null) {
23
- return operand.odata;
24
- }
25
- if (_.isDate(operand)) {
26
- return "datetime'" + encodeURIComponent(operand.toISOString()) + "'";
27
- }
37
+ const operandToOData = function (operand: Operand) {
28
38
  if (operand != null && typeof operand === 'object') {
29
- const duration = [];
39
+ if ('odata' in operand) {
40
+ return operand.odata;
41
+ }
42
+ if (_.isDate(operand)) {
43
+ return "datetime'" + encodeURIComponent(operand.toISOString()) + "'";
44
+ }
45
+
46
+ const duration: Array<string | number> = [];
30
47
  let t = false;
31
48
  if (operand.negative) {
32
49
  duration.push('-');
@@ -61,8 +78,8 @@ let parseOperandFactory = function (defaultResource) {
61
78
  return operand;
62
79
  };
63
80
 
64
- const operandToBindings = function (operand) {
65
- if (operand.bindings != null) {
81
+ const operandToBindings = function (operand: Operand): Binding[] {
82
+ if (typeof operand === 'object' && 'bindings' in operand) {
66
83
  return operand.bindings;
67
84
  }
68
85
  if (
@@ -76,11 +93,11 @@ let parseOperandFactory = function (defaultResource) {
76
93
  return [];
77
94
  };
78
95
 
79
- const operandToSQL = function (operand, resource) {
80
- if (resource == null) {
81
- resource = defaultResource;
82
- }
83
- if (operand.sql != null) {
96
+ const operandToSQL = function (
97
+ operand: Operand,
98
+ resource = defaultResource,
99
+ ): string {
100
+ if (typeof operand === 'object' && 'sql' in operand) {
84
101
  return operand.sql;
85
102
  }
86
103
  if (
@@ -134,17 +151,17 @@ let parseOperandFactory = function (defaultResource) {
134
151
  throw new Error('Unknown operand type: ' + operand);
135
152
  };
136
153
 
137
- return (operand) => ({
154
+ return (operand: Operand): ParsedOperand => ({
138
155
  sql: operandToSQL(operand),
139
156
  bindings: operandToBindings(operand),
140
157
  odata: operandToOData(operand),
141
158
  });
142
159
  };
143
160
 
144
- let parseOperand = null;
161
+ let parseOperand: ReturnType<typeof parseOperandFactory> | null = null;
145
162
  const run = (function () {
146
163
  let running = false;
147
- return function (fn) {
164
+ return function (fn: () => void) {
148
165
  if (!running) {
149
166
  running = true;
150
167
  parseOperand = parseOperandFactory();
@@ -178,10 +195,10 @@ const methodMaps = {
178
195
  TOLOWER: 'LOWER',
179
196
  };
180
197
 
181
- const createExpression = function (lhs, op, rhs) {
198
+ const createExpression = function (lhs: Operand, op?: Operand, rhs?: Operand) {
182
199
  let sql;
183
200
  if (lhs === 'not') {
184
- op = parseOperand(op);
201
+ op = parseOperand!(op!);
185
202
  return {
186
203
  odata: 'not(' + op.odata + ')',
187
204
  sql: 'NOT (\n\t' + op.sql + '\n)',
@@ -189,17 +206,17 @@ const createExpression = function (lhs, op, rhs) {
189
206
  };
190
207
  }
191
208
  if (rhs == null) {
192
- lhs = parseOperand(lhs);
209
+ lhs = parseOperand!(lhs);
193
210
  return {
194
211
  odata: '(' + lhs.odata + ')',
195
212
  sql: lhs.sql,
196
213
  bindings: lhs.bindings,
197
214
  };
198
215
  }
199
- lhs = parseOperand(lhs);
200
- rhs = parseOperand(rhs);
216
+ lhs = parseOperand!(lhs);
217
+ rhs = parseOperand!(rhs);
201
218
  const bindings = lhs.bindings.concat(rhs.bindings);
202
- if (['eq', 'ne'].includes(op)) {
219
+ if (op === 'eq' || op === 'ne') {
203
220
  if ([lhs.sql, rhs.sql].includes('NULL')) {
204
221
  const nullCheck = op === 'eq' ? ' IS NULL' : ' IS NOT NULL';
205
222
  if (lhs.sql === 'NULL') {
@@ -232,10 +249,10 @@ const createExpression = function (lhs, op, rhs) {
232
249
  }
233
250
  }
234
251
  } else {
235
- sql = `${lhs.sql}${sqlOps[op]} ${rhs.sql}`;
252
+ sql = `${lhs.sql}${sqlOps[op as keyof typeof sqlOps]} ${rhs.sql}`;
236
253
  }
237
254
 
238
- if (sqlOpBrackets[op]) {
255
+ if (sqlOpBrackets[op as keyof typeof sqlOpBrackets]) {
239
256
  sql = '(' + sql + ')';
240
257
  }
241
258
  return {
@@ -244,43 +261,44 @@ const createExpression = function (lhs, op, rhs) {
244
261
  bindings,
245
262
  };
246
263
  };
247
- const createMethodCall = function (method, ...args) {
248
- args = args.map((arg) => parseOperand(arg));
249
- const odata = method + '(' + args.map((arg) => arg.odata).join(',') + ')';
264
+ const createMethodCall = function (method: string, ...args: Operand[]) {
265
+ const parsedArgs = args.map((arg) => parseOperand!(arg));
266
+ const odata =
267
+ method + '(' + parsedArgs.map((arg) => arg.odata).join(',') + ')';
250
268
  method = method.toUpperCase();
251
269
  switch (method) {
252
270
  case 'CONTAINS':
253
271
  case 'SUBSTRINGOF':
254
272
  if (method === 'SUBSTRINGOF') {
255
- args.reverse();
273
+ parsedArgs.reverse();
256
274
  }
257
275
  return {
258
- sql: `${args[0].sql} LIKE ('%' || REPLACE(REPLACE(REPLACE(${args[1].sql}, '\\', '\\\\'), '_', '\\_'), '%', '\\%') || '%')`,
259
- bindings: [...args[0].bindings, ...args[1].bindings],
276
+ sql: `${parsedArgs[0].sql} LIKE ('%' || REPLACE(REPLACE(REPLACE(${parsedArgs[1].sql}, '\\', '\\\\'), '_', '\\_'), '%', '\\%') || '%')`,
277
+ bindings: [...parsedArgs[0].bindings, ...parsedArgs[1].bindings],
260
278
  odata,
261
279
  };
262
280
  case 'STARTSWITH':
263
281
  return {
264
- sql: `STARTS_WITH(${args[0].sql}, ${args[1].sql})`,
265
- bindings: [...args[0].bindings, ...args[1].bindings],
282
+ sql: `STARTS_WITH(${parsedArgs[0].sql}, ${parsedArgs[1].sql})`,
283
+ bindings: [...parsedArgs[0].bindings, ...parsedArgs[1].bindings],
266
284
  odata,
267
285
  };
268
286
  case 'ENDSWITH':
269
287
  return {
270
- sql: `${args[0].sql} LIKE ('%' || REPLACE(REPLACE(REPLACE(${args[1].sql}, '\\', '\\\\'), '_', '\\_'), '%', '\\%'))`,
271
- bindings: [...args[0].bindings, ...args[1].bindings],
288
+ sql: `${parsedArgs[0].sql} LIKE ('%' || REPLACE(REPLACE(REPLACE(${parsedArgs[1].sql}, '\\', '\\\\'), '_', '\\_'), '%', '\\%'))`,
289
+ bindings: [...parsedArgs[0].bindings, ...parsedArgs[1].bindings],
272
290
  odata,
273
291
  };
274
292
  case 'CONCAT':
275
293
  return {
276
- sql: '(' + args.map((arg) => arg.sql).join(' || ') + ')',
277
- bindings: _.flatten(args.map((arg) => arg.bindings)),
294
+ sql: '(' + parsedArgs.map((arg) => arg.sql).join(' || ') + ')',
295
+ bindings: _.flatten(parsedArgs.map((arg) => arg.bindings)),
278
296
  odata,
279
297
  };
280
298
  case 'INDEXOF':
281
299
  return {
282
- sql: 'STRPOS(' + args.map((arg) => arg.sql).join(', ') + ') - 1',
283
- bindings: _.flatten(args.map((arg) => arg.bindings)),
300
+ sql: 'STRPOS(' + parsedArgs.map((arg) => arg.sql).join(', ') + ') - 1',
301
+ bindings: _.flatten(parsedArgs.map((arg) => arg.bindings)),
284
302
  odata,
285
303
  };
286
304
  case 'NOW':
@@ -295,60 +313,66 @@ const createMethodCall = function (method, ...args) {
295
313
  case 'HOUR':
296
314
  case 'MINUTE':
297
315
  return {
298
- sql: `EXTRACT('${method}' FROM DATE_TRUNC('milliseconds', ${args[0].sql}))`,
299
- bindings: args[0].bindings,
316
+ sql: `EXTRACT('${method}' FROM DATE_TRUNC('milliseconds', ${parsedArgs[0].sql}))`,
317
+ bindings: parsedArgs[0].bindings,
300
318
  odata,
301
319
  };
302
320
  case 'SECOND':
303
321
  return {
304
- sql: `FLOOR(EXTRACT('${method}' FROM DATE_TRUNC('milliseconds', ${args[0].sql})))`,
305
- bindings: args[0].bindings,
322
+ sql: `FLOOR(EXTRACT('${method}' FROM DATE_TRUNC('milliseconds', ${parsedArgs[0].sql})))`,
323
+ bindings: parsedArgs[0].bindings,
306
324
  odata,
307
325
  };
308
326
  case 'FRACTIONALSECONDS':
309
327
  return {
310
- sql: `EXTRACT('SECOND' FROM DATE_TRUNC('milliseconds', ${args[0].sql})) - FLOOR(EXTRACT('SECOND' FROM DATE_TRUNC('milliseconds', ${args[0].sql})))`,
311
- bindings: args[0].bindings,
328
+ sql: `EXTRACT('SECOND' FROM DATE_TRUNC('milliseconds', ${parsedArgs[0].sql})) - FLOOR(EXTRACT('SECOND' FROM DATE_TRUNC('milliseconds', ${parsedArgs[0].sql})))`,
329
+ bindings: parsedArgs[0].bindings,
312
330
  odata,
313
331
  };
314
332
  case 'TIME':
315
333
  return {
316
- sql: `CAST(DATE_TRUNC('milliseconds', ${args[0].sql}) AS ${method})`,
317
- bindings: args[0].bindings,
334
+ sql: `CAST(DATE_TRUNC('milliseconds', ${parsedArgs[0].sql}) AS ${method})`,
335
+ bindings: parsedArgs[0].bindings,
318
336
  odata,
319
337
  };
320
338
  case 'TOTALSECONDS':
321
339
  return {
322
- sql: `EXTRACT(EPOCH FROM ${args[0].sql})`,
323
- bindings: args[0].bindings,
340
+ sql: `EXTRACT(EPOCH FROM ${parsedArgs[0].sql})`,
341
+ bindings: parsedArgs[0].bindings,
324
342
  odata,
325
343
  };
326
344
  case 'DATE':
327
345
  return {
328
- sql: `DATE(DATE_TRUNC('milliseconds', ${args[0].sql}))`,
329
- bindings: args[0].bindings,
346
+ sql: `DATE(DATE_TRUNC('milliseconds', ${parsedArgs[0].sql}))`,
347
+ bindings: parsedArgs[0].bindings,
330
348
  odata,
331
349
  };
332
350
  default: {
333
351
  if (Object.prototype.hasOwnProperty.call(methodMaps, method)) {
334
- method = methodMaps[method];
352
+ method = methodMaps[method as keyof typeof methodMaps];
335
353
  }
336
354
  switch (method) {
337
355
  case 'SUBSTRING':
338
- args[1].sql += ' + 1';
356
+ parsedArgs[1].sql += ' + 1';
339
357
  break;
340
358
  }
341
- const sql = method + '(' + args.map((arg) => arg.sql).join(', ') + ')';
359
+ const sql =
360
+ method + '(' + parsedArgs.map((arg) => arg.sql).join(', ') + ')';
342
361
  return {
343
362
  sql,
344
- bindings: _.flatten(args.map((arg) => arg.bindings)),
363
+ bindings: _.flatten(parsedArgs.map((arg) => arg.bindings)),
345
364
  odata,
346
365
  };
347
366
  }
348
367
  }
349
368
  };
350
369
 
351
- const operandTest = (lhs, op, rhs, override) => {
370
+ const operandTest = (
371
+ lhs: Operand,
372
+ op?: Operand,
373
+ rhs?: Operand,
374
+ override?: Partial<ParsedOperand>,
375
+ ) => {
352
376
  run(function () {
353
377
  let from;
354
378
  let { odata, sql, bindings } = createExpression(lhs, op, rhs);
@@ -392,7 +416,7 @@ WHERE ${sql}`,
392
416
  });
393
417
  };
394
418
 
395
- const methodTest = (...args) => {
419
+ const methodTest = (...args: [method: string, ...Operand[]]) => {
396
420
  run(function () {
397
421
  const { odata, sql, bindings } = createMethodCall(...args);
398
422
  test(`/pilot?$filter=${odata}`, 'GET', bindings, (result, sqlEquals) => {
@@ -566,7 +590,7 @@ WHERE ${sql}`,
566
590
  });
567
591
 
568
592
  run(function () {
569
- const { odata: keyOdata, bindings: keyBindings } = parseOperand(1);
593
+ const { odata: keyOdata, bindings: keyBindings } = parseOperand!(1);
570
594
  const { odata, bindings } = createExpression('can_fly__plane/id', 'eq', 10);
571
595
  test(
572
596
  '/pilot(' + keyOdata + ')/can_fly__plane?$filter=' + odata,
@@ -600,8 +624,8 @@ run(function () {
600
624
  10,
601
625
  );
602
626
  const name = 'Peter';
603
- const bodyBindings = [['Bind', ['pilot', 'name']], ...bindings];
604
- const insertTest = (result, sqlEquals) => {
627
+ const bodyBindings = [['Bind', ['pilot', 'name']], ...bindings] as const;
628
+ const insertTest: ExpectationSuccessFn = (result, sqlEquals) => {
605
629
  sqlEquals(
606
630
  result,
607
631
  `\
@@ -685,11 +709,11 @@ ${updateWhere}`,
685
709
  expect(result).to.be.an('array');
686
710
  });
687
711
  it('that inserts', () => {
688
- insertTest(result[0], sqlEquals);
712
+ insertTest((result as SqlResult[])[0], sqlEquals);
689
713
  });
690
714
  it('and updates', () => {
691
715
  sqlEquals(
692
- result[1].query,
716
+ (result as SqlResult[])[1],
693
717
  `\
694
718
  UPDATE "pilot"
695
719
  SET "created at" = DEFAULT,
@@ -736,11 +760,10 @@ run(function () {
736
760
  sql,
737
761
  bindings: exprBindings,
738
762
  } = createExpression('name', 'eq', `'${name}'`);
739
- const bindings = [['Bind', ['pilot', 'name']], ...exprBindings];
740
763
  test(
741
764
  `/pilot?$filter=${odata}`,
742
765
  'POST',
743
- bindings,
766
+ [['Bind', ['pilot', 'name']], ...exprBindings],
744
767
  { name },
745
768
  (result, sqlEquals) => {
746
769
  it(`should insert into pilot where '${odata}'`, () => {
@@ -767,20 +790,24 @@ WHERE EXISTS (
767
790
 
768
791
  run(function () {
769
792
  const name = 'Peter';
770
- const { odata: keyOdata, bindings: keyBindings } = parseOperand(1);
793
+ const { odata: keyOdata, bindings: keyBindings } = parseOperand!(1);
771
794
  const {
772
795
  odata,
773
796
  sql,
774
797
  bindings: exprBindings,
775
798
  } = createExpression('name', 'eq', `'${name}'`);
776
- const bodyBindings = [['Bind', ['pilot', 'name']]];
799
+ const bodyBindings = [['Bind', ['pilot', 'name']]] as const;
777
800
  const insertBindings = [
778
801
  ['Bind', ['pilot', 'id']],
779
802
  ...bodyBindings,
780
803
  ...exprBindings,
781
804
  ...keyBindings,
782
- ];
783
- const updateBindings = [...bodyBindings, ...keyBindings, ...exprBindings];
805
+ ] as const;
806
+ const updateBindings = [
807
+ ...bodyBindings,
808
+ ...keyBindings,
809
+ ...exprBindings,
810
+ ] as const;
784
811
  test(
785
812
  '/pilot(' + keyOdata + ')?$filter=' + odata,
786
813
  'PATCH',
@@ -816,7 +843,7 @@ AND "pilot"."id" IN ((
816
843
  });
817
844
  it('that inserts', () => {
818
845
  sqlEquals(
819
- result[0].query,
846
+ (result as SqlResult[])[0],
820
847
  `\
821
848
  INSERT INTO "pilot" ("id", "name")
822
849
  SELECT "$insert"."id", "$insert"."name"
@@ -835,7 +862,7 @@ WHERE EXISTS (
835
862
  });
836
863
  it('and updates', () => {
837
864
  sqlEquals(
838
- result[1].query,
865
+ (result as SqlResult[])[1],
839
866
  `\
840
867
  UPDATE "pilot"
841
868
  SET "created at" = DEFAULT,
@@ -864,7 +891,7 @@ AND "pilot"."id" IN ((
864
891
  });
865
892
 
866
893
  run(function () {
867
- const { odata: keyOdata, bindings: keyBindings } = parseOperand(1);
894
+ const { odata: keyOdata, bindings: keyBindings } = parseOperand!(1);
868
895
  const { odata, bindings, sql } = createExpression(
869
896
  createExpression(1, 'eq', 1),
870
897
  'or',
@@ -1442,14 +1469,13 @@ WHERE CURRENT_TIMESTAMP - DATE_TRUNC('milliseconds', "pilot"."created at") < INT
1442
1469
 
1443
1470
  run(function () {
1444
1471
  const odata = 'now() add now()';
1445
- test.fail(`/pilot?$filter=${odata}`, 'GET', [], (result, sqlEquals) => {
1472
+ test.fail(`/pilot?$filter=${odata}`, 'GET', [], (err) => {
1446
1473
  it(
1447
1474
  'should fail to add current_timestamp to current_timestamp where "' +
1448
1475
  odata +
1449
1476
  '"',
1450
1477
  () => {
1451
- expect(result).to.be.empty;
1452
- expect(sqlEquals).to.be.undefined;
1478
+ expect(err).to.be.instanceOf(Error);
1453
1479
  },
1454
1480
  );
1455
1481
  });
@@ -1,4 +1,5 @@
1
1
  import { expect } from 'chai';
2
+ import type { ExpectationSuccessFn } from './test';
2
3
  import test from './test';
3
4
  import * as ODataParser from '@balena/odata-parser';
4
5
  import {
@@ -9,6 +10,7 @@ import {
9
10
  aliasPilotLicenceFields,
10
11
  aliasLicenceFields,
11
12
  } from './fields';
13
+ import type { SqlResult } from '../../src/AbstractSQLRules2SQL';
12
14
  const aliasPilotFields = aliasFields(
13
15
  'plane.pilot-can fly-plane.pilot',
14
16
  pilotFields,
@@ -151,7 +153,7 @@ test(
151
153
  (result, sqlEquals) => {
152
154
  it('should insert/update the pilot with id 1', () => {
153
155
  sqlEquals(
154
- result[0].query,
156
+ (result as SqlResult[])[0],
155
157
  `\
156
158
  INSERT INTO "pilot" ("id")
157
159
  SELECT "$insert"."id"
@@ -167,7 +169,7 @@ WHERE EXISTS (
167
169
  )`,
168
170
  );
169
171
  sqlEquals(
170
- result[1].query,
172
+ (result as SqlResult[])[1],
171
173
  `\
172
174
  UPDATE "pilot"
173
175
  SET "created at" = DEFAULT,
@@ -214,12 +216,11 @@ INSERT INTO "pilot" DEFAULT VALUES`,
214
216
  });
215
217
 
216
218
  (function () {
217
- // prettier-ignore
218
- const bindings = /** @type {const} */ ([
219
+ const bindings = [
219
220
  ['Bind', ['pilot', 'is_experienced']],
220
221
  ['Bind', 0],
221
- ]);
222
- const testFunc = (result, sqlEquals) => {
222
+ ] as const;
223
+ const testFunc: ExpectationSuccessFn = (result, sqlEquals) => {
223
224
  it('should update the pilot with id 1', () => {
224
225
  sqlEquals(
225
226
  result,
@@ -266,7 +267,7 @@ test(
266
267
  (result, sqlEquals) => {
267
268
  it('should insert/update the pilot-can fly-plane with id 1', () => {
268
269
  sqlEquals(
269
- result[0].query,
270
+ (result as SqlResult[])[0],
270
271
  `\
271
272
  INSERT INTO "pilot-can fly-plane" ("id")
272
273
  SELECT "$insert"."id"
@@ -282,7 +283,7 @@ WHERE EXISTS (
282
283
  )`,
283
284
  );
284
285
  sqlEquals(
285
- result[1].query,
286
+ (result as SqlResult[])[1],
286
287
  `\
287
288
  UPDATE "pilot-can fly-plane"
288
289
  SET "created at" = DEFAULT,
@@ -325,12 +326,11 @@ INSERT INTO "pilot-can fly-plane" DEFAULT VALUES`,
325
326
  });
326
327
 
327
328
  (function () {
328
- // prettier-ignore
329
- const bindings = /** @type {const} */ ([
329
+ const bindings = [
330
330
  ['Bind', ['pilot-can fly-plane', 'pilot']],
331
331
  ['Bind', 0],
332
- ]);
333
- const testFunc = (result, sqlEquals) => {
332
+ ] as const;
333
+ const testFunc: ExpectationSuccessFn = (result, sqlEquals) => {
334
334
  it('should update the pilot with id 1', () => {
335
335
  sqlEquals(
336
336
  result,
@@ -14,8 +14,7 @@ const filterBindsNandString = _.map(
14
14
  () => 'NOT(("pilot"."id") IS NOT NULL AND ("pilot"."id") = (?))',
15
15
  ).join('\nAND ');
16
16
 
17
- // prettier-ignore
18
- const filterBinds = filterIDs.map((_n, i) => /** @type {const} */ (['Bind', i]));
17
+ const filterBinds = filterIDs.map((_n, i) => ['Bind', i] as const);
19
18
 
20
19
  let filterString = `id in (${filterIDs.join(', ')})`;
21
20
  test(
@@ -79,17 +79,18 @@ const sqlEquals = {
79
79
  },
80
80
  } satisfies Record<string, SqlEquals>;
81
81
 
82
+ type ReadonlyBinding = Readonly<AbstractSQLCompiler.Binding>;
82
83
  type ExpectedBindings = ReadonlyArray<
83
- Readonly<AbstractSQLCompiler.Binding | AbstractSQLCompiler.Binding[]>
84
+ ReadonlyBinding | readonly ReadonlyBinding[]
84
85
  >;
85
86
 
86
- type ExpectationSuccessFn = (
87
+ export type ExpectationSuccessFn = (
87
88
  result:
88
89
  | AbstractSQLCompiler.SqlResult
89
90
  | [AbstractSQLCompiler.SqlResult, AbstractSQLCompiler.SqlResult],
90
91
  sqlEquals: SqlEquals,
91
92
  ) => void;
92
- type ExpectationFailFn = (result: Error) => void;
93
+ export type ExpectationFailFn = (result: Error) => void;
93
94
  type ExpectationFn<ExpectFail extends boolean> = ExpectFail extends true
94
95
  ? ExpectationFailFn
95
96
  : ExpectationSuccessFn;
@@ -1,11 +1,12 @@
1
1
  import * as fs from 'node:fs';
2
2
  const typeVocab = fs.readFileSync(
3
3
  require.resolve('@balena/sbvr-types/Type.sbvr'),
4
+ 'utf8',
4
5
  );
5
6
  import { getTestHelpers } from './test';
6
7
  const test = getTestHelpers(typeVocab);
7
8
 
8
- const modifiedAtTrigger = (tableName) => `\
9
+ const modifiedAtTrigger = (tableName: string) => `\
9
10
  DO
10
11
  $$
11
12
  BEGIN
@@ -3,9 +3,10 @@ import { getTestHelpers } from './test';
3
3
 
4
4
  const typeVocab = fs.readFileSync(
5
5
  require.resolve('@balena/sbvr-types/Type.sbvr'),
6
+ 'utf8',
6
7
  );
7
8
 
8
- const modifiedAtTrigger = (tableName) => `\
9
+ const modifiedAtTrigger = (tableName: string) => `\
9
10
  DO
10
11
  $$
11
12
  BEGIN
@@ -24,7 +25,7 @@ END;
24
25
  $$`;
25
26
 
26
27
  describe('reference type', function () {
27
- let test;
28
+ let test: ReturnType<typeof getTestHelpers>;
28
29
  beforeEach(() => {
29
30
  test = getTestHelpers(typeVocab);
30
31
  });
@@ -37,7 +38,7 @@ Term: term
37
38
  Term: term history
38
39
  Fact Type: term history references term
39
40
  Necessity: each term history references exactly one term
40
- Reference Type: informative
41
+ Reference Type: informative
41
42
  `,
42
43
  [
43
44
  `\
@@ -81,7 +82,7 @@ CREATE TABLE IF NOT EXISTS "term history" (
81
82
  Term: term
82
83
  Term: term history
83
84
  Fact Type: term history references term
84
- Reference Type: informative
85
+ Reference Type: informative
85
86
  Necessity: each term history references exactly one term
86
87
  `,
87
88
  [
@@ -4,10 +4,7 @@ import sbvrTypes from '@balena/sbvr-types';
4
4
  import { expect } from 'chai';
5
5
  import * as AbstractSQLCompiler from '../..';
6
6
 
7
- export function getTestHelpers(builtInVocab) {
8
- if (builtInVocab == null) {
9
- builtInVocab = false;
10
- }
7
+ export function getTestHelpers(builtInVocab: string | boolean = false) {
11
8
  // eslint-disable-next-line @typescript-eslint/no-var-requires
12
9
  const SBVRParser = require('@balena/sbvr-parser').SBVRParser.createInstance();
13
10
  SBVRParser.enableReusingMemoizations(SBVRParser._sideEffectingRules);
@@ -22,7 +19,11 @@ export function getTestHelpers(builtInVocab) {
22
19
 
23
20
  let seSoFar = '';
24
21
 
25
- const runExpectation = (it, input, expectation) => {
22
+ const runExpectation = (
23
+ it: Mocha.TestFunction,
24
+ input: string,
25
+ expectation: (result: AbstractSQLCompiler.SqlModel | Error) => void,
26
+ ) => {
26
27
  it(input, function () {
27
28
  let result;
28
29
  try {
@@ -30,7 +31,7 @@ export function getTestHelpers(builtInVocab) {
30
31
  const lf = SBVRParser.matchAll(seSoFar + input, 'Process');
31
32
  const schema = LF2AbstractSQLTranslator(lf, 'Process');
32
33
  result = AbstractSQLCompiler.postgres.compileSchema(schema);
33
- } catch (e) {
34
+ } catch (e: any) {
34
35
  expectation(e);
35
36
  return;
36
37
  }
@@ -38,7 +39,13 @@ export function getTestHelpers(builtInVocab) {
38
39
  });
39
40
  };
40
41
 
41
- const runSchema = (it, input, expectation) => {
42
+ const runSchema = (
43
+ it: Mocha.TestFunction,
44
+ input: string,
45
+ expectation:
46
+ | ((result: AbstractSQLCompiler.SqlModel | Error) => void)
47
+ | string[],
48
+ ) => {
42
49
  runExpectation(it, input, function (result) {
43
50
  seSoFar += input + '\n';
44
51
  if (_.isFunction(expectation)) {
@@ -57,7 +64,13 @@ export function getTestHelpers(builtInVocab) {
57
64
  });
58
65
  };
59
66
 
60
- const runRule = (it, input, expectation) => {
67
+ const runRule = (
68
+ it: Mocha.TestFunction,
69
+ input: string,
70
+ expectation:
71
+ | ((result: AbstractSQLCompiler.SqlModel | Error) => void)
72
+ | string,
73
+ ) => {
61
74
  runExpectation(it, 'Rule: ' + input, function (result) {
62
75
  if (_.isFunction(expectation)) {
63
76
  expectation(result);
package/tsconfig.json CHANGED
@@ -14,8 +14,7 @@
14
14
  "skipLibCheck": true,
15
15
  "exactOptionalPropertyTypes": true,
16
16
  "target": "es2023",
17
- "outDir": "out",
18
- "allowJs": true
17
+ "outDir": "out"
19
18
  },
20
19
  "include": [
21
20
  "src/**/*",
package/.eslintrc.js DELETED
@@ -1,12 +0,0 @@
1
- module.exports = {
2
- extends: ['./node_modules/@balena/lint/config/.eslintrc.js'],
3
- parserOptions: {
4
- project: 'tsconfig.js.json',
5
- sourceType: 'module',
6
- },
7
- env: {
8
- // TODO: Drop this once we convert all .js tests to .ts
9
- mocha: true,
10
- },
11
- root: true,
12
- };
package/tsconfig.js.json DELETED
@@ -1,12 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "compilerOptions": {
4
- "noImplicitAny": false,
5
- "checkJs": true
6
- },
7
- "include": [
8
- "src/**/*",
9
- "test/**/*",
10
- ".eslintrc.js"
11
- ],
12
- }
File without changes
File without changes
File without changes