@redocly/openapi-core 1.18.0 → 1.18.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.
@@ -1,6 +1,7 @@
1
+ import * as pluralize from 'pluralize';
1
2
  import { Oas3Rule, Oas2Rule } from '../../visitors';
2
3
  import { UserContext } from '../../walk';
3
- import { isPathParameter, isSingular } from '../../utils';
4
+ import { isPathParameter } from '../../utils';
4
5
 
5
6
  export const PathSegmentPlural: Oas3Rule | Oas2Rule = (opts) => {
6
7
  const { ignoreLastPathSegment, exceptions } = opts;
@@ -17,7 +18,7 @@ export const PathSegmentPlural: Oas3Rule | Oas2Rule = (opts) => {
17
18
 
18
19
  for (const pathSegment of pathSegments) {
19
20
  if (exceptions && exceptions.includes(pathSegment)) continue;
20
- if (!isPathParameter(pathSegment) && isSingular(pathSegment)) {
21
+ if (!isPathParameter(pathSegment) && pluralize.isSingular(pathSegment)) {
21
22
  report({
22
23
  message: `path segment \`${pathSegment}\` should be plural.`,
23
24
  location: location.key(),
@@ -4,11 +4,11 @@ import { getNodeTypesFromJSONSchema } from './json-schema-adapter';
4
4
 
5
5
  export const ARAZZO_ROOT_TYPE = 'Root';
6
6
 
7
- const operationMethod = {
7
+ export const operationMethod = {
8
8
  type: 'string',
9
9
  enum: ['get', 'post', 'put', 'delete', 'patch'],
10
10
  } as const;
11
- const expectSchema = {
11
+ export const expectSchema = {
12
12
  type: 'object',
13
13
  properties: {
14
14
  statusCode: { type: 'number' },
@@ -58,7 +58,7 @@ const arazzoSourceDescriptionSchema = {
58
58
  additionalProperties: false,
59
59
  required: ['name', 'type', 'url'],
60
60
  } as const;
61
- const sourceDescriptionSchema = {
61
+ export const sourceDescriptionSchema = {
62
62
  type: 'object',
63
63
  oneOf: [
64
64
  openAPISourceDescriptionSchema,
@@ -81,7 +81,7 @@ const extendedOperation = {
81
81
  additionalProperties: false,
82
82
  required: ['path', 'method'],
83
83
  } as const;
84
- const parameter = {
84
+ export const parameter = {
85
85
  type: 'object',
86
86
  oneOf: [
87
87
  {
@@ -96,17 +96,6 @@ const parameter = {
96
96
  required: ['name', 'value'],
97
97
  additionalProperties: false,
98
98
  },
99
- {
100
- type: 'object',
101
- properties: {
102
- $ref: { type: 'string' },
103
- value: {
104
- oneOf: [{ type: 'string' }, { type: 'number' }, { type: 'boolean' }],
105
- },
106
- },
107
- required: ['$ref'],
108
- additionalProperties: false,
109
- },
110
99
  {
111
100
  type: 'object',
112
101
  properties: {
@@ -124,7 +113,7 @@ const parameters = {
124
113
  type: 'array',
125
114
  items: parameter,
126
115
  } as const;
127
- const infoObject = {
116
+ export const infoObject = {
128
117
  type: 'object',
129
118
  properties: {
130
119
  title: { type: 'string' },
@@ -135,7 +124,7 @@ const infoObject = {
135
124
  additionalProperties: false,
136
125
  required: ['title', 'version'],
137
126
  } as const;
138
- const replacement = {
127
+ export const replacement = {
139
128
  type: 'object',
140
129
  properties: {
141
130
  target: { type: 'string' },
@@ -150,7 +139,7 @@ const replacement = {
150
139
  },
151
140
  },
152
141
  } as const;
153
- const requestBody = {
142
+ export const requestBody = {
154
143
  type: 'object',
155
144
  properties: {
156
145
  contentType: { type: 'string' },
@@ -172,7 +161,7 @@ const requestBody = {
172
161
  additionalProperties: false,
173
162
  required: ['payload'],
174
163
  } as const;
175
- const criteriaObject = {
164
+ export const criteriaObject = {
176
165
  type: 'object',
177
166
  properties: {
178
167
  condition: { type: 'string' },
@@ -204,7 +193,7 @@ const criteriaObjects = {
204
193
  type: 'array',
205
194
  items: criteriaObject,
206
195
  } as const;
207
- const inherit = {
196
+ export const inherit = {
208
197
  type: 'string',
209
198
  enum: ['auto', 'none'],
210
199
  } as const;
@@ -242,7 +231,7 @@ const onFailureList = {
242
231
  type: 'array',
243
232
  items: onFailureObject,
244
233
  } as const;
245
- const step = {
234
+ export const step = {
246
235
  type: 'object',
247
236
  properties: {
248
237
  stepId: { type: 'string' },
@@ -257,7 +246,23 @@ const step = {
257
246
  outputs: {
258
247
  type: 'object',
259
248
  additionalProperties: {
260
- type: 'string',
249
+ oneOf: [
250
+ {
251
+ type: 'string',
252
+ },
253
+ {
254
+ type: 'object',
255
+ },
256
+ {
257
+ type: 'array',
258
+ },
259
+ {
260
+ type: 'boolean',
261
+ },
262
+ {
263
+ type: 'number',
264
+ },
265
+ ],
261
266
  },
262
267
  },
263
268
  'x-inherit': inherit,
@@ -301,7 +306,7 @@ const JSONSchema = {
301
306
  required: ['type'],
302
307
  additionalProperties: true,
303
308
  } as const;
304
- const workflow = {
309
+ export const workflow = {
305
310
  type: 'object',
306
311
  properties: {
307
312
  workflowId: { type: 'string' },
@@ -334,11 +334,8 @@ const MessageExample: NodeType = {
334
334
  const Schema: NodeType = {
335
335
  properties: {
336
336
  $id: { type: 'string' },
337
- id: { type: 'string' },
338
337
  $schema: { type: 'string' },
339
338
  definitions: 'NamedSchemas',
340
- $defs: 'NamedSchemas',
341
- $vocabulary: { type: 'string' },
342
339
  externalDocs: 'ExternalDocs',
343
340
  discriminator: 'Discriminator',
344
341
  myArbitraryKeyword: { type: 'boolean' },
@@ -359,16 +356,14 @@ const Schema: NodeType = {
359
356
  required: { type: 'array', items: { type: 'string' } },
360
357
  enum: { type: 'array' },
361
358
  type: (value: any) => {
362
- if (Array.isArray(value)) {
363
- return {
364
- type: 'array',
365
- items: { enum: ['object', 'array', 'string', 'number', 'integer', 'boolean', 'null'] },
366
- };
367
- } else {
368
- return {
369
- enum: ['object', 'array', 'string', 'number', 'integer', 'boolean', 'null'],
370
- };
371
- }
359
+ return Array.isArray(value)
360
+ ? {
361
+ type: 'array',
362
+ items: { enum: ['object', 'array', 'string', 'number', 'integer', 'boolean', 'null'] },
363
+ }
364
+ : {
365
+ enum: ['object', 'array', 'string', 'number', 'integer', 'boolean', 'null'],
366
+ };
372
367
  },
373
368
  allOf: listOf('Schema'),
374
369
  anyOf: listOf('Schema'),
@@ -377,35 +372,12 @@ const Schema: NodeType = {
377
372
  if: 'Schema',
378
373
  then: 'Schema',
379
374
  else: 'Schema',
380
- dependentSchemas: listOf('Schema'),
381
- prefixItems: listOf('Schema'),
382
375
  contains: 'Schema',
383
- minContains: { type: 'integer', minimum: 0 },
384
- maxContains: { type: 'integer', minimum: 0 },
385
376
  patternProperties: { type: 'object' },
386
377
  propertyNames: 'Schema',
387
- unevaluatedItems: (value: unknown) => {
388
- if (typeof value === 'boolean') {
389
- return { type: 'boolean' };
390
- } else {
391
- return 'Schema';
392
- }
393
- },
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
378
  properties: 'SchemaProperties',
403
379
  items: (value: any) => {
404
- if (typeof value === 'boolean') {
405
- return { type: 'boolean' };
406
- } else {
407
- return 'Schema';
408
- }
380
+ return Array.isArray(value) ? listOf('Schema') : 'Schema';
409
381
  },
410
382
  additionalProperties: (value: any) => {
411
383
  return typeof value === 'boolean' ? { type: 'boolean' } : 'Schema';
@@ -417,23 +389,22 @@ const Schema: NodeType = {
417
389
  default: null,
418
390
  readOnly: { type: 'boolean' },
419
391
  writeOnly: { type: 'boolean' },
420
- // xml: 'Xml',
421
392
  examples: { type: 'array' },
422
393
  example: { isExample: true },
423
394
  deprecated: { type: 'boolean' },
424
395
  const: null,
425
396
  $comment: { type: 'string' },
426
- dependencies: { type: 'object' }, // TODO
397
+ additionalItems: (value: any) => {
398
+ return typeof value === 'boolean' ? { type: 'boolean' } : 'Schema';
399
+ },
400
+ dependencies: 'Dependencies',
427
401
  },
428
402
  };
429
403
 
430
404
  const SchemaProperties: NodeType = {
431
405
  properties: {},
432
406
  additionalProperties: (value: any) => {
433
- if (typeof value === 'boolean') {
434
- return { type: 'boolean' };
435
- }
436
- return 'Schema';
407
+ return typeof value === 'boolean' ? { type: 'boolean' } : 'Schema';
437
408
  },
438
409
  };
439
410
 
@@ -584,6 +555,13 @@ const SecurityScheme: NodeType = {
584
555
  extensionsPrefix: 'x-',
585
556
  };
586
557
 
558
+ const Dependencies: NodeType = {
559
+ properties: {},
560
+ additionalProperties: (value: any) => {
561
+ return Array.isArray(value) ? { type: 'array', items: { type: 'string' } } : 'Schema';
562
+ },
563
+ };
564
+
587
565
  // --- Per-protocol node types
588
566
 
589
567
  // http
@@ -1133,4 +1111,5 @@ export const AsyncApi2Types: Record<string, NodeType> = {
1133
1111
  MessageTrait,
1134
1112
  MessageTraitList: listOf('MessageTrait'),
1135
1113
  CorrelationId,
1114
+ Dependencies,
1136
1115
  };
@@ -133,13 +133,13 @@ const Schema: NodeType = {
133
133
  if: 'Schema',
134
134
  then: 'Schema',
135
135
  else: 'Schema',
136
- dependentSchemas: listOf('Schema'),
136
+ dependentSchemas: mapOf('Schema'),
137
137
  dependentRequired: 'DependentRequired',
138
138
  prefixItems: listOf('Schema'),
139
139
  contains: 'Schema',
140
140
  minContains: { type: 'integer', minimum: 0 },
141
141
  maxContains: { type: 'integer', minimum: 0 },
142
- patternProperties: { type: 'object' },
142
+ patternProperties: 'SchemaProperties',
143
143
  propertyNames: 'Schema',
144
144
  unevaluatedItems: (value: unknown) => {
145
145
  if (typeof value === 'boolean') {
@@ -1,4 +1,44 @@
1
1
  import type { FromSchema } from 'json-schema-to-ts';
2
- import type { arazzoSchema } from '../types/arazzo';
2
+ import type {
3
+ arazzoSchema,
4
+ parameter,
5
+ operationMethod,
6
+ expectSchema,
7
+ sourceDescriptionSchema,
8
+ infoObject,
9
+ requestBody,
10
+ replacement,
11
+ inherit,
12
+ criteriaObject,
13
+ step,
14
+ workflow,
15
+ } from '../types/arazzo';
3
16
 
4
17
  export type ArazzoDefinition = FromSchema<typeof arazzoSchema>;
18
+ export type OperationMethod = FromSchema<typeof operationMethod>;
19
+ export type ResponseContext = {
20
+ statusCode: number;
21
+ body: any;
22
+ headers: Headers;
23
+ mimeType: string;
24
+ } & Record<string, any>;
25
+ export type Expect = FromSchema<typeof expectSchema>;
26
+ export type SourceDescription = FromSchema<typeof sourceDescriptionSchema>;
27
+ export type Parameter = FromSchema<typeof parameter>;
28
+ export type InfoObject = FromSchema<typeof infoObject>;
29
+ export type RequestBody = FromSchema<typeof requestBody>;
30
+ export type Replacement = FromSchema<typeof replacement>;
31
+ export type Inherit = FromSchema<typeof inherit>;
32
+ export type CriteriaObject = FromSchema<typeof criteriaObject>;
33
+ export type VerboseLog = {
34
+ method: OperationMethod;
35
+ path: string;
36
+ host: string;
37
+ body?: any;
38
+ headerParams?: Record<string, string>;
39
+ statusCode?: number;
40
+ };
41
+ export type Step = FromSchema<typeof step>;
42
+ export type Workflow = FromSchema<typeof workflow> & {
43
+ steps: Step[];
44
+ };
package/src/utils.ts CHANGED
@@ -2,14 +2,14 @@ import * as fs from 'fs';
2
2
  import { extname } from 'path';
3
3
  import * as minimatch from 'minimatch';
4
4
  import fetch from 'node-fetch';
5
- import * as pluralize from 'pluralize';
6
5
  import { parseYaml } from './js-yaml';
7
- import { UserContext } from './walk';
8
6
  import { env } from './env';
9
7
  import { logger, colorize } from './logger';
10
- import { HttpResolveConfig } from './config';
11
8
  import { HttpsProxyAgent } from 'https-proxy-agent';
12
9
 
10
+ import type { HttpResolveConfig } from './config';
11
+ import type { UserContext } from './walk';
12
+
13
13
  export { parseYaml, stringifyYaml } from './js-yaml';
14
14
 
15
15
  export type StackFrame<T> = {
@@ -146,10 +146,6 @@ export function validateMimeTypeOAS3(
146
146
  }
147
147
  }
148
148
 
149
- export function isSingular(path: string) {
150
- return pluralize.isSingular(path);
151
- }
152
-
153
149
  export function readFileAsStringSync(filePath: string) {
154
150
  return fs.readFileSync(filePath, 'utf-8');
155
151
  }
@@ -267,7 +263,7 @@ export function pickDefined<T extends Record<string, unknown>>(
267
263
  }
268
264
 
269
265
  export function nextTick() {
270
- new Promise((resolve) => {
266
+ return new Promise((resolve) => {
271
267
  setTimeout(resolve);
272
268
  });
273
269
  }
@@ -284,3 +280,40 @@ export function getProxyAgent() {
284
280
  const proxy = process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
285
281
  return proxy ? new HttpsProxyAgent(proxy) : undefined;
286
282
  }
283
+
284
+ /**
285
+ * Checks if two objects are deeply equal.
286
+ * Borrowed the source code from https://github.com/lukeed/dequal.
287
+ */
288
+ export function dequal(foo: any, bar: any): boolean {
289
+ let ctor, len;
290
+ if (foo === bar) return true;
291
+
292
+ if (foo && bar && (ctor = foo.constructor) === bar.constructor) {
293
+ if (ctor === Date) return foo.getTime() === bar.getTime();
294
+ if (ctor === RegExp) return foo.toString() === bar.toString();
295
+
296
+ if (ctor === Array) {
297
+ if ((len = foo.length) === bar.length) {
298
+ while (len-- && dequal(foo[len], bar[len]));
299
+ }
300
+ return len === -1;
301
+ }
302
+
303
+ if (!ctor || typeof foo === 'object') {
304
+ len = 0;
305
+ for (ctor in foo) {
306
+ if (
307
+ Object.prototype.hasOwnProperty.call(foo, ctor) &&
308
+ ++len &&
309
+ !Object.prototype.hasOwnProperty.call(bar, ctor)
310
+ )
311
+ return false;
312
+ if (!(ctor in bar) || !dequal(foo[ctor], bar[ctor])) return false;
313
+ }
314
+ return Object.keys(bar).length === len;
315
+ }
316
+ }
317
+
318
+ return foo !== foo && bar !== bar;
319
+ }