Skip to content

Commit

Permalink
replace deref lib (#140)
Browse files Browse the repository at this point in the history
* replace deref lib

* changeset

* remove v14 support
  • Loading branch information
supertong authored Sep 27, 2023
1 parent b90c88c commit bf09b6c
Show file tree
Hide file tree
Showing 14 changed files with 575 additions and 386 deletions.
6 changes: 6 additions & 0 deletions .changeset/five-bananas-bake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'oas3-chow-chow': major
---

The API has been updated to be an async function.
Remove support for node v14.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:

strategy:
matrix:
node-version: [14.x, 16.x, 18.x]
node-version: [16.x, 18.x]

steps:
- uses: actions/checkout@v2
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import * as fs from "fs";
import * as yaml from "js-yaml";

var doc = yaml.safeLoad(fs.readFileSync("./openapi.yml", "utf8"));
const chow = new ChowChow(doc);
const chow = ChowChow.create(doc);

// For URL: /:pathParam/info?arrParam=x&arrParam=y&other=z
chow.validateRequestByPath(
Expand Down Expand Up @@ -56,7 +56,7 @@ chow.validateResponseByPath("/books/info", "POST", {

You could optionally provide configs to the constructor
```typescript
const chow = new ChowChow(doc, {
const chow = ChowChow.create(doc, {
headerAjvOptions: {},
cookieAjvOptions: {},
pathAjvOptions: { coerceTypes: true },
Expand Down
6 changes: 3 additions & 3 deletions __test__/deref-error.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import ChowChow from '../src';
const fixture = require('./fixtures/deref-error.json');

describe('Deref Error', () => {
it('should throw a proper error', () => {
expect(() => new ChowChow(fixture)).toThrow(
'Missing $ref: #/components/schemas/blahBlahBlah'
it('should throw a proper error', async () => {
await expect(ChowChow.create(fixture)).rejects.toMatchInlineSnapshot(
`[MissingPointerError: Token "blahBlahBlah" does not exist.]`
);
});
});
18 changes: 8 additions & 10 deletions __test__/option.spec.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
import ChowChow from '../src';

describe('Option Body', () => {
it('throw with unknown format', () => {
it('throw with unknown format', async () => {
const fixture = require('./fixtures/option-unknown-fmt.json');

expect(() => {
new ChowChow(fixture);
}).toThrow(
'unknown format "pet-name" ignored in schema at path "#/properties/name"'
await expect(ChowChow.create(fixture)).rejects.toMatchInlineSnapshot(
`[Error: unknown format "pet-name" ignored in schema at path "#/properties/name"]`
);
});

it('success with unknown format if unknown format is allowed', () => {
it('success with unknown format if unknown format is allowed', async () => {
const fixture = require('./fixtures/option-unknown-fmt.json');

expect(() => {
new ChowChow(fixture, {
await expect(
ChowChow.create(fixture, {
responseBodyAjvOptions: {
formats: {
'pet-name': true,
},
},
});
}).not.toThrow();
})
).resolves.toBeTruthy();
});
});
12 changes: 6 additions & 6 deletions __test__/path.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ describe('Path', () => {
describe('Parameter in Operation level', () => {
let chowchow: ChowChow;

beforeAll(() => {
chowchow = new ChowChow(pathFixture);
beforeAll(async () => {
chowchow = await ChowChow.create(pathFixture);
});

it('should validate the path parameters and coerce to the correct type', () => {
Expand All @@ -35,8 +35,8 @@ describe('Path', () => {
describe('Parameter in Path level', () => {
let chowchow: ChowChow;

beforeAll(() => {
chowchow = new ChowChow(parameterInPathLevelFixture);
beforeAll(async () => {
chowchow = await ChowChow.create(parameterInPathLevelFixture);
});

it('should validate the path parameters and coerce to the correct type', () => {
Expand All @@ -62,8 +62,8 @@ describe('Path', () => {
describe('Parameter in Operation level should override Path level', () => {
let chowchow: ChowChow;

beforeAll(() => {
chowchow = new ChowChow(parameterInBothOperationAndPathFixture);
beforeAll(async () => {
chowchow = await ChowChow.create(parameterInBothOperationAndPathFixture);
});

it('should validate the path parameters and coerce to the correct type', () => {
Expand Down
16 changes: 8 additions & 8 deletions __test__/pet-store.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ const fixture = require('./fixtures/pet-store.json');
describe('Pet Store', () => {
let chowchow: ChowChow;

beforeAll(() => {
chowchow = new ChowChow(fixture as any);
beforeAll(async () => {
chowchow = await ChowChow.create(fixture as any);
});

test('It should throw an error if a path is undefined', () => {
Expand Down Expand Up @@ -105,11 +105,11 @@ describe('Pet Store', () => {
});
});
describe('Configure ChowOptions for allErrors', () => {
test('It should fail validation and receive multiple errors if payload is invalid and ChowOptions configured with allErrors:true', () => {
test('It should fail validation and receive multiple errors if payload is invalid and ChowOptions configured with allErrors:true', async () => {
let chowOptions: Partial<ChowOptions> = {
requestBodyAjvOptions: { allErrors: true },
};
chowchow = new ChowChow(fixture as any, chowOptions);
chowchow = await ChowChow.create(fixture as any, chowOptions);

try {
chowchow.validateRequestByPath('/pets', 'post', {
Expand All @@ -131,11 +131,11 @@ describe('Pet Store', () => {
}
});

test('It should fail validation and receive a single error if payload is invalid and ChowOptions configured for allErrors:false', () => {
test('It should fail validation and receive a single error if payload is invalid and ChowOptions configured for allErrors:false', async () => {
let chowOptions: Partial<ChowOptions> = {
requestBodyAjvOptions: { allErrors: false },
};
chowchow = new ChowChow(fixture as any, chowOptions);
chowchow = await ChowChow.create(fixture as any, chowOptions);

try {
chowchow.validateRequestByPath('/pets', 'post', {
Expand All @@ -157,8 +157,8 @@ describe('Pet Store', () => {
}
});

test('It should fail validation and receive a single error if payload is invalid and ChowOptions not configured', () => {
chowchow = new ChowChow(fixture as any);
test('It should fail validation and receive a single error if payload is invalid and ChowOptions not configured', async () => {
chowchow = await ChowChow.create(fixture as any);

try {
chowchow.validateRequestByPath('/pets', 'post', {
Expand Down
4 changes: 2 additions & 2 deletions __test__/query.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ const fixture = require('./fixtures/query.json');
describe('Query', () => {
let chowchow: ChowChow;

beforeAll(() => {
chowchow = new ChowChow(fixture);
beforeAll(async () => {
chowchow = await ChowChow.create(fixture);
});

it('should coerce query parameter to an array', () => {
Expand Down
4 changes: 2 additions & 2 deletions __test__/response.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ const fixture = require('./fixtures/response.json');
describe('Response', () => {
let chowchow: ChowChow;

beforeAll(() => {
chowchow = new ChowChow(fixture);
beforeAll(async () => {
chowchow = await ChowChow.create(fixture);
});

it('should validate the response with status code', () => {
Expand Down
11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@
"singleQuote": true
},
"dependencies": {
"@apidevtools/json-schema-ref-parser": "^11.1.0",
"ajv": "^8.12.0",
"ajv-formats": "^2.1.1",
"better-ajv-errors": "1.2.0",
"json-schema-deref-sync": "^0.14.0",
"oas-validator": "^5.0.8",
"openapi3-ts": "^1.3.0",
"xregexp": "^4.2.4"
},
Expand All @@ -40,10 +41,10 @@
"@types/node": "18.17.11",
"@types/xregexp": "3.0.30",
"babel-core": "6.26.3",
"babel-jest": "29.6.4",
"jest": "29.6.4",
"babel-jest": "^29.7.0",
"jest": "^29.7.0",
"prettier": "2.2.1",
"ts-jest": "29.1.1",
"typescript": "4.9.5"
"ts-jest": "^29.1.1",
"typescript": "5.2.2"
}
}
9 changes: 1 addition & 8 deletions src/compiler/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { OpenAPIObject, PathItemObject } from 'openapi3-ts';
import CompiledPath from './CompiledPath';
import * as deref from 'json-schema-deref-sync';
import { ChowOptions } from '..';
import CompiledOperation from './CompiledOperation';
import { OperationRegisterFunc } from './CompiledPathItem';
Expand All @@ -21,18 +20,12 @@ export interface ResponseMeta {
}

export default function compile(
oas: OpenAPIObject,
document: OpenAPIObject,
options: Partial<ChowOptions>
): {
compiledPaths: CompiledPath[];
compiledOperationById: Map<string, CompiledOperation>;
} {
const document: OpenAPIObject = deref(oas, { failOnMissing: true });

if (document instanceof Error) {
throw document;
}

const compiledOperationById = new Map<string, CompiledOperation>();
const registerOperationById: OperationRegisterFunc = (
operationId: string,
Expand Down
18 changes: 18 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Options as AjvOptions } from 'ajv';
import { OpenAPIObject } from 'openapi3-ts';
import $RefParser from '@apidevtools/json-schema-ref-parser';
import compile, { RequestMeta, ResponseMeta } from './compiler';
import CompiledPath from './compiler/CompiledPath';
import ChowError, {
Expand Down Expand Up @@ -30,6 +31,23 @@ export default class ChowChow {
private compiledPaths: CompiledPath[];
private compiledOperationById: Map<string, CompiledOperation>;

public static async create(
document: object,
options: Partial<ChowOptions> = {}
) {
const res = await $RefParser.dereference(document, {
continueOnError: false,
resolve: {
external: false,
},
dereference: {
circular: false,
},
});

return new ChowChow(res as OpenAPIObject, options);
}

constructor(document: OpenAPIObject, options: Partial<ChowOptions> = {}) {
const { compiledPaths, compiledOperationById } = compile(document, options);
this.compiledPaths = compiledPaths;
Expand Down
1 change: 0 additions & 1 deletion typings.d.ts

This file was deleted.

Loading

0 comments on commit bf09b6c

Please sign in to comment.