From d60613131ac3819aa5795134537be0d898e1eafc Mon Sep 17 00:00:00 2001 From: Mike Elsmore Date: Tue, 20 Jul 2021 12:09:46 +0100 Subject: [PATCH 1/3] Add the Optic middleware to capture the API endpoints --- package.json | 1 + src/config/express.js | 4 +++ yarn.lock | 63 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 7cffcf27..a3d8ba16 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ "starter project" ], "dependencies": { + "@useoptic/express-middleware": "^0.0.5", "axios": "^0.21.1", "bcryptjs": "2.4.3", "bluebird": "^3.5.0", diff --git a/src/config/express.js b/src/config/express.js index a5ab6c7e..4a2426a5 100644 --- a/src/config/express.js +++ b/src/config/express.js @@ -6,6 +6,7 @@ const methodOverride = require('method-override'); const cors = require('cors'); const helmet = require('helmet'); const passport = require('passport'); +const { OpticMiddleware } = require('@useoptic/express-middleware'); const routes = require('../api/routes/v1'); const { logs } = require('./vars'); const strategies = require('./passport'); @@ -24,6 +25,9 @@ app.use(morgan(logs)); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); +// API Documentation +app.use(OpticMiddleware({ enabled: !!(process.env.NODE_ENV !== 'production') })); + // gzip compression app.use(compress()); diff --git a/yarn.lock b/yarn.lock index 60177c86..da311ad0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -198,6 +198,13 @@ enabled "2.0.x" kuler "^2.0.0" +"@elastic/ecs-helpers@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@elastic/ecs-helpers/-/ecs-helpers-1.1.0.tgz#ee7e6f870f75a2222c5d7179b36a628f1db4779e" + integrity sha512-MDLb2aFeGjg46O5mLpdCzT5yOUDnXToJSrco2ShqGIXxNJaM8uJjX+4nd+hRYV4Vex8YJyDtOFEVBldQct6ndg== + dependencies: + fast-json-stringify "^2.4.1" + "@eslint/eslintrc@^0.4.2": version "0.4.2" resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.2.tgz" @@ -418,6 +425,25 @@ version "2.4.0" resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz" +"@useoptic/express-middleware@^0.0.5": + version "0.0.5" + resolved "https://registry.yarnpkg.com/@useoptic/express-middleware/-/express-middleware-0.0.5.tgz#c1a69f4dcee4d4a8e2db2fd4fb375da5dc460a2b" + integrity sha512-p+VEDALXPEDLQHNfM++JdWWg9WauvYUahc4P8ts78G7XbxK2lAtQolQ7kSXxgwtAYAb/V+0dyemh9ovVA2YyYA== + dependencies: + "@elastic/ecs-helpers" "^1.1.0" + "@useoptic/optic-node-sdk" "^0.0.5" + debug "^4.3.1" + +"@useoptic/optic-node-sdk@^0.0.5": + version "0.0.5" + resolved "https://registry.yarnpkg.com/@useoptic/optic-node-sdk/-/optic-node-sdk-0.0.5.tgz#8d97fe52216bacd8b371c7e984d2445e1d6ce16a" + integrity sha512-V2l2lCGVD2+MCyVKc25m3ox5xeIsnqhnJjgX42akgvRmWkDt8mlnNmAyX8otCNRh36X3eR4b5Ctf3b9dx2YTig== + dependencies: + "@elastic/ecs-helpers" "^1.1.0" + debug "^4.3.1" + node-fetch "^2.6.1" + universal-user-agent "^6.0.0" + abbrev@1: version "1.1.1" resolved "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz" @@ -464,7 +490,7 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4: +ajv@^6.10.0, ajv@^6.11.0, ajv@^6.12.3, ajv@^6.12.4: version "6.12.6" resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" dependencies: @@ -1437,6 +1463,11 @@ deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.3" resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz" +deepmerge@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" + integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== + default-require-extensions@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz" @@ -1962,6 +1993,16 @@ fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz" +fast-json-stringify@^2.4.1: + version "2.7.7" + resolved "https://registry.yarnpkg.com/fast-json-stringify/-/fast-json-stringify-2.7.7.tgz#9e1c0f238f566559c3d4b99ae17a8e545381c16e" + integrity sha512-2kiwC/hBlK7QiGALsvj0QxtYwaReLOmAwOWJIxt5WHBB9EwXsqbsu8LCel47yh8NV8CEcFmnZYcXh4BionJcwQ== + dependencies: + ajv "^6.11.0" + deepmerge "^4.2.2" + rfdc "^1.2.0" + string-similarity "^4.0.1" + fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" @@ -3537,6 +3578,11 @@ node-environment-flags@1.0.5: object.getownpropertydescriptors "^2.0.3" semver "^5.7.0" +node-fetch@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + node-preload@^0.2.1: version "0.2.1" resolved "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz" @@ -4585,6 +4631,11 @@ responselike@^1.0.2: dependencies: lowercase-keys "^1.0.0" +rfdc@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" + integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== + right-align@^0.1.1: version "0.1.3" resolved "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz" @@ -4871,6 +4922,11 @@ stack-trace@0.0.x: version "1.5.0" resolved "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz" +string-similarity@^4.0.1: + version "4.0.4" + resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-4.0.4.tgz#42d01ab0b34660ea8a018da8f56a3309bb8b2a5b" + integrity sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ== + "string-width@^1.0.2 || 2": version "2.1.1" resolved "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz" @@ -5245,6 +5301,11 @@ unique-string@^2.0.0: dependencies: crypto-random-string "^2.0.0" +universal-user-agent@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" + integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== + universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" From 6abdb417095b79343b80391a691b056763893e65 Mon Sep 17 00:00:00 2001 From: Mike Elsmore Date: Tue, 20 Jul 2021 12:10:40 +0100 Subject: [PATCH 2/3] Add the Optic configuration and the vendor directory to store the API Specification within --- .optic/.gitignore | 3 +++ .optic/api/specification.json | 1 + .optic/ignore | 16 ++++++++++++++++ optic.yml | 13 +++++++++++++ 4 files changed, 33 insertions(+) create mode 100644 .optic/.gitignore create mode 100644 .optic/api/specification.json create mode 100644 .optic/ignore create mode 100644 optic.yml diff --git a/.optic/.gitignore b/.optic/.gitignore new file mode 100644 index 00000000..182f723f --- /dev/null +++ b/.optic/.gitignore @@ -0,0 +1,3 @@ + +captures/ +optic-temp-* diff --git a/.optic/api/specification.json b/.optic/api/specification.json new file mode 100644 index 00000000..0637a088 --- /dev/null +++ b/.optic/api/specification.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/.optic/ignore b/.optic/ignore new file mode 100644 index 00000000..115e4851 --- /dev/null +++ b/.optic/ignore @@ -0,0 +1,16 @@ +# Default Ignore Rules +# Learn to configure your own at http://localhost:4000/docs/using/advanced-configuration#ignoring-api-paths +OPTIONS (.*) +HEAD (.*) +GET (.*).htm +GET (.*).html +GET (.*).ico +GET (.*).css +GET (.*).js +GET (.*).woff +GET (.*).woff2 +GET (.*).png +GET (.*).jpg +GET (.*).jpeg +GET (.*).svg +GET (.*).gif \ No newline at end of file diff --git a/optic.yml b/optic.yml new file mode 100644 index 00000000..6e499407 --- /dev/null +++ b/optic.yml @@ -0,0 +1,13 @@ +name: "express-rest-es2017-boilerplate" +# Start your api with Optic by running 'api run ' +tasks: + start: + command: "yarn dev" + inboundUrl: http://localhost:4000 + +# Capture traffic from a deployed api by running 'api intercept ' +# pass '--chrome' to capture from your browser's network tab +environments: + production: + host: https://api.github.com # the hostname of the API we should record traffic from + webUI: https://api.github.com/repos/opticdev/optic # the url that should open when a browser flag is passed From 6349f29f0d1528206cc89342a4f005a701d00a49 Mon Sep 17 00:00:00 2001 From: Mike Elsmore Date: Tue, 20 Jul 2021 12:29:03 +0100 Subject: [PATCH 3/3] Add the README block explaining usage of Optic to document API Endpoints and changes to the API --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 458a4ff3..82c4fdc5 100644 --- a/README.md +++ b/README.md @@ -151,6 +151,10 @@ Run deploy script: yarn deploy ``` +## API Documentation + +To simplify documenting your API, we have included [Optic](https://useoptic.com). To use it, you will need to [install the CLI tool](https://useoptic.com/document/#add-an-optic-specification-to-your-api-project), and then you can use `api exec "npm start"` to start capturing your endpoints as you create them. Once you want to review and add them to your API specification run: `api status -- review`. + ## Tutorials - [Create API Documentation Using Squarespace](https://selfaware.blog/home/2018/6/23/api-documentation)