@squiz/dx-json-schema-lib 1.39.0 → 1.39.1-alpha.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.
- package/.npm/_logs/{2023-06-21T06_19_37_197Z-debug-0.log → 2023-06-22T05_23_22_241Z-debug-0.log} +9 -9
- package/jsonCompiler.ts +1 -0
- package/lib/JsonValidationService.d.ts +1 -1
- package/lib/JsonValidationService.js +7 -0
- package/lib/JsonValidationService.js.map +1 -1
- package/lib/manifest/v1/JobV1.d.ts +192 -0
- package/lib/manifest/v1/JobV1.js +9 -0
- package/lib/manifest/v1/JobV1.js.map +1 -0
- package/lib/manifest/v1/JobV1.json +88 -0
- package/lib/manifest/v1/JobV1.spec.d.ts +1 -0
- package/lib/manifest/v1/JobV1.spec.js +75 -0
- package/lib/manifest/v1/JobV1.spec.js.map +1 -0
- package/lib/manifest/v1/__test__/schemas/badFunctionInputJob.json +25 -0
- package/lib/manifest/v1/__test__/schemas/nonObjectFunctionInputJob.json +25 -0
- package/lib/manifest/v1/__test__/schemas/validJob.json +25 -0
- package/lib/manifest/v1/manifestModels.d.ts +1 -0
- package/lib/manifest/v1/manifestModels.js +2 -1
- package/lib/manifest/v1/manifestModels.js.map +1 -1
- package/lib/manifest/v1/manifestSchemas.d.ts +2 -1
- package/lib/manifest/v1/manifestSchemas.js +3 -1
- package/lib/manifest/v1/manifestSchemas.js.map +1 -1
- package/lib/manifest/v1/v1.json +26 -7
- package/package.json +2 -2
- package/src/JsonValidationService.ts +9 -1
- package/src/manifest/v1/JobV1.json +88 -0
- package/src/manifest/v1/JobV1.spec.ts +110 -0
- package/src/manifest/v1/JobV1.ts +447 -0
- package/src/manifest/v1/__test__/schemas/badFunctionInputJob.json +25 -0
- package/src/manifest/v1/__test__/schemas/nonObjectFunctionInputJob.json +25 -0
- package/src/manifest/v1/__test__/schemas/validJob.json +25 -0
- package/src/manifest/v1/manifestModels.ts +1 -0
- package/src/manifest/v1/manifestSchemas.ts +2 -1
- package/src/manifest/v1/v1.json +26 -14
- package/tsconfig.tsbuildinfo +1 -1
package/lib/manifest/v1/v1.json
CHANGED
@@ -4,15 +4,28 @@
|
|
4
4
|
"title": "ComponentManifest",
|
5
5
|
"additionalProperties": false,
|
6
6
|
"properties": {
|
7
|
-
"$schema": {
|
7
|
+
"$schema": {
|
8
|
+
"type": "string",
|
9
|
+
"description": "the manifest schema version"
|
10
|
+
},
|
8
11
|
"namespace": {
|
9
12
|
"type": "string",
|
10
13
|
"description": "Namespace of the component",
|
11
14
|
"$ref": "#/definitions/name-pattern"
|
12
15
|
},
|
13
|
-
"name": {
|
14
|
-
|
15
|
-
|
16
|
+
"name": {
|
17
|
+
"type": "string",
|
18
|
+
"description": "Name of the component",
|
19
|
+
"$ref": "#/definitions/name-pattern"
|
20
|
+
},
|
21
|
+
"displayName": {
|
22
|
+
"type": "string",
|
23
|
+
"description": "Display name of the component"
|
24
|
+
},
|
25
|
+
"description": {
|
26
|
+
"type": "string",
|
27
|
+
"description": "Description of the component"
|
28
|
+
},
|
16
29
|
"mainFunction": {
|
17
30
|
"type": "string",
|
18
31
|
"description": "Name of the main function to be executed at the root of the access url"
|
@@ -84,7 +97,9 @@
|
|
84
97
|
"additionalProperties": false,
|
85
98
|
"description": "The HtmlResponse type is for returning html content. The response out of the function must be a string. This response object also includes references to resources (staticFiles) the component needs to execute correctly. It is up to the integrating system to respect this.",
|
86
99
|
"properties": {
|
87
|
-
"responseType": {
|
100
|
+
"responseType": {
|
101
|
+
"const": "html"
|
102
|
+
},
|
88
103
|
"staticFiles": {
|
89
104
|
"type": "array",
|
90
105
|
"description": "A list of static resources that are required for the component to execute correctly",
|
@@ -251,8 +266,12 @@
|
|
251
266
|
"type": "object",
|
252
267
|
"additionalProperties": false,
|
253
268
|
"properties": {
|
254
|
-
"responseType": {
|
255
|
-
|
269
|
+
"responseType": {
|
270
|
+
"const": "json"
|
271
|
+
},
|
272
|
+
"definition": {
|
273
|
+
"$ref": "http://json-schema.org/draft-07/schema#"
|
274
|
+
},
|
256
275
|
"headers": {
|
257
276
|
"title": "ResponseHeaders",
|
258
277
|
"type": "object",
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@squiz/dx-json-schema-lib",
|
3
|
-
"version": "1.39.
|
3
|
+
"version": "1.39.1-alpha.1",
|
4
4
|
"description": "",
|
5
5
|
"main": "lib/index.js",
|
6
6
|
"scripts": {
|
@@ -31,5 +31,5 @@
|
|
31
31
|
"@squiz/json-schema-library": "7.4.7",
|
32
32
|
"ts-brand": "0.0.2"
|
33
33
|
},
|
34
|
-
"gitHead": "
|
34
|
+
"gitHead": "16b9f02b751a923a71f96684bd46c781fc97dcbc"
|
35
35
|
}
|
@@ -11,6 +11,7 @@ import FormattedText from './formatted-text/v1/formattedText.json';
|
|
11
11
|
import PageContentsSchema from './pageContents/v1/pageContents.json';
|
12
12
|
|
13
13
|
import v1 from './manifest/v1/v1.json';
|
14
|
+
import JobV1 from './manifest/v1/JobV1.json';
|
14
15
|
import { SchemaValidationError, ValidationData, ValidationDataMap } from './errors/SchemaValidationError';
|
15
16
|
import { Draft07, JSONError, JSONSchema, Draft, DraftConfig } from '@squiz/json-schema-library';
|
16
17
|
|
@@ -152,6 +153,9 @@ v1Schema.addRemoteSchema('/MatrixAssetSchema.json', MatrixAssetSchema);
|
|
152
153
|
v1Schema.addRemoteSchema('http://json-schema.org/draft-07/schema', Draft07Schema);
|
153
154
|
v1Schema.addRemoteSchema('http://json-schema.org/draft-07/schema#', Draft07Schema);
|
154
155
|
|
156
|
+
const jobV1Schema = new Draft07(JobV1, defaultConfig);
|
157
|
+
jobV1Schema.addRemoteSchema('/DxComponentInputSchema.json', ComponentInputSchema.getSchema());
|
158
|
+
|
155
159
|
export const ComponentInputMetaSchema: MetaSchemaInput = {
|
156
160
|
root: DxComponentInputSchema,
|
157
161
|
remotes: {
|
@@ -282,12 +286,16 @@ export class JSONSchemaService<P extends AnyPrimitiveType, R extends AnyResolvab
|
|
282
286
|
}
|
283
287
|
|
284
288
|
export class JsonValidationService {
|
285
|
-
validateManifest(manifest: unknown, version: 'v1') {
|
289
|
+
validateManifest(manifest: unknown, version: 'v1' | 'JobV1') {
|
286
290
|
switch (version) {
|
287
291
|
case 'v1': {
|
288
292
|
const validationResult = v1Schema.validate(manifest);
|
289
293
|
return processValidationResult(validationResult);
|
290
294
|
}
|
295
|
+
case 'JobV1': {
|
296
|
+
const validationResult = jobV1Schema.validate(manifest);
|
297
|
+
return processValidationResult(validationResult);
|
298
|
+
}
|
291
299
|
|
292
300
|
default:
|
293
301
|
throw new SchemaValidationError('Invalid manifest version');
|
@@ -0,0 +1,88 @@
|
|
1
|
+
{
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
3
|
+
"type": "object",
|
4
|
+
"title": "JobManifest",
|
5
|
+
"additionalProperties": false,
|
6
|
+
"properties": {
|
7
|
+
"$schema": {
|
8
|
+
"type": "string",
|
9
|
+
"description": "the manifest schema version"
|
10
|
+
},
|
11
|
+
"name": {
|
12
|
+
"type": "string",
|
13
|
+
"description": "Name of the job",
|
14
|
+
"$ref": "#/definitions/name-pattern"
|
15
|
+
},
|
16
|
+
"displayName": {
|
17
|
+
"type": "string",
|
18
|
+
"description": "Display name of the job"
|
19
|
+
},
|
20
|
+
"description": {
|
21
|
+
"type": "string",
|
22
|
+
"description": "Description of the job"
|
23
|
+
},
|
24
|
+
"mainFunction": {
|
25
|
+
"type": "string",
|
26
|
+
"description": "Name of the main function to be executed at the root of the access url"
|
27
|
+
},
|
28
|
+
"version": {
|
29
|
+
"type": "string",
|
30
|
+
"description": "Semver version number",
|
31
|
+
"minLength": 5,
|
32
|
+
"maxLength": 14,
|
33
|
+
"pattern": "^(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)$"
|
34
|
+
},
|
35
|
+
"timeout": {
|
36
|
+
"type": "number",
|
37
|
+
"description": "Timeout in seconds before a job is stopped (min 5s, max 8h)",
|
38
|
+
"minimum": 5,
|
39
|
+
"maximum": 28800
|
40
|
+
},
|
41
|
+
"concurrency": {
|
42
|
+
"type": "number",
|
43
|
+
"description": "The number of these jobs that can be run at once",
|
44
|
+
"minimum": 1
|
45
|
+
},
|
46
|
+
"functions": {
|
47
|
+
"type": "array",
|
48
|
+
"minItems": 0,
|
49
|
+
"items": {
|
50
|
+
"title": "JobFunction",
|
51
|
+
"description": "Job function definition, this object provides the runtime with input validation and what to execute",
|
52
|
+
"type": "object",
|
53
|
+
"properties": {
|
54
|
+
"name": {
|
55
|
+
"type": "string",
|
56
|
+
"$ref": "#/definitions/name-pattern",
|
57
|
+
"description": "Function name"
|
58
|
+
},
|
59
|
+
"entry": {
|
60
|
+
"type": "string",
|
61
|
+
"description": "File path to the javascript file to execute. The file path must be relative to the manifest file and cannot be in a folder above the manifest file."
|
62
|
+
},
|
63
|
+
"input": {
|
64
|
+
"$ref": "DxComponentInputSchema.json"
|
65
|
+
}
|
66
|
+
},
|
67
|
+
"required": ["name", "entry", "input"]
|
68
|
+
}
|
69
|
+
}
|
70
|
+
},
|
71
|
+
"required": [
|
72
|
+
"name",
|
73
|
+
"displayName",
|
74
|
+
"description",
|
75
|
+
"version",
|
76
|
+
"functions",
|
77
|
+
"$schema",
|
78
|
+
"mainFunction",
|
79
|
+
"concurrency",
|
80
|
+
"timeout"
|
81
|
+
],
|
82
|
+
"definitions": {
|
83
|
+
"name-pattern": {
|
84
|
+
"type": "string",
|
85
|
+
"pattern": "^[a-z][a-z0-9_\\-]+$"
|
86
|
+
}
|
87
|
+
}
|
88
|
+
}
|
@@ -0,0 +1,110 @@
|
|
1
|
+
import { readFile } from 'fs/promises';
|
2
|
+
import { resolve } from 'path';
|
3
|
+
import { SchemaValidationError } from '../../errors/SchemaValidationError';
|
4
|
+
import { JsonValidationService } from '../../JsonValidationService';
|
5
|
+
|
6
|
+
const NAME_PATTERN = '^[a-z][a-z0-9_\\-]+$';
|
7
|
+
|
8
|
+
async function fetchTestManifest(filename: string) {
|
9
|
+
const contents = await readFile(resolve(__dirname, '__test__', 'schemas', filename), {
|
10
|
+
encoding: 'utf-8',
|
11
|
+
});
|
12
|
+
return JSON.parse(contents);
|
13
|
+
}
|
14
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
15
|
+
function expectToThrowErrorMatchingTypeAndMessage(received: Function, errorType: Function, message: string) {
|
16
|
+
let error: null | Error = null;
|
17
|
+
|
18
|
+
try {
|
19
|
+
received();
|
20
|
+
} catch (e: any) {
|
21
|
+
error = e;
|
22
|
+
}
|
23
|
+
|
24
|
+
expect(error).toBeDefined();
|
25
|
+
expect(error?.message).toEqual(message);
|
26
|
+
expect(error).toBeInstanceOf(errorType);
|
27
|
+
}
|
28
|
+
|
29
|
+
describe('manifest/JobV1', () => {
|
30
|
+
let validationService: JsonValidationService;
|
31
|
+
|
32
|
+
beforeAll(() => {
|
33
|
+
validationService = new JsonValidationService();
|
34
|
+
});
|
35
|
+
|
36
|
+
it('succeeds on a valid manifest', async () => {
|
37
|
+
const manifest = await fetchTestManifest('validJob.json');
|
38
|
+
expect(validationService.validateManifest(manifest, 'JobV1')).toBeTruthy();
|
39
|
+
});
|
40
|
+
|
41
|
+
it('errors on invalid property types in function input', async () => {
|
42
|
+
const manifest = await fetchTestManifest('badFunctionInputJob.json');
|
43
|
+
|
44
|
+
expectToThrowErrorMatchingTypeAndMessage(
|
45
|
+
() => {
|
46
|
+
validationService.validateManifest(manifest, 'JobV1');
|
47
|
+
},
|
48
|
+
SchemaValidationError,
|
49
|
+
'failed validation: Value `wrongType` at `#/functions/0/input/properties/something/type` does not match any schema',
|
50
|
+
);
|
51
|
+
});
|
52
|
+
|
53
|
+
it('errors on non-object top level input', async () => {
|
54
|
+
const manifest = await fetchTestManifest('nonObjectFunctionInputJob.json');
|
55
|
+
expectToThrowErrorMatchingTypeAndMessage(
|
56
|
+
() => {
|
57
|
+
validationService.validateManifest(manifest, 'JobV1');
|
58
|
+
},
|
59
|
+
SchemaValidationError,
|
60
|
+
'failed validation: Expected value at `#/functions/0/input/type` to be `object`, but value given is `string`',
|
61
|
+
);
|
62
|
+
});
|
63
|
+
|
64
|
+
describe.each(['_my-name', '-my-name', 'MyName', 'myName', '0my-name'])(
|
65
|
+
'fails name-pattern validation for %s',
|
66
|
+
(propertyValue) => {
|
67
|
+
it.each(['name'])(`fails validation for manifests with %s of ${propertyValue}`, async (propertyName) => {
|
68
|
+
const manifest = await fetchTestManifest('validJob.json');
|
69
|
+
|
70
|
+
expectToThrowErrorMatchingTypeAndMessage(
|
71
|
+
() => {
|
72
|
+
validationService.validateManifest(
|
73
|
+
{
|
74
|
+
...manifest,
|
75
|
+
[propertyName]: propertyValue,
|
76
|
+
},
|
77
|
+
'JobV1',
|
78
|
+
);
|
79
|
+
},
|
80
|
+
SchemaValidationError,
|
81
|
+
`failed validation: Value in \`#/${propertyName}\` should match \`${NAME_PATTERN}\`, but received \`${propertyValue}\``,
|
82
|
+
);
|
83
|
+
});
|
84
|
+
|
85
|
+
it('fails validation for manifests with function names of %s', async () => {
|
86
|
+
const manifest = await fetchTestManifest('validJob.json');
|
87
|
+
|
88
|
+
expectToThrowErrorMatchingTypeAndMessage(
|
89
|
+
() => {
|
90
|
+
validationService.validateManifest(
|
91
|
+
{
|
92
|
+
...manifest,
|
93
|
+
functions: [
|
94
|
+
{
|
95
|
+
name: propertyValue,
|
96
|
+
entry: 'main.js',
|
97
|
+
input: {},
|
98
|
+
},
|
99
|
+
],
|
100
|
+
},
|
101
|
+
'JobV1',
|
102
|
+
);
|
103
|
+
},
|
104
|
+
SchemaValidationError,
|
105
|
+
`failed validation: Value in \`#/functions/0/name\` should match \`${NAME_PATTERN}\`, but received \`${propertyValue}\``,
|
106
|
+
);
|
107
|
+
});
|
108
|
+
},
|
109
|
+
);
|
110
|
+
});
|