Skip to content

Commit

Permalink
feat(oas): reduce complexity, increase coverage
Browse files Browse the repository at this point in the history
closes #224
  • Loading branch information
ostridm committed Feb 13, 2024
1 parent 9201593 commit 903dafd
Show file tree
Hide file tree
Showing 3 changed files with 331 additions and 56 deletions.
58 changes: 29 additions & 29 deletions packages/oas/src/converter/Sampler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,35 +14,15 @@ export class Sampler {
tokens: string[];
}
): any {
return this.sample(
'schema' in param
? {
...param.schema,
...(param[VendorExtensions.X_EXAMPLE] !== undefined
? {
[VendorExtensions.X_EXAMPLE]:
param[VendorExtensions.X_EXAMPLE]
}
: {}),
...(param[VendorExtensions.X_EXAMPLES] !== undefined
? {
[VendorExtensions.X_EXAMPLES]:
param[VendorExtensions.X_EXAMPLES]
}
: {}),
...(param.example !== undefined ? { example: param.example } : {})
}
: param,
{
spec: context.spec,
jsonPointer: pointer.compile([
...context.tokens,
'parameters',
context.idx.toString(),
...('schema' in param ? ['schema'] : [])
])
}
);
return this.sample(this.createSchema(param), {
spec: context.spec,
jsonPointer: pointer.compile([
...context.tokens,
'parameters',
context.idx.toString(),
...('schema' in param ? ['schema'] : [])
])
});
}

/**
Expand All @@ -66,4 +46,24 @@ export class Sampler {
throw new ConvertError(e.message, context?.jsonPointer);
}
}

private createSchema(param: OpenAPI.Parameter): Schema {
return 'schema' in param
? {
...param.schema,
...(param[VendorExtensions.X_EXAMPLE] !== undefined
? {
[VendorExtensions.X_EXAMPLE]: param[VendorExtensions.X_EXAMPLE]
}
: {}),
...(param[VendorExtensions.X_EXAMPLES] !== undefined
? {
[VendorExtensions.X_EXAMPLES]:
param[VendorExtensions.X_EXAMPLES]
}
: {}),
...(param.example !== undefined ? { example: param.example } : {})
}
: param;
}
}
80 changes: 53 additions & 27 deletions packages/openapi-sampler/src/traverse/DefaultTraverse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,70 +345,96 @@ export class DefaultTraverse implements Traverse {
const example =
schema[VendorExtensions.X_EXAMPLE] ?? schema[VendorExtensions.X_EXAMPLES];

const schemaKeys = this.findSchemaKeys(schema);
const matchingSchema = this.getMatchingSchema(schema);
const isPrimitiveType = 0 === matchingSchema.keys.length;

if (
!example ||
typeof example !== 'object' ||
0 === schemaKeys.keys.length
) {
if (!example || typeof example !== 'object' || isPrimitiveType) {
return example;
}

return this.matchVendorExampleKeys(example, schemaKeys);
return this.matchVendorExample(example, matchingSchema);
}

private findSchemaKeys(
private getMatchingSchema(
schema: Schema,
depth: number = 0
): { depth: number; keys: string[] } {
if ('items' in schema) {
return this.findSchemaKeys(schema.items, 1 + depth);
return this.getMatchingSchema(schema.items, 1 + depth);
}

return {
depth,
keys: 'properties' in schema ? Object.keys(schema.properties) : []
keys:
'properties' in schema && schema.properties
? Object.keys(schema.properties)
: []
};
}

private matchVendorExampleKeys(
private matchVendorExample(
example: unknown,
schemaKeys: { depth: number; keys: string[] },
possibleExamples: unknown[] = []
matchingSchema: { depth: number; keys: string[] },
possibleExample: unknown[] = []
): unknown {
if (!example || typeof example !== 'object') {
return undefined;
}

if (schemaKeys.depth > 0 && Array.isArray(example)) {
return this.matchVendorExampleKeys(
if (matchingSchema.depth > 0 && Array.isArray(example)) {
return this.matchArrayVendorExample(
example,
matchingSchema,
possibleExample
);
}

return this.matchObjectVendorExample(
example,
matchingSchema,
possibleExample
);
}

private matchArrayVendorExample(
example: unknown,
matchingSchema: { depth: number; keys: string[] },
possibleExample: unknown[]
): unknown {
if (matchingSchema.depth > 0 && Array.isArray(example)) {
possibleExample.push(example);

return this.matchArrayVendorExample(
[...example, undefined].shift(),
{
...schemaKeys,
depth: schemaKeys.depth - 1
...matchingSchema,
depth: matchingSchema.depth - 1
},
[...possibleExamples, example]
possibleExample
);
}

const objectKeys = Object.keys(example);
return !!example && Array.isArray(example)
? undefined
: this.matchObjectVendorExample(example, matchingSchema, possibleExample);
}

if (objectKeys.every((key) => schemaKeys.keys.includes(key))) {
if (possibleExamples.length > 0) {
return possibleExamples.shift();
}
private matchObjectVendorExample(
example: unknown,
matchingSchema: { depth: number; keys: string[] },
possibleExample: unknown[]
): unknown {
const objectKeys = Object.keys(example ?? {});

return example;
if (objectKeys.every((key) => matchingSchema.keys.includes(key))) {
return possibleExample.length > 0 ? possibleExample.shift() : example;
}

for (const key of objectKeys) {
const value = this.matchVendorExampleKeys(example[key], schemaKeys);
const value = this.matchVendorExample(example[key], matchingSchema);
if (value) {
return value;
}
}

return undefined;
}
}
Loading

0 comments on commit 903dafd

Please sign in to comment.