@e22m4u/js-openapi 0.0.5

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 (84) hide show
  1. package/.c8rc +9 -0
  2. package/.commitlintrc +5 -0
  3. package/.editorconfig +13 -0
  4. package/.husky/commit-msg +1 -0
  5. package/.husky/pre-commit +6 -0
  6. package/.mocharc.json +4 -0
  7. package/.prettierrc +7 -0
  8. package/LICENSE +21 -0
  9. package/README.md +510 -0
  10. package/build-cjs.js +16 -0
  11. package/dist/cjs/index.cjs +2695 -0
  12. package/eslint.config.js +41 -0
  13. package/package.json +64 -0
  14. package/src/data-type/index.d.ts +1 -0
  15. package/src/data-type/index.js +1 -0
  16. package/src/data-type/infer-openapi-data-type.d.ts +30 -0
  17. package/src/data-type/infer-openapi-data-type.js +38 -0
  18. package/src/data-validation/data-format-validator-map.d.ts +13 -0
  19. package/src/data-validation/data-format-validator-map.js +36 -0
  20. package/src/data-validation/data-format-validator-map.spec.js +39 -0
  21. package/src/data-validation/data-format-validators.d.ts +84 -0
  22. package/src/data-validation/data-format-validators.js +217 -0
  23. package/src/data-validation/index.d.ts +3 -0
  24. package/src/data-validation/index.js +3 -0
  25. package/src/data-validation/validate-data-with-openapi-schema.d.ts +46 -0
  26. package/src/data-validation/validate-data-with-openapi-schema.js +1913 -0
  27. package/src/data-validation/validate-data-with-openapi-schema.spec.js +6953 -0
  28. package/src/errors/index.d.ts +1 -0
  29. package/src/errors/index.js +1 -0
  30. package/src/errors/oa-data-validation-error.d.ts +6 -0
  31. package/src/errors/oa-data-validation-error.js +6 -0
  32. package/src/errors/oa-data-validation-error.spec.js +17 -0
  33. package/src/index.d.ts +9 -0
  34. package/src/index.js +9 -0
  35. package/src/json-pointer/escape-json-pointer.d.ts +7 -0
  36. package/src/json-pointer/escape-json-pointer.js +18 -0
  37. package/src/json-pointer/escape-json-pointer.spec.js +36 -0
  38. package/src/json-pointer/index.d.ts +3 -0
  39. package/src/json-pointer/index.js +3 -0
  40. package/src/json-pointer/resolve-json-pointer.d.ts +10 -0
  41. package/src/json-pointer/resolve-json-pointer.js +83 -0
  42. package/src/json-pointer/resolve-json-pointer.spec.js +103 -0
  43. package/src/json-pointer/unescape-json-pointer.d.ts +8 -0
  44. package/src/json-pointer/unescape-json-pointer.js +18 -0
  45. package/src/json-pointer/unescape-json-pointer.spec.js +32 -0
  46. package/src/oa-document-builder.d.ts +312 -0
  47. package/src/oa-document-builder.js +450 -0
  48. package/src/oa-document-object/index.d.ts +1 -0
  49. package/src/oa-document-object/index.js +1 -0
  50. package/src/oa-document-object/validate-shallow-oa-document.d.ts +10 -0
  51. package/src/oa-document-object/validate-shallow-oa-document.js +209 -0
  52. package/src/oa-document-object/validate-shallow-oa-document.spec.js +362 -0
  53. package/src/oa-document-scope.d.ts +52 -0
  54. package/src/oa-document-scope.js +228 -0
  55. package/src/oa-reference-object/index.d.ts +3 -0
  56. package/src/oa-reference-object/index.js +3 -0
  57. package/src/oa-reference-object/is-oa-reference-object.d.ts +9 -0
  58. package/src/oa-reference-object/is-oa-reference-object.js +14 -0
  59. package/src/oa-reference-object/is-oa-reference-object.spec.js +19 -0
  60. package/src/oa-reference-object/oa-ref.d.ts +11 -0
  61. package/src/oa-reference-object/oa-ref.js +31 -0
  62. package/src/oa-reference-object/oa-ref.spec.js +56 -0
  63. package/src/oa-reference-object/resolve-oa-reference-object.d.ts +18 -0
  64. package/src/oa-reference-object/resolve-oa-reference-object.js +113 -0
  65. package/src/oa-reference-object/resolve-oa-reference-object.spec.js +233 -0
  66. package/src/oa-specification.d.ts +767 -0
  67. package/src/oa-specification.js +153 -0
  68. package/src/types.d.ts +4 -0
  69. package/src/utils/count-unicode.d.ts +11 -0
  70. package/src/utils/count-unicode.js +15 -0
  71. package/src/utils/index.d.ts +5 -0
  72. package/src/utils/index.js +5 -0
  73. package/src/utils/join-path.d.ts +6 -0
  74. package/src/utils/join-path.js +36 -0
  75. package/src/utils/join-path.spec.js +104 -0
  76. package/src/utils/normalize-path.d.ts +12 -0
  77. package/src/utils/normalize-path.js +22 -0
  78. package/src/utils/normalize-path.spec.js +56 -0
  79. package/src/utils/to-pascal-case.d.ts +6 -0
  80. package/src/utils/to-pascal-case.js +26 -0
  81. package/src/utils/to-pascal-case.spec.js +15 -0
  82. package/src/utils/to-spaced-json.d.ts +17 -0
  83. package/src/utils/to-spaced-json.js +27 -0
  84. package/tsconfig.json +14 -0
@@ -0,0 +1,450 @@
1
+ import {OADocumentScope} from './oa-document-scope.js';
2
+ import {InvalidArgumentError} from '@e22m4u/js-format';
3
+ import {normalizePath} from './utils/normalize-path.js';
4
+ import {isServiceContainer, Service} from '@e22m4u/js-service';
5
+ import {validateShallowOADocument} from './oa-document-object/index.js';
6
+ import {OPENAPI_VERSION, OAOperationMethod} from './oa-specification.js';
7
+
8
+ /**
9
+ * Component type.
10
+ */
11
+ export const OAComponentType = {
12
+ SCHEMA: 'schema',
13
+ RESPONSE: 'response',
14
+ PARAMETER: 'parameter',
15
+ EXAMPLE: 'example',
16
+ REQUEST_BODY: 'requestBody',
17
+ HEADER: 'header',
18
+ SECURITY_SCHEME: 'securityScheme',
19
+ LINK: 'link',
20
+ CALLBACK: 'callback',
21
+ PATH_ITEM: 'pathItem',
22
+ };
23
+
24
+ /**
25
+ * Component types.
26
+ */
27
+ export const OA_COMPONENT_TYPES = Object.values(OAComponentType);
28
+
29
+ /**
30
+ * Component type to components key map.
31
+ */
32
+ export const OA_COMPONENT_TYPE_TO_COMPONENTS_KEY_MAP = {
33
+ [OAComponentType.SCHEMA]: 'schemas',
34
+ [OAComponentType.RESPONSE]: 'responses',
35
+ [OAComponentType.PARAMETER]: 'parameters',
36
+ [OAComponentType.EXAMPLE]: 'examples',
37
+ [OAComponentType.REQUEST_BODY]: 'requestBodies',
38
+ [OAComponentType.HEADER]: 'headers',
39
+ [OAComponentType.SECURITY_SCHEME]: 'securitySchemes',
40
+ [OAComponentType.LINK]: 'links',
41
+ [OAComponentType.CALLBACK]: 'callbacks',
42
+ [OAComponentType.PATH_ITEM]: 'pathItems',
43
+ };
44
+
45
+ /**
46
+ * OpenAPI Document builder.
47
+ */
48
+ export class OADocumentBuilder extends Service {
49
+ /**
50
+ * Document.
51
+ *
52
+ * @private
53
+ * @type {object}
54
+ */
55
+ _document = {
56
+ openapi: OPENAPI_VERSION,
57
+ info: {
58
+ title: 'API Documentation',
59
+ version: '0.0.1',
60
+ },
61
+ };
62
+
63
+ /**
64
+ * Constructor.
65
+ *
66
+ * @param {object} [containerOrDocument]
67
+ * @param {object} [document]
68
+ */
69
+ constructor(containerOrDocument, document) {
70
+ if (isServiceContainer(containerOrDocument)) {
71
+ super(containerOrDocument);
72
+ } else {
73
+ super();
74
+ document = containerOrDocument;
75
+ }
76
+ if (document !== undefined) {
77
+ // если схема документа не является
78
+ // объектом, то выбрасывается ошибка
79
+ if (
80
+ !document ||
81
+ typeof document !== 'object' ||
82
+ Array.isArray(document)
83
+ ) {
84
+ throw new InvalidArgumentError(
85
+ 'OpenAPI Document Object must be an Object, but %v was given.',
86
+ document,
87
+ );
88
+ }
89
+ // чтобы избежать мутации аргумента,
90
+ // выполняется копирование документа
91
+ document = structuredClone(document);
92
+ // если версия OpenAPI не определена,
93
+ // то устанавливается версия по умолчанию
94
+ if (!document.openapi) {
95
+ document.openapi = this._document.openapi;
96
+ }
97
+ // если Info Object не определен,
98
+ // то устанавливается значение по умолчанию
99
+ if (!document.info) {
100
+ document.info = this._document.info;
101
+ }
102
+ // если свойство "info" не является
103
+ // объектом, то выбрасывается ошибка
104
+ if (
105
+ !document.info ||
106
+ typeof document.info !== 'object' ||
107
+ Array.isArray(document.info)
108
+ ) {
109
+ throw new InvalidArgumentError(
110
+ 'Property "info" must be an Object, but %v was given.',
111
+ document.info,
112
+ );
113
+ }
114
+ // если свойство "info.title" не определено,
115
+ // то устанавливается значение по умолчанию
116
+ if (!document.info.title) {
117
+ document.info.title = this._document.info.title;
118
+ }
119
+ // если свойство "info.version" не определено,
120
+ // то устанавливается значение по умолчанию
121
+ if (!document.info.version) {
122
+ document.info.version = this._document.info.version;
123
+ }
124
+ // поверхностная проверка свойств документа
125
+ // выполняется после установки значений по умолчанию
126
+ validateShallowOADocument(document);
127
+ this._document = document;
128
+ }
129
+ }
130
+
131
+ /**
132
+ * Define component.
133
+ *
134
+ * @param {string} type
135
+ * @param {object} definition
136
+ * @returns {this}
137
+ */
138
+ defineComponent(type, definition) {
139
+ // type
140
+ if (!OA_COMPONENT_TYPES.includes(type)) {
141
+ throw new InvalidArgumentError(
142
+ 'Components type %v is not supported.',
143
+ type,
144
+ );
145
+ }
146
+ // definition
147
+ if (
148
+ !definition ||
149
+ typeof definition !== 'object' ||
150
+ Array.isArray(definition)
151
+ ) {
152
+ throw new InvalidArgumentError(
153
+ 'Component definition must be an Object, but %v was given.',
154
+ definition,
155
+ );
156
+ }
157
+ // definition.name
158
+ if (!definition.name || typeof definition.name !== 'string') {
159
+ throw new InvalidArgumentError(
160
+ 'Property "name" must be a non-empty String, but %v was given.',
161
+ definition.name,
162
+ );
163
+ }
164
+ // definition[type]
165
+ const component = definition[type];
166
+ if (
167
+ !component ||
168
+ typeof component !== 'object' ||
169
+ Array.isArray(component)
170
+ ) {
171
+ throw new InvalidArgumentError(
172
+ 'Property %v must be an Object, but %v was given.',
173
+ type,
174
+ component,
175
+ );
176
+ }
177
+ // components key
178
+ const key = OA_COMPONENT_TYPE_TO_COMPONENTS_KEY_MAP[type];
179
+ if (!key) {
180
+ throw new InvalidArgumentError(
181
+ 'Component type %v does not have a reference to the components key.',
182
+ type,
183
+ );
184
+ }
185
+ this._document.components = this._document.components || {};
186
+ this._document.components[key] = this._document.components[key] || {};
187
+ this._document.components[key][definition.name] =
188
+ structuredClone(component);
189
+ return this;
190
+ }
191
+
192
+ /**
193
+ * Has component.
194
+ *
195
+ * @param {string} type
196
+ * @param {string} name
197
+ * @returns {boolean}
198
+ */
199
+ hasComponent(type, name) {
200
+ // name
201
+ if (!name || typeof name !== 'string') {
202
+ throw new InvalidArgumentError(
203
+ 'Parameter "name" must be a non-empty String, but %v was given.',
204
+ name,
205
+ );
206
+ }
207
+ // components key
208
+ const key = OA_COMPONENT_TYPE_TO_COMPONENTS_KEY_MAP[type];
209
+ if (!key) {
210
+ throw new InvalidArgumentError(
211
+ 'Component type %v does not have a reference to the components key.',
212
+ type,
213
+ );
214
+ }
215
+ return Boolean(
216
+ this._document.components &&
217
+ this._document.components[key] &&
218
+ this._document.components[key][name],
219
+ );
220
+ }
221
+
222
+ /**
223
+ * Get component.
224
+ *
225
+ * @param {string} type
226
+ * @param {string} name
227
+ * @returns {object}
228
+ */
229
+ getComponent(type, name) {
230
+ // name
231
+ if (!name || typeof name !== 'string') {
232
+ throw new InvalidArgumentError(
233
+ 'Parameter "name" must be a non-empty String, but %v was given.',
234
+ name,
235
+ );
236
+ }
237
+ // components key
238
+ const key = OA_COMPONENT_TYPE_TO_COMPONENTS_KEY_MAP[type];
239
+ if (!key) {
240
+ throw new InvalidArgumentError(
241
+ 'Component type %v does not have a reference to the components key.',
242
+ type,
243
+ );
244
+ }
245
+ const component =
246
+ this._document &&
247
+ this._document.components &&
248
+ this._document.components[key] &&
249
+ this._document.components[key][name];
250
+ if (!component) {
251
+ throw new InvalidArgumentError(
252
+ 'Component "#/components/%s/%s" does not exist.',
253
+ key,
254
+ name,
255
+ );
256
+ }
257
+ return component;
258
+ }
259
+
260
+ /**
261
+ * Define schema component.
262
+ *
263
+ * @param {object} schemaDef
264
+ * @returns {this}
265
+ */
266
+ defineSchemaComponent(schemaDef) {
267
+ return this.defineComponent(OAComponentType.SCHEMA, schemaDef);
268
+ }
269
+
270
+ /**
271
+ * Define response component.
272
+ *
273
+ * @param {object} responseDef
274
+ * @returns {this}
275
+ */
276
+ defineResponseComponent(responseDef) {
277
+ return this.defineComponent(OAComponentType.RESPONSE, responseDef);
278
+ }
279
+
280
+ /**
281
+ * Define parameter component.
282
+ *
283
+ * @param {object} parameterDef
284
+ * @returns {this}
285
+ */
286
+ defineParameterComponent(parameterDef) {
287
+ return this.defineComponent(OAComponentType.PARAMETER, parameterDef);
288
+ }
289
+
290
+ /**
291
+ * Define example component.
292
+ *
293
+ * @param {object} exampleDef
294
+ * @returns {this}
295
+ */
296
+ defineExampleComponent(exampleDef) {
297
+ return this.defineComponent(OAComponentType.EXAMPLE, exampleDef);
298
+ }
299
+
300
+ /**
301
+ * Define request body component.
302
+ *
303
+ * @param {object} requestBodyDef
304
+ * @returns {this}
305
+ */
306
+ defineRequestBodyComponent(requestBodyDef) {
307
+ return this.defineComponent(OAComponentType.REQUEST_BODY, requestBodyDef);
308
+ }
309
+
310
+ /**
311
+ * Define header component.
312
+ *
313
+ * @param {object} headerDef
314
+ * @returns {this}
315
+ */
316
+ defineHeaderComponent(headerDef) {
317
+ return this.defineComponent(OAComponentType.HEADER, headerDef);
318
+ }
319
+
320
+ /**
321
+ * Define security scheme component.
322
+ *
323
+ * @param {object} securitySchemeDef
324
+ * @returns {this}
325
+ */
326
+ defineSecuritySchemeComponent(securitySchemeDef) {
327
+ return this.defineComponent(
328
+ OAComponentType.SECURITY_SCHEME,
329
+ securitySchemeDef,
330
+ );
331
+ }
332
+
333
+ /**
334
+ * Define link component.
335
+ *
336
+ * @param {object} linkDef
337
+ * @returns {this}
338
+ */
339
+ defineLinkComponent(linkDef) {
340
+ return this.defineComponent(OAComponentType.LINK, linkDef);
341
+ }
342
+
343
+ /**
344
+ * Define callback component.
345
+ *
346
+ * @param {object} callbackDef
347
+ * @returns {this}
348
+ */
349
+ defineCallbackComponent(callbackDef) {
350
+ return this.defineComponent(OAComponentType.CALLBACK, callbackDef);
351
+ }
352
+
353
+ /**
354
+ * Define path item component.
355
+ *
356
+ * @param {object} pathItemDef
357
+ * @returns {this}
358
+ */
359
+ definePathItemComponent(pathItemDef) {
360
+ return this.defineComponent(OAComponentType.PATH_ITEM, pathItemDef);
361
+ }
362
+
363
+ /**
364
+ * Define operation.
365
+ *
366
+ * @param {object} operationDef
367
+ */
368
+ defineOperation(operationDef) {
369
+ if (
370
+ !operationDef ||
371
+ typeof operationDef !== 'object' ||
372
+ Array.isArray(operationDef)
373
+ ) {
374
+ throw new InvalidArgumentError(
375
+ 'Operation Definition must be an Object, but %v was given.',
376
+ operationDef,
377
+ );
378
+ }
379
+ // path
380
+ if (!operationDef.path || typeof operationDef.path !== 'string') {
381
+ throw new InvalidArgumentError(
382
+ 'Property "path" must be a non-empty String, but %v was given.',
383
+ operationDef.path,
384
+ );
385
+ }
386
+ // method
387
+ if (!operationDef.method || typeof operationDef.method !== 'string') {
388
+ throw new InvalidArgumentError(
389
+ 'Property "method" must be a non-empty String, but %v was given.',
390
+ operationDef.method,
391
+ );
392
+ }
393
+ if (!Object.values(OAOperationMethod).includes(operationDef.method)) {
394
+ throw new InvalidArgumentError(
395
+ 'Property "method" must be one of values: %l, but %v was given.',
396
+ Object.values(OAOperationMethod),
397
+ );
398
+ }
399
+ // operation
400
+ if (
401
+ !operationDef.operation ||
402
+ typeof operationDef.operation !== 'object' ||
403
+ Array.isArray(operationDef.operation)
404
+ ) {
405
+ throw new InvalidArgumentError(
406
+ 'Property "operation" must be an Object, but %v was given.',
407
+ operationDef.operation,
408
+ );
409
+ }
410
+ const normalizedPath = normalizePath(operationDef.path);
411
+ if (!this._document.paths) {
412
+ this._document.paths = {};
413
+ }
414
+ if (!this._document.paths[normalizedPath]) {
415
+ this._document.paths[normalizedPath] = {};
416
+ }
417
+ this._document.paths[normalizedPath][operationDef.method] = structuredClone(
418
+ operationDef.operation,
419
+ );
420
+ }
421
+
422
+ /**
423
+ * Create scope.
424
+ *
425
+ * @param {object} [options]
426
+ * @returns {OADocumentScope}
427
+ */
428
+ createScope(options) {
429
+ return new OADocumentScope(this, options);
430
+ }
431
+
432
+ /**
433
+ * Build.
434
+ *
435
+ * @returns {object}
436
+ */
437
+ build() {
438
+ return structuredClone(this._document);
439
+ }
440
+
441
+ /**
442
+ * Build JSON.
443
+ *
444
+ * @param {string|number} [space]
445
+ * @returns {string}
446
+ */
447
+ buildJson(space = 0) {
448
+ return JSON.stringify(this.build(), null, space);
449
+ }
450
+ }
@@ -0,0 +1 @@
1
+ export * from './validate-shallow-oa-document.js';
@@ -0,0 +1 @@
1
+ export * from './validate-shallow-oa-document.js';
@@ -0,0 +1,10 @@
1
+ import {OADocumentObject} from '../oa-specification.js';
2
+
3
+ /**
4
+ * Validate shallow OADocumentObject.
5
+ *
6
+ * @param documentObject
7
+ */
8
+ export declare function validateShallowOADocument(
9
+ documentObject: OADocumentObject,
10
+ ): void;
@@ -0,0 +1,209 @@
1
+ import {InvalidArgumentError} from '@e22m4u/js-format';
2
+
3
+ /**
4
+ * Validate shallow OADocumentObject.
5
+ *
6
+ * @param {object} documentObject
7
+ */
8
+ export function validateShallowOADocument(documentObject) {
9
+ if (
10
+ !documentObject ||
11
+ typeof documentObject !== 'object' ||
12
+ Array.isArray(documentObject)
13
+ ) {
14
+ throw new InvalidArgumentError(
15
+ 'OpenAPI Document Object must be an Object, but %v was given.',
16
+ documentObject,
17
+ );
18
+ }
19
+ // openapi
20
+ if (!documentObject.openapi || typeof documentObject.openapi !== 'string') {
21
+ throw new InvalidArgumentError(
22
+ 'Property "openapi" must be a non-empty String, but %v was given.',
23
+ documentObject.openapi,
24
+ );
25
+ }
26
+ // info
27
+ if (
28
+ !documentObject.info ||
29
+ typeof documentObject.info !== 'object' ||
30
+ Array.isArray(documentObject.info)
31
+ ) {
32
+ throw new InvalidArgumentError(
33
+ 'Property "info" must be an Object, but %v was given.',
34
+ documentObject.info,
35
+ );
36
+ }
37
+ // info.title
38
+ if (
39
+ !documentObject.info.title ||
40
+ typeof documentObject.info.title !== 'string'
41
+ ) {
42
+ throw new InvalidArgumentError(
43
+ 'Property "info.title" must be a non-empty String, but %v was given.',
44
+ documentObject.info.title,
45
+ );
46
+ }
47
+ // info.version
48
+ if (
49
+ !documentObject.info.version ||
50
+ typeof documentObject.info.version !== 'string'
51
+ ) {
52
+ throw new InvalidArgumentError(
53
+ 'Property "info.version" must be a non-empty String, but %v was given.',
54
+ documentObject.info.version,
55
+ );
56
+ }
57
+ // jsonSchemaDialect
58
+ if (documentObject.jsonSchemaDialect !== undefined) {
59
+ if (
60
+ !documentObject.jsonSchemaDialect ||
61
+ typeof documentObject.jsonSchemaDialect !== 'string'
62
+ ) {
63
+ throw new InvalidArgumentError(
64
+ 'Property "jsonSchemaDialect" must be a non-empty String, ' +
65
+ 'but %v was given.',
66
+ documentObject.jsonSchemaDialect,
67
+ );
68
+ }
69
+ }
70
+ // servers
71
+ if (documentObject.servers !== undefined) {
72
+ if (!Array.isArray(documentObject.servers)) {
73
+ throw new InvalidArgumentError(
74
+ 'Property "servers" must be an Array, but %v was given.',
75
+ documentObject.servers,
76
+ );
77
+ }
78
+ // servers[n]
79
+ documentObject.servers.forEach((serverObject, index) => {
80
+ if (
81
+ !serverObject ||
82
+ typeof serverObject !== 'object' ||
83
+ Array.isArray(serverObject)
84
+ ) {
85
+ throw new InvalidArgumentError(
86
+ 'Element "servers[%d]" must be an Object, but %v was given.',
87
+ index,
88
+ serverObject,
89
+ );
90
+ }
91
+ // servers[n].url
92
+ if (!serverObject.url || typeof serverObject.url !== 'string') {
93
+ throw new InvalidArgumentError(
94
+ 'Property "servers[%d].url" must be a non-empty String, ' +
95
+ 'but %v was given.',
96
+ index,
97
+ serverObject.url,
98
+ );
99
+ }
100
+ });
101
+ }
102
+ // paths
103
+ if (documentObject.paths !== undefined) {
104
+ if (
105
+ !documentObject.paths ||
106
+ typeof documentObject.paths !== 'object' ||
107
+ Array.isArray(documentObject.paths)
108
+ ) {
109
+ throw new InvalidArgumentError(
110
+ 'Property "paths" must be an Object, but %v was given.',
111
+ documentObject.paths,
112
+ );
113
+ }
114
+ }
115
+ // webhooks
116
+ if (documentObject.webhooks !== undefined) {
117
+ if (
118
+ !documentObject.webhooks ||
119
+ typeof documentObject.webhooks !== 'object' ||
120
+ Array.isArray(documentObject.webhooks)
121
+ ) {
122
+ throw new InvalidArgumentError(
123
+ 'Property "webhooks" must be an Object, but %v was given.',
124
+ documentObject.webhooks,
125
+ );
126
+ }
127
+ }
128
+ // components
129
+ if (documentObject.components !== undefined) {
130
+ if (
131
+ !documentObject.components ||
132
+ typeof documentObject.components !== 'object' ||
133
+ Array.isArray(documentObject.components)
134
+ ) {
135
+ throw new InvalidArgumentError(
136
+ 'Property "components" must be an Object, but %v was given.',
137
+ documentObject.components,
138
+ );
139
+ }
140
+ }
141
+ // security
142
+ if (documentObject.security !== undefined) {
143
+ if (!Array.isArray(documentObject.security)) {
144
+ throw new InvalidArgumentError(
145
+ 'Property "security" must be an Array, but %v was given.',
146
+ documentObject.security,
147
+ );
148
+ }
149
+ // security[n]
150
+ documentObject.security.forEach((securityRequirementObject, index) => {
151
+ if (
152
+ !securityRequirementObject ||
153
+ typeof securityRequirementObject !== 'object' ||
154
+ Array.isArray(securityRequirementObject)
155
+ ) {
156
+ throw new InvalidArgumentError(
157
+ 'Element "security[%d]" must be an Object, but %v was given.',
158
+ index,
159
+ securityRequirementObject,
160
+ );
161
+ }
162
+ });
163
+ }
164
+ // tags
165
+ if (documentObject.tags !== undefined) {
166
+ if (!Array.isArray(documentObject.tags)) {
167
+ throw new InvalidArgumentError(
168
+ 'Property "tags" must be an Array, but %v was given.',
169
+ documentObject.tags,
170
+ );
171
+ }
172
+ // tags[n]
173
+ documentObject.tags.forEach((tagObject, index) => {
174
+ if (
175
+ !tagObject ||
176
+ typeof tagObject !== 'object' ||
177
+ Array.isArray(tagObject)
178
+ ) {
179
+ throw new InvalidArgumentError(
180
+ 'Element "tags[%d]" must be an Object, but %v was given.',
181
+ index,
182
+ tagObject,
183
+ );
184
+ }
185
+ // tags[n].name
186
+ if (!tagObject.name || typeof tagObject.name !== 'string') {
187
+ throw new InvalidArgumentError(
188
+ 'Property "tags[%d].name" must be a non-empty String, ' +
189
+ 'but %v was given.',
190
+ index,
191
+ tagObject.name,
192
+ );
193
+ }
194
+ });
195
+ }
196
+ // externalDocs
197
+ if (documentObject.externalDocs !== undefined) {
198
+ if (
199
+ !documentObject.externalDocs ||
200
+ typeof documentObject.externalDocs !== 'object' ||
201
+ Array.isArray(documentObject.externalDocs)
202
+ ) {
203
+ throw new InvalidArgumentError(
204
+ 'Property "externalDocs" must be an Object, but %v was given.',
205
+ documentObject.externalDocs,
206
+ );
207
+ }
208
+ }
209
+ }