From 2a6a2402d5296bfcbb032ecff6e9be17dcd28073 Mon Sep 17 00:00:00 2001 From: Jon Ursenbach Date: Thu, 2 Dec 2021 12:02:51 -0800 Subject: [PATCH] feat: adding support for OpenAPI 3.1 (#378) * feat: adding support for OpenAPI 3.1 * ci: adding an env variable to alleviate chalk's flakiness in ci * chore(deps): upgrading oas to the latest release * chore: updating oas to v17 * chore(deps): upgrading oas and oas-normalize * test: adding tests for oas 3.1 and json vs yaml uploads --- .github/workflows/ci.yml | 4 + __tests__/__fixtures__/invalid-oas-3.1.json | 27 + __tests__/__fixtures__/swagger.json | 1 - .../cmds/__snapshots__/openapi.test.js.snap | 14 + __tests__/cmds/openapi.test.js | 407 +++++---- package-lock.json | 851 ++++++++++++------ package.json | 5 +- src/cmds/openapi.js | 16 +- src/cmds/swagger.js | 34 +- 9 files changed, 861 insertions(+), 498 deletions(-) create mode 100644 __tests__/__fixtures__/invalid-oas-3.1.json delete mode 100644 __tests__/__fixtures__/swagger.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a5d0a8c84..c02252b98 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,3 +25,7 @@ jobs: - name: Run tests run: npm test + env: + # `chalk` has troubles with color detection while on CI and also in how it's used within our tests. + # https://github.com/chalk/supports-color/issues/106 + FORCE_COLOR: 1 diff --git a/__tests__/__fixtures__/invalid-oas-3.1.json b/__tests__/__fixtures__/invalid-oas-3.1.json new file mode 100644 index 000000000..8be1021a1 --- /dev/null +++ b/__tests__/__fixtures__/invalid-oas-3.1.json @@ -0,0 +1,27 @@ +{ + "openapi": "3.0.0", + "info": { + "version": "1.0.0", + "title": "Invalid API", + "description": "This definition should not validate because the `mutualTLS` security type is only available on OpenAPI 3.1" + }, + "paths": { + "/": { + "post": { + "responses": { + "200": { + "description": "OK" + } + }, + "security": [{ "tlsAuth": [] }] + } + } + }, + "components": { + "securitySchemes": { + "tlsAuth": { + "type": "mutualTLS" + } + } + } +} diff --git a/__tests__/__fixtures__/swagger.json b/__tests__/__fixtures__/swagger.json deleted file mode 100644 index 816847f31..000000000 --- a/__tests__/__fixtures__/swagger.json +++ /dev/null @@ -1 +0,0 @@ -{"swagger":"2.0","info":{"description":"This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.","version":"1.0.0","title":"Swagger Petstore","termsOfService":"http://swagger.io/terms/","contact":{"email":"apiteam@swagger.io"},"license":{"name":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}},"host":"petstore.swagger.io","basePath":"/v2","tags":[{"name":"pet","description":"Everything about your Pets","externalDocs":{"description":"Find out more","url":"http://swagger.io"}},{"name":"store","description":"Access to Petstore orders"},{"name":"user","description":"Operations about user","externalDocs":{"description":"Find out more about our store","url":"http://swagger.io"}}],"schemes":["http"],"paths":{"/pet":{"post":{"tags":["pet"],"summary":"Add a new pet to the store","description":"","operationId":"addPet","consumes":["application/json","application/xml"],"produces":["application/xml","application/json"],"parameters":[{"in":"body","name":"body","description":"Pet object that needs to be added to the store","required":true,"schema":{"$ref":"#/definitions/Pet"}}],"responses":{"405":{"description":"Invalid input"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]},"put":{"tags":["pet"],"summary":"Update an existing pet","description":"","operationId":"updatePet","consumes":["application/json","application/xml"],"produces":["application/xml","application/json"],"parameters":[{"in":"body","name":"body","description":"Pet object that needs to be added to the store","required":true,"schema":{"$ref":"#/definitions/Pet"}}],"responses":{"400":{"description":"Invalid ID supplied"},"404":{"description":"Pet not found"},"405":{"description":"Validation exception"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/pet/findByStatus":{"get":{"tags":["pet"],"summary":"Finds Pets by status","description":"Multiple status values can be provided with comma separated strings","operationId":"findPetsByStatus","produces":["application/xml","application/json"],"parameters":[{"name":"status","in":"query","description":"Status values that need to be considered for filter","required":true,"type":"array","items":{"type":"string","enum":["available","pending","sold"],"default":"available"},"collectionFormat":"multi"}],"responses":{"200":{"description":"successful operation","schema":{"type":"array","items":{"$ref":"#/definitions/Pet"}}},"400":{"description":"Invalid status value"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/pet/findByTags":{"get":{"tags":["pet"],"summary":"Finds Pets by tags","description":"Muliple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.","operationId":"findPetsByTags","produces":["application/xml","application/json"],"parameters":[{"name":"tags","in":"query","description":"Tags to filter by","required":true,"type":"array","items":{"type":"string"},"collectionFormat":"multi"}],"responses":{"200":{"description":"successful operation","schema":{"type":"array","items":{"$ref":"#/definitions/Pet"}}},"400":{"description":"Invalid tag value"}},"security":[{"petstore_auth":["write:pets","read:pets"]}],"deprecated":true}},"/pet/{petId}":{"get":{"tags":["pet"],"summary":"Find pet by ID","description":"Returns a single pet","operationId":"getPetById","produces":["application/xml","application/json"],"parameters":[{"name":"petId","in":"path","description":"ID of pet to return","required":true,"type":"integer","format":"int64"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/Pet"}},"400":{"description":"Invalid ID supplied"},"404":{"description":"Pet not found"}},"security":[{"api_key":[]}]},"post":{"tags":["pet"],"summary":"Updates a pet in the store with form data","description":"","operationId":"updatePetWithForm","consumes":["application/x-www-form-urlencoded"],"produces":["application/xml","application/json"],"parameters":[{"name":"petId","in":"path","description":"ID of pet that needs to be updated","required":true,"type":"integer","format":"int64"},{"name":"name","in":"formData","description":"Updated name of the pet","required":false,"type":"string"},{"name":"status","in":"formData","description":"Updated status of the pet","required":false,"type":"string"}],"responses":{"405":{"description":"Invalid input"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]},"delete":{"tags":["pet"],"summary":"Deletes a pet","description":"","operationId":"deletePet","produces":["application/xml","application/json"],"parameters":[{"name":"api_key","in":"header","required":false,"type":"string"},{"name":"petId","in":"path","description":"Pet id to delete","required":true,"type":"integer","format":"int64"}],"responses":{"400":{"description":"Invalid ID supplied"},"404":{"description":"Pet not found"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/pet/{petId}/uploadImage":{"post":{"tags":["pet"],"summary":"uploads an image","description":"","operationId":"uploadFile","consumes":["multipart/form-data"],"produces":["application/json"],"parameters":[{"name":"petId","in":"path","description":"ID of pet to update","required":true,"type":"integer","format":"int64"},{"name":"additionalMetadata","in":"formData","description":"Additional data to pass to server","required":false,"type":"string"},{"name":"file","in":"formData","description":"file to upload","required":false,"type":"file"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/ApiResponse"}}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/store/inventory":{"get":{"tags":["store"],"summary":"Returns pet inventories by status","description":"Returns a map of status codes to quantities","operationId":"getInventory","produces":["application/json"],"parameters":[],"responses":{"200":{"description":"successful operation","schema":{"type":"object","additionalProperties":{"type":"integer","format":"int32"}}}},"security":[{"api_key":[]}]}},"/store/order":{"post":{"tags":["store"],"summary":"Place an order for a pet","description":"","operationId":"placeOrder","produces":["application/xml","application/json"],"parameters":[{"in":"body","name":"body","description":"order placed for purchasing the pet","required":true,"schema":{"$ref":"#/definitions/Order"}}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/Order"}},"400":{"description":"Invalid Order"}}}},"/store/order/{orderId}":{"get":{"tags":["store"],"summary":"Find purchase order by ID","description":"For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions","operationId":"getOrderById","produces":["application/xml","application/json"],"parameters":[{"name":"orderId","in":"path","description":"ID of pet that needs to be fetched","required":true,"type":"integer","maximum":10.0,"minimum":1.0,"format":"int64"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/Order"}},"400":{"description":"Invalid ID supplied"},"404":{"description":"Order not found"}}},"delete":{"tags":["store"],"summary":"Delete purchase order by ID","description":"For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors","operationId":"deleteOrder","produces":["application/xml","application/json"],"parameters":[{"name":"orderId","in":"path","description":"ID of the order that needs to be deleted","required":true,"type":"integer","minimum":1.0,"format":"int64"}],"responses":{"400":{"description":"Invalid ID supplied"},"404":{"description":"Order not found"}}}},"/user":{"post":{"tags":["user"],"summary":"Create user","description":"This can only be done by the logged in user.","operationId":"createUser","produces":["application/xml","application/json"],"parameters":[{"in":"body","name":"body","description":"Created user object","required":true,"schema":{"$ref":"#/definitions/User"}}],"responses":{"default":{"description":"successful operation"}}}},"/user/createWithArray":{"post":{"tags":["user"],"summary":"Creates list of users with given input array","description":"","operationId":"createUsersWithArrayInput","produces":["application/xml","application/json"],"parameters":[{"in":"body","name":"body","description":"List of user object","required":true,"schema":{"type":"array","items":{"$ref":"#/definitions/User"}}}],"responses":{"default":{"description":"successful operation"}}}},"/user/createWithList":{"post":{"tags":["user"],"summary":"Creates list of users with given input array","description":"","operationId":"createUsersWithListInput","produces":["application/xml","application/json"],"parameters":[{"in":"body","name":"body","description":"List of user object","required":true,"schema":{"type":"array","items":{"$ref":"#/definitions/User"}}}],"responses":{"default":{"description":"successful operation"}}}},"/user/login":{"get":{"tags":["user"],"summary":"Logs user into the system","description":"","operationId":"loginUser","produces":["application/xml","application/json"],"parameters":[{"name":"username","in":"query","description":"The user name for login","required":true,"type":"string"},{"name":"password","in":"query","description":"The password for login in clear text","required":true,"type":"string"}],"responses":{"200":{"description":"successful operation","schema":{"type":"string"},"headers":{"X-Rate-Limit":{"type":"integer","format":"int32","description":"calls per hour allowed by the user"},"X-Expires-After":{"type":"string","format":"date-time","description":"date in UTC when token expires"}}},"400":{"description":"Invalid username/password supplied"}}}},"/user/logout":{"get":{"tags":["user"],"summary":"Logs out current logged in user session","description":"","operationId":"logoutUser","produces":["application/xml","application/json"],"parameters":[],"responses":{"default":{"description":"successful operation"}}}},"/user/{username}":{"get":{"tags":["user"],"summary":"Get user by user name","description":"","operationId":"getUserByName","produces":["application/xml","application/json"],"parameters":[{"name":"username","in":"path","description":"The name that needs to be fetched. Use user1 for testing. ","required":true,"type":"string"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/User"}},"400":{"description":"Invalid username supplied"},"404":{"description":"User not found"}}},"put":{"tags":["user"],"summary":"Updated user","description":"This can only be done by the logged in user.","operationId":"updateUser","produces":["application/xml","application/json"],"parameters":[{"name":"username","in":"path","description":"name that need to be updated","required":true,"type":"string"},{"in":"body","name":"body","description":"Updated user object","required":true,"schema":{"$ref":"#/definitions/User"}}],"responses":{"400":{"description":"Invalid user supplied"},"404":{"description":"User not found"}}},"delete":{"tags":["user"],"summary":"Delete user","description":"This can only be done by the logged in user.","operationId":"deleteUser","produces":["application/xml","application/json"],"parameters":[{"name":"username","in":"path","description":"The name that needs to be deleted","required":true,"type":"string"}],"responses":{"400":{"description":"Invalid username supplied"},"404":{"description":"User not found"}}}}},"securityDefinitions":{"petstore_auth":{"type":"oauth2","authorizationUrl":"http://petstore.swagger.io/oauth/dialog","flow":"implicit","scopes":{"write:pets":"modify pets in your account","read:pets":"read your pets"}},"api_key":{"type":"apiKey","name":"api_key","in":"header"}},"definitions":{"Order":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"petId":{"type":"integer","format":"int64"},"quantity":{"type":"integer","format":"int32"},"shipDate":{"type":"string","format":"date-time"},"status":{"type":"string","description":"Order Status","enum":["placed","approved","delivered"]},"complete":{"type":"boolean","default":false}},"xml":{"name":"Order"}},"Category":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"}},"xml":{"name":"Category"}},"User":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"username":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string"},"password":{"type":"string"},"phone":{"type":"string"},"userStatus":{"type":"integer","format":"int32","description":"User Status"}},"xml":{"name":"User"}},"Tag":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"}},"xml":{"name":"Tag"}},"Pet":{"type":"object","required":["name","photoUrls"],"properties":{"id":{"type":"integer","format":"int64"},"category":{"$ref":"#/definitions/Category"},"name":{"type":"string","example":"doggie"},"photoUrls":{"type":"array","xml":{"name":"photoUrl","wrapped":true},"items":{"type":"string"}},"tags":{"type":"array","xml":{"name":"tag","wrapped":true},"items":{"$ref":"#/definitions/Tag"}},"status":{"type":"string","description":"pet status in the store","enum":["available","pending","sold"]}},"xml":{"name":"Pet"}},"ApiResponse":{"type":"object","properties":{"code":{"type":"integer","format":"int32"},"type":{"type":"string"},"message":{"type":"string"}}}},"externalDocs":{"description":"Find out more about Swagger","url":"http://swagger.io"}} \ No newline at end of file diff --git a/__tests__/cmds/__snapshots__/openapi.test.js.snap b/__tests__/cmds/__snapshots__/openapi.test.js.snap index 632c53a38..c8e446ddb 100644 --- a/__tests__/cmds/__snapshots__/openapi.test.js.snap +++ b/__tests__/cmds/__snapshots__/openapi.test.js.snap @@ -1,5 +1,19 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`rdme openapi error handling should throw an error if an invalid OpenAPI 3.1 definition is supplied 1`] = ` +[SyntaxError: OpenAPI schema validation failed. + +REQUIRED must have required property 'openIdConnectUrl' + +  24 | "components": { +  25 | "securitySchemes": { +> 26 | "tlsAuth": { +  | ^ ☹️ openIdConnectUrl is missing here! +  27 | "type": "mutualTLS" +  28 | } +  29 | }] +`; + exports[`rdme openapi should bundle and upload the expected content 1`] = ` Object { "components": Object { diff --git a/__tests__/cmds/openapi.test.js b/__tests__/cmds/openapi.test.js index b8dcc8393..c432c23c5 100644 --- a/__tests__/cmds/openapi.test.js +++ b/__tests__/cmds/openapi.test.js @@ -6,6 +6,7 @@ const swagger = require('../../src/cmds/swagger'); const openapi = require('../../src/cmds/openapi'); const key = 'API_KEY'; +const id = '5aa0409b7cf527a93bfb44df'; const version = '1.0.0'; jest.mock('../../src/lib/prompts'); @@ -31,182 +32,161 @@ describe('rdme openapi', () => { nock.cleanAll(); }); - it('should POST a discovered file if none provided', () => { - promptHandler.createOasPrompt.mockResolvedValue({ option: 'create' }); - - const mock = nock(config.host) - .get('/api/v1/version') - .basicAuth({ user: key }) - .reply(200, [{ version }]) - .post('/api/v1/version') - .basicAuth({ user: key }) - .reply(200, { from: '1.0.1', version: '1.0.1' }) - .get('/api/v1/api-specification') - .basicAuth({ user: key }) - .reply(200, []) - .post('/api/v1/api-specification', body => body.match('form-data; name="spec"')) - .delayConnection(1000) - .basicAuth({ user: key }) - .reply(201, { _id: 1 }, { location: exampleRefLocation }); - - // Surface our test fixture to the root directory so rdme can autodiscover it. It's easier to do - // this than mocking out the fs module because mocking the fs module here causes Jest sourcemaps - // to break. - fs.copyFileSync('./__tests__/__fixtures__/swagger.json', './swagger.json'); - - return openapi.run({ key }).then(() => { - expect(console.log).toHaveBeenCalledTimes(2); - - const output = getCommandOutput(); - expect(output).toMatch(/we found swagger.json/i); - expect(output).toMatch(/successfully uploaded/); - expect(output).toMatch(exampleRefLocation); - expect(output).toMatch(/to update your openapi or swagger file/i); - - fs.unlinkSync('./swagger.json'); - return mock.done(); - }); - }); - - it('should error if API errors', () => { - const mock = nock(config.host) - .get(`/api/v1/version/${version}`) - .basicAuth({ user: key }) - .reply(200, { version: '1.0.0' }) - .get('/api/v1/api-specification') - .basicAuth({ user: key }) - .reply(200, []) - .post('/api/v1/api-specification', body => body.match('form-data; name="spec"')) - .delayConnection(1000) - .basicAuth({ user: key }) - .reply(400, { - error: 'SPEC_VERSION_NOTFOUND', - message: - "The version you specified ({version}) doesn't match any of the existing versions ({versions_list}) in ReadMe.", - suggestion: '...a suggestion to resolve the issue...', - help: 'If you need help, email support@readme.io and mention log "fake-metrics-uuid".', - }); - - return openapi.run({ spec: './__tests__/__fixtures__/swagger.json', key, version }).then(() => { - expect(console.log).toHaveBeenCalledTimes(1); - - const output = getCommandOutput(); - expect(output).toMatch(/The version you specified/); - - mock.done(); - }); - }); - - it('should POST to the swagger api if no id provided', () => { - const mock = nock(config.host) - .get('/api/v1/api-specification') - .basicAuth({ user: key }) - .reply(200, []) - .get(`/api/v1/version/${version}`) - .basicAuth({ user: key }) - .reply(200, { version: '1.0.0' }) - .post('/api/v1/api-specification', body => body.match('form-data; name="spec"')) - .basicAuth({ user: key }) - .reply(201, { _id: 1 }, { location: exampleRefLocation }); - - return openapi.run({ spec: './__tests__/__fixtures__/swagger.json', key, version }).then(() => { - expect(console.log).toHaveBeenCalledTimes(1); - - const output = getCommandOutput(); - expect(output).not.toMatch(/we found swagger.json/i); - expect(output).toMatch(/successfully uploaded/); - expect(output).toMatch(exampleRefLocation); - expect(output).toMatch(/to update your openapi or swagger file/i); - - mock.done(); + describe('upload', () => { + it.each([ + ['Swagger 2.0', 'json', '2.0'], + ['Swagger 2.0', 'yaml', '2.0'], + ['OpenAPI 3.0', 'json', '3.0'], + ['OpenAPI 3.0', 'yaml', '3.0'], + ['OpenAPI 3.1', 'json', '3.1'], + ['OpenAPI 3.1', 'yaml', '3.1'], + ])('should support uploading a %s definition (format: %s)', (_, format, specVersion) => { + const mock = nock(config.host) + .get('/api/v1/api-specification') + .basicAuth({ user: key }) + .reply(200, []) + .get(`/api/v1/version/${version}`) + .basicAuth({ user: key }) + .reply(200, { version: '1.0.0' }) + .post('/api/v1/api-specification', body => body.match('form-data; name="spec"')) + .basicAuth({ user: key }) + .reply(201, { _id: 1 }, { location: exampleRefLocation }); + + return openapi + .run({ + spec: require.resolve(`@readme/oas-examples/${specVersion}/${format}/petstore.${format}`), + key, + version, + }) + .then(() => { + expect(console.log).toHaveBeenCalledTimes(1); + + const output = getCommandOutput(); + expect(output).not.toMatch(/we found swagger.json/i); + expect(output).toMatch(/successfully uploaded/); + expect(output).toMatch(exampleRefLocation); + expect(output).toMatch(/to update your openapi or swagger definition/i); + + mock.done(); + }); }); - }); - it('should properly bubble up validation error if invalid swagger is uploaded', () => { - const mock = nock(config.host) - .get(`/api/v1/version/${version}`) - .basicAuth({ user: key }) - .reply(200, { version: '1.0.0' }) - .get('/api/v1/api-specification') - .basicAuth({ user: key }) - .reply(200, []) - .post('/api/v1/api-specification', body => body.match('form-data; name="spec"')) - .delayConnection(1000) - .basicAuth({ user: key }) - .reply(500, { - error: 'INTERNAL_ERROR', - message: 'Unknown error (README VALIDATION ERROR "x-samples-languages" must be of type "Array")', - suggestion: '...a suggestion to resolve the issue...', - help: 'If you need help, email support@readme.io and mention log "fake-metrics-uuid".', + it('should discover and upload an API definition if none is provided', () => { + promptHandler.createOasPrompt.mockResolvedValue({ option: 'create' }); + + const mock = nock(config.host) + .get('/api/v1/version') + .basicAuth({ user: key }) + .reply(200, [{ version }]) + .post('/api/v1/version') + .basicAuth({ user: key }) + .reply(200, { from: '1.0.1', version: '1.0.1' }) + .get('/api/v1/api-specification') + .basicAuth({ user: key }) + .reply(200, []) + .post('/api/v1/api-specification', body => body.match('form-data; name="spec"')) + .delayConnection(1000) + .basicAuth({ user: key }) + .reply(201, { _id: 1 }, { location: exampleRefLocation }); + + // Surface our test fixture to the root directory so rdme can autodiscover it. It's easier to do + // this than mocking out the fs module because mocking the fs module here causes Jest sourcemaps + // to break. + fs.copyFileSync(require.resolve('@readme/oas-examples/2.0/json/petstore.json'), './swagger.json'); + + return openapi.run({ key }).then(() => { + expect(console.log).toHaveBeenCalledTimes(2); + + const output = getCommandOutput(); + expect(output).toMatch(/we found swagger.json/i); + expect(output).toMatch(/successfully uploaded/); + expect(output).toMatch(exampleRefLocation); + expect(output).toMatch(/to update your openapi or swagger definition/i); + + fs.unlinkSync('./swagger.json'); + return mock.done(); }); - - return openapi.run({ spec: './__tests__/__fixtures__/invalid-swagger.json', key, version }).then(() => { - expect(console.log).toHaveBeenCalledTimes(1); - - const output = getCommandOutput(); - expect(output).toMatch(/Unknown error \(README VALIDATION ERROR "x-samples-languages" /); - - mock.done(); }); }); - it.todo('should return a 404 if version flag not found'); - - it('should request a version list if version is not found', () => { - promptHandler.generatePrompts.mockResolvedValue({ - option: 'create', - newVersion: '1.0.1', + describe('updates / resyncs', () => { + it.each([ + ['Swagger 2.0', 'json', '2.0'], + ['Swagger 2.0', 'yaml', '2.0'], + ['OpenAPI 3.0', 'json', '3.0'], + ['OpenAPI 3.0', 'yaml', '3.0'], + ['OpenAPI 3.1', 'json', '3.1'], + ['OpenAPI 3.1', 'yaml', '3.1'], + ])('should support updating a %s definition (format: %s)', (_, format, specVersion) => { + const mock = nock(config.host) + .put(`/api/v1/api-specification/${id}`, body => body.match('form-data; name="spec"')) + .basicAuth({ user: key }) + .reply(201, { body: '{ id: 1 }' }); + + return openapi + .run({ + spec: require.resolve(`@readme/oas-examples/${specVersion}/${format}/petstore.${format}`), + key, + id, + version, + }) + .then(() => { + mock.done(); + }); }); - const mock = nock(config.host) - .get('/api/v1/version') - .basicAuth({ user: key }) - .reply(200, [{ version: '1.0.1' }]) - .post('/api/v1/version') - .basicAuth({ user: key }) - .reply(200, { from: '1.0.1', version: '1.0.1' }) - .get('/api/v1/api-specification') - .basicAuth({ user: key }) - .reply(200, []) - .post('/api/v1/api-specification', body => body.match('form-data; name="spec"')) - .basicAuth({ user: key }) - .reply(201, { _id: 1 }, { location: exampleRefLocation }); + it('should still support `token`', () => { + const mock = nock(config.host) + .put(`/api/v1/api-specification/${id}`, body => body.match('form-data; name="spec"')) + .basicAuth({ user: key }) + .reply(201, { id: 1 }, { location: exampleRefLocation }); - return openapi.run({ spec: './__tests__/__fixtures__/swagger.json', key }).then(() => { - mock.done(); - }); - }); + return openapi + .run({ spec: require.resolve('@readme/oas-examples/3.1/json/petstore.json'), token: `${key}-${id}`, version }) + .then(() => { + expect(console.warn).toHaveBeenCalledTimes(1); + expect(console.log).toHaveBeenCalledTimes(1); - it('should PUT to the swagger api if id is provided', () => { - const id = '5aa0409b7cf527a93bfb44df'; + const output = getCommandOutput(); - const mock = nock(config.host) - .put(`/api/v1/api-specification/${id}`, body => body.match('form-data; name="spec"')) - .basicAuth({ user: key }) - .reply(201, { body: '{ id: 1 }' }); + expect(output).toMatch(/using `rdme` with --token has been deprecated/i); - return openapi.run({ spec: './__tests__/__fixtures__/swagger.json', key, id, version }).then(() => { - mock.done(); + mock.done(); + }); }); }); - it('should still work with `token`', () => { - const id = '5aa0409b7cf527a93bfb44df'; + describe('versioning', () => { + it.todo('should return a 404 if version flag not found'); - const mock = nock(config.host) - .put(`/api/v1/api-specification/${id}`, body => body.match('form-data; name="spec"')) - .basicAuth({ user: key }) - .reply(201, { id: 1 }, { location: exampleRefLocation }); - - return openapi.run({ spec: './__tests__/__fixtures__/swagger.json', token: `${key}-${id}`, version }).then(() => { - expect(console.warn).toHaveBeenCalledTimes(1); - expect(console.log).toHaveBeenCalledTimes(1); - - const output = getCommandOutput(); - - expect(output).toMatch(/using `rdme` with --token/i); + it('should request a version list if version is not found', () => { + promptHandler.generatePrompts.mockResolvedValue({ + option: 'create', + newVersion: '1.0.1', + }); - mock.done(); + const mock = nock(config.host) + .get('/api/v1/version') + .basicAuth({ user: key }) + .reply(200, [{ version: '1.0.1' }]) + .post('/api/v1/version') + .basicAuth({ user: key }) + .reply(200, { from: '1.0.1', version: '1.0.1' }) + .get('/api/v1/api-specification') + .basicAuth({ user: key }) + .reply(200, []) + .post('/api/v1/api-specification', body => body.match('form-data; name="spec"')) + .basicAuth({ user: key }) + .reply(201, { _id: 1 }, { location: exampleRefLocation }); + + return openapi.run({ spec: require.resolve('@readme/oas-examples/2.0/json/petstore.json'), key }).then(() => { + const output = getCommandOutput(); + expect(output).toMatch(/successfully uploaded/); + expect(output).toMatch(exampleRefLocation); + expect(output).toMatch(/to update your openapi or swagger definition/i); + + mock.done(); + }); }); }); @@ -236,45 +216,108 @@ describe('rdme openapi', () => { const output = getCommandOutput(); expect(output).toMatch(/successfully uploaded/); expect(output).toMatch(exampleRefLocation); - expect(output).toMatch(/to update your openapi or swagger file/i); + expect(output).toMatch(/to update your openapi or swagger definition/i); mock.done(); }); }); - it('should error if no api key provided', async () => { - await expect(openapi.run({ spec: './__tests__/__fixtures__/swagger.json' })).rejects.toThrow( - 'No project API key provided. Please use `--key`.' - ); - }); + describe('error handling', () => { + it('should error if no api key provided', async () => { + await expect( + openapi.run({ spec: require.resolve('@readme/oas-examples/3.0/json/petstore.json') }) + ).rejects.toThrow('No project API key provided. Please use `--key`.'); + }); - it('should error if no file was provided or able to be discovered', async () => { - const mock = nock(config.host) - .get(`/api/v1/version/${version}`) - .basicAuth({ user: key }) - .reply(200, { version: '1.0.0' }); + it('should error if no file was provided or able to be discovered', async () => { + const mock = nock(config.host) + .get(`/api/v1/version/${version}`) + .basicAuth({ user: key }) + .reply(200, { version: '1.0.0' }); - await expect(openapi.run({ key, version })).rejects.toThrow(/We couldn't find an OpenAPI or Swagger file./); + await expect(openapi.run({ key, version })).rejects.toThrow(/We couldn't find an OpenAPI or Swagger definition./); - mock.done(); - }); + mock.done(); + }); - it('should throw an error if file is invalid', async () => { - const id = '5aa0409b7cf527a93bfb44df'; + it('should throw an error if an invalid OpenAPI 3.0 definition is supplied', async () => { + await expect( + openapi.run({ spec: './__tests__/__fixtures__/invalid-oas.json', key, id, version }) + ).rejects.toThrow('Token "Error" does not exist.'); + }); - await expect(openapi.run({ spec: './__tests__/__fixtures__/invalid-oas.json', key, id, version })).rejects.toThrow( - 'Token "Error" does not exist.' - ); + it('should throw an error if an invalid OpenAPI 3.1 definition is supplied', async () => { + await expect( + openapi.run({ spec: './__tests__/__fixtures__/invalid-oas-3.1.json', key, id, version }) + ).rejects.toMatchSnapshot(); + }); + + it('should throw an error if an in valid Swagger definition is supplied', () => { + const mock = nock(config.host) + .get(`/api/v1/version/${version}`) + .basicAuth({ user: key }) + .reply(200, { version: '1.0.0' }) + .get('/api/v1/api-specification') + .basicAuth({ user: key }) + .reply(200, []) + .post('/api/v1/api-specification', body => body.match('form-data; name="spec"')) + .delayConnection(1000) + .basicAuth({ user: key }) + .reply(500, { + error: 'INTERNAL_ERROR', + message: 'Unknown error (README VALIDATION ERROR "x-samples-languages" must be of type "Array")', + suggestion: '...a suggestion to resolve the issue...', + help: 'If you need help, email support@readme.io and mention log "fake-metrics-uuid".', + }); + + return openapi.run({ spec: './__tests__/__fixtures__/invalid-swagger.json', key, version }).then(() => { + expect(console.log).toHaveBeenCalledTimes(1); + + const output = getCommandOutput(); + expect(output).toMatch(/Unknown error \(README VALIDATION ERROR "x-samples-languages" /); + + mock.done(); + }); + }); + + it('should error if API errors', () => { + const mock = nock(config.host) + .get(`/api/v1/version/${version}`) + .basicAuth({ user: key }) + .reply(200, { version: '1.0.0' }) + .get('/api/v1/api-specification') + .basicAuth({ user: key }) + .reply(200, []) + .post('/api/v1/api-specification', body => body.match('form-data; name="spec"')) + .delayConnection(1000) + .basicAuth({ user: key }) + .reply(400, { + error: 'SPEC_VERSION_NOTFOUND', + message: + "The version you specified ({version}) doesn't match any of the existing versions ({versions_list}) in ReadMe.", + suggestion: '...a suggestion to resolve the issue...', + help: 'If you need help, email support@readme.io and mention log "fake-metrics-uuid".', + }); + + return openapi + .run({ spec: require.resolve('@readme/oas-examples/2.0/json/petstore.json'), key, version }) + .then(() => { + expect(console.log).toHaveBeenCalledTimes(1); + + const output = getCommandOutput(); + expect(output).toMatch(/The version you specified/); + + mock.done(); + }); + }); }); }); describe('rdme swagger', () => { it('should run `rdme openapi`', async () => { - const id = '5aa0409b7cf527a93bfb44df'; - await expect(swagger.run({ spec: '', key, id, version })).rejects.toThrow( - "We couldn't find an OpenAPI or Swagger file.\n\n" + - 'Run `rdme openapi ./path/to/file` to upload an existing file or `rdme oas init` to create a fresh one!' + "We couldn't find an OpenAPI or Swagger definition.\n\n" + + 'Run `rdme openapi ./path/to/api/definition` to upload an existing definition or `rdme oas init` to create a fresh one!' ); }); }); diff --git a/package-lock.json b/package-lock.json index 6cce041b9..380b53be1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,8 +21,8 @@ "gray-matter": "^4.0.1", "isemail": "^3.1.3", "node-fetch": "^2.6.1", - "oas": "^14.6.1", - "oas-normalize": "^4.0.0", + "oas": "^17.2.0", + "oas-normalize": "^5.0.3", "open": "^8.2.1", "parse-link-header": "^1.0.1", "read": "^1.0.7", @@ -35,6 +35,7 @@ }, "devDependencies": { "@readme/eslint-config": "^8.0.2", + "@readme/oas-examples": "^4.3.2", "eslint": "^8.3.0", "jest": "^27.2.0", "nock": "^13.1.1", @@ -84,29 +85,12 @@ "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==" }, - "node_modules/@apidevtools/swagger-parser": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz", - "integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==", - "dependencies": { - "@apidevtools/json-schema-ref-parser": "^9.0.6", - "@apidevtools/openapi-schemas": "^2.0.4", - "@apidevtools/swagger-methods": "^3.0.2", - "@jsdevtools/ono": "^7.1.3", - "call-me-maybe": "^1.0.1", - "z-schema": "^5.0.1" - }, - "peerDependencies": { - "openapi-types": ">=7" - } - }, "node_modules/@babel/code-frame": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", - "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", - "dev": true, + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.0.tgz", + "integrity": "sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA==", "dependencies": { - "@babel/highlight": "^7.14.5" + "@babel/highlight": "^7.16.0" }, "engines": { "node": ">=6.9.0" @@ -397,10 +381,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", - "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", - "dev": true, + "version": "7.15.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", + "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==", "engines": { "node": ">=6.9.0" } @@ -429,12 +412,11 @@ } }, "node_modules/@babel/highlight": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", - "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", - "dev": true, + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.0.tgz", + "integrity": "sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g==", "dependencies": { - "@babel/helper-validator-identifier": "^7.14.5", + "@babel/helper-validator-identifier": "^7.15.7", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -682,7 +664,6 @@ "version": "7.16.3", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.3.tgz", "integrity": "sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ==", - "dev": true, "dependencies": { "regenerator-runtime": "^0.13.4" }, @@ -1427,6 +1408,84 @@ "node": ">= 8" } }, + "node_modules/@readme/better-ajv-errors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@readme/better-ajv-errors/-/better-ajv-errors-1.1.1.tgz", + "integrity": "sha512-3FmPBv2fYj2Qgvg8Qq3wEL7CxLPA6nwkVGafdEfS/85DIUx9z0iZcHu48no/l0HOk9PCKUDqpinN6bTtLxD0og==", + "dependencies": { + "@babel/code-frame": "^7.16.0", + "@babel/runtime": "^7.16.0", + "chalk": "^4.1.2", + "json-to-ast": "^2.0.3", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0" + }, + "engines": { + "node": "^12 || ^14 || ^16" + }, + "peerDependencies": { + "ajv": "4.11.8 - 8" + } + }, + "node_modules/@readme/better-ajv-errors/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@readme/better-ajv-errors/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@readme/better-ajv-errors/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@readme/better-ajv-errors/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@readme/better-ajv-errors/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@readme/eslint-config": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@readme/eslint-config/-/eslint-config-8.0.2.tgz", @@ -1461,6 +1520,90 @@ "prettier": "^2.0.2" } }, + "node_modules/@readme/oas-examples": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@readme/oas-examples/-/oas-examples-4.3.2.tgz", + "integrity": "sha512-zEK4w0BtSc5f4To7LyFOyGdv/El2oOy/xbU3KW3kzmbH3P4ZFYAHpMrXViZYsKjUZJ5w8VGNJeVfTXVs89eZkA==", + "dev": true + }, + "node_modules/@readme/openapi-parser": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@readme/openapi-parser/-/openapi-parser-1.1.0.tgz", + "integrity": "sha512-gGoZk7yZ1MIFaFYgqm6HVaXgeIs4hCvVLys801llZF9CcXXE4DWBrpUk1VgU94cA08th6GWBLcMHiREr65Cw1A==", + "dependencies": { + "@apidevtools/json-schema-ref-parser": "github:erunion/json-schema-ref-parser#fix/dates-as-strings", + "@apidevtools/openapi-schemas": "^2.1.0", + "@apidevtools/swagger-methods": "^3.0.2", + "@jsdevtools/ono": "^7.1.3", + "@readme/better-ajv-errors": "^1.1.0", + "ajv": "^8.6.3", + "ajv-draft-04": "^1.0.0", + "call-me-maybe": "^1.0.1" + }, + "peerDependencies": { + "openapi-types": ">=7" + } + }, + "node_modules/@readme/openapi-parser/node_modules/@apidevtools/json-schema-ref-parser": { + "version": "0.0.0-dev", + "resolved": "git+ssh://git@github.com/erunion/json-schema-ref-parser.git#402904c92c8465db788be70655c3773c6e42a051", + "license": "MIT", + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.6", + "call-me-maybe": "^1.0.1", + "js-yaml": "^4.1.0" + } + }, + "node_modules/@readme/openapi-parser/node_modules/ajv": { + "version": "8.6.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.3.tgz", + "integrity": "sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@readme/openapi-parser/node_modules/ajv-draft-04": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", + "peerDependencies": { + "ajv": "^8.5.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/@readme/openapi-parser/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/@readme/openapi-parser/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@readme/openapi-parser/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, "node_modules/@sinonjs/commons": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", @@ -1868,7 +2011,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -2030,15 +2172,15 @@ } }, "node_modules/array.prototype.map": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.3.tgz", - "integrity": "sha512-nNcb30v0wfDyIe26Yif3PcV1JXQp4zEeEfupG7L4SRjnD6HLbO5b2a7eVSba53bOx4YCHYMBHt+Fp4vYstneRA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.4.tgz", + "integrity": "sha512-Qds9QnX7A0qISY7JT5WuJO0NJPE9CMlC6JzHQfhpqAAQQzufVRoeH7EzUY5GcPTx72voG8LV/5eo+b8Qi8hmhA==", "dependencies": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", + "es-abstract": "^1.19.0", "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.5" + "is-string": "^1.0.7" }, "engines": { "node": ">= 0.4" @@ -2549,6 +2691,14 @@ "node": ">= 0.12.0" } }, + "node_modules/code-error-fragment": { + "version": "0.0.230", + "resolved": "https://registry.npmjs.org/code-error-fragment/-/code-error-fragment-0.0.230.tgz", + "integrity": "sha512-cadkfKp6932H8UkhzE/gcUqhRMNf8jHzkAN7+5Myabswaghu4xABTgPHDCjW+dBAJxj/SpkTYokpzDqY4pCzQw==", + "engines": { + "node": ">= 4" + } + }, "node_modules/collect-v8-coverage": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", @@ -3122,16 +3272,16 @@ } }, "node_modules/es-aggregate-error": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/es-aggregate-error/-/es-aggregate-error-1.0.5.tgz", - "integrity": "sha512-lCJhahEBlzD0WnPEpFCWqjxm4DI4fzuq1PVxLfsGdHImCWSUhASlv+lrBX4Wc47g62SAO4+axBUfUMgJYIhilg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/es-aggregate-error/-/es-aggregate-error-1.0.7.tgz", + "integrity": "sha512-Zob/KUAOQUTvCzqgL2FEgtqNLPX5rYW3VhlldZ6La4W2mJUv3J8DmD0/sPxuD+kSAKF6nuceJ3uOSvCaaTLUyQ==", "dependencies": { "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", + "es-abstract": "^1.19.0", "function-bind": "^1.1.1", - "functions-have-names": "^1.2.1", - "get-intrinsic": "^1.0.1", - "globalthis": "^1.0.1" + "functions-have-names": "^1.2.2", + "get-intrinsic": "^1.1.1", + "globalthis": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -3163,11 +3313,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-get-iterator/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" - }, "node_modules/es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", @@ -4254,8 +4399,7 @@ "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-diff": { "version": "1.2.0", @@ -4282,8 +4426,7 @@ "node_modules/fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, "node_modules/fast-levenshtein": { "version": "2.0.6", @@ -4586,6 +4729,11 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==" + }, "node_modules/gray-matter": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", @@ -4929,11 +5077,12 @@ } }, "node_modules/is-arguments": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", - "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", "dependencies": { - "call-bind": "^1.0.0" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -5239,6 +5388,11 @@ "node": ">=8" } }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, "node_modules/isemail": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz", @@ -5331,9 +5485,12 @@ } }, "node_modules/iterate-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.1.tgz", - "integrity": "sha512-3Q6tudGN05kbkDQDI4CqjaBf4qf85w6W6GnuZDtUVYwKgtC1q8yxYX7CZed7N+tLzQqS6roujWvszf13T+n9aw==" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.2.tgz", + "integrity": "sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/iterate-value": { "version": "1.0.2", @@ -6798,8 +6955,7 @@ "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/js-yaml": { "version": "3.13.1", @@ -6915,8 +7071,7 @@ "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -6930,6 +7085,18 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, + "node_modules/json-to-ast": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/json-to-ast/-/json-to-ast-2.1.0.tgz", + "integrity": "sha512-W9Lq347r8tA1DfMvAGn9QNcgYm4Wm7Yc+k8e6vezpMnRT+NHbtlxgNBXRVjXe9YM6eTn6+p/MKOlV/aABJcSnQ==", + "dependencies": { + "code-error-fragment": "0.0.230", + "grapheme-splitter": "^1.0.4" + }, + "engines": { + "node": ">= 4" + } + }, "node_modules/json2yaml": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/json2yaml/-/json2yaml-1.1.0.tgz", @@ -6962,9 +7129,9 @@ } }, "node_modules/jsonpointer": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.1.0.tgz", - "integrity": "sha512-CXcRvMyTlnR53xMcKnuMzfCA5i/nfblTnnr74CZb6C4vG39eu6w51t7nKmU5MfLfbTgGItliNyjO/ciNPDqClg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.0.tgz", + "integrity": "sha512-PNYZIdMjVIvVgDSYKTT63Y+KZ6IZvGRNNWcxwD+GNnUz1MKPfv30J8ueCjdwcN0nDx2SlshgyB7Oy0epAzVRRg==", "engines": { "node": ">=0.10.0" } @@ -7024,7 +7191,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, "engines": { "node": ">=6" } @@ -7085,21 +7251,6 @@ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" - }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" - }, - "node_modules/lodash.kebabcase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", - "integrity": "sha1-hImxyw0p/4gZXM7KRI/21swpXDY=" - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -7461,24 +7612,24 @@ "dev": true }, "node_modules/oas": { - "version": "14.6.1", - "resolved": "https://registry.npmjs.org/oas/-/oas-14.6.1.tgz", - "integrity": "sha512-PDO6+i1GOaTyi0SqqvO/OsVMExRE0ftNIr7t00H0drgOvHG0D+nItwC74cttRLZT980Dlg7KktKA/70RfSivMg==", + "version": "17.2.0", + "resolved": "https://registry.npmjs.org/oas/-/oas-17.2.0.tgz", + "integrity": "sha512-6KSd2P6/r4l9Kr3FrdklnWHqWexkmxIRByfgTVY0whFl08FbdSIH3+YMLF6Gc5NqeBnGcZguxfFQHsSPy79f5Q==", "dependencies": { "@apidevtools/json-schema-ref-parser": "^9.0.6", "cardinal": "^2.1.1", - "colors": "^1.1.2", + "chalk": "^4.1.2", "glob": "^7.1.2", "inquirer": "^8.1.2", "json-schema-merge-allof": "^0.8.1", "json2yaml": "^1.1.0", - "jsonpointer": "^4.1.0", - "lodash.kebabcase": "^4.1.1", + "jsonpointer": "^5.0.0", "memoizee": "^0.4.14", "minimist": "^1.2.0", - "oas-normalize": "^4.0.1", + "oas-normalize": "^5.0.1", + "openapi-types": "^9.3.0", "path-to-regexp": "^6.2.0", - "swagger-inline": "^4.1.5" + "swagger-inline": "^5.0.2" }, "bin": { "oas": "bin/oas" @@ -7509,11 +7660,11 @@ } }, "node_modules/oas-normalize": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/oas-normalize/-/oas-normalize-4.0.3.tgz", - "integrity": "sha512-5ub1AfbJY2zzRvHir1SwXVXCqysS7EWLvgR2pgKO4J26Q050i2qK47Imshm+W//6JCFFhbFKq5E2OCcgXCVEpQ==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/oas-normalize/-/oas-normalize-5.0.3.tgz", + "integrity": "sha512-9LTMftmjA1YI2I8L1liwkW276zUoyyRTBOBxA1Q9iOiIiHwXtU65nIe6zsNVzwCYWA1NQdEjpEnagSVN+ZHwng==", "dependencies": { - "@apidevtools/swagger-parser": "^10.0.3", + "@readme/openapi-parser": "^1.1.0", "js-yaml": "^4.1.0", "node-fetch": "^2.6.1", "swagger2openapi": "^7.0.8" @@ -7599,6 +7750,65 @@ "url": "https://github.com/Mermade/oas-kit?sponsor=1" } }, + "node_modules/oas/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/oas/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/oas/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/oas/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/oas/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -7738,10 +7948,9 @@ } }, "node_modules/openapi-types": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-9.2.0.tgz", - "integrity": "sha512-3x0gg8DxhpZ5MVki7AK6jmMdVIZASmVGo9CoUtD+nksLdkqz7EzWKdfS9Oxxq1J7idnZV0b3LjqcvizfKFySpQ==", - "peer": true + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-9.3.0.tgz", + "integrity": "sha512-sR23YjmuwDSMsQVZDHbV9mPgi0RyniQlqR0AQxTC2/F3cpSjRFMH3CFPjoWvNqhC4OxPkDYNb2l8Mc1Me6D/KQ==" }, "node_modules/optionator": { "version": "0.8.3", @@ -8240,10 +8449,9 @@ } }, "node_modules/regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", - "dev": true + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" }, "node_modules/regexp-tree": { "version": "0.1.24", @@ -8298,6 +8506,14 @@ "node": ">=0.10.0" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/requireindex": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", @@ -8832,9 +9048,9 @@ } }, "node_modules/swagger-inline": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/swagger-inline/-/swagger-inline-4.1.5.tgz", - "integrity": "sha512-17Z3PkrVo/FvJ/Sd+B6tnjbV59gvCnHtRwl4Xw7r0Kmr6DujSYMWFVo2iiXmDuIowA8jJuUMqQx66XPx4aQm9Q==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/swagger-inline/-/swagger-inline-5.0.2.tgz", + "integrity": "sha512-Vdvuv9TzlnnRzue9ydXQBCe0otxh+rXz6vsLnUXwNqFjGWn/2OATYnyVEHojmKXS1fuMkaunVNsv0a9JT08UBw==", "dependencies": { "commander": "^6.0.0", "globby": "^11.0.1", @@ -9221,7 +9437,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -9302,14 +9517,6 @@ "resolved": "https://registry.npmjs.org/validate.io-number/-/validate.io-number-1.0.3.tgz", "integrity": "sha1-9j/+2iSL8opnqNSODjtGGhZluvg=" }, - "node_modules/validator": { - "version": "13.6.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.6.0.tgz", - "integrity": "sha512-gVgKbdbHgtxpRyR8K0O6oFZPhhB5tT1jeEHZR0Znr9Svg03U0+r9DXWMrnRAB+HtCStDQKlaIZm42tVsVjqtjg==", - "engines": { - "node": ">= 0.10" - } - }, "node_modules/w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", @@ -9548,31 +9755,6 @@ "engines": { "node": ">=10" } - }, - "node_modules/z-schema": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.1.tgz", - "integrity": "sha512-Gp8xU2lULhREqTWj9t4BEAeA7M835n4fWJ9KjGWksV3wmLUdOJo2hAr+QYvkVZIGOOTyeN274g1f95dKRsgYgQ==", - "dependencies": { - "lodash.get": "^4.4.2", - "lodash.isequal": "^4.5.0", - "validator": "^13.6.0" - }, - "bin": { - "z-schema": "bin/z-schema" - }, - "engines": { - "node": ">=8.0.0" - }, - "optionalDependencies": { - "commander": "^2.7.1" - } - }, - "node_modules/z-schema/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "optional": true } }, "dependencies": { @@ -9612,26 +9794,12 @@ "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==" }, - "@apidevtools/swagger-parser": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz", - "integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==", - "requires": { - "@apidevtools/json-schema-ref-parser": "^9.0.6", - "@apidevtools/openapi-schemas": "^2.0.4", - "@apidevtools/swagger-methods": "^3.0.2", - "@jsdevtools/ono": "^7.1.3", - "call-me-maybe": "^1.0.1", - "z-schema": "^5.0.1" - } - }, "@babel/code-frame": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", - "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", - "dev": true, + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.0.tgz", + "integrity": "sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA==", "requires": { - "@babel/highlight": "^7.14.5" + "@babel/highlight": "^7.16.0" } }, "@babel/compat-data": { @@ -9850,10 +10018,9 @@ } }, "@babel/helper-validator-identifier": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", - "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", - "dev": true + "version": "7.15.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", + "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==" }, "@babel/helper-validator-option": { "version": "7.14.5", @@ -9873,12 +10040,11 @@ } }, "@babel/highlight": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", - "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", - "dev": true, + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.0.tgz", + "integrity": "sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g==", "requires": { - "@babel/helper-validator-identifier": "^7.14.5", + "@babel/helper-validator-identifier": "^7.15.7", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -10062,7 +10228,6 @@ "version": "7.16.3", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.3.tgz", "integrity": "sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ==", - "dev": true, "requires": { "regenerator-runtime": "^0.13.4" } @@ -10679,6 +10844,59 @@ "fastq": "^1.6.0" } }, + "@readme/better-ajv-errors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@readme/better-ajv-errors/-/better-ajv-errors-1.1.1.tgz", + "integrity": "sha512-3FmPBv2fYj2Qgvg8Qq3wEL7CxLPA6nwkVGafdEfS/85DIUx9z0iZcHu48no/l0HOk9PCKUDqpinN6bTtLxD0og==", + "requires": { + "@babel/code-frame": "^7.16.0", + "@babel/runtime": "^7.16.0", + "chalk": "^4.1.2", + "json-to-ast": "^2.0.3", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "@readme/eslint-config": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@readme/eslint-config/-/eslint-config-8.0.2.tgz", @@ -10705,6 +10923,74 @@ "eslint-plugin-you-dont-need-lodash-underscore": "^6.12.0" } }, + "@readme/oas-examples": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@readme/oas-examples/-/oas-examples-4.3.2.tgz", + "integrity": "sha512-zEK4w0BtSc5f4To7LyFOyGdv/El2oOy/xbU3KW3kzmbH3P4ZFYAHpMrXViZYsKjUZJ5w8VGNJeVfTXVs89eZkA==", + "dev": true + }, + "@readme/openapi-parser": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@readme/openapi-parser/-/openapi-parser-1.1.0.tgz", + "integrity": "sha512-gGoZk7yZ1MIFaFYgqm6HVaXgeIs4hCvVLys801llZF9CcXXE4DWBrpUk1VgU94cA08th6GWBLcMHiREr65Cw1A==", + "requires": { + "@apidevtools/json-schema-ref-parser": "github:erunion/json-schema-ref-parser#fix/dates-as-strings", + "@apidevtools/openapi-schemas": "^2.1.0", + "@apidevtools/swagger-methods": "^3.0.2", + "@jsdevtools/ono": "^7.1.3", + "@readme/better-ajv-errors": "^1.1.0", + "ajv": "^8.6.3", + "ajv-draft-04": "^1.0.0", + "call-me-maybe": "^1.0.1" + }, + "dependencies": { + "@apidevtools/json-schema-ref-parser": { + "version": "git+ssh://git@github.com/erunion/json-schema-ref-parser.git#402904c92c8465db788be70655c3773c6e42a051", + "from": "@apidevtools/json-schema-ref-parser@github:erunion/json-schema-ref-parser#fix/dates-as-strings", + "requires": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.6", + "call-me-maybe": "^1.0.1", + "js-yaml": "^4.1.0" + } + }, + "ajv": { + "version": "8.6.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.3.tgz", + "integrity": "sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-draft-04": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", + "requires": {} + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "requires": { + "argparse": "^2.0.1" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + } + } + }, "@sinonjs/commons": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", @@ -11014,7 +11300,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -11127,15 +11412,15 @@ } }, "array.prototype.map": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.3.tgz", - "integrity": "sha512-nNcb30v0wfDyIe26Yif3PcV1JXQp4zEeEfupG7L4SRjnD6HLbO5b2a7eVSba53bOx4YCHYMBHt+Fp4vYstneRA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.4.tgz", + "integrity": "sha512-Qds9QnX7A0qISY7JT5WuJO0NJPE9CMlC6JzHQfhpqAAQQzufVRoeH7EzUY5GcPTx72voG8LV/5eo+b8Qi8hmhA==", "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", + "es-abstract": "^1.19.0", "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.5" + "is-string": "^1.0.7" } }, "ast-types-flow": { @@ -11512,6 +11797,11 @@ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", "dev": true }, + "code-error-fragment": { + "version": "0.0.230", + "resolved": "https://registry.npmjs.org/code-error-fragment/-/code-error-fragment-0.0.230.tgz", + "integrity": "sha512-cadkfKp6932H8UkhzE/gcUqhRMNf8jHzkAN7+5Myabswaghu4xABTgPHDCjW+dBAJxj/SpkTYokpzDqY4pCzQw==" + }, "collect-v8-coverage": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", @@ -11974,16 +12264,16 @@ } }, "es-aggregate-error": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/es-aggregate-error/-/es-aggregate-error-1.0.5.tgz", - "integrity": "sha512-lCJhahEBlzD0WnPEpFCWqjxm4DI4fzuq1PVxLfsGdHImCWSUhASlv+lrBX4Wc47g62SAO4+axBUfUMgJYIhilg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/es-aggregate-error/-/es-aggregate-error-1.0.7.tgz", + "integrity": "sha512-Zob/KUAOQUTvCzqgL2FEgtqNLPX5rYW3VhlldZ6La4W2mJUv3J8DmD0/sPxuD+kSAKF6nuceJ3uOSvCaaTLUyQ==", "requires": { "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", + "es-abstract": "^1.19.0", "function-bind": "^1.1.1", - "functions-have-names": "^1.2.1", - "get-intrinsic": "^1.0.1", - "globalthis": "^1.0.1" + "functions-have-names": "^1.2.2", + "get-intrinsic": "^1.1.1", + "globalthis": "^1.0.2" } }, "es-array-method-boxes-properly": { @@ -12004,13 +12294,6 @@ "is-set": "^2.0.2", "is-string": "^1.0.5", "isarray": "^2.0.5" - }, - "dependencies": { - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" - } } }, "es-to-primitive": { @@ -12823,8 +13106,7 @@ "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-diff": { "version": "1.2.0", @@ -12848,8 +13130,7 @@ "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, "fast-levenshtein": { "version": "2.0.6", @@ -13070,6 +13351,11 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" }, + "grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==" + }, "gray-matter": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", @@ -13314,11 +13600,12 @@ } }, "is-arguments": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", - "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", "requires": { - "call-bind": "^1.0.0" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" } }, "is-arrayish": { @@ -13510,6 +13797,11 @@ "is-docker": "^2.0.0" } }, + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, "isemail": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz", @@ -13583,9 +13875,9 @@ } }, "iterate-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.1.tgz", - "integrity": "sha512-3Q6tudGN05kbkDQDI4CqjaBf4qf85w6W6GnuZDtUVYwKgtC1q8yxYX7CZed7N+tLzQqS6roujWvszf13T+n9aw==" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.2.tgz", + "integrity": "sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw==" }, "iterate-value": { "version": "1.0.2", @@ -14796,8 +15088,7 @@ "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "js-yaml": { "version": "3.13.1", @@ -14889,8 +15180,7 @@ "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -14904,6 +15194,15 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, + "json-to-ast": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/json-to-ast/-/json-to-ast-2.1.0.tgz", + "integrity": "sha512-W9Lq347r8tA1DfMvAGn9QNcgYm4Wm7Yc+k8e6vezpMnRT+NHbtlxgNBXRVjXe9YM6eTn6+p/MKOlV/aABJcSnQ==", + "requires": { + "code-error-fragment": "0.0.230", + "grapheme-splitter": "^1.0.4" + } + }, "json2yaml": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/json2yaml/-/json2yaml-1.1.0.tgz", @@ -14921,9 +15220,9 @@ } }, "jsonpointer": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.1.0.tgz", - "integrity": "sha512-CXcRvMyTlnR53xMcKnuMzfCA5i/nfblTnnr74CZb6C4vG39eu6w51t7nKmU5MfLfbTgGItliNyjO/ciNPDqClg==" + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.0.tgz", + "integrity": "sha512-PNYZIdMjVIvVgDSYKTT63Y+KZ6IZvGRNNWcxwD+GNnUz1MKPfv30J8ueCjdwcN0nDx2SlshgyB7Oy0epAzVRRg==" }, "jsx-ast-utils": { "version": "3.2.1", @@ -14970,8 +15269,7 @@ "leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" }, "levn": { "version": "0.3.0", @@ -15022,21 +15320,6 @@ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" - }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" - }, - "lodash.kebabcase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", - "integrity": "sha1-hImxyw0p/4gZXM7KRI/21swpXDY=" - }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -15341,24 +15624,64 @@ "dev": true }, "oas": { - "version": "14.6.1", - "resolved": "https://registry.npmjs.org/oas/-/oas-14.6.1.tgz", - "integrity": "sha512-PDO6+i1GOaTyi0SqqvO/OsVMExRE0ftNIr7t00H0drgOvHG0D+nItwC74cttRLZT980Dlg7KktKA/70RfSivMg==", + "version": "17.2.0", + "resolved": "https://registry.npmjs.org/oas/-/oas-17.2.0.tgz", + "integrity": "sha512-6KSd2P6/r4l9Kr3FrdklnWHqWexkmxIRByfgTVY0whFl08FbdSIH3+YMLF6Gc5NqeBnGcZguxfFQHsSPy79f5Q==", "requires": { "@apidevtools/json-schema-ref-parser": "^9.0.6", "cardinal": "^2.1.1", - "colors": "^1.1.2", + "chalk": "^4.1.2", "glob": "^7.1.2", "inquirer": "^8.1.2", "json-schema-merge-allof": "^0.8.1", "json2yaml": "^1.1.0", - "jsonpointer": "^4.1.0", - "lodash.kebabcase": "^4.1.1", + "jsonpointer": "^5.0.0", "memoizee": "^0.4.14", "minimist": "^1.2.0", - "oas-normalize": "^4.0.1", + "oas-normalize": "^5.0.1", + "openapi-types": "^9.3.0", "path-to-regexp": "^6.2.0", - "swagger-inline": "^4.1.5" + "swagger-inline": "^5.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } } }, "oas-kit-common": { @@ -15380,11 +15703,11 @@ } }, "oas-normalize": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/oas-normalize/-/oas-normalize-4.0.3.tgz", - "integrity": "sha512-5ub1AfbJY2zzRvHir1SwXVXCqysS7EWLvgR2pgKO4J26Q050i2qK47Imshm+W//6JCFFhbFKq5E2OCcgXCVEpQ==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/oas-normalize/-/oas-normalize-5.0.3.tgz", + "integrity": "sha512-9LTMftmjA1YI2I8L1liwkW276zUoyyRTBOBxA1Q9iOiIiHwXtU65nIe6zsNVzwCYWA1NQdEjpEnagSVN+ZHwng==", "requires": { - "@apidevtools/swagger-parser": "^10.0.3", + "@readme/openapi-parser": "^1.1.0", "js-yaml": "^4.1.0", "node-fetch": "^2.6.1", "swagger2openapi": "^7.0.8" @@ -15550,10 +15873,9 @@ } }, "openapi-types": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-9.2.0.tgz", - "integrity": "sha512-3x0gg8DxhpZ5MVki7AK6jmMdVIZASmVGo9CoUtD+nksLdkqz7EzWKdfS9Oxxq1J7idnZV0b3LjqcvizfKFySpQ==", - "peer": true + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-9.3.0.tgz", + "integrity": "sha512-sR23YjmuwDSMsQVZDHbV9mPgi0RyniQlqR0AQxTC2/F3cpSjRFMH3CFPjoWvNqhC4OxPkDYNb2l8Mc1Me6D/KQ==" }, "optionator": { "version": "0.8.3", @@ -15929,10 +16251,9 @@ "integrity": "sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w==" }, "regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", - "dev": true + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" }, "regexp-tree": { "version": "0.1.24", @@ -15966,6 +16287,11 @@ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + }, "requireindex": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", @@ -16401,9 +16727,9 @@ } }, "swagger-inline": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/swagger-inline/-/swagger-inline-4.1.5.tgz", - "integrity": "sha512-17Z3PkrVo/FvJ/Sd+B6tnjbV59gvCnHtRwl4Xw7r0Kmr6DujSYMWFVo2iiXmDuIowA8jJuUMqQx66XPx4aQm9Q==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/swagger-inline/-/swagger-inline-5.0.2.tgz", + "integrity": "sha512-Vdvuv9TzlnnRzue9ydXQBCe0otxh+rXz6vsLnUXwNqFjGWn/2OATYnyVEHojmKXS1fuMkaunVNsv0a9JT08UBw==", "requires": { "commander": "^6.0.0", "globby": "^11.0.1", @@ -16710,7 +17036,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "requires": { "punycode": "^2.1.0" } @@ -16787,11 +17112,6 @@ "resolved": "https://registry.npmjs.org/validate.io-number/-/validate.io-number-1.0.3.tgz", "integrity": "sha1-9j/+2iSL8opnqNSODjtGGhZluvg=" }, - "validator": { - "version": "13.6.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.6.0.tgz", - "integrity": "sha512-gVgKbdbHgtxpRyR8K0O6oFZPhhB5tT1jeEHZR0Znr9Svg03U0+r9DXWMrnRAB+HtCStDQKlaIZm42tVsVjqtjg==" - }, "w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", @@ -16974,25 +17294,6 @@ "version": "20.2.7", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.7.tgz", "integrity": "sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==" - }, - "z-schema": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.1.tgz", - "integrity": "sha512-Gp8xU2lULhREqTWj9t4BEAeA7M835n4fWJ9KjGWksV3wmLUdOJo2hAr+QYvkVZIGOOTyeN274g1f95dKRsgYgQ==", - "requires": { - "commander": "^2.7.1", - "lodash.get": "^4.4.2", - "lodash.isequal": "^4.5.0", - "validator": "^13.6.0" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "optional": true - } - } } } } diff --git a/package.json b/package.json index 2e995f598..09541b2fa 100644 --- a/package.json +++ b/package.json @@ -45,8 +45,8 @@ "gray-matter": "^4.0.1", "isemail": "^3.1.3", "node-fetch": "^2.6.1", - "oas": "^14.6.1", - "oas-normalize": "^4.0.0", + "oas": "^17.2.0", + "oas-normalize": "^5.0.3", "open": "^8.2.1", "parse-link-header": "^1.0.1", "read": "^1.0.7", @@ -56,6 +56,7 @@ }, "devDependencies": { "@readme/eslint-config": "^8.0.2", + "@readme/oas-examples": "^4.3.2", "eslint": "^8.3.0", "jest": "^27.2.0", "nock": "^13.1.1", diff --git a/src/cmds/openapi.js b/src/cmds/openapi.js index 47bbf571f..a753a4ac4 100644 --- a/src/cmds/openapi.js +++ b/src/cmds/openapi.js @@ -14,7 +14,7 @@ const { file: tmpFile } = require('tmp-promise'); exports.command = 'openapi'; exports.usage = 'openapi [file] [options]'; -exports.description = 'Upload, or sync, your OpenAPI/Swagger file to ReadMe.'; +exports.description = 'Upload, or resync, your OpenAPI/Swagger definition to ReadMe.'; exports.category = 'apis'; exports.position = 1; @@ -28,7 +28,7 @@ exports.args = [ { name: 'id', type: String, - description: `Unique identifier for your specification. Use this if you're resyncing an existing specification`, + description: `Unique identifier for your API definition. Use this if you're resyncing an existing API definition`, }, { name: 'token', @@ -79,7 +79,7 @@ exports.run = async function (opts) { '', `\t${chalk.green(`${data.headers.get('location')}`)}`, '', - 'To update your OpenAPI or Swagger file, run the following:', + 'To update your OpenAPI or Swagger definition, run the following:', '', // eslint-disable-next-line no-underscore-dangle `\t${chalk.green(`rdme openapi FILE --key=${key} --id=${body._id}`)}`, @@ -105,8 +105,8 @@ exports.run = async function (opts) { } let bundledSpec; - const oas = new OASNormalize(specPath, { enablePaths: true }); - await oas.validate().catch(err => { + const oas = new OASNormalize(specPath, { colorizeErrors: true, enablePaths: true }); + await oas.validate(false, { validate: { colorizeErrors: true } }).catch(err => { return Promise.reject(err); }); await oas @@ -205,7 +205,7 @@ exports.run = async function (opts) { return callApi(spec, selectedVersion); } - // If the user didn't supply a specification, let's try to locate what they've got, and upload + // If the user didn't supply an API specification, let's try to locate what they've got, and upload // that. If they don't have any, let's let the user know how they can get one going. return new Promise((resolve, reject) => { ['swagger.json', 'swagger.yaml', 'openapi.json', 'openapi.yaml'].forEach(file => { @@ -219,8 +219,8 @@ exports.run = async function (opts) { reject( new Error( - "We couldn't find an OpenAPI or Swagger file.\n\n" + - 'Run `rdme openapi ./path/to/file` to upload an existing file or `rdme oas init` to create a fresh one!' + "We couldn't find an OpenAPI or Swagger definition.\n\n" + + 'Run `rdme openapi ./path/to/api/definition` to upload an existing definition or `rdme oas init` to create a fresh one!' ) ); }); diff --git a/src/cmds/swagger.js b/src/cmds/swagger.js index 9253a5a99..8fd066761 100644 --- a/src/cmds/swagger.js +++ b/src/cmds/swagger.js @@ -3,37 +3,11 @@ const openapi = require('./openapi'); exports.command = 'swagger'; exports.usage = 'swagger [file] [options]'; exports.description = 'Alias for `rdme openapi` [deprecated].'; -exports.category = 'apis'; -exports.position = 2; +exports.category = openapi.category; +exports.position = openapi.position + 1; -exports.hiddenArgs = ['token', 'spec']; -exports.args = [ - { - name: 'key', - type: String, - description: 'Project API key', - }, - { - name: 'id', - type: String, - description: `Unique identifier for your specification. Use this if you're resyncing an existing specification`, - }, - { - name: 'token', - type: String, - description: 'Project token. Deprecated, please use `--key` instead', - }, - { - name: 'version', - type: String, - description: 'Project version', - }, - { - name: 'spec', - type: String, - defaultOption: true, - }, -]; +exports.hiddenArgs = openapi.hiddenArgs; +exports.args = openapi.args; exports.run = async function (opts) { console.warn('`rdme swagger` has been deprecated. Please use `rdme openapi` instead.');