@movable/rollup-plugin-manifest-validator 3.2.0-app-validation

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 (55) hide show
  1. package/.mocharc.yml +3 -0
  2. package/babel.config.json +11 -0
  3. package/dist/apps/index.js +15 -0
  4. package/dist/apps/plugins/app-manifest-validator.js +44 -0
  5. package/dist/apps/utils/app-manifest-validator.js +44 -0
  6. package/dist/apps/validators/ajvCompiler.js +43 -0
  7. package/dist/apps/validators/erroringValidator.js +16 -0
  8. package/dist/apps/validators/index.js +23 -0
  9. package/dist/apps/validators/warningValidator.js +16 -0
  10. package/dist/index.js +21 -0
  11. package/dist/packages/index.js +15 -0
  12. package/dist/packages/plugins/package-manifest-validator.js +44 -0
  13. package/dist/packages/utils/package-manifest-validator.js +44 -0
  14. package/dist/packages/validators/ajvCompiler.js +43 -0
  15. package/dist/packages/validators/erroringValidator.js +16 -0
  16. package/dist/packages/validators/index.js +23 -0
  17. package/dist/packages/validators/warningValidator.js +16 -0
  18. package/dist/schemas/enums.js +14 -0
  19. package/dist/schemas/erroringSchemaApps.js +809 -0
  20. package/dist/schemas/erroringSchemaPackages.js +17 -0
  21. package/dist/schemas/index.js +39 -0
  22. package/dist/schemas/warningSchemaApps.js +8 -0
  23. package/dist/schemas/warningSchemaPackages.js +504 -0
  24. package/package.json +42 -0
  25. package/src/apps/index.js +3 -0
  26. package/src/apps/plugins/app-manifest-validator.js +22 -0
  27. package/src/apps/utils/app-manifest-validator.js +31 -0
  28. package/src/apps/validators/ajvCompiler.js +28 -0
  29. package/src/apps/validators/erroringValidator.js +4 -0
  30. package/src/apps/validators/index.js +4 -0
  31. package/src/apps/validators/warningValidator.js +4 -0
  32. package/src/index.js +4 -0
  33. package/src/packages/index.js +3 -0
  34. package/src/packages/plugins/package-manifest-validator.js +19 -0
  35. package/src/packages/utils/package-manifest-validator.js +31 -0
  36. package/src/packages/validators/ajvCompiler.js +28 -0
  37. package/src/packages/validators/erroringValidator.js +4 -0
  38. package/src/packages/validators/index.js +4 -0
  39. package/src/packages/validators/warningValidator.js +4 -0
  40. package/src/schemas/enums.js +130 -0
  41. package/src/schemas/erroringSchemaApps.js +468 -0
  42. package/src/schemas/erroringSchemaPackages.js +8 -0
  43. package/src/schemas/index.js +6 -0
  44. package/src/schemas/warningSchemaApps.js +1 -0
  45. package/src/schemas/warningSchemaPackages.js +304 -0
  46. package/test/fixtures/blankFile.js +0 -0
  47. package/test/fixtures/invalidField.yml +3 -0
  48. package/test/fixtures/master-app-manifest.yml +72 -0
  49. package/test/fixtures/master-package-manifest.yml +100 -0
  50. package/test/fixtures/noName.yml +1 -0
  51. package/test/helpers/lib.js +10 -0
  52. package/test/plugins/app-manifest-validation.js +34 -0
  53. package/test/plugins/package-manifest-validation.js +62 -0
  54. package/test/utils/app-manifest-validation.js +785 -0
  55. package/test/utils/package-manifest-validation.js +1515 -0
@@ -0,0 +1,304 @@
1
+ import { studioIcons, fieldTypes, propertyTypes, contextOptionTypes } from './enums';
2
+
3
+ const strNumBool = ['string', 'number', 'boolean'];
4
+
5
+ const fieldSchema = {
6
+ type: 'object',
7
+ properties: {
8
+ allows_dynamic: { type: 'boolean' },
9
+ default: { type: strNumBool },
10
+ description: { type: 'string' },
11
+ label: { type: 'string' },
12
+ max: { type: 'number' },
13
+ name: { type: 'string' },
14
+ options: {
15
+ type: 'array',
16
+ items: {
17
+ type: 'object',
18
+ properties: {
19
+ value: { type: strNumBool },
20
+ label: { type: ['string', 'number'] }
21
+ },
22
+ required: ['value', 'label'],
23
+ additionalProperties: false
24
+ }
25
+ },
26
+ placeholder: { type: ['string', 'number'] },
27
+ preview_text: { type: 'array', items: { type: strNumBool } },
28
+ provider: { type: 'string' },
29
+ template: { type: 'string' },
30
+ type: { type: 'string', enum: fieldTypes },
31
+ value: { type: strNumBool },
32
+ heading: { type: 'string' }
33
+ },
34
+ required: ['name', 'label', 'type'],
35
+ additionalProperties: false,
36
+ allOf: [
37
+ {
38
+ if: {
39
+ properties: { type: { enum: ['number', 'token'] } }
40
+ },
41
+ else: {
42
+ not: { required: ['max'] }
43
+ }
44
+ },
45
+ {
46
+ if: {
47
+ properties: { type: { const: 'oAuthAccount' } }
48
+ },
49
+ then: {
50
+ required: ['provider']
51
+ },
52
+ else: {
53
+ not: { required: ['provider'] }
54
+ }
55
+ },
56
+ {
57
+ if: {
58
+ properties: { type: { const: 'data-source' } }
59
+ },
60
+ else: {
61
+ not: { required: ['template'] }
62
+ }
63
+ },
64
+ {
65
+ if: {
66
+ properties: { type: { enum: ['select', 'radio', 'checkbox'] } }
67
+ },
68
+ else: {
69
+ not: { required: ['options'] }
70
+ }
71
+ }
72
+ ]
73
+ };
74
+
75
+ const dynamicPropertySchema = {
76
+ propertyGroupKey: { type: 'string' },
77
+ propertyPath: { type: 'string' },
78
+ propertyPreview: { type: strNumBool },
79
+ propertyFallback: { type: strNumBool },
80
+ propertyValue: { type: 'string' },
81
+ context: {
82
+ type: 'object'
83
+ }
84
+ };
85
+
86
+ const toolSchema = {
87
+ type: 'object',
88
+ properties: {
89
+ class_names: { type: 'string' },
90
+ fields: { type: 'array', items: fieldSchema },
91
+ icon: { type: 'string', enum: studioIcons },
92
+ label: { type: 'string' },
93
+ name: { type: 'string' },
94
+ type: { type: 'string' },
95
+ locked: { type: 'boolean' },
96
+ dynamic_fields: {
97
+ type: 'array',
98
+ items: {
99
+ type: 'object',
100
+ properties: {
101
+ type: { type: 'string', enum: propertyTypes },
102
+ name: { type: 'string' },
103
+ label: { type: 'string' },
104
+ allow_static_option: { type: 'boolean' }
105
+ },
106
+ required: ['name', 'label'],
107
+ additionalProperties: false
108
+ }
109
+ },
110
+ defaults: {
111
+ type: 'object',
112
+ properties: {
113
+ dynamicProperty: {
114
+ type: 'object',
115
+ properties: dynamicPropertySchema,
116
+ required: ['propertyPath'],
117
+ additionalProperties: false
118
+ },
119
+ height: { type: 'number' },
120
+ width: { type: 'number' }
121
+ },
122
+ additionalProperties: false
123
+ }
124
+ },
125
+ required: ['name', 'icon', 'label', 'type'],
126
+ additionalProperties: false
127
+ };
128
+
129
+ const propertySchema = {
130
+ type: 'object',
131
+ properties: {
132
+ name: { type: 'string' },
133
+ label: { type: 'string' },
134
+ description: { type: 'string' },
135
+ type: { type: 'string', enum: propertyTypes },
136
+ preview_text: {
137
+ type: 'array',
138
+ items: { type: strNumBool }
139
+ },
140
+ preview_values: { type: 'array', items: { type: strNumBool } },
141
+ context_options: {
142
+ type: 'array',
143
+ items: {
144
+ type: 'object',
145
+ properties: {
146
+ name: { type: 'string' },
147
+ type: { type: 'string', enum: contextOptionTypes },
148
+ description: { type: 'string' },
149
+ defaultValue: { type: 'number' },
150
+ options: {
151
+ type: 'array',
152
+ minItems: 1,
153
+ items: {
154
+ type: 'object',
155
+ properties: {
156
+ label: { type: 'string' },
157
+ value: { type: strNumBool }
158
+ },
159
+ required: ['value', 'label'],
160
+ additionalProperties: false
161
+ }
162
+ }
163
+ },
164
+ required: ['name', 'type'],
165
+ additionalProperties: false,
166
+ allOf: [
167
+ {
168
+ if: {
169
+ properties: { type: { enum: ['select'] } }
170
+ },
171
+ then: {
172
+ required: ['options']
173
+ }
174
+ }
175
+ ]
176
+ }
177
+ }
178
+ },
179
+ required: ['name', 'label'],
180
+ additionalProperties: false
181
+ };
182
+
183
+ export default {
184
+ type: 'object',
185
+ properties: {
186
+ name: { type: 'string' },
187
+ label: { type: 'string' },
188
+ query_params: {
189
+ type: 'object',
190
+ patternProperties: { '.*': { type: 'string' } }
191
+ },
192
+ cold_states: {
193
+ type: 'array',
194
+ items: {
195
+ type: 'object',
196
+ properties: {
197
+ name: { type: 'string' },
198
+ width: { type: 'number' },
199
+ height: { type: 'number' }
200
+ },
201
+ required: ['name'],
202
+ additionalProperties: false
203
+ }
204
+ },
205
+ integration_ids: {
206
+ type: 'array',
207
+ items: {
208
+ type: 'string',
209
+ pattern: '^[a-zA-Z0-9]+$',
210
+ minLength: 15,
211
+ maxLength: 15
212
+ }
213
+ },
214
+ fields: {
215
+ type: 'array',
216
+ items: fieldSchema
217
+ },
218
+ field_headings: {
219
+ type: 'array',
220
+ items: {
221
+ type: 'object',
222
+ required: ['name', 'label'],
223
+ properties: {
224
+ name: { type: 'string' },
225
+ label: { type: 'string' },
226
+ toggleable: { type: 'boolean' },
227
+ default_toggle_collapsed: { type: 'boolean' }
228
+ }
229
+ }
230
+ },
231
+ studio_options: {
232
+ type: 'object',
233
+ properties: {
234
+ prohibit_custom_params: { type: 'boolean' },
235
+ framework_version: { type: 'string', pattern: '^(\\d+\\.){2}\\d+$' },
236
+ tools: { type: 'array', items: toolSchema },
237
+ preview_fields: { type: 'array', items: { type: 'string' } },
238
+ property_groups: {
239
+ type: 'array',
240
+ items: {
241
+ type: 'object',
242
+ properties: {
243
+ name: { type: 'string' },
244
+ label: { type: 'string' },
245
+ description: { type: 'string' },
246
+ properties: { type: 'array', items: propertySchema }
247
+ },
248
+ required: ['name', 'label', 'properties'],
249
+ additionalProperties: false
250
+ },
251
+ minItems: 1,
252
+ maxItems: 1
253
+ },
254
+ element_modifiers: {
255
+ type: 'array',
256
+ items: {
257
+ type: 'object',
258
+ properties: {
259
+ name: { type: 'string' },
260
+ label: { type: 'string' },
261
+ description: { type: 'string' }
262
+ },
263
+ required: ['name', 'label'],
264
+ additionalProperties: false
265
+ }
266
+ },
267
+ property_modifiers: {
268
+ type: 'array',
269
+ items: {
270
+ type: 'object',
271
+ properties: {
272
+ name: { type: 'string' },
273
+ label: { type: 'string' },
274
+ type: { type: 'string', enum: propertyTypes },
275
+ preview_text: { type: 'array', items: { type: strNumBool } },
276
+ description: { type: 'string' },
277
+ propertyInputs: {
278
+ type: 'array',
279
+ items: {
280
+ type: 'object',
281
+ properties: {
282
+ name: { type: 'string' },
283
+ variableName: { type: 'string' },
284
+ label: { type: 'string' },
285
+ allow_static_option: { type: 'boolean' },
286
+ type: { type: 'string' }
287
+ },
288
+ required: ['name', 'label', 'variableName'],
289
+ additionalProperties: false
290
+ }
291
+ }
292
+ },
293
+ required: ['name', 'label'],
294
+ additionalProperties: false
295
+ }
296
+ }
297
+ },
298
+ additionalProperties: false
299
+ }
300
+ },
301
+ name: true,
302
+ required: ['name'],
303
+ additionalProperties: false
304
+ };
File without changes
@@ -0,0 +1,3 @@
1
+ name: bad manifest
2
+ field: bongo
3
+ fields: bingo
@@ -0,0 +1,72 @@
1
+ name: master-blaster
2
+ authors:
3
+ - test-author@movableink.com
4
+ integration_ids:
5
+ - abcde0123456789
6
+ - fghij0123456789
7
+ javascript_file: dist/index.js
8
+ html_file: app/index.html
9
+ css_file: app/styles/style.css
10
+ description: this is an app description
11
+ category: 'data: rendering'
12
+ icon_v2: tools
13
+ width: 400
14
+ height: 300
15
+ format: 'jpeg'
16
+ quality: 85
17
+ expose_advanced_options: true
18
+ fields:
19
+ - name: test-field
20
+ label: Test Field
21
+ type: text
22
+ - name: test-field-with-options
23
+ label: Test Field With Options
24
+ type: select
25
+ value: 0
26
+ options:
27
+ - label: '1'
28
+ value: 0
29
+ - label: '2'
30
+ value: 1
31
+ - label: '3'
32
+ value: 2
33
+ - name: dataSourceField
34
+ type: data-source
35
+ label: Dr. DataSource
36
+ template: DD
37
+ studio_options:
38
+ framework_version: '3.1'
39
+ tools:
40
+ - name: Hammer
41
+ label: For when all you've got are nails.
42
+ icon: pin
43
+ type: cool-tool
44
+ property_groups:
45
+ - name: master-blaster
46
+ label: MB Prop Group
47
+ properties:
48
+ - name: mb-prop-group-property
49
+ label: MB Prop Group Property
50
+ type: image
51
+ preview_text:
52
+ - 5:30 PM
53
+ - 6:15 PM
54
+ preview_values:
55
+ - 33
56
+ - 99
57
+ context_options:
58
+ - name: context-option-1
59
+ type: select
60
+ description: I am number 1 context option!
61
+ defaultValue: 6
62
+ options:
63
+ - label: six
64
+ value: 6
65
+ label: seven
66
+ value: 7
67
+ capture_options:
68
+ timeout: 8s
69
+ cache_ttl: 60s
70
+ query_params:
71
+ mb_param1: '[mb:param_1]'
72
+ mb_param2: '[mb:param_2]'
@@ -0,0 +1,100 @@
1
+ name: master-blaster
2
+ label: Master Blaster
3
+ query_params:
4
+ mb_param1: '[mb:param_1]'
5
+ mb_param2: '[mb:param_2]'
6
+ integration_ids:
7
+ - abcde0123456789
8
+ - fghij0123456789
9
+ cold_states:
10
+ - name: default
11
+ width: 500
12
+ height: 500
13
+ - name: beyond_thunderdome
14
+ fields:
15
+ - name: selectField
16
+ label: Mr. Selectfield
17
+ type: select
18
+ description: I am a Select Field
19
+ allows_dynamic: true
20
+ options:
21
+ - label: opt1
22
+ value: true
23
+ - label: opt2
24
+ value: 2
25
+ - label: opt3
26
+ value: three
27
+ default: three
28
+ preview_text:
29
+ - Alo!
30
+ - name: textField
31
+ label: Mrs. Textfield
32
+ type: text
33
+ placeholder: Let me hold that for you.
34
+ default: true
35
+ preview_text:
36
+ - Strings
37
+ - name: tokenField
38
+ label: Dr. Tokenfield
39
+ value: Panama
40
+ type: token
41
+ max: 50
42
+ preview_text:
43
+ - Bools
44
+ - name: oAuthField
45
+ type: oAuthAccount
46
+ label: Sir O'Authfield
47
+ default: 6
48
+ provider: The Royal Family
49
+ - name: dataSourceField
50
+ type: data-source
51
+ label: Dr. DataSource
52
+ template: DD
53
+ studio_options:
54
+ prohibit_custom_params: false
55
+ framework_version: 2.29.0
56
+ tools:
57
+ - name: Hammer
58
+ label: For when all you've got are nails.
59
+ icon: pin
60
+ type: cool-tool
61
+ property_groups:
62
+ - name: master-blaster
63
+ label: MB Prop Group
64
+ properties:
65
+ - name: mb-prop-group-property
66
+ label: MB Prop Group Property
67
+ type: image
68
+ preview_text:
69
+ - 5:30 PM
70
+ - 6:15 PM
71
+ preview_values:
72
+ - 33
73
+ - 99
74
+ context_options:
75
+ - name: context-option-1
76
+ type: select
77
+ description: I am number 1 context option!
78
+ defaultValue: 6
79
+ options:
80
+ - label: six
81
+ value: 6
82
+ label: seven
83
+ value: 7
84
+ element_modifiers:
85
+ - name: element-modifier-1
86
+ label: Element Modifier 1
87
+ description: Increases or decreases complexity score
88
+ property_modifiers:
89
+ - name: property-modifier-1
90
+ label: Property Modifier 1
91
+ type: text
92
+ description: Initiates spin cycle
93
+ preview_text:
94
+ - Spin spin spin
95
+ propertyInputs:
96
+ - name: primaryInput
97
+ variableName: primaryInput
98
+ label: Primary String
99
+ allow_static_option: true
100
+ type: any
@@ -0,0 +1 @@
1
+ cat: dog
@@ -0,0 +1,10 @@
1
+ export const MANIFEST_PATH = 'test/fixtures/master-package-manifest.yml';
2
+ export const MANIFEST_PATH_APPS = 'test/fixtures/master-app-manifest.yml';
3
+
4
+ export const SHOULD_NOT_HAVE_PROPERTY_MESSAGE = 'should NOT have additional properties';
5
+ export const ALLOWED_VALUES_MESSAGE = 'should be equal to one of the allowed values';
6
+ export { TOP_LEVEL_PROHIBITED_PROPERTY_MESSAGE as TOP_LEVEL_PROHIBITED_PROPERTY_MESSAGE } from '../../src/packages/utils/package-manifest-validator';
7
+ export { TOP_LEVEL_PROHIBITED_PROPERTY_MESSAGE as TOP_LEVEL_PROHIBITED_PROPERTY_MESSAGE_APP } from '../../src/apps/utils/app-manifest-validator';
8
+
9
+ export const generateShouldHavePropertyMessage = (property) =>
10
+ `should have required property '${property}'`;
@@ -0,0 +1,34 @@
1
+ import { describe, it } from 'mocha';
2
+ import { expect } from 'chai';
3
+ import { rollup } from 'rollup';
4
+ import { manifestValidatorPluginApps } from '../../src/apps';
5
+ import { MANIFEST_PATH_APPS } from '../helpers/lib';
6
+
7
+ describe('appManifestValidator plugin', async () => {
8
+ it('watches the manifest', async () => {
9
+ const bundler = await rollup({
10
+ input: 'test/fixtures/blankFile.js',
11
+ plugins: [manifestValidatorPluginApps({ manifestPath: MANIFEST_PATH_APPS })]
12
+ });
13
+
14
+ await bundler.generate({});
15
+
16
+ expect(bundler.watchFiles.includes(MANIFEST_PATH_APPS)).to.be.true;
17
+ });
18
+
19
+ it('throws errors', async () => {
20
+ try {
21
+ await rollup({
22
+ input: 'test/fixtures/blankFile.js',
23
+ plugins: [manifestValidatorPluginApps({ manifestPath: 'test/fixtures/noName.yml' })]
24
+ });
25
+
26
+ // ensure catch
27
+ expect(false).to.be.true;
28
+ } catch ({ message: fullMessage }) {
29
+ expect(fullMessage).to.contain('should NOT have additional properties');
30
+ expect(fullMessage).to.contain("should have required property 'name'");
31
+ expect(fullMessage).to.contain("should have required property 'authors'");
32
+ }
33
+ });
34
+ });
@@ -0,0 +1,62 @@
1
+ import { describe, it } from 'mocha';
2
+ import { expect } from 'chai';
3
+ import { rollup } from 'rollup';
4
+ import { manifestValidatorPluginPackages } from '../../src/packages';
5
+ import { MANIFEST_PATH } from '../helpers/lib';
6
+
7
+ describe('pacakgeManifestValidator plugin', async () => {
8
+ it('watches the manifest', async () => {
9
+ const bundler = await rollup({
10
+ input: 'test/fixtures/blankFile.js',
11
+ plugins: [manifestValidatorPluginPackages({ manifestPath: MANIFEST_PATH })]
12
+ });
13
+
14
+ await bundler.generate({});
15
+
16
+ expect(bundler.watchFiles.includes(MANIFEST_PATH)).to.be.true;
17
+ });
18
+
19
+ it('throws errors', async () => {
20
+ try {
21
+ await rollup({
22
+ input: 'test/fixtures/blankFile.js',
23
+ plugins: [manifestValidatorPluginPackages({ manifestPath: 'test/fixtures/noName.yml' })]
24
+ });
25
+
26
+ // ensure catch
27
+ expect(false).to.be.true;
28
+ } catch ({ message: fullMessage }) {
29
+ const [{ message }] = JSON.parse(fullMessage.replace(/INVALID PACKAGE MANIFEST:|\n/g, ''));
30
+ expect(message).to.equal("should have required property 'name'");
31
+ }
32
+ });
33
+
34
+ it('warns', async () => {
35
+ const warnings = [];
36
+
37
+ await rollup({
38
+ onwarn: (warning) => {
39
+ warnings.push(warning.toString());
40
+ },
41
+ input: 'test/fixtures/blankFile.js',
42
+ plugins: [manifestValidatorPluginPackages({ manifestPath: 'test/fixtures/invalidField.yml' })]
43
+ });
44
+
45
+ expect(warnings).to.include.members([
46
+ "(at position 1 plugin) 'PACKAGE MANIFEST VALIDATION WARNING': {\n" +
47
+ ' "message": "should NOT have additional properties",\n' +
48
+ ' "dataPath": "package-manifest.yml",\n' +
49
+ ' "params": {\n' +
50
+ ' "additionalProperty": "field"\n' +
51
+ ' }\n' +
52
+ '}',
53
+ "(at position 1 plugin) 'PACKAGE MANIFEST VALIDATION WARNING': {\n" +
54
+ ' "message": "should be array",\n' +
55
+ ' "dataPath": ".fields",\n' +
56
+ ' "params": {\n' +
57
+ ' "type": "array"\n' +
58
+ ' }\n' +
59
+ '}'
60
+ ]);
61
+ });
62
+ });