@redocly/openapi-core 1.1.0 → 1.2.0

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 (60) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/lib/bundle.d.ts +2 -2
  3. package/lib/bundle.js +24 -22
  4. package/lib/config/builtIn.js +4 -0
  5. package/lib/config/config-resolvers.js +19 -6
  6. package/lib/config/config.d.ts +9 -9
  7. package/lib/config/config.js +32 -17
  8. package/lib/config/rules.d.ts +2 -2
  9. package/lib/config/types.d.ts +9 -3
  10. package/lib/index.d.ts +1 -1
  11. package/lib/index.js +7 -6
  12. package/lib/lint.js +10 -16
  13. package/lib/oas-types.d.ts +16 -10
  14. package/lib/oas-types.js +52 -26
  15. package/lib/rules/async2/channels-kebab-case.d.ts +2 -0
  16. package/lib/rules/async2/channels-kebab-case.js +19 -0
  17. package/lib/rules/async2/index.d.ts +12 -0
  18. package/lib/rules/async2/index.js +22 -0
  19. package/lib/rules/async2/no-channel-trailing-slash.d.ts +2 -0
  20. package/lib/rules/async2/no-channel-trailing-slash.js +16 -0
  21. package/lib/rules/common/scalar-property-missing-example.js +1 -1
  22. package/lib/rules/common/spec.d.ts +2 -2
  23. package/lib/rules/common/spec.js +3 -3
  24. package/lib/rules/oas2/index.js +1 -1
  25. package/lib/rules/oas3/index.js +1 -1
  26. package/lib/types/asyncapi.d.ts +2 -0
  27. package/lib/types/asyncapi.js +1027 -0
  28. package/lib/types/redocly-yaml.js +3 -0
  29. package/lib/typings/asyncapi.d.ts +21 -0
  30. package/lib/typings/asyncapi.js +2 -0
  31. package/lib/visitors.d.ts +12 -0
  32. package/lib/walk.d.ts +3 -3
  33. package/package.json +2 -1
  34. package/src/__tests__/lint.test.ts +36 -6
  35. package/src/bundle.ts +27 -28
  36. package/src/config/__tests__/__snapshots__/config.test.ts.snap +24 -0
  37. package/src/config/__tests__/config.test.ts +15 -4
  38. package/src/config/builtIn.ts +4 -0
  39. package/src/config/config-resolvers.ts +25 -6
  40. package/src/config/config.ts +51 -27
  41. package/src/config/rules.ts +2 -2
  42. package/src/config/types.ts +14 -4
  43. package/src/index.ts +7 -1
  44. package/src/lint.ts +13 -22
  45. package/src/oas-types.ts +59 -21
  46. package/src/rules/async2/__tests__/channels-kebab-case.test.ts +141 -0
  47. package/src/rules/async2/__tests__/no-channel-trailing-slash.test.ts +97 -0
  48. package/src/rules/async2/channels-kebab-case.ts +18 -0
  49. package/src/rules/async2/index.ts +22 -0
  50. package/src/rules/async2/no-channel-trailing-slash.ts +15 -0
  51. package/src/rules/common/scalar-property-missing-example.ts +2 -2
  52. package/src/rules/common/spec.ts +2 -2
  53. package/src/rules/oas2/index.ts +2 -2
  54. package/src/rules/oas3/index.ts +2 -2
  55. package/src/types/asyncapi.ts +1136 -0
  56. package/src/types/redocly-yaml.ts +3 -0
  57. package/src/typings/asyncapi.ts +26 -0
  58. package/src/visitors.ts +22 -0
  59. package/src/walk.ts +3 -3
  60. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,1136 @@
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: 'Schema',
394
+ unevaluatedProperties: (value: unknown) => {
395
+ if (typeof value === 'boolean') {
396
+ return { type: 'boolean' };
397
+ } else {
398
+ return 'Schema';
399
+ }
400
+ },
401
+ summary: { type: 'string' },
402
+ properties: 'SchemaProperties',
403
+ items: (value: any) => {
404
+ if (typeof value === 'boolean') {
405
+ return { type: 'boolean' };
406
+ } else {
407
+ return 'Schema';
408
+ }
409
+ },
410
+ additionalProperties: (value: any) => {
411
+ return typeof value === 'boolean' ? { type: 'boolean' } : 'Schema';
412
+ },
413
+ description: { type: 'string' },
414
+ format: { type: 'string' },
415
+ contentEncoding: { type: 'string' },
416
+ contentMediaType: { type: 'string' },
417
+ default: null,
418
+ readOnly: { type: 'boolean' },
419
+ writeOnly: { type: 'boolean' },
420
+ // xml: 'Xml',
421
+ examples: { type: 'array' },
422
+ example: { isExample: true },
423
+ deprecated: { type: 'boolean' },
424
+ const: null,
425
+ $comment: { type: 'string' },
426
+ dependencies: { type: 'object' }, // TODO
427
+ },
428
+ };
429
+
430
+ const SchemaProperties: NodeType = {
431
+ properties: {},
432
+ additionalProperties: (value: any) => {
433
+ if (typeof value === 'boolean') {
434
+ return { type: 'boolean' };
435
+ }
436
+ return 'Schema';
437
+ },
438
+ };
439
+
440
+ const DiscriminatorMapping: NodeType = {
441
+ properties: {},
442
+ additionalProperties: (value: any) => {
443
+ if (isMappingRef(value)) {
444
+ return { type: 'string', directResolveAs: 'Schema' };
445
+ } else {
446
+ return { type: 'string' };
447
+ }
448
+ },
449
+ };
450
+
451
+ const Discriminator: NodeType = {
452
+ properties: {
453
+ propertyName: { type: 'string' },
454
+ mapping: 'DiscriminatorMapping',
455
+ },
456
+ required: ['propertyName'],
457
+ };
458
+
459
+ const Components: NodeType = {
460
+ properties: {
461
+ messages: 'NamedMessages',
462
+ parameters: 'NamedParameters',
463
+ schemas: 'NamedSchemas',
464
+ correlationIds: 'NamedCorrelationIds',
465
+ messageTraits: 'NamedMessageTraits',
466
+ operationTraits: 'NamedOperationTraits',
467
+ streamHeaders: 'NamedStreamHeaders',
468
+ securitySchemes: 'NamedSecuritySchemes',
469
+ servers: 'ServerMap',
470
+ serverVariables: 'ServerVariablesMap',
471
+ channels: 'ChannelMap',
472
+ serverBindings: 'ServerBindings',
473
+ channelBindings: 'ChannelBindings',
474
+ operationBindings: 'OperationBindings',
475
+ messageBindings: 'MessageBindings',
476
+ },
477
+ };
478
+
479
+ const ImplicitFlow: NodeType = {
480
+ properties: {
481
+ refreshUrl: { type: 'string' },
482
+ scopes: { type: 'object', additionalProperties: { type: 'string' } }, // TODO: validate scopes
483
+ authorizationUrl: { type: 'string' },
484
+ },
485
+ required: ['authorizationUrl', 'scopes'],
486
+ };
487
+
488
+ const PasswordFlow: NodeType = {
489
+ properties: {
490
+ refreshUrl: { type: 'string' },
491
+ scopes: { type: 'object', additionalProperties: { type: 'string' } }, // TODO: validate scopes
492
+ tokenUrl: { type: 'string' },
493
+ },
494
+ required: ['tokenUrl', 'scopes'],
495
+ };
496
+
497
+ const ClientCredentials: NodeType = {
498
+ properties: {
499
+ refreshUrl: { type: 'string' },
500
+ scopes: { type: 'object', additionalProperties: { type: 'string' } }, // TODO: validate scopes
501
+ tokenUrl: { type: 'string' },
502
+ },
503
+ required: ['tokenUrl', 'scopes'],
504
+ };
505
+
506
+ const AuthorizationCode: NodeType = {
507
+ properties: {
508
+ refreshUrl: { type: 'string' },
509
+ authorizationUrl: { type: 'string' },
510
+ scopes: { type: 'object', additionalProperties: { type: 'string' } }, // TODO: validate scopes
511
+ tokenUrl: { type: 'string' },
512
+ },
513
+ required: ['authorizationUrl', 'tokenUrl', 'scopes'],
514
+ };
515
+
516
+ const SecuritySchemeFlows: NodeType = {
517
+ properties: {
518
+ implicit: 'ImplicitFlow',
519
+ password: 'PasswordFlow',
520
+ clientCredentials: 'ClientCredentials',
521
+ authorizationCode: 'AuthorizationCode',
522
+ },
523
+ };
524
+
525
+ const SecurityScheme: NodeType = {
526
+ properties: {
527
+ type: {
528
+ enum: [
529
+ 'userPassword',
530
+ 'apiKey',
531
+ 'X509',
532
+ 'symmetricEncryption',
533
+ 'asymmetricEncryption',
534
+ 'httpApiKey',
535
+ 'http',
536
+ 'oauth2',
537
+ 'openIdConnect',
538
+ 'plain',
539
+ 'scramSha256',
540
+ 'scramSha512',
541
+ 'gssapi',
542
+ ],
543
+ },
544
+ description: { type: 'string' },
545
+ name: { type: 'string' },
546
+ in: { type: 'string', enum: ['query', 'header', 'cookie', 'user', 'password'] },
547
+ scheme: { type: 'string' },
548
+ bearerFormat: { type: 'string' },
549
+ flows: 'SecuritySchemeFlows',
550
+ openIdConnectUrl: { type: 'string' },
551
+ },
552
+ required(value) {
553
+ switch (value?.type) {
554
+ case 'apiKey':
555
+ return ['type', 'in'];
556
+ case 'httpApiKey':
557
+ return ['type', 'name', 'in'];
558
+ case 'http':
559
+ return ['type', 'scheme'];
560
+ case 'oauth2':
561
+ return ['type', 'flows'];
562
+ case 'openIdConnect':
563
+ return ['type', 'openIdConnectUrl'];
564
+ default:
565
+ return ['type'];
566
+ }
567
+ },
568
+ allowed(value) {
569
+ switch (value?.type) {
570
+ case 'apiKey':
571
+ return ['type', 'in', 'description'];
572
+ case 'httpApiKey':
573
+ return ['type', 'name', 'in', 'description'];
574
+ case 'http':
575
+ return ['type', 'scheme', 'bearerFormat', 'description'];
576
+ case 'oauth2':
577
+ return ['type', 'flows', 'description'];
578
+ case 'openIdConnect':
579
+ return ['type', 'openIdConnectUrl', 'description'];
580
+ default:
581
+ return ['type', 'description'];
582
+ }
583
+ },
584
+ extensionsPrefix: 'x-',
585
+ };
586
+
587
+ // --- Per-protocol node types
588
+
589
+ // http
590
+ const HttpChannelBinding: NodeType = {
591
+ properties: {}, // empty object
592
+ };
593
+ ChannelBindings.properties.http = HttpChannelBinding;
594
+
595
+ const HttpServerBinding: NodeType = {
596
+ properties: {}, // empty object
597
+ };
598
+ ServerBindings.properties.http = HttpServerBinding;
599
+
600
+ const HttpMessageBinding: NodeType = {
601
+ properties: {
602
+ headers: 'Schema',
603
+ bindingVersion: { type: 'string' },
604
+ },
605
+ };
606
+ MessageBindings.properties.http = HttpMessageBinding;
607
+
608
+ const HttpOperationBinding: NodeType = {
609
+ properties: {
610
+ type: { type: 'string' },
611
+ method: {
612
+ type: 'string',
613
+ enum: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS', 'CONNECT', 'TRACE'],
614
+ },
615
+ headers: 'Schema',
616
+ bindingVersion: { type: 'string' },
617
+ },
618
+ };
619
+ OperationBindings.properties.http = HttpOperationBinding;
620
+
621
+ // ws
622
+ const WsChannelBinding: NodeType = {
623
+ properties: {
624
+ method: { type: 'string' },
625
+ query: 'Schema',
626
+ headers: 'Schema',
627
+ bindingVersion: { type: 'string' },
628
+ },
629
+ };
630
+ ChannelBindings.properties.ws = WsChannelBinding;
631
+
632
+ const WsServerBinding: NodeType = {
633
+ properties: {}, // empty object
634
+ };
635
+ ServerBindings.properties.ws = WsServerBinding;
636
+
637
+ const WsMessageBinding: NodeType = {
638
+ properties: {}, // empty object
639
+ };
640
+ MessageBindings.properties.ws = WsMessageBinding;
641
+
642
+ const WsOperationBinding: NodeType = {
643
+ properties: {}, // empty object
644
+ };
645
+ OperationBindings.properties.ws = WsOperationBinding;
646
+
647
+ // kafka
648
+ const KafkaTopicConfiguration: NodeType = {
649
+ properties: {
650
+ 'cleanup.policy': { type: 'array', items: { enum: ['delete', 'compact'] } },
651
+ 'retention.ms': { type: 'integer' },
652
+ 'retention.bytes': { type: 'integer' },
653
+ 'delete.retention.ms': { type: 'integer' },
654
+ 'max.message.bytes': { type: 'integer' },
655
+ },
656
+ };
657
+ const KafkaChannelBinding: NodeType = {
658
+ properties: {
659
+ topic: { type: 'string' },
660
+ partitions: { type: 'integer' },
661
+ replicas: { type: 'integer' },
662
+ topicConfiguration: 'KafkaTopicConfiguration',
663
+ bindingVersion: { type: 'string' },
664
+ },
665
+ };
666
+ ChannelBindings.properties.kafka = KafkaChannelBinding;
667
+
668
+ const KafkaServerBinding: NodeType = {
669
+ properties: {}, // empty object
670
+ };
671
+ ServerBindings.properties.kafka = KafkaServerBinding;
672
+
673
+ const KafkaMessageBinding: NodeType = {
674
+ properties: {
675
+ key: 'Schema', // TODO: add avro support
676
+ schemaIdLocation: { type: 'string' },
677
+ schemaIdPayloadEncoding: { type: 'string' },
678
+ schemaLookupStrategy: { type: 'string' },
679
+ bindingVersion: { type: 'string' },
680
+ },
681
+ };
682
+ MessageBindings.properties.kafka = KafkaMessageBinding;
683
+
684
+ const KafkaOperationBinding: NodeType = {
685
+ properties: {
686
+ groupId: 'Schema',
687
+ clientId: 'Schema',
688
+ bindingVersion: { type: 'string' },
689
+ },
690
+ };
691
+ OperationBindings.properties.kafka = KafkaOperationBinding;
692
+
693
+ // anypointmq
694
+ const AnypointmqChannelBinding: NodeType = {
695
+ properties: {
696
+ destination: { type: 'string' },
697
+ destinationType: { type: 'string' },
698
+ bindingVersion: { type: 'string' },
699
+ },
700
+ };
701
+ ChannelBindings.properties.anypointmq = AnypointmqChannelBinding;
702
+
703
+ const AnypointmqServerBinding: NodeType = {
704
+ properties: {}, // empty object
705
+ };
706
+ ServerBindings.properties.anypointmq = AnypointmqServerBinding;
707
+
708
+ const AnypointmqMessageBinding: NodeType = {
709
+ properties: {
710
+ headers: 'Schema',
711
+ bindingVersion: { type: 'string' },
712
+ },
713
+ };
714
+ MessageBindings.properties.anypointmq = AnypointmqMessageBinding;
715
+
716
+ const AnypointmqOperationBinding: NodeType = {
717
+ properties: {}, // empty object
718
+ };
719
+ OperationBindings.properties.anypointmq = AnypointmqOperationBinding;
720
+
721
+ // amqp
722
+ const AmqpChannelBinding: NodeType = {
723
+ properties: {}, // empty object
724
+ };
725
+ ChannelBindings.properties.amqp = AmqpChannelBinding;
726
+
727
+ const AmqpServerBinding: NodeType = {
728
+ properties: {}, // empty object
729
+ };
730
+ ServerBindings.properties.amqp = AmqpServerBinding;
731
+
732
+ const AmqpMessageBinding: NodeType = {
733
+ properties: {
734
+ contentEncoding: { type: 'string' },
735
+ messageType: { type: 'string' },
736
+ bindingVersion: { type: 'string' },
737
+ },
738
+ };
739
+ MessageBindings.properties.amqp = AmqpMessageBinding;
740
+
741
+ const AmqpOperationBinding: NodeType = {
742
+ // TODO: some fields are subscribe only
743
+ properties: {
744
+ expiration: { type: 'integer' },
745
+ userId: { type: 'string' },
746
+ cc: { type: 'array', items: { type: 'string' } },
747
+ priority: { type: 'integer' },
748
+ deliveryMode: { type: 'integer' }, // TODO: enum: [1, 2]
749
+ mandatory: { type: 'boolean' },
750
+ bcc: { type: 'array', items: { type: 'string' } },
751
+ replyTo: { type: 'string' },
752
+ timestamp: { type: 'boolean' },
753
+ ack: { type: 'boolean' },
754
+ bindingVersion: { type: 'string' },
755
+ },
756
+ };
757
+ OperationBindings.properties.amqp = AmqpOperationBinding;
758
+
759
+ // amqp1
760
+ const Amqp1ChannelBinding: NodeType = {
761
+ properties: {}, // empty object
762
+ };
763
+ ChannelBindings.properties.amqp1 = Amqp1ChannelBinding;
764
+
765
+ const Amqp1ServerBinding: NodeType = {
766
+ properties: {}, // empty object
767
+ };
768
+ ServerBindings.properties.amqp1 = Amqp1ServerBinding;
769
+
770
+ const Amqp1MessageBinding: NodeType = {
771
+ properties: {}, // empty object
772
+ };
773
+ MessageBindings.properties.amqp1 = Amqp1MessageBinding;
774
+
775
+ const Amqp1OperationBinding: NodeType = {
776
+ properties: {}, // empty object
777
+ };
778
+ OperationBindings.properties.amqp1 = Amqp1OperationBinding;
779
+
780
+ // mqtt
781
+ const MqttChannelBinding: NodeType = {
782
+ properties: {
783
+ qos: { type: 'integer' },
784
+ retain: { type: 'boolean' },
785
+ bindingVersion: { type: 'string' },
786
+ },
787
+ };
788
+ ChannelBindings.properties.mqtt = MqttChannelBinding;
789
+
790
+ const MqttServerBindingLastWill: NodeType = {
791
+ properties: {
792
+ topic: { type: 'string' },
793
+ qos: { type: 'integer' },
794
+ message: { type: 'string' },
795
+ retain: { type: 'boolean' },
796
+ },
797
+ };
798
+ const MqttServerBinding: NodeType = {
799
+ properties: {
800
+ clientId: { type: 'string' },
801
+ cleanSession: { type: 'boolean' },
802
+ lastWill: 'MqttServerBindingLastWill',
803
+ keepAlive: { type: 'integer' },
804
+ bindingVersion: { type: 'string' },
805
+ },
806
+ };
807
+ ServerBindings.properties.mqtt = MqttServerBinding;
808
+
809
+ const MqttMessageBinding: NodeType = {
810
+ properties: {
811
+ bindingVersion: { type: 'string' },
812
+ },
813
+ };
814
+ MessageBindings.properties.mqtt = MqttMessageBinding;
815
+
816
+ const MqttOperationBinding: NodeType = {
817
+ properties: {
818
+ qos: { type: 'integer' },
819
+ retain: { type: 'boolean' },
820
+ bindingVersion: { type: 'string' },
821
+ },
822
+ };
823
+ OperationBindings.properties.mqtt = MqttOperationBinding;
824
+
825
+ // mqtt5
826
+ const Mqtt5ChannelBinding: NodeType = {
827
+ properties: {}, // empty object
828
+ };
829
+ ChannelBindings.properties.mqtt5 = Mqtt5ChannelBinding;
830
+
831
+ const Mqtt5ServerBinding: NodeType = {
832
+ properties: {}, // empty object
833
+ };
834
+ ServerBindings.properties.mqtt5 = Mqtt5ServerBinding;
835
+
836
+ const Mqtt5MessageBinding: NodeType = {
837
+ properties: {}, // empty object
838
+ };
839
+ MessageBindings.properties.mqtt5 = Mqtt5MessageBinding;
840
+
841
+ const Mqtt5OperationBinding: NodeType = {
842
+ properties: {}, // empty object
843
+ };
844
+ OperationBindings.properties.mqtt5 = Mqtt5OperationBinding;
845
+
846
+ // nats
847
+ const NatsChannelBinding: NodeType = {
848
+ properties: {}, // empty object
849
+ };
850
+ ChannelBindings.properties.nats = NatsChannelBinding;
851
+
852
+ const NatsServerBinding: NodeType = {
853
+ properties: {}, // empty object
854
+ };
855
+ ServerBindings.properties.nats = NatsServerBinding;
856
+
857
+ const NatsMessageBinding: NodeType = {
858
+ properties: {}, // empty object
859
+ };
860
+ MessageBindings.properties.nats = NatsMessageBinding;
861
+
862
+ const NatsOperationBinding: NodeType = {
863
+ properties: {
864
+ queue: { type: 'string' },
865
+ bindingVersion: { type: 'string' },
866
+ },
867
+ };
868
+ OperationBindings.properties.nats = NatsOperationBinding;
869
+
870
+ // jms
871
+ const JmsChannelBinding: NodeType = {
872
+ properties: {
873
+ destination: { type: 'string' },
874
+ destinationType: { type: 'string' },
875
+ bindingVersion: { type: 'string' },
876
+ },
877
+ };
878
+ ChannelBindings.properties.jms = JmsChannelBinding;
879
+
880
+ const JmsServerBinding: NodeType = {
881
+ properties: {}, // empty object
882
+ };
883
+ ServerBindings.properties.jms = JmsServerBinding;
884
+
885
+ const JmsMessageBinding: NodeType = {
886
+ properties: {
887
+ headers: 'Schema',
888
+ bindingVersion: { type: 'string' },
889
+ },
890
+ };
891
+ MessageBindings.properties.jms = JmsMessageBinding;
892
+
893
+ const JmsOperationBinding: NodeType = {
894
+ properties: {
895
+ headers: 'Schema',
896
+ bindingVersion: { type: 'string' },
897
+ },
898
+ };
899
+ OperationBindings.properties.jms = JmsOperationBinding;
900
+
901
+ // sns
902
+
903
+ // solace
904
+ const SolaceChannelBinding: NodeType = {
905
+ properties: {}, // empty object
906
+ };
907
+ ChannelBindings.properties.solace = SolaceChannelBinding;
908
+
909
+ const SolaceServerBinding: NodeType = {
910
+ properties: {
911
+ bindingVersion: { type: 'string' },
912
+ msgVpn: { type: 'string' },
913
+ },
914
+ };
915
+ ServerBindings.properties.solace = SolaceServerBinding;
916
+
917
+ const SolaceMessageBinding: NodeType = {
918
+ properties: {}, // empty object
919
+ };
920
+ MessageBindings.properties.solace = SolaceMessageBinding;
921
+
922
+ const SolaceDestination: NodeType = {
923
+ properties: {
924
+ destinationType: { type: 'string', enum: ['queue', 'topic'] },
925
+ deliveryMode: { type: 'string', enum: ['direct', 'persistent'] },
926
+ 'queue.name': { type: 'string' },
927
+ 'queue.topicSubscriptions': { type: 'array', items: { type: 'string' } },
928
+ 'queue.accessType': { type: 'string', enum: ['exclusive', 'nonexclusive'] },
929
+ 'queue.maxMsgSpoolSize': { type: 'string' },
930
+ 'queue.maxTtl': { type: 'string' },
931
+ 'topic.topicSubscriptions': { type: 'array', items: { type: 'string' } },
932
+ },
933
+ };
934
+ const SolaceOperationBinding: NodeType = {
935
+ properties: {
936
+ bindingVersion: { type: 'string' },
937
+ destinations: listOf('SolaceDestination'),
938
+ },
939
+ };
940
+ OperationBindings.properties.solace = SolaceOperationBinding;
941
+
942
+ // sqs
943
+
944
+ // stomp
945
+ const StompChannelBinding: NodeType = {
946
+ properties: {}, // empty object
947
+ };
948
+ ChannelBindings.properties.stomp = StompChannelBinding;
949
+
950
+ const StompServerBinding: NodeType = {
951
+ properties: {}, // empty object
952
+ };
953
+ ServerBindings.properties.stomp = StompServerBinding;
954
+
955
+ const StompMessageBinding: NodeType = {
956
+ properties: {}, // empty object
957
+ };
958
+ MessageBindings.properties.stomp = StompMessageBinding;
959
+
960
+ const StompOperationBinding: NodeType = {
961
+ properties: {}, // empty object
962
+ };
963
+ OperationBindings.properties.stomp = StompOperationBinding;
964
+
965
+ // redis
966
+ const RedisChannelBinding: NodeType = {
967
+ properties: {}, // empty object
968
+ };
969
+ ChannelBindings.properties.redis = RedisChannelBinding;
970
+
971
+ const RedisServerBinding: NodeType = {
972
+ properties: {}, // empty object
973
+ };
974
+ ServerBindings.properties.redis = RedisServerBinding;
975
+
976
+ const RedisMessageBinding: NodeType = {
977
+ properties: {}, // empty object
978
+ };
979
+ MessageBindings.properties.redis = RedisMessageBinding;
980
+
981
+ const RedisOperationBinding: NodeType = {
982
+ properties: {}, // empty object
983
+ };
984
+ OperationBindings.properties.redis = RedisOperationBinding;
985
+
986
+ // mercure
987
+ const MercureChannelBinding: NodeType = {
988
+ properties: {}, // empty object
989
+ };
990
+ ChannelBindings.properties.mercure = MercureChannelBinding;
991
+
992
+ const MercureServerBinding: NodeType = {
993
+ properties: {}, // empty object
994
+ };
995
+ ServerBindings.properties.mercure = MercureServerBinding;
996
+
997
+ const MercureMessageBinding: NodeType = {
998
+ properties: {}, // empty object
999
+ };
1000
+ MessageBindings.properties.mercure = MercureMessageBinding;
1001
+
1002
+ const MercureOperationBinding: NodeType = {
1003
+ properties: {}, // empty object
1004
+ };
1005
+ OperationBindings.properties.mercure = MercureOperationBinding;
1006
+
1007
+ // ibmmq
1008
+ // googlepubsub
1009
+ // pulsar
1010
+
1011
+ // --- End per-protocol node types
1012
+
1013
+ export const AsyncApi2Types: Record<string, NodeType> = {
1014
+ Root,
1015
+ Tag,
1016
+ TagList: listOf('Tag'),
1017
+ ServerMap,
1018
+ ExternalDocs,
1019
+ Server,
1020
+ ServerVariable,
1021
+ ServerVariablesMap: mapOf('ServerVariable'),
1022
+ SecurityRequirement,
1023
+ SecurityRequirementList: listOf('SecurityRequirement'),
1024
+ Info,
1025
+ Contact,
1026
+ License,
1027
+
1028
+ HttpServerBinding,
1029
+ HttpChannelBinding,
1030
+ HttpMessageBinding,
1031
+ HttpOperationBinding,
1032
+
1033
+ WsServerBinding,
1034
+ WsChannelBinding,
1035
+ WsMessageBinding,
1036
+ WsOperationBinding,
1037
+
1038
+ KafkaServerBinding,
1039
+ KafkaTopicConfiguration,
1040
+ KafkaChannelBinding,
1041
+ KafkaMessageBinding,
1042
+ KafkaOperationBinding,
1043
+
1044
+ AnypointmqServerBinding,
1045
+ AnypointmqChannelBinding,
1046
+ AnypointmqMessageBinding,
1047
+ AnypointmqOperationBinding,
1048
+
1049
+ AmqpServerBinding,
1050
+ AmqpChannelBinding,
1051
+ AmqpMessageBinding,
1052
+ AmqpOperationBinding,
1053
+
1054
+ Amqp1ServerBinding,
1055
+ Amqp1ChannelBinding,
1056
+ Amqp1MessageBinding,
1057
+ Amqp1OperationBinding,
1058
+
1059
+ MqttServerBindingLastWill,
1060
+ MqttServerBinding,
1061
+ MqttChannelBinding,
1062
+ MqttMessageBinding,
1063
+ MqttOperationBinding,
1064
+
1065
+ Mqtt5ServerBinding,
1066
+ Mqtt5ChannelBinding,
1067
+ Mqtt5MessageBinding,
1068
+ Mqtt5OperationBinding,
1069
+
1070
+ NatsServerBinding,
1071
+ NatsChannelBinding,
1072
+ NatsMessageBinding,
1073
+ NatsOperationBinding,
1074
+
1075
+ JmsServerBinding,
1076
+ JmsChannelBinding,
1077
+ JmsMessageBinding,
1078
+ JmsOperationBinding,
1079
+
1080
+ SolaceServerBinding,
1081
+ SolaceChannelBinding,
1082
+ SolaceMessageBinding,
1083
+ SolaceDestination,
1084
+ SolaceOperationBinding,
1085
+
1086
+ StompServerBinding,
1087
+ StompChannelBinding,
1088
+ StompMessageBinding,
1089
+ StompOperationBinding,
1090
+
1091
+ RedisServerBinding,
1092
+ RedisChannelBinding,
1093
+ RedisMessageBinding,
1094
+ RedisOperationBinding,
1095
+
1096
+ MercureServerBinding,
1097
+ MercureChannelBinding,
1098
+ MercureMessageBinding,
1099
+ MercureOperationBinding,
1100
+
1101
+ ServerBindings,
1102
+ ChannelBindings,
1103
+ ChannelMap,
1104
+ Channel,
1105
+ Parameter,
1106
+ ParametersMap: mapOf('Parameter'),
1107
+ Operation,
1108
+ Schema,
1109
+ MessageExample,
1110
+ SchemaProperties,
1111
+ DiscriminatorMapping,
1112
+ Discriminator,
1113
+ Components,
1114
+ NamedSchemas: mapOf('Schema'),
1115
+ NamedMessages: mapOf('Message'),
1116
+ NamedMessageTraits: mapOf('MessageTrait'),
1117
+ NamedOperationTraits: mapOf('OperationTrait'),
1118
+ NamedParameters: mapOf('Parameter'),
1119
+ NamedSecuritySchemes: mapOf('SecurityScheme'),
1120
+ NamedCorrelationIds: mapOf('CorrelationId'),
1121
+ NamedStreamHeaders: mapOf('StreamHeader'),
1122
+ ImplicitFlow,
1123
+ PasswordFlow,
1124
+ ClientCredentials,
1125
+ AuthorizationCode,
1126
+ SecuritySchemeFlows,
1127
+ SecurityScheme,
1128
+ Message,
1129
+ MessageBindings,
1130
+ OperationBindings,
1131
+ OperationTrait,
1132
+ OperationTraitList: listOf('OperationTrait'),
1133
+ MessageTrait,
1134
+ MessageTraitList: listOf('MessageTrait'),
1135
+ CorrelationId,
1136
+ };