@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.
Files changed (34) hide show
  1. package/.npm/_logs/{2023-06-21T06_19_37_197Z-debug-0.log → 2023-06-22T05_23_22_241Z-debug-0.log} +9 -9
  2. package/jsonCompiler.ts +1 -0
  3. package/lib/JsonValidationService.d.ts +1 -1
  4. package/lib/JsonValidationService.js +7 -0
  5. package/lib/JsonValidationService.js.map +1 -1
  6. package/lib/manifest/v1/JobV1.d.ts +192 -0
  7. package/lib/manifest/v1/JobV1.js +9 -0
  8. package/lib/manifest/v1/JobV1.js.map +1 -0
  9. package/lib/manifest/v1/JobV1.json +88 -0
  10. package/lib/manifest/v1/JobV1.spec.d.ts +1 -0
  11. package/lib/manifest/v1/JobV1.spec.js +75 -0
  12. package/lib/manifest/v1/JobV1.spec.js.map +1 -0
  13. package/lib/manifest/v1/__test__/schemas/badFunctionInputJob.json +25 -0
  14. package/lib/manifest/v1/__test__/schemas/nonObjectFunctionInputJob.json +25 -0
  15. package/lib/manifest/v1/__test__/schemas/validJob.json +25 -0
  16. package/lib/manifest/v1/manifestModels.d.ts +1 -0
  17. package/lib/manifest/v1/manifestModels.js +2 -1
  18. package/lib/manifest/v1/manifestModels.js.map +1 -1
  19. package/lib/manifest/v1/manifestSchemas.d.ts +2 -1
  20. package/lib/manifest/v1/manifestSchemas.js +3 -1
  21. package/lib/manifest/v1/manifestSchemas.js.map +1 -1
  22. package/lib/manifest/v1/v1.json +26 -7
  23. package/package.json +2 -2
  24. package/src/JsonValidationService.ts +9 -1
  25. package/src/manifest/v1/JobV1.json +88 -0
  26. package/src/manifest/v1/JobV1.spec.ts +110 -0
  27. package/src/manifest/v1/JobV1.ts +447 -0
  28. package/src/manifest/v1/__test__/schemas/badFunctionInputJob.json +25 -0
  29. package/src/manifest/v1/__test__/schemas/nonObjectFunctionInputJob.json +25 -0
  30. package/src/manifest/v1/__test__/schemas/validJob.json +25 -0
  31. package/src/manifest/v1/manifestModels.ts +1 -0
  32. package/src/manifest/v1/manifestSchemas.ts +2 -1
  33. package/src/manifest/v1/v1.json +26 -14
  34. package/tsconfig.tsbuildinfo +1 -1
@@ -4,15 +4,28 @@
4
4
  "title": "ComponentManifest",
5
5
  "additionalProperties": false,
6
6
  "properties": {
7
- "$schema": { "type": "string", "description": "the manifest schema version" },
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": { "type": "string", "description": "Name of the component", "$ref": "#/definitions/name-pattern" },
14
- "displayName": { "type": "string", "description": "Display name of the component" },
15
- "description": { "type": "string", "description": "Description of the component" },
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": { "const": "html" },
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": { "const": "json" },
255
- "definition": { "$ref": "http://json-schema.org/draft-07/schema#" },
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.0",
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": "ade72ff2cba5a65be6010587a58e8f49153fc806"
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
+ });