diff --git a/packages/techdocs-cli/.eslintrc.js b/packages/techdocs-cli/.eslintrc.js index 13573efa9c..503c048748 100644 --- a/packages/techdocs-cli/.eslintrc.js +++ b/packages/techdocs-cli/.eslintrc.js @@ -1,3 +1,6 @@ module.exports = { - extends: [require.resolve('@backstage/cli/config/eslint')], + extends: [require.resolve('@backstage/cli/config/eslint.backend')], + rules: { + 'no-console': 0, + }, }; diff --git a/packages/techdocs-cli/README.md b/packages/techdocs-cli/README.md index d7c17210bd..8d86363c12 100644 --- a/packages/techdocs-cli/README.md +++ b/packages/techdocs-cli/README.md @@ -3,3 +3,49 @@ Check out the [TechDocs README](https://github.com/spotify/backstage/blob/master/plugins/techdocs/README.md) to learn more. **WIP: This cli is a work in progress. It is not ready for use yet. Follow our progress on [the Backstage Discord](https://discord.gg/MUpMjP2) under #docs-like-code or on [our GitHub Milestone](https://github.com/spotify/backstage/milestone/15).** + +## Getting Started + +You'll need Docker installed and running to use this. You will also need to build the container located at `plugins/techdocs/mkdocs/container` under the tag `mkdocs:local-dev`, as you can see in the commands from below: + +```bash +docker build plugins/techdocs/mkdocs/container -t mkdocs:local-dev +``` + +From that point, you can invoke the CLI from any project with a docs folder. Try out our example! + +```bash +cd plugins/techdocs/mkdocs/mock-docs +npx @techdocs/cli serve +``` + +## Local Development + +You'll need Docker installed and running to use this. You will also need to build the container located at `plugins/techdocs/mkdocs/container` under the tag `mkdocs:local-dev`, as you can see in the commands from below: + +```bash +docker build plugins/techdocs/mkdocs/container -t mkdocs:local-dev +``` + +Once that is built, you'll need to manually create an `alias` for running the CLI locally: + +```bash +cd packages/techdocs-cli +echo "$(pwd)/bin/techdocs" + +# Copy the value from above and add it in [HERE] below +# For more convenience, add it to your ~/.zshrc or ~/.bash_profile +# otherwise you'll lose it when you open a new Terminal +alias techdocs="[HERE]" +``` + +From that point, you can invoke `techdocs` from any project with a docs folder. Try out our example! + +```bash +cd plugins/techdocs/mkdocs/mock-docs +techdocs serve +``` + +You should have a `localhost:3000` serving TechDocs in Backstage, as well as `localhost:8000` serving Mkdocs (which won't open up and be exposed to the user). + +Happy hacking! diff --git a/packages/techdocs-cli/bin/build b/packages/techdocs-cli/bin/build new file mode 100755 index 0000000000..c0a1cacdfc --- /dev/null +++ b/packages/techdocs-cli/bin/build @@ -0,0 +1,35 @@ +# Copyright 2020 Spotify AB +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e + +ROOT_DIR=$(git rev-parse --show-toplevel) +TECHDOCS_PREVIEW_SOURCE=$ROOT_DIR/plugins/techdocs/dist +TECHDOCS_PREVIEW_DEST=$ROOT_DIR/packages/techdocs-cli/dist/techdocs-preview-bundle + +# Build the CLI +backstage-cli build --outputs cjs + +# Create export of the TechDocs plugin +yarn workspace @backstage/plugin-techdocs export + +# Copy over export to techdocs-cli dist/ folder +cp -r $TECHDOCS_PREVIEW_SOURCE $TECHDOCS_PREVIEW_DEST + +# Clean output +yarn workspace @backstage/plugin-techdocs clean + +# Write to console +echo "[techdocs-cli]: Built the dist/ folder" +echo "[techdocs-cli]: Imported @backstage/plugin-techdocs dist/ folder into techdocs-preview-bundle/" diff --git a/packages/techdocs-cli/package.json b/packages/techdocs-cli/package.json index 9176d6012d..c8985367b0 100644 --- a/packages/techdocs-cli/package.json +++ b/packages/techdocs-cli/package.json @@ -1,8 +1,8 @@ { - "name": "@backstage/techdocs-cli", + "name": "@techdocs/cli", "description": "CLI for running TechDocs locally.", "version": "0.1.1-alpha.13", - "private": true, + "private": false, "publishConfig": { "access": "public" }, @@ -18,7 +18,7 @@ "license": "Apache-2.0", "main": "dist/index.cjs.js", "scripts": { - "build": "backstage-cli build --outputs cjs", + "build": "./bin/build", "lint": "backstage-cli lint", "test": "backstage-cli test --passWithNoTests", "clean": "backstage-cli clean", @@ -28,7 +28,11 @@ "techdocs": "bin/techdocs-cli" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.13" + "@spotify/eslint-config": "^7.0.0", + "@spotify/prettier-config": "^7.0.0", + "@types/serve-handler": "^6.1.0", + "eslint": "^7.1.0", + "eslint-plugin-import": "^2.22.0" }, "files": [ "bin", @@ -36,7 +40,15 @@ ], "nodemonConfig": { "watch": "./src", - "exec": "bin/techdocs-cli", + "exec": "bin/build && bin/techdocs-cli", "ext": "ts" + }, + "dependencies": { + "@backstage/cli": "^0.1.1-alpha.13", + "@backstage/plugin-techdocs": "^0.1.1-alpha.13", + "chalk": "^4.1.0", + "commander": "^5.1.0", + "fs-extra": "^9.0.1", + "serve-handler": "^6.1.3" } } diff --git a/packages/techdocs-cli/src/index.ts b/packages/techdocs-cli/src/index.ts index a010f4bfe5..f9ab1c45de 100644 --- a/packages/techdocs-cli/src/index.ts +++ b/packages/techdocs-cli/src/index.ts @@ -13,5 +13,77 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import program from 'commander'; +import { version } from './lib/version'; +// import chalk from 'chalk'; +import { spawn } from 'child_process'; +import path from 'path'; +// import HTTPServer from './lib/httpServer'; -export const techDocsCli = () => {}; +const run = (workingDirectory: string, name: string, args: string[] = []) => { + const child = spawn(name, args, { + cwd: workingDirectory, + stdio: ['inherit', 'inherit', 'inherit'], + shell: true, + env: { + ...process.env, + FORCE_COLOR: 'true', + }, + }); + + child.once('error', error => { + console.error(error); + }); + child.once('exit', code => { + console.log('exited!', code); + }); +}; + +const main = (argv: string[]) => { + program.name('techdocs-cli').version(version); + + program + .command('serve') + .description('Serve a documentation project locally') + .action(() => { + // const techdocsPreviewBundlePath = path.join( + // __dirname, + // '..', + // 'dist', + // 'techdocs-preview-bundle', + // ); + + // new HTTPServer(techdocsPreviewBundlePath, 3000).serve(); + + run(process.env.PWD!, 'docker', [ + 'run', + '-it', + '-w', + '/content', + '-v', + '$(pwd):/content', + '-p', + '8000:8000', + 'mkdocs:local-dev', + 'serve', + '-a', + '0.0.0.0:8000', + ]); + + const pluginPath = path.join( + require.resolve('@backstage/plugin-techdocs'), + '..', + '..', + ); + + run( + pluginPath, + path.join(require.resolve('@backstage/cli'), '../../bin/backstage-cli'), + ['plugin:serve'], + ); + }); + + program.parse(argv); +}; + +main(process.argv); diff --git a/packages/techdocs-cli/src/lib/httpServer.ts b/packages/techdocs-cli/src/lib/httpServer.ts new file mode 100644 index 0000000000..6ca02fc7e9 --- /dev/null +++ b/packages/techdocs-cli/src/lib/httpServer.ts @@ -0,0 +1,35 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import serveHandler from 'serve-handler'; +import http from 'http'; + +export default class HTTPServer { + constructor(public dir: string, public port: number) {} + + serve() { + const server = http.createServer((request, response) => { + return serveHandler(request, response, { + public: this.dir, + trailingSlash: true, + }); + }); + + server.listen(this.port, () => { + console.log('Running at http://localhost:3000'); + }); + } +} diff --git a/packages/techdocs-cli/src/lib/paths.ts b/packages/techdocs-cli/src/lib/paths.ts new file mode 100644 index 0000000000..be3f3dcee8 --- /dev/null +++ b/packages/techdocs-cli/src/lib/paths.ts @@ -0,0 +1,150 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import fs from 'fs-extra'; +import { dirname, resolve as resolvePath } from 'path'; + +export type ResolveFunc = (...paths: string[]) => string; + +// Common paths and resolve functions used by the cli. +// Currently assumes it is being executed within a monorepo. +export type Paths = { + // Root dir of the cli itself, containing package.json + ownDir: string; + + // Monorepo root dir of the cli itself. Only accessible when running inside Backstage repo. + ownRoot: string; + + // The location of the app that the cli is being executed in + targetDir: string; + + // The monorepo root package of the app that the cli is being executed in. + targetRoot: string; + + // Resolve a path relative to own repo + resolveOwn: ResolveFunc; + + // Resolve a path relative to own monorepo root. Only accessible when running inside Backstage repo. + resolveOwnRoot: ResolveFunc; + + // Resolve a path relative to the app + resolveTarget: ResolveFunc; + + // Resolve a path relative to the app repo root + resolveTargetRoot: ResolveFunc; +}; + +// Looks for a package.json that has name: "root" to identify the root of the monorepo +export function findRootPath(topPath: string): string { + let path = topPath; + + // Some sanity check to avoid infinite loop + for (let i = 0; i < 1000; i++) { + const packagePath = resolvePath(path, 'package.json'); + const exists = fs.pathExistsSync(packagePath); + if (exists) { + try { + const data = fs.readJsonSync(packagePath); + if (data.name === 'root' || data.name.includes('backstage-e2e')) { + return path; + } + } catch (error) { + throw new Error( + `Failed to parse package.json file while searching for root, ${error}`, + ); + } + } + + const newPath = dirname(path); + if (newPath === path) { + throw new Error( + `No package.json with name "root" found as a parent of ${topPath}`, + ); + } + path = newPath; + } + + throw new Error( + `Iteration limit reached when searching for root package.json at ${topPath}`, + ); +} + +// Finds the root of the cli package itself +export function findOwnDir() { + // Known relative locations of package in dist/dev + const pathDist = '..'; + const pathDev = '../..'; + + // Check the closest dir first + const pkgInDist = resolvePath(__dirname, pathDist, 'package.json'); + const isDist = fs.pathExistsSync(pkgInDist); + + const path = isDist ? pathDist : pathDev; + return resolvePath(__dirname, path); +} + +// Finds the root of the monorepo that the cli exists in. Only accessible when running inside Backstage repo. +export function findOwnRootPath(ownDir: string) { + const isLocal = fs.pathExistsSync(resolvePath(ownDir, 'src')); + if (!isLocal) { + throw new Error( + 'Tried to access monorepo package root dir outside of Backstage repository', + ); + } + + return resolvePath(ownDir, '../..'); +} + +export function findPaths(): Paths { + const ownDir = findOwnDir(); + const targetDir = fs.realpathSync(process.cwd()); + + // Lazy load this as it will throw an error if we're not inside the Backstage repo. + let ownRoot = ''; + const getOwnRoot = () => { + if (!ownRoot) { + ownRoot = findOwnRootPath(ownDir); + } + return ownRoot; + }; + + // We're not always running in a monorepo, so we lazy init this to only crash commands + // that require a monorepo when we're not in one. + let targetRoot = ''; + const getTargetRoot = () => { + if (!targetRoot) { + targetRoot = findRootPath(targetDir); + } + return targetRoot; + }; + + return { + ownDir, + get ownRoot() { + return getOwnRoot(); + }, + targetDir, + get targetRoot() { + return getTargetRoot(); + }, + resolveOwn: (...paths) => resolvePath(ownDir, ...paths), + resolveOwnRoot: (...paths) => resolvePath(getOwnRoot(), ...paths), + resolveTarget: (...paths) => resolvePath(targetDir, ...paths), + resolveTargetRoot: (...paths) => resolvePath(getTargetRoot(), ...paths), + }; +} + +export const paths = findPaths(); diff --git a/packages/techdocs-cli/src/lib/version.ts b/packages/techdocs-cli/src/lib/version.ts new file mode 100644 index 0000000000..24734b87cc --- /dev/null +++ b/packages/techdocs-cli/src/lib/version.ts @@ -0,0 +1,26 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import fs from 'fs-extra'; +import { paths } from './paths'; + +export function findVersion() { + const pkgContent = fs.readFileSync(paths.resolveOwn('package.json'), 'utf8'); + return JSON.parse(pkgContent).version; +} + +export const version = findVersion(); +export const isDev = fs.pathExistsSync(paths.resolveOwn('src')); diff --git a/yarn.lock b/yarn.lock index 29fe56eb44..fbdde05008 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2559,7 +2559,7 @@ resolved "https://registry.npmjs.org/@spotify/eslint-config-typescript/-/eslint-config-typescript-7.0.0.tgz#fc5227e3344f74b41ac3a530df24a95ac13254e4" integrity sha512-28I/SAf68NKbWZ5IY0WYMa0D18PxWdC9DP9gRbOTlZufmsS8jEgqf3zBUWmP6XOf1nihpKWcqvbFUG5H7/JYXA== -"@spotify/eslint-config@^7.0.1": +"@spotify/eslint-config@^7.0.0", "@spotify/eslint-config@^7.0.1": version "7.0.1" resolved "https://registry.npmjs.org/@spotify/eslint-config/-/eslint-config-7.0.1.tgz#07a21cfd7fce89cfc2c6dd5ea5d747e741201b66" integrity sha512-8GI/TZGUhS4pr7oipT2MjrZFRgXcKzk9YImEusUdD2f5vlCniRFIBQNrvTMkyjfdQqvIVqJPLcdVPXeAgprsMw== @@ -2576,6 +2576,11 @@ eslint-plugin-react "^7.12.4" eslint-plugin-react-hooks "^4.0.0" +"@spotify/prettier-config@^7.0.0": + version "7.0.0" + resolved "https://registry.npmjs.org/@spotify/prettier-config/-/prettier-config-7.0.0.tgz#47750979d1282197295108b6958360660a955c16" + integrity sha512-lIMcx/2oDqTtW84iHKkRJe+8U6HK6GPwWH5sJp9UEHcDpdXomOQYvwcGXy2I2zwPQQ14gYYE6nEJuSnnYqsYRw== + "@spotify/prettier-config@^8.0.0": version "8.0.0" resolved "https://registry.npmjs.org/@spotify/prettier-config/-/prettier-config-8.0.0.tgz#8b6c2bd579ddc54887155a0721fe04e96c89f7f2" @@ -3960,6 +3965,13 @@ "@types/node" "*" rollup "^0.63.4" +"@types/serve-handler@^6.1.0": + version "6.1.0" + resolved "https://registry.npmjs.org/@types/serve-handler/-/serve-handler-6.1.0.tgz#6952aaf864e542297ce8a2480b3e0d9ea59de7f6" + integrity sha512-F9BpWotLZrQvq1CdE3oCnVmQUb6dWq20HSB/qjF4mG7WkZjPQ6fye8veznMKoBPhFJve4yz9C1NOITdTcoLngQ== + dependencies: + "@types/node" "*" + "@types/serve-static@*": version "1.13.3" resolved "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.3.tgz#eb7e1c41c4468272557e897e9171ded5e2ded9d1" @@ -5938,7 +5950,7 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^4.0.0: +chalk@^4.0.0, chalk@^4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== @@ -6505,6 +6517,11 @@ contains-path@^0.1.0: resolved "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= +content-disposition@0.5.2: + version "0.5.2" + resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" + integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= + content-disposition@0.5.3: version "0.5.3" resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" @@ -8139,6 +8156,25 @@ eslint-plugin-import@^2.20.2: resolve "^1.17.0" tsconfig-paths "^3.9.0" +eslint-plugin-import@^2.22.0: + version "2.22.0" + resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.0.tgz#92f7736fe1fde3e2de77623c838dd992ff5ffb7e" + integrity sha512-66Fpf1Ln6aIS5Gr/55ts19eUuoDhAbZgnr6UxK5hbDx6l/QgQgx61AePq+BV4PP2uXQFClgMVzep5zZ94qqsxg== + dependencies: + array-includes "^3.1.1" + array.prototype.flat "^1.2.3" + contains-path "^0.1.0" + debug "^2.6.9" + doctrine "1.5.0" + eslint-import-resolver-node "^0.3.3" + eslint-module-utils "^2.6.0" + has "^1.0.3" + minimatch "^3.0.4" + object.values "^1.1.1" + read-pkg-up "^2.0.0" + resolve "^1.17.0" + tsconfig-paths "^3.9.0" + eslint-plugin-jest@^23.6.0: version "23.8.2" resolved "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-23.8.2.tgz#6f28b41c67ef635f803ebd9e168f6b73858eb8d4" @@ -8659,6 +8695,13 @@ fast-shallow-equal@^1.0.0: resolved "https://registry.npmjs.org/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz#d4dcaf6472440dcefa6f88b98e3251e27f25628b" integrity sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw== +fast-url-parser@1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" + integrity sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0= + dependencies: + punycode "^1.3.2" + fastest-stable-stringify@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/fastest-stable-stringify/-/fastest-stable-stringify-1.0.1.tgz#9122d406d4c9d98bea644a6b6853d5874b87b028" @@ -9145,6 +9188,16 @@ fs-extra@^9.0.0: jsonfile "^6.0.1" universalify "^1.0.0" +fs-extra@^9.0.1: + version "9.0.1" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz#910da0062437ba4c39fedd863f1675ccfefcb9fc" + integrity sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^1.0.0" + fs-minipass@^1.2.5: version "1.2.7" resolved "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" @@ -12764,6 +12817,18 @@ mime-db@1.44.0: resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== +mime-db@~1.33.0: + version "1.33.0" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" + integrity sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ== + +mime-types@2.1.18: + version "2.1.18" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" + integrity sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ== + dependencies: + mime-db "~1.33.0" + mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: version "2.1.26" resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz#9c921fc09b7e149a65dfdc0da4d20997200b0a06" @@ -14253,7 +14318,7 @@ path-is-absolute@^1.0.0: resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -path-is-inside@^1.0.2: +path-is-inside@1.0.2, path-is-inside@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= @@ -14290,6 +14355,11 @@ path-to-regexp@0.1.7: resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= +path-to-regexp@2.2.1: + version "2.2.1" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz#90b617025a16381a879bc82a38d4e8bdeb2bcf45" + integrity sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ== + path-type@^1.0.0: version "1.1.0" resolved "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" @@ -15189,7 +15259,7 @@ punycode@1.3.2: resolved "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= -punycode@^1.2.4: +punycode@^1.2.4, punycode@^1.3.2: version "1.4.1" resolved "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= @@ -15301,6 +15371,11 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" +range-parser@1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" + integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= + range-parser@^1.2.1, range-parser@~1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" @@ -16705,6 +16780,20 @@ serve-favicon@^2.5.0: parseurl "~1.3.2" safe-buffer "5.1.1" +serve-handler@^6.1.3: + version "6.1.3" + resolved "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz#1bf8c5ae138712af55c758477533b9117f6435e8" + integrity sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w== + dependencies: + bytes "3.0.0" + content-disposition "0.5.2" + fast-url-parser "1.1.3" + mime-types "2.1.18" + minimatch "3.0.4" + path-is-inside "1.0.2" + path-to-regexp "2.2.1" + range-parser "1.2.0" + serve-index@^1.9.1: version "1.9.1" resolved "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239"