@qrvey/formula-lang 0.4.0 → 0.5.0
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/.vscode/launch.json +15 -0
- package/CHANGELOG.md +12 -0
- package/dist/bundle.js +23152 -0
- package/dist/cjs/constants/index.d.ts +53 -0
- package/dist/cjs/constants/index.js +117 -0
- package/dist/cjs/constants/index.js.map +1 -0
- package/dist/cjs/constants/interfaces.d.ts +91 -0
- package/dist/cjs/constants/interfaces.js +3 -0
- package/dist/cjs/constants/interfaces.js.map +1 -0
- package/dist/cjs/errors/definitions.d.ts +43 -0
- package/dist/cjs/errors/definitions.js +91 -0
- package/dist/cjs/errors/definitions.js.map +1 -0
- package/dist/cjs/errors/elasticsearch.d.ts +24 -0
- package/dist/cjs/errors/elasticsearch.js +30 -0
- package/dist/cjs/errors/elasticsearch.js.map +1 -0
- package/dist/cjs/errors/engineErrors.d.ts +2 -0
- package/dist/cjs/errors/engineErrors.js +25 -0
- package/dist/cjs/errors/engineErrors.js.map +1 -0
- package/dist/cjs/errors/index.d.ts +2 -0
- package/dist/cjs/errors/index.js +21 -0
- package/dist/cjs/errors/index.js.map +1 -0
- package/dist/cjs/errors/snowflake.d.ts +15 -0
- package/dist/cjs/errors/snowflake.js +20 -0
- package/dist/cjs/errors/snowflake.js.map +1 -0
- package/dist/cjs/functions/abs.d.ts +5 -0
- package/dist/cjs/functions/abs.js +38 -0
- package/dist/cjs/functions/abs.js.map +1 -0
- package/dist/cjs/functions/datedif.d.ts +5 -0
- package/dist/cjs/functions/datedif.js +64 -0
- package/dist/cjs/functions/datedif.js.map +1 -0
- package/dist/cjs/functions/day.d.ts +5 -0
- package/dist/cjs/functions/day.js +39 -0
- package/dist/cjs/functions/day.js.map +1 -0
- package/dist/cjs/functions/hour.d.ts +5 -0
- package/dist/cjs/functions/hour.js +39 -0
- package/dist/cjs/functions/hour.js.map +1 -0
- package/dist/cjs/functions/if.d.ts +5 -0
- package/dist/cjs/functions/if.js +52 -0
- package/dist/cjs/functions/if.js.map +1 -0
- package/dist/cjs/functions/ifs.d.ts +5 -0
- package/dist/cjs/functions/ifs.js +74 -0
- package/dist/cjs/functions/ifs.js.map +1 -0
- package/dist/cjs/functions/index.d.ts +4 -0
- package/dist/cjs/functions/index.js +33 -0
- package/dist/cjs/functions/index.js.map +1 -0
- package/dist/cjs/functions/mid.d.ts +5 -0
- package/dist/cjs/functions/mid.js +54 -0
- package/dist/cjs/functions/mid.js.map +1 -0
- package/dist/cjs/functions/minute.d.ts +5 -0
- package/dist/cjs/functions/minute.js +39 -0
- package/dist/cjs/functions/minute.js.map +1 -0
- package/dist/cjs/functions/month.d.ts +5 -0
- package/dist/cjs/functions/month.js +39 -0
- package/dist/cjs/functions/month.js.map +1 -0
- package/dist/cjs/functions/second.d.ts +5 -0
- package/dist/cjs/functions/second.js +39 -0
- package/dist/cjs/functions/second.js.map +1 -0
- package/dist/cjs/functions/year.d.ts +5 -0
- package/dist/cjs/functions/year.js +39 -0
- package/dist/cjs/functions/year.js.map +1 -0
- package/dist/cjs/grammar/generated/qformula.lang.d.ts +13 -0
- package/dist/cjs/grammar/generated/qformula.lang.js +50 -0
- package/dist/cjs/grammar/generated/qformula.lang.js.map +1 -0
- package/dist/cjs/grammar/qformula.grammar.d.ts +1 -0
- package/dist/cjs/grammar/qformula.grammar.js +18 -0
- package/dist/cjs/grammar/qformula.grammar.js.map +1 -0
- package/dist/cjs/index.d.ts +10 -0
- package/dist/cjs/index.js +33 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/main.d.ts +1 -0
- package/dist/cjs/main.js +69 -0
- package/dist/cjs/main.js.map +1 -0
- package/dist/cjs/parser/json-parser.d.ts +3 -0
- package/dist/cjs/parser/json-parser.js +201 -0
- package/dist/cjs/parser/json-parser.js.map +1 -0
- package/dist/cjs/parser/syntax-errors.d.ts +3 -0
- package/dist/cjs/parser/syntax-errors.js +28 -0
- package/dist/cjs/parser/syntax-errors.js.map +1 -0
- package/dist/cjs/transpiler/columnTranspilation.d.ts +3 -0
- package/dist/cjs/transpiler/columnTranspilation.js +29 -0
- package/dist/cjs/transpiler/columnTranspilation.js.map +1 -0
- package/dist/cjs/transpiler/index.d.ts +18 -0
- package/dist/cjs/transpiler/index.js +107 -0
- package/dist/cjs/transpiler/index.js.map +1 -0
- package/dist/cjs/transpiler/unshiftCustomFunctions.d.ts +2 -0
- package/dist/cjs/transpiler/unshiftCustomFunctions.js +14 -0
- package/dist/cjs/transpiler/unshiftCustomFunctions.js.map +1 -0
- package/dist/cjs/transpiler/validateFuncStructure.d.ts +2 -0
- package/dist/cjs/transpiler/validateFuncStructure.js +41 -0
- package/dist/cjs/transpiler/validateFuncStructure.js.map +1 -0
- package/dist/cjs/utils/customFunctions.d.ts +4 -0
- package/dist/cjs/utils/customFunctions.js +35 -0
- package/dist/cjs/utils/customFunctions.js.map +1 -0
- package/dist/cjs/utils/elasticsearch/index.d.ts +2 -0
- package/dist/cjs/utils/elasticsearch/index.js +22 -0
- package/dist/cjs/utils/elasticsearch/index.js.map +1 -0
- package/dist/cjs/utils/elasticsearch/scripts.d.ts +11 -0
- package/dist/cjs/utils/elasticsearch/scripts.js +57 -0
- package/dist/cjs/utils/elasticsearch/scripts.js.map +1 -0
- package/dist/cjs/utils/getMonthMaxDayAllowed.d.ts +7 -0
- package/dist/cjs/utils/getMonthMaxDayAllowed.js +26 -0
- package/dist/cjs/utils/getMonthMaxDayAllowed.js.map +1 -0
- package/dist/cjs/utils/getNodeValue.d.ts +2 -0
- package/dist/cjs/utils/getNodeValue.js +13 -0
- package/dist/cjs/utils/getNodeValue.js.map +1 -0
- package/dist/cjs/utils/getVariableType.d.ts +3 -0
- package/dist/cjs/utils/getVariableType.js +19 -0
- package/dist/cjs/utils/getVariableType.js.map +1 -0
- package/dist/cjs/utils/index.d.ts +10 -0
- package/dist/cjs/utils/index.js +29 -0
- package/dist/cjs/utils/index.js.map +1 -0
- package/dist/cjs/utils/isDateParam.d.ts +2 -0
- package/dist/cjs/utils/isDateParam.js +12 -0
- package/dist/cjs/utils/isDateParam.js.map +1 -0
- package/dist/cjs/utils/isNumberParam.d.ts +2 -0
- package/dist/cjs/utils/isNumberParam.js +12 -0
- package/dist/cjs/utils/isNumberParam.js.map +1 -0
- package/dist/cjs/utils/isPositiveNumberParam.d.ts +2 -0
- package/dist/cjs/utils/isPositiveNumberParam.js +12 -0
- package/dist/cjs/utils/isPositiveNumberParam.js.map +1 -0
- package/dist/cjs/utils/isStringParam.d.ts +2 -0
- package/dist/cjs/utils/isStringParam.js +12 -0
- package/dist/cjs/utils/isStringParam.js.map +1 -0
- package/dist/cjs/utils/isValidDate.d.ts +1 -0
- package/dist/cjs/utils/isValidDate.js +8 -0
- package/dist/cjs/utils/isValidDate.js.map +1 -0
- package/dist/cjs/utils/sql/index.d.ts +1 -0
- package/dist/cjs/utils/sql/index.js +6 -0
- package/dist/cjs/utils/sql/index.js.map +1 -0
- package/dist/cjs/utils/sql/scripts.d.ts +3 -0
- package/dist/cjs/utils/sql/scripts.js +44 -0
- package/dist/cjs/utils/sql/scripts.js.map +1 -0
- package/dist/constants/index.d.ts +11 -2
- package/dist/constants/index.js +11 -0
- package/dist/constants/index.js.map +1 -1
- package/dist/constants/interfaces.d.ts +13 -3
- package/dist/errors/definitions.d.ts +20 -3
- package/dist/errors/definitions.js +20 -2
- package/dist/errors/definitions.js.map +1 -1
- package/dist/grammar/generated/qformula.lang.d.ts +9 -0
- package/dist/grammar/generated/qformula.lang.js +5 -4
- package/dist/grammar/generated/qformula.lang.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.html +21 -0
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts +1 -0
- package/dist/main.js +65 -0
- package/dist/main.js.map +1 -0
- package/dist/module/constants/index.d.ts +53 -0
- package/dist/module/constants/index.js +114 -0
- package/dist/module/constants/index.js.map +1 -0
- package/dist/module/constants/interfaces.d.ts +91 -0
- package/dist/module/constants/interfaces.js +2 -0
- package/dist/module/constants/interfaces.js.map +1 -0
- package/dist/module/errors/definitions.d.ts +43 -0
- package/dist/module/errors/definitions.js +78 -0
- package/dist/module/errors/definitions.js.map +1 -0
- package/dist/module/errors/elasticsearch.d.ts +24 -0
- package/dist/module/errors/elasticsearch.js +27 -0
- package/dist/module/errors/elasticsearch.js.map +1 -0
- package/dist/module/errors/engineErrors.d.ts +2 -0
- package/dist/module/errors/engineErrors.js +21 -0
- package/dist/module/errors/engineErrors.js.map +1 -0
- package/dist/module/errors/index.d.ts +2 -0
- package/dist/module/errors/index.js +5 -0
- package/dist/module/errors/index.js.map +1 -0
- package/dist/module/errors/snowflake.d.ts +15 -0
- package/dist/module/errors/snowflake.js +17 -0
- package/dist/module/errors/snowflake.js.map +1 -0
- package/dist/module/functions/abs.d.ts +5 -0
- package/dist/module/functions/abs.js +35 -0
- package/dist/module/functions/abs.js.map +1 -0
- package/dist/module/functions/datedif.d.ts +5 -0
- package/dist/module/functions/datedif.js +61 -0
- package/dist/module/functions/datedif.js.map +1 -0
- package/dist/module/functions/day.d.ts +5 -0
- package/dist/module/functions/day.js +36 -0
- package/dist/module/functions/day.js.map +1 -0
- package/dist/module/functions/hour.d.ts +5 -0
- package/dist/module/functions/hour.js +36 -0
- package/dist/module/functions/hour.js.map +1 -0
- package/dist/module/functions/if.d.ts +5 -0
- package/dist/module/functions/if.js +49 -0
- package/dist/module/functions/if.js.map +1 -0
- package/dist/module/functions/ifs.d.ts +5 -0
- package/dist/module/functions/ifs.js +71 -0
- package/dist/module/functions/ifs.js.map +1 -0
- package/dist/module/functions/index.d.ts +4 -0
- package/dist/module/functions/index.js +29 -0
- package/dist/module/functions/index.js.map +1 -0
- package/dist/module/functions/mid.d.ts +5 -0
- package/dist/module/functions/mid.js +51 -0
- package/dist/module/functions/mid.js.map +1 -0
- package/dist/module/functions/minute.d.ts +5 -0
- package/dist/module/functions/minute.js +36 -0
- package/dist/module/functions/minute.js.map +1 -0
- package/dist/module/functions/month.d.ts +5 -0
- package/dist/module/functions/month.js +36 -0
- package/dist/module/functions/month.js.map +1 -0
- package/dist/module/functions/second.d.ts +5 -0
- package/dist/module/functions/second.js +36 -0
- package/dist/module/functions/second.js.map +1 -0
- package/dist/module/functions/year.d.ts +5 -0
- package/dist/module/functions/year.js +36 -0
- package/dist/module/functions/year.js.map +1 -0
- package/dist/module/grammar/generated/qformula.lang.d.ts +13 -0
- package/dist/module/grammar/generated/qformula.lang.js +45 -0
- package/dist/module/grammar/generated/qformula.lang.js.map +1 -0
- package/dist/module/grammar/qformula.grammar.d.ts +1 -0
- package/dist/module/grammar/qformula.grammar.js +2 -0
- package/dist/module/grammar/qformula.grammar.js.map +1 -0
- package/dist/module/index.d.ts +10 -0
- package/dist/module/index.js +20 -0
- package/dist/module/index.js.map +1 -0
- package/dist/module/main.d.ts +1 -0
- package/dist/module/main.js +67 -0
- package/dist/module/main.js.map +1 -0
- package/dist/module/parser/json-parser.d.ts +3 -0
- package/dist/module/parser/json-parser.js +197 -0
- package/dist/module/parser/json-parser.js.map +1 -0
- package/dist/module/parser/syntax-errors.d.ts +3 -0
- package/dist/module/parser/syntax-errors.js +24 -0
- package/dist/module/parser/syntax-errors.js.map +1 -0
- package/dist/module/transpiler/columnTranspilation.d.ts +3 -0
- package/dist/module/transpiler/columnTranspilation.js +25 -0
- package/dist/module/transpiler/columnTranspilation.js.map +1 -0
- package/dist/module/transpiler/index.d.ts +18 -0
- package/dist/module/transpiler/index.js +102 -0
- package/dist/module/transpiler/index.js.map +1 -0
- package/dist/module/transpiler/unshiftCustomFunctions.d.ts +2 -0
- package/dist/module/transpiler/unshiftCustomFunctions.js +10 -0
- package/dist/module/transpiler/unshiftCustomFunctions.js.map +1 -0
- package/dist/module/transpiler/validateFuncStructure.d.ts +2 -0
- package/dist/module/transpiler/validateFuncStructure.js +37 -0
- package/dist/module/transpiler/validateFuncStructure.js.map +1 -0
- package/dist/module/utils/customFunctions.d.ts +4 -0
- package/dist/module/utils/customFunctions.js +29 -0
- package/dist/module/utils/customFunctions.js.map +1 -0
- package/dist/module/utils/elasticsearch/index.d.ts +2 -0
- package/dist/module/utils/elasticsearch/index.js +16 -0
- package/dist/module/utils/elasticsearch/index.js.map +1 -0
- package/dist/module/utils/elasticsearch/scripts.d.ts +11 -0
- package/dist/module/utils/elasticsearch/scripts.js +46 -0
- package/dist/module/utils/elasticsearch/scripts.js.map +1 -0
- package/dist/module/utils/getMonthMaxDayAllowed.d.ts +7 -0
- package/dist/module/utils/getMonthMaxDayAllowed.js +22 -0
- package/dist/module/utils/getMonthMaxDayAllowed.js.map +1 -0
- package/dist/module/utils/getNodeValue.d.ts +2 -0
- package/dist/module/utils/getNodeValue.js +9 -0
- package/dist/module/utils/getNodeValue.js.map +1 -0
- package/dist/module/utils/getVariableType.d.ts +3 -0
- package/dist/module/utils/getVariableType.js +14 -0
- package/dist/module/utils/getVariableType.js.map +1 -0
- package/dist/module/utils/index.d.ts +10 -0
- package/dist/module/utils/index.js +11 -0
- package/dist/module/utils/index.js.map +1 -0
- package/dist/module/utils/isDateParam.d.ts +2 -0
- package/dist/module/utils/isDateParam.js +8 -0
- package/dist/module/utils/isDateParam.js.map +1 -0
- package/dist/module/utils/isNumberParam.d.ts +2 -0
- package/dist/module/utils/isNumberParam.js +8 -0
- package/dist/module/utils/isNumberParam.js.map +1 -0
- package/dist/module/utils/isPositiveNumberParam.d.ts +2 -0
- package/dist/module/utils/isPositiveNumberParam.js +8 -0
- package/dist/module/utils/isPositiveNumberParam.js.map +1 -0
- package/dist/module/utils/isStringParam.d.ts +2 -0
- package/dist/module/utils/isStringParam.js +8 -0
- package/dist/module/utils/isStringParam.js.map +1 -0
- package/dist/module/utils/isValidDate.d.ts +1 -0
- package/dist/module/utils/isValidDate.js +4 -0
- package/dist/module/utils/isValidDate.js.map +1 -0
- package/dist/module/utils/sql/index.d.ts +1 -0
- package/dist/module/utils/sql/index.js +2 -0
- package/dist/module/utils/sql/index.js.map +1 -0
- package/dist/module/utils/sql/scripts.d.ts +3 -0
- package/dist/module/utils/sql/scripts.js +39 -0
- package/dist/module/utils/sql/scripts.js.map +1 -0
- package/dist/parser/json-parser.js +26 -15
- package/dist/parser/json-parser.js.map +1 -1
- package/dist/parser/syntax-errors.d.ts +3 -0
- package/dist/parser/syntax-errors.js +20 -0
- package/dist/parser/syntax-errors.js.map +1 -0
- package/dist/transpiler/columnTranspilation.d.ts +2 -2
- package/dist/transpiler/columnTranspilation.js +10 -4
- package/dist/transpiler/columnTranspilation.js.map +1 -1
- package/dist/transpiler/index.d.ts +4 -4
- package/dist/transpiler/index.js +28 -20
- package/dist/transpiler/index.js.map +1 -1
- package/dist/transpiler/unshiftCustomFunctions.d.ts +2 -0
- package/dist/transpiler/unshiftCustomFunctions.js +10 -0
- package/dist/transpiler/unshiftCustomFunctions.js.map +1 -0
- package/dist/utils/customFunctions.d.ts +1 -0
- package/dist/utils/customFunctions.js +10 -2
- package/dist/utils/customFunctions.js.map +1 -1
- package/dist/utils/elasticsearch/index.d.ts +1 -1
- package/dist/utils/elasticsearch/index.js +1 -1
- package/dist/utils/elasticsearch/index.js.map +1 -1
- package/dist/utils/elasticsearch/scripts.d.ts +1 -0
- package/dist/utils/elasticsearch/scripts.js +14 -4
- package/dist/utils/elasticsearch/scripts.js.map +1 -1
- package/jest.config.ts +6 -0
- package/package.json +21 -6
- package/__tests__/integration/__mocks__/context.ts +0 -23
- package/__tests__/integration/__mocks__/elasticsearchScripts.ts +0 -28
- package/__tests__/integration/__mocks__/sqlScripts.ts +0 -21
- package/__tests__/integration/elasticsearch.test.ts +0 -172
- package/__tests__/integration/expression.test.ts +0 -56
- package/__tests__/integration/redshift.test.ts +0 -142
- package/__tests__/integration/sonwflake.test.ts +0 -138
- package/__tests__/unit/parser.test.ts +0 -236
- package/__tests__/unit/transpiler.test.ts +0 -128
- package/bitbucket-pipelines.yml +0 -63
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import { ENGINES, Transpile } from '../../src';
|
|
2
|
-
import { datePart, dateDif } from './__mocks__/sqlScripts';
|
|
3
|
-
import { basicContext } from './__mocks__/context';
|
|
4
|
-
const currentEngine = ENGINES.SNOWFLAKE;
|
|
5
|
-
|
|
6
|
-
describe('SNOWFLAKE Transpile program', () => {
|
|
7
|
-
test('Basic case', () => {
|
|
8
|
-
const result = Transpile('1 + 2', currentEngine);
|
|
9
|
-
expect(result?.expression).toBe('(1 + 2)');
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
test('MID function', () => {
|
|
13
|
-
const result = Transpile('MID("test", 1, 5)', currentEngine);
|
|
14
|
-
expect(result?.expression).toBe(`SUBSTRING('test', 1, 5)`);
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
test('Should transpile a function inside another function', () => {
|
|
18
|
-
const program = 'MID(MID("This is a test", 1, 5), 1, 2)';
|
|
19
|
-
const result = Transpile(program, currentEngine);
|
|
20
|
-
expect(result?.valid).toBe(true);
|
|
21
|
-
expect(result?.expression).toBe(
|
|
22
|
-
"SUBSTRING(SUBSTRING('This is a test', 1, 5), 1, 2)",
|
|
23
|
-
);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
test('ABS function', () => {
|
|
27
|
-
const result = Transpile('ABS(5)', currentEngine);
|
|
28
|
-
expect(result?.expression).toBe(`ABS(5)`);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test('Cast Date string', () => {
|
|
32
|
-
const result = Transpile('"12/31/2022 13:35:45"', currentEngine);
|
|
33
|
-
expect(result?.expression).toBe(
|
|
34
|
-
`CAST('2022-12-31T13:35:45.000Z' AS TIMESTAMPTZ)`,
|
|
35
|
-
);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
test('DAY function', () => {
|
|
39
|
-
const result = Transpile('DAY("12/31/2023")', currentEngine);
|
|
40
|
-
expect(result?.expression).toBe(datePart('day'));
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
test('DAY function with a variable Column', () => {
|
|
44
|
-
const result = Transpile('DAY([DateID1])', currentEngine, basicContext);
|
|
45
|
-
const column = '"Origin_Date_Column_Test"';
|
|
46
|
-
const mock = datePart('day', column).replace(/\n/g, '');
|
|
47
|
-
expect(result?.expression?.replace(/\n/g, '')).toBe(mock);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
test('MONTH function', () => {
|
|
51
|
-
const result = Transpile('MONTH("12/31/2023")', currentEngine);
|
|
52
|
-
expect(result?.expression).toBe(datePart('month'));
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
test('YEAR function', () => {
|
|
56
|
-
const result = Transpile('YEAR("12/31/2023")', currentEngine);
|
|
57
|
-
expect(result?.expression).toBe(datePart('year'));
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
test('HOUR function', () => {
|
|
61
|
-
const result = Transpile('HOUR("12/31/2023")', currentEngine);
|
|
62
|
-
expect(result?.expression).toBe(datePart('hour'));
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
test('MINUTE function', () => {
|
|
66
|
-
const result = Transpile('MINUTE("12/31/2023")', currentEngine);
|
|
67
|
-
expect(result?.expression).toBe(datePart('minute'));
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
test('SECOND function', () => {
|
|
71
|
-
const result = Transpile('SECOND("12/31/2023")', currentEngine);
|
|
72
|
-
expect(result?.expression).toBe(datePart('second'));
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
test('DATEDIF function with Y unit', () => {
|
|
76
|
-
const result = Transpile(
|
|
77
|
-
'DATEDIF("12/31/2023", "12/31/2022", "Y")',
|
|
78
|
-
currentEngine,
|
|
79
|
-
);
|
|
80
|
-
const mock = dateDif('year');
|
|
81
|
-
expect(result?.expression).toBe(mock);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
test('DATEDIF function with M unit', () => {
|
|
85
|
-
const result = Transpile(
|
|
86
|
-
'DATEDIF("12/31/2023", "12/31/2022", "M")',
|
|
87
|
-
currentEngine,
|
|
88
|
-
);
|
|
89
|
-
const mock = dateDif('month');
|
|
90
|
-
expect(result?.expression).toBe(mock);
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
test('DATEDIF function with D unit', () => {
|
|
94
|
-
const result = Transpile(
|
|
95
|
-
'DATEDIF("12/31/2023", "12/31/2022", "D")',
|
|
96
|
-
currentEngine,
|
|
97
|
-
);
|
|
98
|
-
const mock = dateDif('day');
|
|
99
|
-
expect(result?.expression).toBe(mock);
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
test('DATEDIF function with a not valid Unit', () => {
|
|
103
|
-
const result = Transpile(
|
|
104
|
-
'DATEDIF("12/31/2023", "12/31/2022", "X")',
|
|
105
|
-
currentEngine,
|
|
106
|
-
);
|
|
107
|
-
expect(result).not.toBeUndefined();
|
|
108
|
-
expect(result?.valid).toBe(false);
|
|
109
|
-
expect(result?.error).not.toBeUndefined();
|
|
110
|
-
expect(result?.error?.code).toBe('DATE_DIF_UNIT_PARAM');
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
test('IF function full parameters', () => {
|
|
114
|
-
const result = Transpile('IF(5 = 1, "True", "False")', currentEngine);
|
|
115
|
-
expect(result).not.toBeUndefined();
|
|
116
|
-
expect(result?.error).toBeUndefined();
|
|
117
|
-
expect(result?.expression).toBe(`IFF((5 = 1), 'True', 'False')`);
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
test('IF function basic parameters', () => {
|
|
121
|
-
const result = Transpile('IF(5 = 1, "True")', currentEngine);
|
|
122
|
-
expect(result).not.toBeUndefined();
|
|
123
|
-
expect(result?.error).toBeUndefined();
|
|
124
|
-
expect(result?.expression).toBe(`IFF((5 = 1), 'True', FALSE)`);
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
test('IFS function basic parameters', () => {
|
|
128
|
-
const result = Transpile(
|
|
129
|
-
'IFS(5>10, "Greater than 10", 5>5, "Greater than 5",5>0, "Greater than 0")',
|
|
130
|
-
currentEngine,
|
|
131
|
-
);
|
|
132
|
-
expect(result).not.toBeUndefined();
|
|
133
|
-
expect(result?.error).toBeUndefined();
|
|
134
|
-
expect(result?.expression).toBe(
|
|
135
|
-
`IFF((5 > 10), 'Greater than 10', IFF((5 > 5), 'Greater than 5', IFF((5 > 0), 'Greater than 0', NULL)))`,
|
|
136
|
-
);
|
|
137
|
-
});
|
|
138
|
-
});
|
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
import { AST_TYPES } from '../../src/constants';
|
|
2
|
-
import { calculateAST, FormulaLang } from '../../src';
|
|
3
|
-
import {
|
|
4
|
-
BinaryExpressionAST,
|
|
5
|
-
FormulaContext,
|
|
6
|
-
LiteralAST,
|
|
7
|
-
UnaryExpressionAST,
|
|
8
|
-
VariableAST,
|
|
9
|
-
} from '../../src/constants/interfaces';
|
|
10
|
-
|
|
11
|
-
describe('Parser tests suite', () => {
|
|
12
|
-
test('Should parse a single node', () => {
|
|
13
|
-
const program = '1 + 2';
|
|
14
|
-
const parser = FormulaLang.parser;
|
|
15
|
-
const { topNode } = parser.parse(program);
|
|
16
|
-
const ast = calculateAST(program, topNode);
|
|
17
|
-
expect(ast?.body).not.toBeUndefined();
|
|
18
|
-
|
|
19
|
-
const body = ast?.body as BinaryExpressionAST;
|
|
20
|
-
expect(body.operator).toBe('+');
|
|
21
|
-
expect(body.type).toBe(AST_TYPES.binaryExpression);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
test('Should fail a logic operation', () => {
|
|
25
|
-
const program = '1 <';
|
|
26
|
-
const parser = FormulaLang.parser;
|
|
27
|
-
const { topNode } = parser.parse(program);
|
|
28
|
-
const ast = calculateAST(program, topNode);
|
|
29
|
-
expect(ast?.body).not.toBeUndefined();
|
|
30
|
-
|
|
31
|
-
const body = ast?.body as BinaryExpressionAST;
|
|
32
|
-
expect(body.operator).toBe('<');
|
|
33
|
-
expect(body.type).toBe(AST_TYPES.binaryExpression);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
describe('Value types', () => {
|
|
37
|
-
test('Should return a unary expression', () => {
|
|
38
|
-
const program = '-2';
|
|
39
|
-
const parser = FormulaLang.parser;
|
|
40
|
-
const { topNode } = parser.parse(program);
|
|
41
|
-
const ast = calculateAST(program, topNode);
|
|
42
|
-
expect(ast?.body).not.toBeUndefined();
|
|
43
|
-
|
|
44
|
-
const body = ast?.body as UnaryExpressionAST;
|
|
45
|
-
expect(body.operator).toEqual('-');
|
|
46
|
-
const numberResult = body.right as LiteralAST;
|
|
47
|
-
expect(numberResult.type).toEqual('Literal');
|
|
48
|
-
expect(numberResult.dataType).toEqual('number');
|
|
49
|
-
expect(numberResult.value).toEqual(2);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
test('Should return a boolean expression', () => {
|
|
53
|
-
const program = 'false';
|
|
54
|
-
const parser = FormulaLang.parser;
|
|
55
|
-
const { topNode } = parser.parse(program);
|
|
56
|
-
const ast = calculateAST(program, topNode);
|
|
57
|
-
expect(ast?.body).not.toBeUndefined();
|
|
58
|
-
|
|
59
|
-
const body = ast?.body as LiteralAST;
|
|
60
|
-
expect(body.type).toEqual('Literal');
|
|
61
|
-
expect(body.dataType).toEqual('boolean');
|
|
62
|
-
expect(body.value).toEqual(false);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
test('Should return a null expression', () => {
|
|
66
|
-
const program = 'null';
|
|
67
|
-
const parser = FormulaLang.parser;
|
|
68
|
-
const { topNode } = parser.parse(program);
|
|
69
|
-
const ast = calculateAST(program, topNode);
|
|
70
|
-
expect(ast?.body).not.toBeUndefined();
|
|
71
|
-
|
|
72
|
-
const body = ast?.body as LiteralAST;
|
|
73
|
-
expect(body.type).toEqual('Literal');
|
|
74
|
-
expect(body.dataType).toEqual('null');
|
|
75
|
-
expect(body.value).toEqual(null);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
test('Should return a array expression', () => {
|
|
79
|
-
const program = '<1,2,3>';
|
|
80
|
-
const parser = FormulaLang.parser;
|
|
81
|
-
const { topNode } = parser.parse(program);
|
|
82
|
-
const ast = calculateAST(program, topNode);
|
|
83
|
-
expect(ast?.body).not.toBeUndefined();
|
|
84
|
-
|
|
85
|
-
const body = ast?.body as LiteralAST;
|
|
86
|
-
expect(body.type).toEqual('Literal');
|
|
87
|
-
expect(body.dataType).toEqual('array');
|
|
88
|
-
const arrayValue = body.value as Array<LiteralAST>;
|
|
89
|
-
|
|
90
|
-
expect(arrayValue[0].type).toEqual('Literal');
|
|
91
|
-
expect(arrayValue[0].dataType).toEqual('number');
|
|
92
|
-
expect(arrayValue[0].value).toEqual(1);
|
|
93
|
-
expect(arrayValue[1].type).toEqual('Literal');
|
|
94
|
-
expect(arrayValue[1].dataType).toEqual('number');
|
|
95
|
-
expect(arrayValue[1].value).toEqual(2);
|
|
96
|
-
expect(arrayValue[2].type).toEqual('Literal');
|
|
97
|
-
expect(arrayValue[2].dataType).toEqual('number');
|
|
98
|
-
expect(arrayValue[2].value).toEqual(3);
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
describe('Date literals', () => {
|
|
103
|
-
test('Should fail with a date without time', () => {
|
|
104
|
-
const program = '"31/12/2022"';
|
|
105
|
-
const parser = FormulaLang.parser;
|
|
106
|
-
const { topNode } = parser.parse(program);
|
|
107
|
-
const ast = calculateAST(program, topNode);
|
|
108
|
-
expect(ast?.body).not.toBeUndefined();
|
|
109
|
-
|
|
110
|
-
const body = ast?.body as LiteralAST;
|
|
111
|
-
expect(body.value).toEqual('31/12/2022');
|
|
112
|
-
expect(body.dataType).toBe('string');
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
test('Should return a date without time', () => {
|
|
116
|
-
const program = '"12/31/2022"';
|
|
117
|
-
const parser = FormulaLang.parser;
|
|
118
|
-
const { topNode } = parser.parse(program);
|
|
119
|
-
const ast = calculateAST(program, topNode);
|
|
120
|
-
expect(ast?.body).not.toBeUndefined();
|
|
121
|
-
|
|
122
|
-
const body = ast?.body as LiteralAST;
|
|
123
|
-
expect(body.value).toEqual('2022-12-31T00:00:00.000Z');
|
|
124
|
-
expect(body.dataType).toBe('date');
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
test('Should return a date with time', () => {
|
|
128
|
-
const program = '"12/31/2022 15:22:18"';
|
|
129
|
-
const parser = FormulaLang.parser;
|
|
130
|
-
const { topNode } = parser.parse(program);
|
|
131
|
-
const ast = calculateAST(program, topNode);
|
|
132
|
-
expect(ast?.body).not.toBeUndefined();
|
|
133
|
-
|
|
134
|
-
const body = ast?.body as LiteralAST;
|
|
135
|
-
expect(body.value).toEqual('2022-12-31T15:22:18.000Z');
|
|
136
|
-
expect(body.dataType).toBe('date');
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
test('Should return a date with invalid time', () => {
|
|
140
|
-
const program = '"12/31/2022 15:89:18"';
|
|
141
|
-
const parser = FormulaLang.parser;
|
|
142
|
-
const { topNode } = parser.parse(program);
|
|
143
|
-
const ast = calculateAST(program, topNode);
|
|
144
|
-
expect(ast?.body).not.toBeUndefined();
|
|
145
|
-
|
|
146
|
-
const body = ast?.body as LiteralAST;
|
|
147
|
-
expect(body.value).toEqual('12/31/2022 15:89:18');
|
|
148
|
-
expect(body.dataType).toBe('string');
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
test('Should return string with invalid dates february with 31', () => {
|
|
152
|
-
const program = '"02/31/2022 15:23:18"';
|
|
153
|
-
const parser = FormulaLang.parser;
|
|
154
|
-
const { topNode } = parser.parse(program);
|
|
155
|
-
const ast = calculateAST(program, topNode);
|
|
156
|
-
expect(ast?.body).not.toBeUndefined();
|
|
157
|
-
|
|
158
|
-
const body = ast?.body as LiteralAST;
|
|
159
|
-
expect(body.value).toEqual('02/31/2022 15:23:18');
|
|
160
|
-
expect(body.dataType).toBe('string');
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
test('Should return date valid for leap years february with 29', () => {
|
|
164
|
-
const program = '"02/29/2024"';
|
|
165
|
-
const parser = FormulaLang.parser;
|
|
166
|
-
const { topNode } = parser.parse(program);
|
|
167
|
-
const ast = calculateAST(program, topNode);
|
|
168
|
-
expect(ast?.body).not.toBeUndefined();
|
|
169
|
-
|
|
170
|
-
const body = ast?.body as LiteralAST;
|
|
171
|
-
expect(body.value).toEqual('2024-02-29T00:00:00.000Z');
|
|
172
|
-
expect(body.dataType).toBe('date');
|
|
173
|
-
});
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
describe('Parser with context', () => {
|
|
177
|
-
const context: FormulaContext = {
|
|
178
|
-
model: [
|
|
179
|
-
{
|
|
180
|
-
id: 'column.test',
|
|
181
|
-
label: 'Column Test',
|
|
182
|
-
column: 'Origin_Column_Test',
|
|
183
|
-
type: 'string',
|
|
184
|
-
},
|
|
185
|
-
{
|
|
186
|
-
id: 'NOW',
|
|
187
|
-
label: 'NOW',
|
|
188
|
-
type: 'string',
|
|
189
|
-
},
|
|
190
|
-
],
|
|
191
|
-
};
|
|
192
|
-
test('Should return a column without context', () => {
|
|
193
|
-
const program = '[columnNoContext]';
|
|
194
|
-
const parser = FormulaLang.parser;
|
|
195
|
-
const { topNode } = parser.parse(program);
|
|
196
|
-
const ast = calculateAST(program, topNode, context);
|
|
197
|
-
expect(ast?.body).not.toBeUndefined();
|
|
198
|
-
|
|
199
|
-
const body = ast?.body as VariableAST;
|
|
200
|
-
expect(body.value).toEqual('columnNoContext');
|
|
201
|
-
expect(body.type).toEqual('Variable');
|
|
202
|
-
expect(body.context).toBeUndefined();
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
test('Should return a column with context', () => {
|
|
206
|
-
const program = '[column.test]';
|
|
207
|
-
const parser = FormulaLang.parser;
|
|
208
|
-
const { topNode } = parser.parse(program);
|
|
209
|
-
const ast = calculateAST(program, topNode, context);
|
|
210
|
-
expect(ast?.body).not.toBeUndefined();
|
|
211
|
-
|
|
212
|
-
const body = ast?.body as VariableAST;
|
|
213
|
-
expect(body.value).toEqual('column.test');
|
|
214
|
-
expect(body.type).toEqual('Column');
|
|
215
|
-
expect(body.context?.id).toEqual('column.test');
|
|
216
|
-
expect(body.context?.type).toEqual('string');
|
|
217
|
-
expect(body.context?.label).toEqual('Column Test');
|
|
218
|
-
expect(body.context?.column).toEqual('Origin_Column_Test');
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
test('Should return a token with context', () => {
|
|
222
|
-
const program = '[NOW]';
|
|
223
|
-
const parser = FormulaLang.parser;
|
|
224
|
-
const { topNode } = parser.parse(program);
|
|
225
|
-
const ast = calculateAST(program, topNode, context);
|
|
226
|
-
expect(ast?.body).not.toBeUndefined();
|
|
227
|
-
|
|
228
|
-
const body = ast?.body as VariableAST;
|
|
229
|
-
expect(body.value).toEqual('{{NOW}}');
|
|
230
|
-
expect(body.type).toEqual('Token');
|
|
231
|
-
expect(body.context?.id).toEqual('NOW');
|
|
232
|
-
expect(body.context?.type).toEqual('string');
|
|
233
|
-
expect(body.context?.label).toEqual('NOW');
|
|
234
|
-
});
|
|
235
|
-
});
|
|
236
|
-
});
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import { ENGINES } from '../../src/constants';
|
|
2
|
-
import { ProgramAST } from '../../src/constants/interfaces';
|
|
3
|
-
import { Transpiler } from '../../src/transpiler';
|
|
4
|
-
|
|
5
|
-
describe('Transpiler tests suit', () => {
|
|
6
|
-
test('Should resolve basic arithmetic operation', () => {
|
|
7
|
-
const AST: ProgramAST = {
|
|
8
|
-
type: 'Program',
|
|
9
|
-
exp: '1 + 1',
|
|
10
|
-
lang: 'QrveyLang',
|
|
11
|
-
version: '0.0.0',
|
|
12
|
-
body: {
|
|
13
|
-
operator: '+',
|
|
14
|
-
type: 'BinaryExpression',
|
|
15
|
-
left: {
|
|
16
|
-
type: 'Literal',
|
|
17
|
-
dataType: 'number',
|
|
18
|
-
value: 1,
|
|
19
|
-
},
|
|
20
|
-
right: {
|
|
21
|
-
type: 'Literal',
|
|
22
|
-
dataType: 'number',
|
|
23
|
-
value: 2,
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
} as ProgramAST;
|
|
27
|
-
|
|
28
|
-
const transpiler = new Transpiler(AST, ENGINES.ELASTICSEARCH);
|
|
29
|
-
const result = transpiler.get();
|
|
30
|
-
expect(result.expression).toBe('(1 + 2)');
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
test('Should resolve basic logic operation', () => {
|
|
34
|
-
const AST: ProgramAST = {
|
|
35
|
-
type: 'Program',
|
|
36
|
-
exp: '1 <= 1',
|
|
37
|
-
lang: 'QrveyLang',
|
|
38
|
-
version: '0.0.0',
|
|
39
|
-
body: {
|
|
40
|
-
operator: '<=',
|
|
41
|
-
type: 'BinaryExpression',
|
|
42
|
-
left: {
|
|
43
|
-
type: 'Literal',
|
|
44
|
-
dataType: 'number',
|
|
45
|
-
value: 1,
|
|
46
|
-
},
|
|
47
|
-
right: {
|
|
48
|
-
type: 'Literal',
|
|
49
|
-
dataType: 'number',
|
|
50
|
-
value: 2,
|
|
51
|
-
},
|
|
52
|
-
},
|
|
53
|
-
} as ProgramAST;
|
|
54
|
-
|
|
55
|
-
const transpiler = new Transpiler(AST, ENGINES.ELASTICSEARCH);
|
|
56
|
-
const result = transpiler.get();
|
|
57
|
-
expect(result.expression).toBe('(1 <= 2)');
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
test('Should resolve MID function', () => {
|
|
61
|
-
const AST: ProgramAST = {
|
|
62
|
-
type: 'Program',
|
|
63
|
-
exp: 'MID("string", 2, 3)',
|
|
64
|
-
lang: 'QrveyLang',
|
|
65
|
-
version: '0.0.0',
|
|
66
|
-
body: {
|
|
67
|
-
type: 'FunctionCall',
|
|
68
|
-
name: 'MID',
|
|
69
|
-
arguments: [
|
|
70
|
-
{
|
|
71
|
-
type: 'Literal',
|
|
72
|
-
dataType: 'string',
|
|
73
|
-
value: 'string',
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
type: 'Literal',
|
|
77
|
-
dataType: 'number',
|
|
78
|
-
value: 2,
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
type: 'Literal',
|
|
82
|
-
dataType: 'number',
|
|
83
|
-
value: 3,
|
|
84
|
-
},
|
|
85
|
-
],
|
|
86
|
-
},
|
|
87
|
-
} as ProgramAST;
|
|
88
|
-
|
|
89
|
-
const transpiler = new Transpiler(AST, ENGINES.ELASTICSEARCH);
|
|
90
|
-
const result = transpiler.get();
|
|
91
|
-
expect(result.expression).toBe(`'string'.substring(2, 3)`);
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
test('Should throw a exception because is a invalid expression (function does not exists)', () => {
|
|
95
|
-
const AST: ProgramAST = {
|
|
96
|
-
type: 'Program',
|
|
97
|
-
exp: 'MID1("string", 2, 3)',
|
|
98
|
-
lang: 'QrveyLang',
|
|
99
|
-
version: '0.0.0',
|
|
100
|
-
body: {
|
|
101
|
-
type: 'FunctionCall',
|
|
102
|
-
name: 'MID1',
|
|
103
|
-
arguments: [
|
|
104
|
-
{
|
|
105
|
-
type: 'Literal',
|
|
106
|
-
dataType: 'string',
|
|
107
|
-
value: 'string',
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
type: 'Literal',
|
|
111
|
-
dataType: 'number',
|
|
112
|
-
value: 2,
|
|
113
|
-
},
|
|
114
|
-
{
|
|
115
|
-
type: 'Literal',
|
|
116
|
-
dataType: 'number',
|
|
117
|
-
value: 3,
|
|
118
|
-
},
|
|
119
|
-
],
|
|
120
|
-
},
|
|
121
|
-
} as ProgramAST;
|
|
122
|
-
|
|
123
|
-
const transpiler = new Transpiler(AST, ENGINES.ELASTICSEARCH);
|
|
124
|
-
const result = transpiler.get();
|
|
125
|
-
expect(result.valid).toBe(false);
|
|
126
|
-
expect(result.error).not.toBeUndefined();
|
|
127
|
-
});
|
|
128
|
-
});
|
package/bitbucket-pipelines.yml
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
image: node:16
|
|
2
|
-
|
|
3
|
-
clone:
|
|
4
|
-
depth: full # SonarCloud scanner needs the full history to assign issues properly
|
|
5
|
-
|
|
6
|
-
unitTesting: &unitTesting
|
|
7
|
-
name: Unit tests
|
|
8
|
-
caches:
|
|
9
|
-
- node
|
|
10
|
-
- npm
|
|
11
|
-
script:
|
|
12
|
-
- npm run test:coverage
|
|
13
|
-
artifacts:
|
|
14
|
-
# store coverage report
|
|
15
|
-
- coverage/**
|
|
16
|
-
|
|
17
|
-
sonar: &sonar
|
|
18
|
-
name: SonarQube analysis
|
|
19
|
-
image: maven:3.3.9
|
|
20
|
-
caches:
|
|
21
|
-
- sonar
|
|
22
|
-
script:
|
|
23
|
-
- pipe: sonarsource/sonarqube-scan:1.2.0
|
|
24
|
-
variables:
|
|
25
|
-
SONAR_HOST_URL: ${SONAR_HOST_URL} # Get the value from the repository/workspace variable.
|
|
26
|
-
SONAR_TOKEN: ${SONAR_TOKEN} # Get the value from the repository/workspace variable. You shouldn't set secret in clear text here.
|
|
27
|
-
|
|
28
|
-
pipelines:
|
|
29
|
-
branches:
|
|
30
|
-
develop:
|
|
31
|
-
- step:
|
|
32
|
-
name: 'Install, lint, and build'
|
|
33
|
-
caches:
|
|
34
|
-
- node
|
|
35
|
-
- npm
|
|
36
|
-
script:
|
|
37
|
-
- npm ci --unsafe-perm
|
|
38
|
-
- npm run lint
|
|
39
|
-
- npm run build
|
|
40
|
-
- step:
|
|
41
|
-
<<: *unitTesting
|
|
42
|
-
- step:
|
|
43
|
-
<<: *sonar
|
|
44
|
-
default:
|
|
45
|
-
- step:
|
|
46
|
-
name: 'Install, lint, and build'
|
|
47
|
-
caches:
|
|
48
|
-
- node
|
|
49
|
-
- npm
|
|
50
|
-
script:
|
|
51
|
-
- npm ci --unsafe-perm
|
|
52
|
-
- npm run lint
|
|
53
|
-
- npm run build
|
|
54
|
-
- step:
|
|
55
|
-
<<: *unitTesting
|
|
56
|
-
|
|
57
|
-
definitions:
|
|
58
|
-
caches:
|
|
59
|
-
npm: $HOME/.npm
|
|
60
|
-
sonar: ~/.sonar
|
|
61
|
-
services:
|
|
62
|
-
docker:
|
|
63
|
-
memory: 2048
|