@redocly/openapi-core 1.1.0 → 1.2.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 (77) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +250 -7
  3. package/lib/bundle.d.ts +12 -6
  4. package/lib/bundle.js +34 -24
  5. package/lib/config/builtIn.js +4 -0
  6. package/lib/config/config-resolvers.js +19 -6
  7. package/lib/config/config.d.ts +9 -9
  8. package/lib/config/config.js +32 -17
  9. package/lib/config/load.d.ts +3 -2
  10. package/lib/config/load.js +2 -2
  11. package/lib/config/rules.d.ts +2 -2
  12. package/lib/config/types.d.ts +10 -3
  13. package/lib/index.d.ts +4 -3
  14. package/lib/index.js +10 -6
  15. package/lib/lint.js +10 -16
  16. package/lib/oas-types.d.ts +16 -10
  17. package/lib/oas-types.js +52 -26
  18. package/lib/rules/async2/channels-kebab-case.d.ts +2 -0
  19. package/lib/rules/async2/channels-kebab-case.js +19 -0
  20. package/lib/rules/async2/index.d.ts +12 -0
  21. package/lib/rules/async2/index.js +22 -0
  22. package/lib/rules/async2/no-channel-trailing-slash.d.ts +2 -0
  23. package/lib/rules/async2/no-channel-trailing-slash.js +16 -0
  24. package/lib/rules/common/assertions/asserts.js +12 -4
  25. package/lib/rules/common/scalar-property-missing-example.js +1 -1
  26. package/lib/rules/common/spec.d.ts +2 -2
  27. package/lib/rules/common/spec.js +3 -3
  28. package/lib/rules/oas2/index.js +1 -1
  29. package/lib/rules/oas3/index.js +1 -1
  30. package/lib/rules/oas3/no-server-example.com.js +3 -2
  31. package/lib/types/asyncapi.d.ts +2 -0
  32. package/lib/types/asyncapi.js +1034 -0
  33. package/lib/types/oas3_1.js +8 -1
  34. package/lib/types/redocly-yaml.js +3 -0
  35. package/lib/typings/asyncapi.d.ts +21 -0
  36. package/lib/typings/asyncapi.js +2 -0
  37. package/lib/visitors.d.ts +12 -0
  38. package/lib/walk.d.ts +3 -3
  39. package/package.json +4 -2
  40. package/src/__tests__/__snapshots__/bundle.test.ts.snap +1 -1
  41. package/src/__tests__/bundle.test.ts +65 -25
  42. package/src/__tests__/fixtures/lint/openapi.yaml +10 -0
  43. package/src/__tests__/fixtures/redocly.yaml +2 -0
  44. package/src/__tests__/lint.test.ts +67 -8
  45. package/src/bundle.ts +62 -35
  46. package/src/config/__tests__/__snapshots__/config.test.ts.snap +24 -0
  47. package/src/config/__tests__/config.test.ts +15 -4
  48. package/src/config/__tests__/load.test.ts +35 -2
  49. package/src/config/builtIn.ts +4 -0
  50. package/src/config/config-resolvers.ts +25 -6
  51. package/src/config/config.ts +51 -27
  52. package/src/config/load.ts +11 -4
  53. package/src/config/rules.ts +2 -2
  54. package/src/config/types.ts +17 -4
  55. package/src/index.ts +10 -2
  56. package/src/lint.ts +13 -22
  57. package/src/oas-types.ts +59 -21
  58. package/src/rules/async2/__tests__/channels-kebab-case.test.ts +141 -0
  59. package/src/rules/async2/__tests__/no-channel-trailing-slash.test.ts +97 -0
  60. package/src/rules/async2/channels-kebab-case.ts +18 -0
  61. package/src/rules/async2/index.ts +22 -0
  62. package/src/rules/async2/no-channel-trailing-slash.ts +15 -0
  63. package/src/rules/common/assertions/asserts.ts +16 -4
  64. package/src/rules/common/scalar-property-missing-example.ts +2 -2
  65. package/src/rules/common/spec.ts +2 -2
  66. package/src/rules/oas2/index.ts +2 -2
  67. package/src/rules/oas3/__tests__/no-server-example.com.test.ts +36 -1
  68. package/src/rules/oas3/__tests__/spec/spec.test.ts +1 -1
  69. package/src/rules/oas3/index.ts +2 -2
  70. package/src/rules/oas3/no-server-example.com.ts +3 -2
  71. package/src/types/asyncapi.ts +1142 -0
  72. package/src/types/oas3_1.ts +7 -1
  73. package/src/types/redocly-yaml.ts +3 -0
  74. package/src/typings/asyncapi.ts +26 -0
  75. package/src/visitors.ts +22 -0
  76. package/src/walk.ts +3 -3
  77. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,1142 @@
1
+ import { NodeType, listOf, mapOf } from '.';
2
+ import { isMappingRef } from '../ref-utils';
3
+
4
+ const Root: NodeType = {
5
+ properties: {
6
+ asyncapi: null, // TODO: validate semver format and supported version
7
+ info: 'Info',
8
+ id: { type: 'string' },
9
+ servers: 'ServerMap',
10
+ channels: 'ChannelMap',
11
+ components: 'Components',
12
+ tags: 'TagList',
13
+ externalDocs: 'ExternalDocs',
14
+ defaultContentType: { type: 'string' },
15
+ },
16
+ required: ['asyncapi', 'channels', 'info'],
17
+ };
18
+
19
+ const Channel: NodeType = {
20
+ properties: {
21
+ description: { type: 'string' },
22
+ subscribe: 'Operation',
23
+ publish: 'Operation',
24
+ parameters: 'ParametersMap',
25
+ bindings: 'ChannelBindings',
26
+ servers: { type: 'array', items: { type: 'string' } },
27
+ },
28
+ };
29
+
30
+ const ChannelMap: NodeType = {
31
+ properties: {},
32
+ additionalProperties: 'Channel',
33
+ };
34
+
35
+ const ChannelBindings: NodeType = {
36
+ properties: {},
37
+ allowed() {
38
+ // allow all supported values, not all have deep linting
39
+ return [
40
+ 'http',
41
+ 'ws',
42
+ 'kafka',
43
+ 'anypointmq',
44
+ 'amqp',
45
+ 'amqp1',
46
+ 'mqtt',
47
+ 'mqtt5',
48
+ 'nats',
49
+ 'jms',
50
+ 'sns',
51
+ 'solace',
52
+ 'sqs',
53
+ 'stomp',
54
+ 'redis',
55
+ 'mercure',
56
+ 'ibmmq',
57
+ 'googlepubsub',
58
+ 'pulsar',
59
+ ];
60
+ },
61
+ additionalProperties: { type: 'object' },
62
+ };
63
+
64
+ const Tag: NodeType = {
65
+ properties: {
66
+ name: { type: 'string' },
67
+ description: { type: 'string' },
68
+ externalDocs: 'ExternalDocs',
69
+ },
70
+ required: ['name'],
71
+ };
72
+
73
+ const ExternalDocs: NodeType = {
74
+ properties: {
75
+ description: { type: 'string' },
76
+ url: { type: 'string' },
77
+ },
78
+ required: ['url'],
79
+ };
80
+
81
+ const SecurityRequirement: NodeType = {
82
+ properties: {},
83
+ additionalProperties: { type: 'array', items: { type: 'string' } },
84
+ };
85
+
86
+ const ServerBindings: NodeType = {
87
+ properties: {},
88
+ allowed() {
89
+ // allow all supported values, not all have deep linting
90
+ return [
91
+ 'http',
92
+ 'ws',
93
+ 'kafka',
94
+ 'anypointmq',
95
+ 'amqp',
96
+ 'amqp1',
97
+ 'mqtt',
98
+ 'mqtt5',
99
+ 'nats',
100
+ 'jms',
101
+ 'sns',
102
+ 'solace',
103
+ 'sqs',
104
+ 'stomp',
105
+ 'redis',
106
+ 'mercure',
107
+ 'ibmmq',
108
+ 'googlepubsub',
109
+ 'pulsar',
110
+ ];
111
+ },
112
+ additionalProperties: { type: 'object' },
113
+ };
114
+
115
+ const Server: NodeType = {
116
+ properties: {
117
+ url: { type: 'string' },
118
+ protocol: { type: 'string' },
119
+ protocolVersion: { type: 'string' },
120
+ description: { type: 'string' },
121
+ variables: 'ServerVariablesMap',
122
+ security: 'SecurityRequirementList',
123
+ bindings: 'ServerBindings',
124
+ tags: 'TagList',
125
+ },
126
+ required: ['url', 'protocol'],
127
+ };
128
+
129
+ const ServerMap: NodeType = {
130
+ properties: {},
131
+ additionalProperties: (_value: any, key: string) =>
132
+ key.match(/^[A-Za-z0-9_\-]+$/) ? 'Server' : undefined,
133
+ };
134
+
135
+ const ServerVariable: NodeType = {
136
+ properties: {
137
+ enum: {
138
+ type: 'array',
139
+ items: { type: 'string' },
140
+ },
141
+ default: { type: 'string' },
142
+ description: { type: 'string' },
143
+ examples: {
144
+ type: 'array',
145
+ items: { type: 'string' },
146
+ },
147
+ },
148
+ required: [],
149
+ };
150
+
151
+ const Info: NodeType = {
152
+ properties: {
153
+ title: { type: 'string' },
154
+ version: { type: 'string' },
155
+ description: { type: 'string' },
156
+ termsOfService: { type: 'string' },
157
+ contact: 'Contact',
158
+ license: 'License',
159
+ },
160
+ required: ['title', 'version'],
161
+ };
162
+
163
+ const Contact: NodeType = {
164
+ properties: {
165
+ name: { type: 'string' },
166
+ url: { type: 'string' },
167
+ email: { type: 'string' },
168
+ },
169
+ };
170
+
171
+ const License: NodeType = {
172
+ properties: {
173
+ name: { type: 'string' },
174
+ url: { type: 'string' },
175
+ },
176
+ required: ['name'],
177
+ };
178
+
179
+ const Parameter: NodeType = {
180
+ properties: {
181
+ description: { type: 'string' },
182
+ schema: 'Schema',
183
+ location: { type: 'string' },
184
+ },
185
+ };
186
+
187
+ const CorrelationId: NodeType = {
188
+ properties: {
189
+ description: { type: 'string' },
190
+ location: { type: 'string' },
191
+ },
192
+ required: ['location'],
193
+ };
194
+
195
+ const Message: NodeType = {
196
+ properties: {
197
+ messageId: { type: 'string' },
198
+ headers: 'Schema',
199
+ payload: 'Schema', // TODO: strictly this does not cover all cases
200
+ correlationId: 'CorrelationId',
201
+
202
+ schemaFormat: { type: 'string' }, // TODO: support official list of schema formats and custom values
203
+ contentType: { type: 'string' },
204
+ name: { type: 'string' },
205
+ title: { type: 'string' },
206
+ summary: { type: 'string' },
207
+ description: { type: 'string' },
208
+ tags: 'TagList',
209
+ externalDocs: 'ExternalDocs',
210
+ bindings: 'MessageBindings',
211
+ // examples: 'MessageExampleList', // TODO: add support for message examples
212
+ traits: 'MessageTraitList',
213
+ },
214
+ additionalProperties: {},
215
+ };
216
+
217
+ const MessageBindings: NodeType = {
218
+ properties: {},
219
+ allowed() {
220
+ // allow all supported values, not all have deep linting
221
+ return [
222
+ 'http',
223
+ 'ws',
224
+ 'kafka',
225
+ 'anypointmq',
226
+ 'amqp',
227
+ 'amqp1',
228
+ 'mqtt',
229
+ 'mqtt5',
230
+ 'nats',
231
+ 'jms',
232
+ 'sns',
233
+ 'solace',
234
+ 'sqs',
235
+ 'stomp',
236
+ 'redis',
237
+ 'mercure',
238
+ 'ibmmq',
239
+ 'googlepubsub',
240
+ 'pulsar',
241
+ ];
242
+ },
243
+ additionalProperties: { type: 'object' },
244
+ };
245
+
246
+ const OperationBindings: NodeType = {
247
+ properties: {},
248
+ allowed() {
249
+ // allow all supported values, not all have deep linting
250
+ return [
251
+ 'http',
252
+ 'ws',
253
+ 'kafka',
254
+ 'anypointmq',
255
+ 'amqp',
256
+ 'amqp1',
257
+ 'mqtt',
258
+ 'mqtt5',
259
+ 'nats',
260
+ 'jms',
261
+ 'sns',
262
+ 'solace',
263
+ 'sqs',
264
+ 'stomp',
265
+ 'redis',
266
+ 'mercure',
267
+ 'ibmmq',
268
+ 'googlepubsub',
269
+ 'pulsar',
270
+ ];
271
+ },
272
+ additionalProperties: { type: 'object' },
273
+ };
274
+
275
+ const OperationTrait: NodeType = {
276
+ properties: {
277
+ tags: {
278
+ type: 'array',
279
+ items: { type: 'string' },
280
+ },
281
+ summary: { type: 'string' },
282
+ description: { type: 'string' },
283
+ externalDocs: 'ExternalDocs',
284
+ operationId: { type: 'string' },
285
+ security: 'SecurityRequirementList',
286
+
287
+ bindings: 'OperationBindings',
288
+ },
289
+ required: [],
290
+ };
291
+
292
+ const MessageTrait: NodeType = {
293
+ properties: {
294
+ messageId: { type: 'string' },
295
+ headers: 'Schema',
296
+ correlationId: 'CorrelationId',
297
+
298
+ schemaFormat: { type: 'string' },
299
+ contentType: { type: 'string' },
300
+ name: { type: 'string' },
301
+ title: { type: 'string' },
302
+ summary: { type: 'string' },
303
+ description: { type: 'string' },
304
+ tags: 'TagList',
305
+ externalDocs: 'ExternalDocs',
306
+ bindings: 'MessageBindings',
307
+ // examples: 'MessageExampleList', // TODO: support examples for message traits
308
+ },
309
+ additionalProperties: {},
310
+ };
311
+
312
+ const Operation: NodeType = {
313
+ properties: {
314
+ tags: {
315
+ type: 'array',
316
+ items: { type: 'string' },
317
+ },
318
+ summary: { type: 'string' },
319
+ description: { type: 'string' },
320
+ externalDocs: 'ExternalDocs',
321
+ operationId: { type: 'string' },
322
+ security: 'SecurityRequirementList',
323
+
324
+ bindings: 'OperationBindings',
325
+ traits: 'OperationTraitList',
326
+ message: 'Message',
327
+ },
328
+ required: [],
329
+ };
330
+
331
+ const MessageExample: NodeType = {
332
+ properties: {
333
+ payload: { isExample: true },
334
+ summary: { type: 'string' },
335
+ name: { type: 'string' },
336
+ headers: { type: 'object' },
337
+ },
338
+ };
339
+
340
+ const Schema: NodeType = {
341
+ properties: {
342
+ $id: { type: 'string' },
343
+ id: { type: 'string' },
344
+ $schema: { type: 'string' },
345
+ definitions: 'NamedSchemas',
346
+ $defs: 'NamedSchemas',
347
+ $vocabulary: { type: 'string' },
348
+ externalDocs: 'ExternalDocs',
349
+ discriminator: 'Discriminator',
350
+ myArbitraryKeyword: { type: 'boolean' },
351
+ title: { type: 'string' },
352
+ multipleOf: { type: 'number', minimum: 0 },
353
+ maximum: { type: 'number' },
354
+ minimum: { type: 'number' },
355
+ exclusiveMaximum: { type: 'number' },
356
+ exclusiveMinimum: { type: 'number' },
357
+ maxLength: { type: 'integer', minimum: 0 },
358
+ minLength: { type: 'integer', minimum: 0 },
359
+ pattern: { type: 'string' },
360
+ maxItems: { type: 'integer', minimum: 0 },
361
+ minItems: { type: 'integer', minimum: 0 },
362
+ uniqueItems: { type: 'boolean' },
363
+ maxProperties: { type: 'integer', minimum: 0 },
364
+ minProperties: { type: 'integer', minimum: 0 },
365
+ required: { type: 'array', items: { type: 'string' } },
366
+ enum: { type: 'array' },
367
+ type: (value: any) => {
368
+ if (Array.isArray(value)) {
369
+ return {
370
+ type: 'array',
371
+ items: { enum: ['object', 'array', 'string', 'number', 'integer', 'boolean', 'null'] },
372
+ };
373
+ } else {
374
+ return {
375
+ enum: ['object', 'array', 'string', 'number', 'integer', 'boolean', 'null'],
376
+ };
377
+ }
378
+ },
379
+ allOf: listOf('Schema'),
380
+ anyOf: listOf('Schema'),
381
+ oneOf: listOf('Schema'),
382
+ not: 'Schema',
383
+ if: 'Schema',
384
+ then: 'Schema',
385
+ else: 'Schema',
386
+ dependentSchemas: listOf('Schema'),
387
+ prefixItems: listOf('Schema'),
388
+ contains: 'Schema',
389
+ minContains: { type: 'integer', minimum: 0 },
390
+ maxContains: { type: 'integer', minimum: 0 },
391
+ patternProperties: { type: 'object' },
392
+ propertyNames: 'Schema',
393
+ unevaluatedItems: (value: unknown) => {
394
+ if (typeof value === 'boolean') {
395
+ return { type: 'boolean' };
396
+ } else {
397
+ return 'Schema';
398
+ }
399
+ },
400
+ unevaluatedProperties: (value: unknown) => {
401
+ if (typeof value === 'boolean') {
402
+ return { type: 'boolean' };
403
+ } else {
404
+ return 'Schema';
405
+ }
406
+ },
407
+ summary: { type: 'string' },
408
+ properties: 'SchemaProperties',
409
+ items: (value: any) => {
410
+ if (typeof value === 'boolean') {
411
+ return { type: 'boolean' };
412
+ } else {
413
+ return 'Schema';
414
+ }
415
+ },
416
+ additionalProperties: (value: any) => {
417
+ return typeof value === 'boolean' ? { type: 'boolean' } : 'Schema';
418
+ },
419
+ description: { type: 'string' },
420
+ format: { type: 'string' },
421
+ contentEncoding: { type: 'string' },
422
+ contentMediaType: { type: 'string' },
423
+ default: null,
424
+ readOnly: { type: 'boolean' },
425
+ writeOnly: { type: 'boolean' },
426
+ // xml: 'Xml',
427
+ examples: { type: 'array' },
428
+ example: { isExample: true },
429
+ deprecated: { type: 'boolean' },
430
+ const: null,
431
+ $comment: { type: 'string' },
432
+ dependencies: { type: 'object' }, // TODO
433
+ },
434
+ };
435
+
436
+ const SchemaProperties: NodeType = {
437
+ properties: {},
438
+ additionalProperties: (value: any) => {
439
+ if (typeof value === 'boolean') {
440
+ return { type: 'boolean' };
441
+ }
442
+ return 'Schema';
443
+ },
444
+ };
445
+
446
+ const DiscriminatorMapping: NodeType = {
447
+ properties: {},
448
+ additionalProperties: (value: any) => {
449
+ if (isMappingRef(value)) {
450
+ return { type: 'string', directResolveAs: 'Schema' };
451
+ } else {
452
+ return { type: 'string' };
453
+ }
454
+ },
455
+ };
456
+
457
+ const Discriminator: NodeType = {
458
+ properties: {
459
+ propertyName: { type: 'string' },
460
+ mapping: 'DiscriminatorMapping',
461
+ },
462
+ required: ['propertyName'],
463
+ };
464
+
465
+ const Components: NodeType = {
466
+ properties: {
467
+ messages: 'NamedMessages',
468
+ parameters: 'NamedParameters',
469
+ schemas: 'NamedSchemas',
470
+ correlationIds: 'NamedCorrelationIds',
471
+ messageTraits: 'NamedMessageTraits',
472
+ operationTraits: 'NamedOperationTraits',
473
+ streamHeaders: 'NamedStreamHeaders',
474
+ securitySchemes: 'NamedSecuritySchemes',
475
+ servers: 'ServerMap',
476
+ serverVariables: 'ServerVariablesMap',
477
+ channels: 'ChannelMap',
478
+ serverBindings: 'ServerBindings',
479
+ channelBindings: 'ChannelBindings',
480
+ operationBindings: 'OperationBindings',
481
+ messageBindings: 'MessageBindings',
482
+ },
483
+ };
484
+
485
+ const ImplicitFlow: NodeType = {
486
+ properties: {
487
+ refreshUrl: { type: 'string' },
488
+ scopes: { type: 'object', additionalProperties: { type: 'string' } }, // TODO: validate scopes
489
+ authorizationUrl: { type: 'string' },
490
+ },
491
+ required: ['authorizationUrl', 'scopes'],
492
+ };
493
+
494
+ const PasswordFlow: NodeType = {
495
+ properties: {
496
+ refreshUrl: { type: 'string' },
497
+ scopes: { type: 'object', additionalProperties: { type: 'string' } }, // TODO: validate scopes
498
+ tokenUrl: { type: 'string' },
499
+ },
500
+ required: ['tokenUrl', 'scopes'],
501
+ };
502
+
503
+ const ClientCredentials: NodeType = {
504
+ properties: {
505
+ refreshUrl: { type: 'string' },
506
+ scopes: { type: 'object', additionalProperties: { type: 'string' } }, // TODO: validate scopes
507
+ tokenUrl: { type: 'string' },
508
+ },
509
+ required: ['tokenUrl', 'scopes'],
510
+ };
511
+
512
+ const AuthorizationCode: NodeType = {
513
+ properties: {
514
+ refreshUrl: { type: 'string' },
515
+ authorizationUrl: { type: 'string' },
516
+ scopes: { type: 'object', additionalProperties: { type: 'string' } }, // TODO: validate scopes
517
+ tokenUrl: { type: 'string' },
518
+ },
519
+ required: ['authorizationUrl', 'tokenUrl', 'scopes'],
520
+ };
521
+
522
+ const SecuritySchemeFlows: NodeType = {
523
+ properties: {
524
+ implicit: 'ImplicitFlow',
525
+ password: 'PasswordFlow',
526
+ clientCredentials: 'ClientCredentials',
527
+ authorizationCode: 'AuthorizationCode',
528
+ },
529
+ };
530
+
531
+ const SecurityScheme: NodeType = {
532
+ properties: {
533
+ type: {
534
+ enum: [
535
+ 'userPassword',
536
+ 'apiKey',
537
+ 'X509',
538
+ 'symmetricEncryption',
539
+ 'asymmetricEncryption',
540
+ 'httpApiKey',
541
+ 'http',
542
+ 'oauth2',
543
+ 'openIdConnect',
544
+ 'plain',
545
+ 'scramSha256',
546
+ 'scramSha512',
547
+ 'gssapi',
548
+ ],
549
+ },
550
+ description: { type: 'string' },
551
+ name: { type: 'string' },
552
+ in: { type: 'string', enum: ['query', 'header', 'cookie', 'user', 'password'] },
553
+ scheme: { type: 'string' },
554
+ bearerFormat: { type: 'string' },
555
+ flows: 'SecuritySchemeFlows',
556
+ openIdConnectUrl: { type: 'string' },
557
+ },
558
+ required(value) {
559
+ switch (value?.type) {
560
+ case 'apiKey':
561
+ return ['type', 'in'];
562
+ case 'httpApiKey':
563
+ return ['type', 'name', 'in'];
564
+ case 'http':
565
+ return ['type', 'scheme'];
566
+ case 'oauth2':
567
+ return ['type', 'flows'];
568
+ case 'openIdConnect':
569
+ return ['type', 'openIdConnectUrl'];
570
+ default:
571
+ return ['type'];
572
+ }
573
+ },
574
+ allowed(value) {
575
+ switch (value?.type) {
576
+ case 'apiKey':
577
+ return ['type', 'in', 'description'];
578
+ case 'httpApiKey':
579
+ return ['type', 'name', 'in', 'description'];
580
+ case 'http':
581
+ return ['type', 'scheme', 'bearerFormat', 'description'];
582
+ case 'oauth2':
583
+ return ['type', 'flows', 'description'];
584
+ case 'openIdConnect':
585
+ return ['type', 'openIdConnectUrl', 'description'];
586
+ default:
587
+ return ['type', 'description'];
588
+ }
589
+ },
590
+ extensionsPrefix: 'x-',
591
+ };
592
+
593
+ // --- Per-protocol node types
594
+
595
+ // http
596
+ const HttpChannelBinding: NodeType = {
597
+ properties: {}, // empty object
598
+ };
599
+ ChannelBindings.properties.http = HttpChannelBinding;
600
+
601
+ const HttpServerBinding: NodeType = {
602
+ properties: {}, // empty object
603
+ };
604
+ ServerBindings.properties.http = HttpServerBinding;
605
+
606
+ const HttpMessageBinding: NodeType = {
607
+ properties: {
608
+ headers: 'Schema',
609
+ bindingVersion: { type: 'string' },
610
+ },
611
+ };
612
+ MessageBindings.properties.http = HttpMessageBinding;
613
+
614
+ const HttpOperationBinding: NodeType = {
615
+ properties: {
616
+ type: { type: 'string' },
617
+ method: {
618
+ type: 'string',
619
+ enum: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS', 'CONNECT', 'TRACE'],
620
+ },
621
+ headers: 'Schema',
622
+ bindingVersion: { type: 'string' },
623
+ },
624
+ };
625
+ OperationBindings.properties.http = HttpOperationBinding;
626
+
627
+ // ws
628
+ const WsChannelBinding: NodeType = {
629
+ properties: {
630
+ method: { type: 'string' },
631
+ query: 'Schema',
632
+ headers: 'Schema',
633
+ bindingVersion: { type: 'string' },
634
+ },
635
+ };
636
+ ChannelBindings.properties.ws = WsChannelBinding;
637
+
638
+ const WsServerBinding: NodeType = {
639
+ properties: {}, // empty object
640
+ };
641
+ ServerBindings.properties.ws = WsServerBinding;
642
+
643
+ const WsMessageBinding: NodeType = {
644
+ properties: {}, // empty object
645
+ };
646
+ MessageBindings.properties.ws = WsMessageBinding;
647
+
648
+ const WsOperationBinding: NodeType = {
649
+ properties: {}, // empty object
650
+ };
651
+ OperationBindings.properties.ws = WsOperationBinding;
652
+
653
+ // kafka
654
+ const KafkaTopicConfiguration: NodeType = {
655
+ properties: {
656
+ 'cleanup.policy': { type: 'array', items: { enum: ['delete', 'compact'] } },
657
+ 'retention.ms': { type: 'integer' },
658
+ 'retention.bytes': { type: 'integer' },
659
+ 'delete.retention.ms': { type: 'integer' },
660
+ 'max.message.bytes': { type: 'integer' },
661
+ },
662
+ };
663
+ const KafkaChannelBinding: NodeType = {
664
+ properties: {
665
+ topic: { type: 'string' },
666
+ partitions: { type: 'integer' },
667
+ replicas: { type: 'integer' },
668
+ topicConfiguration: 'KafkaTopicConfiguration',
669
+ bindingVersion: { type: 'string' },
670
+ },
671
+ };
672
+ ChannelBindings.properties.kafka = KafkaChannelBinding;
673
+
674
+ const KafkaServerBinding: NodeType = {
675
+ properties: {}, // empty object
676
+ };
677
+ ServerBindings.properties.kafka = KafkaServerBinding;
678
+
679
+ const KafkaMessageBinding: NodeType = {
680
+ properties: {
681
+ key: 'Schema', // TODO: add avro support
682
+ schemaIdLocation: { type: 'string' },
683
+ schemaIdPayloadEncoding: { type: 'string' },
684
+ schemaLookupStrategy: { type: 'string' },
685
+ bindingVersion: { type: 'string' },
686
+ },
687
+ };
688
+ MessageBindings.properties.kafka = KafkaMessageBinding;
689
+
690
+ const KafkaOperationBinding: NodeType = {
691
+ properties: {
692
+ groupId: 'Schema',
693
+ clientId: 'Schema',
694
+ bindingVersion: { type: 'string' },
695
+ },
696
+ };
697
+ OperationBindings.properties.kafka = KafkaOperationBinding;
698
+
699
+ // anypointmq
700
+ const AnypointmqChannelBinding: NodeType = {
701
+ properties: {
702
+ destination: { type: 'string' },
703
+ destinationType: { type: 'string' },
704
+ bindingVersion: { type: 'string' },
705
+ },
706
+ };
707
+ ChannelBindings.properties.anypointmq = AnypointmqChannelBinding;
708
+
709
+ const AnypointmqServerBinding: NodeType = {
710
+ properties: {}, // empty object
711
+ };
712
+ ServerBindings.properties.anypointmq = AnypointmqServerBinding;
713
+
714
+ const AnypointmqMessageBinding: NodeType = {
715
+ properties: {
716
+ headers: 'Schema',
717
+ bindingVersion: { type: 'string' },
718
+ },
719
+ };
720
+ MessageBindings.properties.anypointmq = AnypointmqMessageBinding;
721
+
722
+ const AnypointmqOperationBinding: NodeType = {
723
+ properties: {}, // empty object
724
+ };
725
+ OperationBindings.properties.anypointmq = AnypointmqOperationBinding;
726
+
727
+ // amqp
728
+ const AmqpChannelBinding: NodeType = {
729
+ properties: {}, // empty object
730
+ };
731
+ ChannelBindings.properties.amqp = AmqpChannelBinding;
732
+
733
+ const AmqpServerBinding: NodeType = {
734
+ properties: {}, // empty object
735
+ };
736
+ ServerBindings.properties.amqp = AmqpServerBinding;
737
+
738
+ const AmqpMessageBinding: NodeType = {
739
+ properties: {
740
+ contentEncoding: { type: 'string' },
741
+ messageType: { type: 'string' },
742
+ bindingVersion: { type: 'string' },
743
+ },
744
+ };
745
+ MessageBindings.properties.amqp = AmqpMessageBinding;
746
+
747
+ const AmqpOperationBinding: NodeType = {
748
+ // TODO: some fields are subscribe only
749
+ properties: {
750
+ expiration: { type: 'integer' },
751
+ userId: { type: 'string' },
752
+ cc: { type: 'array', items: { type: 'string' } },
753
+ priority: { type: 'integer' },
754
+ deliveryMode: { type: 'integer' }, // TODO: enum: [1, 2]
755
+ mandatory: { type: 'boolean' },
756
+ bcc: { type: 'array', items: { type: 'string' } },
757
+ replyTo: { type: 'string' },
758
+ timestamp: { type: 'boolean' },
759
+ ack: { type: 'boolean' },
760
+ bindingVersion: { type: 'string' },
761
+ },
762
+ };
763
+ OperationBindings.properties.amqp = AmqpOperationBinding;
764
+
765
+ // amqp1
766
+ const Amqp1ChannelBinding: NodeType = {
767
+ properties: {}, // empty object
768
+ };
769
+ ChannelBindings.properties.amqp1 = Amqp1ChannelBinding;
770
+
771
+ const Amqp1ServerBinding: NodeType = {
772
+ properties: {}, // empty object
773
+ };
774
+ ServerBindings.properties.amqp1 = Amqp1ServerBinding;
775
+
776
+ const Amqp1MessageBinding: NodeType = {
777
+ properties: {}, // empty object
778
+ };
779
+ MessageBindings.properties.amqp1 = Amqp1MessageBinding;
780
+
781
+ const Amqp1OperationBinding: NodeType = {
782
+ properties: {}, // empty object
783
+ };
784
+ OperationBindings.properties.amqp1 = Amqp1OperationBinding;
785
+
786
+ // mqtt
787
+ const MqttChannelBinding: NodeType = {
788
+ properties: {
789
+ qos: { type: 'integer' },
790
+ retain: { type: 'boolean' },
791
+ bindingVersion: { type: 'string' },
792
+ },
793
+ };
794
+ ChannelBindings.properties.mqtt = MqttChannelBinding;
795
+
796
+ const MqttServerBindingLastWill: NodeType = {
797
+ properties: {
798
+ topic: { type: 'string' },
799
+ qos: { type: 'integer' },
800
+ message: { type: 'string' },
801
+ retain: { type: 'boolean' },
802
+ },
803
+ };
804
+ const MqttServerBinding: NodeType = {
805
+ properties: {
806
+ clientId: { type: 'string' },
807
+ cleanSession: { type: 'boolean' },
808
+ lastWill: 'MqttServerBindingLastWill',
809
+ keepAlive: { type: 'integer' },
810
+ bindingVersion: { type: 'string' },
811
+ },
812
+ };
813
+ ServerBindings.properties.mqtt = MqttServerBinding;
814
+
815
+ const MqttMessageBinding: NodeType = {
816
+ properties: {
817
+ bindingVersion: { type: 'string' },
818
+ },
819
+ };
820
+ MessageBindings.properties.mqtt = MqttMessageBinding;
821
+
822
+ const MqttOperationBinding: NodeType = {
823
+ properties: {
824
+ qos: { type: 'integer' },
825
+ retain: { type: 'boolean' },
826
+ bindingVersion: { type: 'string' },
827
+ },
828
+ };
829
+ OperationBindings.properties.mqtt = MqttOperationBinding;
830
+
831
+ // mqtt5
832
+ const Mqtt5ChannelBinding: NodeType = {
833
+ properties: {}, // empty object
834
+ };
835
+ ChannelBindings.properties.mqtt5 = Mqtt5ChannelBinding;
836
+
837
+ const Mqtt5ServerBinding: NodeType = {
838
+ properties: {}, // empty object
839
+ };
840
+ ServerBindings.properties.mqtt5 = Mqtt5ServerBinding;
841
+
842
+ const Mqtt5MessageBinding: NodeType = {
843
+ properties: {}, // empty object
844
+ };
845
+ MessageBindings.properties.mqtt5 = Mqtt5MessageBinding;
846
+
847
+ const Mqtt5OperationBinding: NodeType = {
848
+ properties: {}, // empty object
849
+ };
850
+ OperationBindings.properties.mqtt5 = Mqtt5OperationBinding;
851
+
852
+ // nats
853
+ const NatsChannelBinding: NodeType = {
854
+ properties: {}, // empty object
855
+ };
856
+ ChannelBindings.properties.nats = NatsChannelBinding;
857
+
858
+ const NatsServerBinding: NodeType = {
859
+ properties: {}, // empty object
860
+ };
861
+ ServerBindings.properties.nats = NatsServerBinding;
862
+
863
+ const NatsMessageBinding: NodeType = {
864
+ properties: {}, // empty object
865
+ };
866
+ MessageBindings.properties.nats = NatsMessageBinding;
867
+
868
+ const NatsOperationBinding: NodeType = {
869
+ properties: {
870
+ queue: { type: 'string' },
871
+ bindingVersion: { type: 'string' },
872
+ },
873
+ };
874
+ OperationBindings.properties.nats = NatsOperationBinding;
875
+
876
+ // jms
877
+ const JmsChannelBinding: NodeType = {
878
+ properties: {
879
+ destination: { type: 'string' },
880
+ destinationType: { type: 'string' },
881
+ bindingVersion: { type: 'string' },
882
+ },
883
+ };
884
+ ChannelBindings.properties.jms = JmsChannelBinding;
885
+
886
+ const JmsServerBinding: NodeType = {
887
+ properties: {}, // empty object
888
+ };
889
+ ServerBindings.properties.jms = JmsServerBinding;
890
+
891
+ const JmsMessageBinding: NodeType = {
892
+ properties: {
893
+ headers: 'Schema',
894
+ bindingVersion: { type: 'string' },
895
+ },
896
+ };
897
+ MessageBindings.properties.jms = JmsMessageBinding;
898
+
899
+ const JmsOperationBinding: NodeType = {
900
+ properties: {
901
+ headers: 'Schema',
902
+ bindingVersion: { type: 'string' },
903
+ },
904
+ };
905
+ OperationBindings.properties.jms = JmsOperationBinding;
906
+
907
+ // sns
908
+
909
+ // solace
910
+ const SolaceChannelBinding: NodeType = {
911
+ properties: {}, // empty object
912
+ };
913
+ ChannelBindings.properties.solace = SolaceChannelBinding;
914
+
915
+ const SolaceServerBinding: NodeType = {
916
+ properties: {
917
+ bindingVersion: { type: 'string' },
918
+ msgVpn: { type: 'string' },
919
+ },
920
+ };
921
+ ServerBindings.properties.solace = SolaceServerBinding;
922
+
923
+ const SolaceMessageBinding: NodeType = {
924
+ properties: {}, // empty object
925
+ };
926
+ MessageBindings.properties.solace = SolaceMessageBinding;
927
+
928
+ const SolaceDestination: NodeType = {
929
+ properties: {
930
+ destinationType: { type: 'string', enum: ['queue', 'topic'] },
931
+ deliveryMode: { type: 'string', enum: ['direct', 'persistent'] },
932
+ 'queue.name': { type: 'string' },
933
+ 'queue.topicSubscriptions': { type: 'array', items: { type: 'string' } },
934
+ 'queue.accessType': { type: 'string', enum: ['exclusive', 'nonexclusive'] },
935
+ 'queue.maxMsgSpoolSize': { type: 'string' },
936
+ 'queue.maxTtl': { type: 'string' },
937
+ 'topic.topicSubscriptions': { type: 'array', items: { type: 'string' } },
938
+ },
939
+ };
940
+ const SolaceOperationBinding: NodeType = {
941
+ properties: {
942
+ bindingVersion: { type: 'string' },
943
+ destinations: listOf('SolaceDestination'),
944
+ },
945
+ };
946
+ OperationBindings.properties.solace = SolaceOperationBinding;
947
+
948
+ // sqs
949
+
950
+ // stomp
951
+ const StompChannelBinding: NodeType = {
952
+ properties: {}, // empty object
953
+ };
954
+ ChannelBindings.properties.stomp = StompChannelBinding;
955
+
956
+ const StompServerBinding: NodeType = {
957
+ properties: {}, // empty object
958
+ };
959
+ ServerBindings.properties.stomp = StompServerBinding;
960
+
961
+ const StompMessageBinding: NodeType = {
962
+ properties: {}, // empty object
963
+ };
964
+ MessageBindings.properties.stomp = StompMessageBinding;
965
+
966
+ const StompOperationBinding: NodeType = {
967
+ properties: {}, // empty object
968
+ };
969
+ OperationBindings.properties.stomp = StompOperationBinding;
970
+
971
+ // redis
972
+ const RedisChannelBinding: NodeType = {
973
+ properties: {}, // empty object
974
+ };
975
+ ChannelBindings.properties.redis = RedisChannelBinding;
976
+
977
+ const RedisServerBinding: NodeType = {
978
+ properties: {}, // empty object
979
+ };
980
+ ServerBindings.properties.redis = RedisServerBinding;
981
+
982
+ const RedisMessageBinding: NodeType = {
983
+ properties: {}, // empty object
984
+ };
985
+ MessageBindings.properties.redis = RedisMessageBinding;
986
+
987
+ const RedisOperationBinding: NodeType = {
988
+ properties: {}, // empty object
989
+ };
990
+ OperationBindings.properties.redis = RedisOperationBinding;
991
+
992
+ // mercure
993
+ const MercureChannelBinding: NodeType = {
994
+ properties: {}, // empty object
995
+ };
996
+ ChannelBindings.properties.mercure = MercureChannelBinding;
997
+
998
+ const MercureServerBinding: NodeType = {
999
+ properties: {}, // empty object
1000
+ };
1001
+ ServerBindings.properties.mercure = MercureServerBinding;
1002
+
1003
+ const MercureMessageBinding: NodeType = {
1004
+ properties: {}, // empty object
1005
+ };
1006
+ MessageBindings.properties.mercure = MercureMessageBinding;
1007
+
1008
+ const MercureOperationBinding: NodeType = {
1009
+ properties: {}, // empty object
1010
+ };
1011
+ OperationBindings.properties.mercure = MercureOperationBinding;
1012
+
1013
+ // ibmmq
1014
+ // googlepubsub
1015
+ // pulsar
1016
+
1017
+ // --- End per-protocol node types
1018
+
1019
+ export const AsyncApi2Types: Record<string, NodeType> = {
1020
+ Root,
1021
+ Tag,
1022
+ TagList: listOf('Tag'),
1023
+ ServerMap,
1024
+ ExternalDocs,
1025
+ Server,
1026
+ ServerVariable,
1027
+ ServerVariablesMap: mapOf('ServerVariable'),
1028
+ SecurityRequirement,
1029
+ SecurityRequirementList: listOf('SecurityRequirement'),
1030
+ Info,
1031
+ Contact,
1032
+ License,
1033
+
1034
+ HttpServerBinding,
1035
+ HttpChannelBinding,
1036
+ HttpMessageBinding,
1037
+ HttpOperationBinding,
1038
+
1039
+ WsServerBinding,
1040
+ WsChannelBinding,
1041
+ WsMessageBinding,
1042
+ WsOperationBinding,
1043
+
1044
+ KafkaServerBinding,
1045
+ KafkaTopicConfiguration,
1046
+ KafkaChannelBinding,
1047
+ KafkaMessageBinding,
1048
+ KafkaOperationBinding,
1049
+
1050
+ AnypointmqServerBinding,
1051
+ AnypointmqChannelBinding,
1052
+ AnypointmqMessageBinding,
1053
+ AnypointmqOperationBinding,
1054
+
1055
+ AmqpServerBinding,
1056
+ AmqpChannelBinding,
1057
+ AmqpMessageBinding,
1058
+ AmqpOperationBinding,
1059
+
1060
+ Amqp1ServerBinding,
1061
+ Amqp1ChannelBinding,
1062
+ Amqp1MessageBinding,
1063
+ Amqp1OperationBinding,
1064
+
1065
+ MqttServerBindingLastWill,
1066
+ MqttServerBinding,
1067
+ MqttChannelBinding,
1068
+ MqttMessageBinding,
1069
+ MqttOperationBinding,
1070
+
1071
+ Mqtt5ServerBinding,
1072
+ Mqtt5ChannelBinding,
1073
+ Mqtt5MessageBinding,
1074
+ Mqtt5OperationBinding,
1075
+
1076
+ NatsServerBinding,
1077
+ NatsChannelBinding,
1078
+ NatsMessageBinding,
1079
+ NatsOperationBinding,
1080
+
1081
+ JmsServerBinding,
1082
+ JmsChannelBinding,
1083
+ JmsMessageBinding,
1084
+ JmsOperationBinding,
1085
+
1086
+ SolaceServerBinding,
1087
+ SolaceChannelBinding,
1088
+ SolaceMessageBinding,
1089
+ SolaceDestination,
1090
+ SolaceOperationBinding,
1091
+
1092
+ StompServerBinding,
1093
+ StompChannelBinding,
1094
+ StompMessageBinding,
1095
+ StompOperationBinding,
1096
+
1097
+ RedisServerBinding,
1098
+ RedisChannelBinding,
1099
+ RedisMessageBinding,
1100
+ RedisOperationBinding,
1101
+
1102
+ MercureServerBinding,
1103
+ MercureChannelBinding,
1104
+ MercureMessageBinding,
1105
+ MercureOperationBinding,
1106
+
1107
+ ServerBindings,
1108
+ ChannelBindings,
1109
+ ChannelMap,
1110
+ Channel,
1111
+ Parameter,
1112
+ ParametersMap: mapOf('Parameter'),
1113
+ Operation,
1114
+ Schema,
1115
+ MessageExample,
1116
+ SchemaProperties,
1117
+ DiscriminatorMapping,
1118
+ Discriminator,
1119
+ Components,
1120
+ NamedSchemas: mapOf('Schema'),
1121
+ NamedMessages: mapOf('Message'),
1122
+ NamedMessageTraits: mapOf('MessageTrait'),
1123
+ NamedOperationTraits: mapOf('OperationTrait'),
1124
+ NamedParameters: mapOf('Parameter'),
1125
+ NamedSecuritySchemes: mapOf('SecurityScheme'),
1126
+ NamedCorrelationIds: mapOf('CorrelationId'),
1127
+ NamedStreamHeaders: mapOf('StreamHeader'),
1128
+ ImplicitFlow,
1129
+ PasswordFlow,
1130
+ ClientCredentials,
1131
+ AuthorizationCode,
1132
+ SecuritySchemeFlows,
1133
+ SecurityScheme,
1134
+ Message,
1135
+ MessageBindings,
1136
+ OperationBindings,
1137
+ OperationTrait,
1138
+ OperationTraitList: listOf('OperationTrait'),
1139
+ MessageTrait,
1140
+ MessageTraitList: listOf('MessageTrait'),
1141
+ CorrelationId,
1142
+ };