@balena/abstract-sql-compiler 10.2.4 → 10.2.5-build-tests-ts-c00e9270589111b882d4894fc437dd8b0343ecce-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.
@@ -0,0 +1,292 @@
1
+ import * as fs from 'node:fs';
2
+ import * as ODataParser from '@balena/odata-parser';
3
+ import { OData2AbstractSQL } from '@balena/odata-to-abstract-sql';
4
+ const sbvrModel = fs.readFileSync(require.resolve('../model.sbvr'), 'utf8');
5
+
6
+ import * as AbstractSQLCompiler from '../..';
7
+
8
+ import { expect } from 'chai';
9
+ import _ from 'lodash';
10
+
11
+ const generateClientModel = function (input: string) {
12
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
13
+ const sbvrTypes = require('@balena/sbvr-types').default;
14
+ const typeVocab = fs.readFileSync(
15
+ require.resolve('@balena/sbvr-types/Type.sbvr'),
16
+ 'utf8',
17
+ );
18
+
19
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
20
+ const SBVRParser = require('@balena/sbvr-parser').SBVRParser.createInstance();
21
+ SBVRParser.enableReusingMemoizations(SBVRParser._sideEffectingRules);
22
+ SBVRParser.AddCustomAttribute('Database ID Field:');
23
+ SBVRParser.AddCustomAttribute('Database Table Name:');
24
+ SBVRParser.AddBuiltInVocab(typeVocab);
25
+
26
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
27
+ const LF2AbstractSQL = require('@balena/lf-to-abstract-sql');
28
+ const LF2AbstractSQLTranslator = LF2AbstractSQL.createTranslator(sbvrTypes);
29
+
30
+ const lf = SBVRParser.matchAll(input, 'Process');
31
+ const abstractSql = LF2AbstractSQLTranslator(lf, 'Process');
32
+ return abstractSql;
33
+ };
34
+
35
+ export const clientModel = generateClientModel(sbvrModel);
36
+ const odata2AbstractSQL = new OData2AbstractSQL(clientModel);
37
+
38
+ const bindingsTest = function (
39
+ actualBindings: AbstractSQLCompiler.Binding[],
40
+ expectedBindings: AbstractSQLCompiler.Binding[] | false = false,
41
+ ) {
42
+ if (expectedBindings === false) {
43
+ it('should not have any bindings', () => {
44
+ expect(actualBindings).to.be.empty;
45
+ });
46
+ } else {
47
+ it('should have matching bindings', () => {
48
+ expect(actualBindings).to.deep.equal(expectedBindings);
49
+ });
50
+ }
51
+ };
52
+
53
+ type SqlEquals = (
54
+ actual:
55
+ | AbstractSQLCompiler.SqlResult
56
+ | AbstractSQLCompiler.SqlResult[]
57
+ | string,
58
+ expected: string,
59
+ ) => void;
60
+ const equals: SqlEquals = (actual, expected) => {
61
+ if (typeof actual !== 'string') {
62
+ if (Array.isArray(actual)) {
63
+ throw new Error('Expected a single query, got multiple');
64
+ }
65
+ actual = actual.query;
66
+ }
67
+ expect(actual).to.equal(expected);
68
+ };
69
+ const sqlEquals = {
70
+ websql: equals,
71
+ mysql: equals,
72
+ postgres(actual, expected) {
73
+ let num = 1;
74
+ while (_.includes(expected, '?')) {
75
+ expected = expected.replace('?', '$' + num);
76
+ num++;
77
+ }
78
+ equals(actual, expected);
79
+ },
80
+ } satisfies Record<string, SqlEquals>;
81
+
82
+ type ExpectedBindings = ReadonlyArray<
83
+ Readonly<AbstractSQLCompiler.Binding | AbstractSQLCompiler.Binding[]>
84
+ >;
85
+
86
+ type ExpectationSuccessFn = (
87
+ result:
88
+ | AbstractSQLCompiler.SqlResult
89
+ | [AbstractSQLCompiler.SqlResult, AbstractSQLCompiler.SqlResult],
90
+ sqlEquals: SqlEquals,
91
+ ) => void;
92
+ type ExpectationFailFn = (result: Error) => void;
93
+ type ExpectationFn<ExpectFail extends boolean> = ExpectFail extends true
94
+ ? ExpectationFailFn
95
+ : ExpectationSuccessFn;
96
+
97
+ function runExpectation<ExpectFail extends boolean>(
98
+ describe: Mocha.SuiteFunction,
99
+ engine: keyof typeof sqlEquals,
100
+ expectFailure: ExpectFail,
101
+ input: string,
102
+ method: ODataParser.SupportedMethod,
103
+ expectedBindings: ExpectedBindings | false,
104
+ body: Record<string, unknown>,
105
+ expectation: ExpectationFn<ExpectFail>,
106
+ ): void;
107
+ function runExpectation<ExpectFail extends boolean>(
108
+ describe: Mocha.SuiteFunction,
109
+ engine: keyof typeof sqlEquals,
110
+ expectFailure: ExpectFail,
111
+ input: string,
112
+ method: ODataParser.SupportedMethod,
113
+ expectedBindings: ExpectedBindings | false,
114
+ expectation: ExpectationFn<ExpectFail>,
115
+ ): void;
116
+ function runExpectation<ExpectFail extends boolean>(
117
+ describe: Mocha.SuiteFunction,
118
+ engine: keyof typeof sqlEquals,
119
+ expectFailure: ExpectFail,
120
+ input: string,
121
+ method: ODataParser.SupportedMethod,
122
+ expectation: ExpectationFn<ExpectFail>,
123
+ ): void;
124
+ function runExpectation<ExpectFail extends boolean>(
125
+ describe: Mocha.SuiteFunction,
126
+ engine: keyof typeof sqlEquals,
127
+ expectFailure: ExpectFail,
128
+ input: string,
129
+ expectation: ExpectationFn<ExpectFail>,
130
+ ): void;
131
+ function runExpectation<ExpectFail extends boolean>(
132
+ describe: Mocha.SuiteFunction,
133
+ engine: keyof typeof sqlEquals,
134
+ expectFailure: ExpectFail,
135
+ input: string,
136
+ ...args:
137
+ | [expectation: ExpectationFn<ExpectFail>]
138
+ | [
139
+ method: ODataParser.SupportedMethod,
140
+ expectation: ExpectationFn<ExpectFail>,
141
+ ]
142
+ | [
143
+ method: ODataParser.SupportedMethod,
144
+ expectedBindings: ExpectedBindings | false,
145
+ expectation: ExpectationFn<ExpectFail>,
146
+ ]
147
+ | [
148
+ method: ODataParser.SupportedMethod,
149
+ expectedBindings: ExpectedBindings | false,
150
+ body: Record<string, unknown>,
151
+ expectation: ExpectationFn<ExpectFail>,
152
+ ]
153
+ ): void {
154
+ let method: ODataParser.SupportedMethod = 'GET';
155
+ let expectedBindings: ExpectedBindings | false = false;
156
+ let body: Record<string, unknown> = {};
157
+ let expectation: ExpectationFn<ExpectFail>;
158
+ switch (args.length) {
159
+ case 1:
160
+ [expectation] = args;
161
+ break;
162
+ case 2:
163
+ [method, expectation] = args;
164
+ break;
165
+ case 3:
166
+ [method, expectedBindings, expectation] = args;
167
+ break;
168
+ case 4:
169
+ [method, expectedBindings, body, expectation] = args;
170
+ break;
171
+ }
172
+
173
+ describe(
174
+ 'Parsing ' + method + ' ' + _.truncate(input, { length: 100 }),
175
+ function () {
176
+ let result;
177
+ try {
178
+ const odataAST = ODataParser.parse(input);
179
+ const { tree, extraBodyVars } = odata2AbstractSQL.match(
180
+ odataAST.tree,
181
+ method,
182
+ _.keys(body),
183
+ 0,
184
+ );
185
+ _.assign(body, extraBodyVars);
186
+ result = AbstractSQLCompiler[engine].compileRule(tree);
187
+ } catch (e: any) {
188
+ if (!expectFailure) {
189
+ throw e;
190
+ }
191
+ (expectation as ExpectationFailFn)(e);
192
+ return;
193
+ }
194
+ if (Array.isArray(result)) {
195
+ for (let i = 0; i < result.length; i++) {
196
+ const actualResult = result[i];
197
+ if (expectedBindings === false) {
198
+ bindingsTest(actualResult.bindings, false);
199
+ } else if (expectedBindings[0][0] === 'Bind') {
200
+ bindingsTest(
201
+ actualResult.bindings,
202
+ expectedBindings as AbstractSQLCompiler.Binding[],
203
+ );
204
+ } else {
205
+ bindingsTest(
206
+ actualResult.bindings,
207
+ expectedBindings[i] as AbstractSQLCompiler.Binding[],
208
+ );
209
+ }
210
+ }
211
+ } else {
212
+ bindingsTest(
213
+ result.bindings,
214
+ expectedBindings as AbstractSQLCompiler.Binding[],
215
+ );
216
+ }
217
+ (expectation as ExpectationSuccessFn)(result, sqlEquals[engine]);
218
+ },
219
+ );
220
+ }
221
+
222
+ interface BoundRunExpectation<ExpectFail extends boolean> {
223
+ (
224
+ input: string,
225
+ method: ODataParser.SupportedMethod,
226
+ expectedBindings: ExpectedBindings | false,
227
+ body: Record<string, unknown>,
228
+ expectation: ExpectationFn<ExpectFail>,
229
+ ): void;
230
+ (
231
+ input: string,
232
+ method: ODataParser.SupportedMethod,
233
+ expectedBindings: ExpectedBindings | false,
234
+ expectation: ExpectationFn<ExpectFail>,
235
+ ): void;
236
+ (
237
+ input: string,
238
+ method: ODataParser.SupportedMethod,
239
+ expectation: ExpectationFn<ExpectFail>,
240
+ ): void;
241
+ (input: string, expectation: ExpectationFn<ExpectFail>): void;
242
+ (
243
+ input: string,
244
+ ...args:
245
+ | [expectation: ExpectationFn<ExpectFail>]
246
+ | [
247
+ method: ODataParser.SupportedMethod,
248
+ expectation: ExpectationFn<ExpectFail>,
249
+ ]
250
+ | [
251
+ method: ODataParser.SupportedMethod,
252
+ expectedBindings: ExpectedBindings | false,
253
+ expectation: ExpectationFn<ExpectFail>,
254
+ ]
255
+ | [
256
+ method: ODataParser.SupportedMethod,
257
+ expectedBindings: ExpectedBindings | false,
258
+ body: Record<string, unknown>,
259
+ expectation: ExpectationFn<ExpectFail>,
260
+ ]
261
+ ): void;
262
+ }
263
+
264
+ type MochaBoundRunExpectation = BoundRunExpectation<false> & {
265
+ fail: BoundRunExpectation<true>;
266
+ skip: BoundRunExpectation<false>;
267
+ only: BoundRunExpectation<false>;
268
+ };
269
+ const bindRunExpectation = function (engine: keyof typeof sqlEquals) {
270
+ const bound: MochaBoundRunExpectation = runExpectation.bind(
271
+ null,
272
+ describe,
273
+ engine,
274
+ false,
275
+ );
276
+ bound.fail = runExpectation.bind(null, describe, engine, true);
277
+ bound.skip = runExpectation.bind(null, describe.skip, engine, false);
278
+ // eslint-disable-next-line no-only-tests/no-only-tests -- this is a false positive
279
+ bound.only = runExpectation.bind(null, describe.only, engine, false);
280
+ return bound;
281
+ };
282
+
283
+ const testFn = bindRunExpectation('postgres') as MochaBoundRunExpectation & {
284
+ postgres: MochaBoundRunExpectation;
285
+ mysql: MochaBoundRunExpectation;
286
+ websql: MochaBoundRunExpectation;
287
+ };
288
+ testFn.postgres = bindRunExpectation('postgres');
289
+ testFn.mysql = bindRunExpectation('mysql');
290
+ testFn.websql = bindRunExpectation('websql');
291
+
292
+ export default testFn;
@@ -1,138 +0,0 @@
1
- import * as fs from 'node:fs';
2
- import * as ODataParser from '@balena/odata-parser';
3
- import { OData2AbstractSQL } from '@balena/odata-to-abstract-sql';
4
- const sbvrModel = fs.readFileSync(require.resolve('../model.sbvr'), 'utf8');
5
-
6
- import * as AbstractSQLCompiler from '../..';
7
-
8
- import { expect } from 'chai';
9
- import _ from 'lodash';
10
-
11
- const generateClientModel = function (input) {
12
- // eslint-disable-next-line @typescript-eslint/no-var-requires
13
- const sbvrTypes = require('@balena/sbvr-types').default;
14
- const typeVocab = fs.readFileSync(
15
- require.resolve('@balena/sbvr-types/Type.sbvr'),
16
- 'utf8',
17
- );
18
-
19
- // eslint-disable-next-line @typescript-eslint/no-var-requires
20
- const SBVRParser = require('@balena/sbvr-parser').SBVRParser.createInstance();
21
- SBVRParser.enableReusingMemoizations(SBVRParser._sideEffectingRules);
22
- SBVRParser.AddCustomAttribute('Database ID Field:');
23
- SBVRParser.AddCustomAttribute('Database Table Name:');
24
- SBVRParser.AddBuiltInVocab(typeVocab);
25
-
26
- // eslint-disable-next-line @typescript-eslint/no-var-requires
27
- const LF2AbstractSQL = require('@balena/lf-to-abstract-sql');
28
- const LF2AbstractSQLTranslator = LF2AbstractSQL.createTranslator(sbvrTypes);
29
-
30
- const lf = SBVRParser.matchAll(input, 'Process');
31
- const abstractSql = LF2AbstractSQLTranslator(lf, 'Process');
32
- return abstractSql;
33
- };
34
-
35
- export const clientModel = generateClientModel(sbvrModel);
36
- const odata2AbstractSQL = new OData2AbstractSQL(clientModel);
37
-
38
- const bindingsTest = function (actualBindings, expectedBindings) {
39
- if (expectedBindings == null) {
40
- expectedBindings = false;
41
- }
42
- if (expectedBindings === false) {
43
- it('should not have any bindings', () => {
44
- expect(actualBindings).to.be.empty;
45
- });
46
- } else {
47
- it('should have matching bindings', () => {
48
- expect(actualBindings).to.deep.equal(expectedBindings);
49
- });
50
- }
51
- };
52
-
53
- const equals = (actual, expected) => {
54
- expect(actual).to.equal(expected);
55
- };
56
- const sqlEquals = {
57
- websql: equals,
58
- mysql: equals,
59
- postgres(actual, expected) {
60
- let num = 1;
61
- while (_.includes(expected, '?')) {
62
- expected = expected.replace('?', '$' + num);
63
- num++;
64
- }
65
- equals(actual, expected);
66
- },
67
- };
68
-
69
- const runExpectation = function (describe, engine, input, ...args) {
70
- /** @type {import('@balena/odata-parser').SupportedMethod} */
71
- let method = 'GET';
72
- let expectedBindings = false;
73
- let body = {};
74
- let expectation;
75
- switch (args.length) {
76
- case 1:
77
- [expectation] = args;
78
- break;
79
- case 2:
80
- [method, expectation] = args;
81
- break;
82
- case 3:
83
- [method, expectedBindings, expectation] = args;
84
- break;
85
- case 4:
86
- [method, expectedBindings, body, expectation] = args;
87
- break;
88
- }
89
-
90
- describe(
91
- 'Parsing ' + method + ' ' + _.truncate(input, { length: 100 }),
92
- function () {
93
- let result;
94
- try {
95
- input = ODataParser.parse(input);
96
- const { tree, extraBodyVars } = odata2AbstractSQL.match(
97
- input.tree,
98
- method,
99
- _.keys(body),
100
- 0,
101
- );
102
- _.assign(body, extraBodyVars);
103
- result = AbstractSQLCompiler[engine].compileRule(tree);
104
- } catch (e) {
105
- expectation(e);
106
- return;
107
- }
108
- if (Array.isArray(result)) {
109
- for (let i = 0; i < result.length; i++) {
110
- const actualResult = result[i];
111
- if (expectedBindings[0][0] === 'Bind') {
112
- bindingsTest(actualResult.bindings, expectedBindings);
113
- } else {
114
- bindingsTest(actualResult.bindings, expectedBindings[i]);
115
- }
116
- }
117
- } else {
118
- bindingsTest(result.bindings, expectedBindings);
119
- }
120
- expectation(result, sqlEquals[engine]);
121
- },
122
- );
123
- };
124
-
125
- const bindRunExpectation = function (engine) {
126
- const bound = runExpectation.bind(null, describe, engine);
127
- bound.skip = runExpectation.bind(null, describe.skip, engine);
128
- // eslint-disable-next-line no-only-tests/no-only-tests -- this is a false positive
129
- bound.only = runExpectation.bind(null, describe.only, engine);
130
- return bound;
131
- };
132
-
133
- const testFn = bindRunExpectation('postgres');
134
- testFn.postgres = bindRunExpectation('postgres');
135
- testFn.mysql = bindRunExpectation('mysql');
136
- testFn.websql = bindRunExpectation('websql');
137
-
138
- export default testFn;