From b673a7366019dc65b9ccc99168925db5eb0989ac Mon Sep 17 00:00:00 2001 From: Simon Lecoq <22963968+lowlighter@users.noreply.github.com> Date: Thu, 19 Dec 2024 01:03:35 +0000 Subject: [PATCH 01/10] feat(action): auto-discovery of deno.json and auto-populate defaults --- action.yml | 11 +- action/index.js | 64 ++- action/node_modules/.bin/mkdirp | 1 + action/node_modules/.package-lock.json | 105 ++++ action/node_modules/error-ex/LICENSE | 21 + action/node_modules/error-ex/README.md | 144 +++++ action/node_modules/error-ex/index.js | 141 +++++ action/node_modules/error-ex/package.json | 46 ++ .../fast-safe-stringify/.travis.yml | 8 + .../fast-safe-stringify/CHANGELOG.md | 17 + .../node_modules/fast-safe-stringify/LICENSE | 23 + .../fast-safe-stringify/benchmark.js | 137 +++++ .../fast-safe-stringify/index.d.ts | 23 + .../node_modules/fast-safe-stringify/index.js | 229 ++++++++ .../fast-safe-stringify/package.json | 46 ++ .../fast-safe-stringify/readme.md | 170 ++++++ .../fast-safe-stringify/test-stable.js | 404 ++++++++++++++ .../node_modules/fast-safe-stringify/test.js | 397 +++++++++++++ action/node_modules/graceful-fs/LICENSE | 15 + action/node_modules/graceful-fs/README.md | 143 +++++ action/node_modules/graceful-fs/clone.js | 23 + .../node_modules/graceful-fs/graceful-fs.js | 448 +++++++++++++++ .../graceful-fs/legacy-streams.js | 118 ++++ action/node_modules/graceful-fs/package.json | 53 ++ action/node_modules/graceful-fs/polyfills.js | 355 ++++++++++++ action/node_modules/is-arrayish/.editorconfig | 18 + action/node_modules/is-arrayish/.istanbul.yml | 4 + action/node_modules/is-arrayish/.npmignore | 5 + action/node_modules/is-arrayish/.travis.yml | 17 + action/node_modules/is-arrayish/LICENSE | 21 + action/node_modules/is-arrayish/README.md | 16 + action/node_modules/is-arrayish/index.js | 10 + action/node_modules/is-arrayish/package.json | 34 ++ .../json-parse-better-errors/CHANGELOG.md | 46 ++ .../json-parse-better-errors/LICENSE.md | 7 + .../json-parse-better-errors/README.md | 46 ++ .../json-parse-better-errors/index.js | 38 ++ .../json-parse-better-errors/package.json | 45 ++ action/node_modules/jsonc/LICENSE | 21 + action/node_modules/jsonc/README.md | 97 ++++ action/node_modules/jsonc/index.js | 5 + action/node_modules/jsonc/lib/helper.d.ts | 19 + action/node_modules/jsonc/lib/helper.js | 118 ++++ action/node_modules/jsonc/lib/interfaces.d.ts | 24 + action/node_modules/jsonc/lib/interfaces.js | 2 + action/node_modules/jsonc/lib/jsonc.d.ts | 357 ++++++++++++ action/node_modules/jsonc/lib/jsonc.js | 527 ++++++++++++++++++ action/node_modules/jsonc/lib/jsonc.safe.d.ts | 451 +++++++++++++++ action/node_modules/jsonc/lib/jsonc.safe.js | 460 +++++++++++++++ action/node_modules/jsonc/package.json | 102 ++++ action/node_modules/minimist/.eslintrc | 29 + .../node_modules/minimist/.github/FUNDING.yml | 12 + action/node_modules/minimist/.nycrc | 14 + action/node_modules/minimist/CHANGELOG.md | 298 ++++++++++ action/node_modules/minimist/LICENSE | 18 + action/node_modules/minimist/README.md | 121 ++++ action/node_modules/minimist/example/parse.js | 4 + action/node_modules/minimist/index.js | 263 +++++++++ action/node_modules/minimist/package.json | 75 +++ action/node_modules/minimist/test/all_bool.js | 34 ++ action/node_modules/minimist/test/bool.js | 177 ++++++ action/node_modules/minimist/test/dash.js | 43 ++ .../minimist/test/default_bool.js | 37 ++ action/node_modules/minimist/test/dotted.js | 24 + action/node_modules/minimist/test/kv_short.js | 32 ++ action/node_modules/minimist/test/long.js | 33 ++ action/node_modules/minimist/test/num.js | 38 ++ action/node_modules/minimist/test/parse.js | 209 +++++++ .../minimist/test/parse_modified.js | 11 + action/node_modules/minimist/test/proto.js | 64 +++ action/node_modules/minimist/test/short.js | 69 +++ .../node_modules/minimist/test/stop_early.js | 17 + action/node_modules/minimist/test/unknown.js | 104 ++++ .../node_modules/minimist/test/whitespace.js | 10 + action/node_modules/mkdirp/LICENSE | 21 + action/node_modules/mkdirp/bin/cmd.js | 33 ++ action/node_modules/mkdirp/bin/usage.txt | 12 + action/node_modules/mkdirp/index.js | 102 ++++ action/node_modules/mkdirp/package.json | 33 ++ action/node_modules/mkdirp/readme.markdown | 100 ++++ action/node_modules/parse-json/index.js | 33 ++ action/node_modules/parse-json/license | 9 + action/node_modules/parse-json/package.json | 43 ++ action/node_modules/parse-json/readme.md | 83 +++ action/node_modules/strip-bom/index.d.ts | 14 + action/node_modules/strip-bom/index.js | 15 + action/node_modules/strip-bom/license | 9 + action/node_modules/strip-bom/package.json | 42 ++ action/node_modules/strip-bom/readme.md | 54 ++ .../strip-json-comments/index.d.ts | 36 ++ .../node_modules/strip-json-comments/index.js | 77 +++ .../node_modules/strip-json-comments/license | 9 + .../strip-json-comments/package.json | 47 ++ .../strip-json-comments/readme.md | 78 +++ action/package-lock.json | 180 +++++- action/package.json | 1 + 96 files changed, 8389 insertions(+), 10 deletions(-) create mode 120000 action/node_modules/.bin/mkdirp create mode 100644 action/node_modules/error-ex/LICENSE create mode 100644 action/node_modules/error-ex/README.md create mode 100644 action/node_modules/error-ex/index.js create mode 100644 action/node_modules/error-ex/package.json create mode 100644 action/node_modules/fast-safe-stringify/.travis.yml create mode 100644 action/node_modules/fast-safe-stringify/CHANGELOG.md create mode 100644 action/node_modules/fast-safe-stringify/LICENSE create mode 100644 action/node_modules/fast-safe-stringify/benchmark.js create mode 100644 action/node_modules/fast-safe-stringify/index.d.ts create mode 100644 action/node_modules/fast-safe-stringify/index.js create mode 100644 action/node_modules/fast-safe-stringify/package.json create mode 100644 action/node_modules/fast-safe-stringify/readme.md create mode 100644 action/node_modules/fast-safe-stringify/test-stable.js create mode 100644 action/node_modules/fast-safe-stringify/test.js create mode 100644 action/node_modules/graceful-fs/LICENSE create mode 100644 action/node_modules/graceful-fs/README.md create mode 100644 action/node_modules/graceful-fs/clone.js create mode 100644 action/node_modules/graceful-fs/graceful-fs.js create mode 100644 action/node_modules/graceful-fs/legacy-streams.js create mode 100644 action/node_modules/graceful-fs/package.json create mode 100644 action/node_modules/graceful-fs/polyfills.js create mode 100644 action/node_modules/is-arrayish/.editorconfig create mode 100644 action/node_modules/is-arrayish/.istanbul.yml create mode 100644 action/node_modules/is-arrayish/.npmignore create mode 100644 action/node_modules/is-arrayish/.travis.yml create mode 100644 action/node_modules/is-arrayish/LICENSE create mode 100644 action/node_modules/is-arrayish/README.md create mode 100644 action/node_modules/is-arrayish/index.js create mode 100644 action/node_modules/is-arrayish/package.json create mode 100644 action/node_modules/json-parse-better-errors/CHANGELOG.md create mode 100644 action/node_modules/json-parse-better-errors/LICENSE.md create mode 100644 action/node_modules/json-parse-better-errors/README.md create mode 100644 action/node_modules/json-parse-better-errors/index.js create mode 100644 action/node_modules/json-parse-better-errors/package.json create mode 100644 action/node_modules/jsonc/LICENSE create mode 100644 action/node_modules/jsonc/README.md create mode 100644 action/node_modules/jsonc/index.js create mode 100644 action/node_modules/jsonc/lib/helper.d.ts create mode 100644 action/node_modules/jsonc/lib/helper.js create mode 100644 action/node_modules/jsonc/lib/interfaces.d.ts create mode 100644 action/node_modules/jsonc/lib/interfaces.js create mode 100644 action/node_modules/jsonc/lib/jsonc.d.ts create mode 100644 action/node_modules/jsonc/lib/jsonc.js create mode 100644 action/node_modules/jsonc/lib/jsonc.safe.d.ts create mode 100644 action/node_modules/jsonc/lib/jsonc.safe.js create mode 100644 action/node_modules/jsonc/package.json create mode 100644 action/node_modules/minimist/.eslintrc create mode 100644 action/node_modules/minimist/.github/FUNDING.yml create mode 100644 action/node_modules/minimist/.nycrc create mode 100644 action/node_modules/minimist/CHANGELOG.md create mode 100644 action/node_modules/minimist/LICENSE create mode 100644 action/node_modules/minimist/README.md create mode 100644 action/node_modules/minimist/example/parse.js create mode 100644 action/node_modules/minimist/index.js create mode 100644 action/node_modules/minimist/package.json create mode 100644 action/node_modules/minimist/test/all_bool.js create mode 100644 action/node_modules/minimist/test/bool.js create mode 100644 action/node_modules/minimist/test/dash.js create mode 100644 action/node_modules/minimist/test/default_bool.js create mode 100644 action/node_modules/minimist/test/dotted.js create mode 100644 action/node_modules/minimist/test/kv_short.js create mode 100644 action/node_modules/minimist/test/long.js create mode 100644 action/node_modules/minimist/test/num.js create mode 100644 action/node_modules/minimist/test/parse.js create mode 100644 action/node_modules/minimist/test/parse_modified.js create mode 100644 action/node_modules/minimist/test/proto.js create mode 100644 action/node_modules/minimist/test/short.js create mode 100644 action/node_modules/minimist/test/stop_early.js create mode 100644 action/node_modules/minimist/test/unknown.js create mode 100644 action/node_modules/minimist/test/whitespace.js create mode 100644 action/node_modules/mkdirp/LICENSE create mode 100755 action/node_modules/mkdirp/bin/cmd.js create mode 100644 action/node_modules/mkdirp/bin/usage.txt create mode 100644 action/node_modules/mkdirp/index.js create mode 100644 action/node_modules/mkdirp/package.json create mode 100644 action/node_modules/mkdirp/readme.markdown create mode 100644 action/node_modules/parse-json/index.js create mode 100644 action/node_modules/parse-json/license create mode 100644 action/node_modules/parse-json/package.json create mode 100644 action/node_modules/parse-json/readme.md create mode 100644 action/node_modules/strip-bom/index.d.ts create mode 100644 action/node_modules/strip-bom/index.js create mode 100644 action/node_modules/strip-bom/license create mode 100644 action/node_modules/strip-bom/package.json create mode 100644 action/node_modules/strip-bom/readme.md create mode 100644 action/node_modules/strip-json-comments/index.d.ts create mode 100644 action/node_modules/strip-json-comments/index.js create mode 100644 action/node_modules/strip-json-comments/license create mode 100644 action/node_modules/strip-json-comments/package.json create mode 100644 action/node_modules/strip-json-comments/readme.md diff --git a/action.yml b/action.yml index 9c661d4e..3fae2e03 100644 --- a/action.yml +++ b/action.yml @@ -7,12 +7,15 @@ branding: icon: globe inputs: + deno-config: + description: The path to a local Deno config file (deno.json and deno.jsonc are auto-discovered). If it contains a "deploy" field, other inputs will default to its content. + required: false project: - description: The name or ID of the project to deploy - required: true + description: The name or ID of the project to deploy (required if when not set in Deno config) + required: false entrypoint: - description: The path or URL to the entrypoint file - required: true + description: The path or URL to the entrypoint file (required if when not set in Deno config) + required: false import-map: description: The path or URL to an import map file required: false diff --git a/action/index.js b/action/index.js index 464c94cd..b8498f34 100644 --- a/action/index.js +++ b/action/index.js @@ -11,16 +11,70 @@ import { walk, } from "./deps.js"; import process from "node:process"; +import { jsonc } from "jsonc"; +import { tmpdir } from "node:os"; +import { existsSync } from "node:fs"; +import { readFile, writeFile } from "node:fs/promises"; // The origin of the server to make Deploy requests to. const ORIGIN = process.env.DEPLOY_API_ENDPOINT ?? "https://dash.deno.com"; async function main() { - const projectId = core.getInput("project", { required: true }); - const entrypoint = core.getInput("entrypoint", { required: true }); - const importMap = core.getInput("import-map", {}); - const include = core.getMultilineInput("include", {}); - const exclude = core.getMultilineInput("exclude", {}); + // Try to resolve and parse a deno config file + let denoConfig = core.getInput("deno-config", {}); + let denoConfigHasDeployInfo = false; + const denoParsedConfig = {}; + for (let path of [denoConfig, "deno.json", "deno.jsonc"]) { + path = resolve(process.cwd(), path); + if (existsSync(path)) { + denoConfig = path; + break; + } + } + if (denoConfig) { + core.info(`Found a Deno configuration file: ${denoConfig}`); + Object.assign( + denoParsedConfig, + jsonc.parse(await readFile(denoConfig, "utf-8")), + ); + // Defaults deno deploy inputs if present in configuration file + if (denoParsedConfig.deploy) { + core.info(`The configuration file has a "deploy" field`); + if ( + denoParsedConfig.deploy.project && denoParsedConfig.deploy.entrypoint + ) { + denoConfigHasDeployInfo = true; + core.info(`The "deploy" field seems to be valid`); + } else { + core.warning( + `Could not read "project" and "entrypoint" values from the "deploy" field of the configuration file`, + ); + } + } + // Create an temporary import map if present in configuration file + // This lets user use deno.jsonc files as import-map since jsonc is not directly supported + if (denoParsedConfig.imports) { + core.info(`The configuration file has a "imports" field`); + denoParsedConfig.importMap = path.join(tmpdir(), "importMap.json"); + await writeFile( + denoParsedConfig.importMap, + JSON.stringify({ imports: denoParsedConfig.imports }), + ); + } + } + + const projectId = + core.getInput("project", { required: !denoConfigHasDeployInfo }) || + denoParsedConfig.deploy?.project; + const entrypoint = + core.getInput("entrypoint", { required: !denoConfigHasDeployInfo }) || + denoParsedConfig.deploy?.entrypoint; + const importMap = core.getInput("import-map", {}) || + (denoParsedConfig.importMap ?? ""); + const include = denoParsedConfig.deploy?.include || + core.getMultilineInput("include", {}); + const exclude = denoParsedConfig.deploy?.exclude || + core.getMultilineInput("exclude", {}); const cwd = resolve(process.cwd(), core.getInput("root", {})); if (github.context.eventName === "pull_request") { diff --git a/action/node_modules/.bin/mkdirp b/action/node_modules/.bin/mkdirp new file mode 120000 index 00000000..017896ce --- /dev/null +++ b/action/node_modules/.bin/mkdirp @@ -0,0 +1 @@ +../mkdirp/bin/cmd.js \ No newline at end of file diff --git a/action/node_modules/.package-lock.json b/action/node_modules/.package-lock.json index b46c4ad4..a7585232 100644 --- a/action/node_modules/.package-lock.json +++ b/action/node_modules/.package-lock.json @@ -164,6 +164,21 @@ "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "license": "MIT" + }, "node_modules/fetch-blob": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.4.tgz", @@ -197,6 +212,18 @@ "node": ">=12.20.0" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, "node_modules/is-plain-object": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", @@ -213,6 +240,50 @@ "node": ">=16" } }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "license": "MIT" + }, + "node_modules/jsonc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jsonc/-/jsonc-2.0.0.tgz", + "integrity": "sha512-B281bLCT2TRMQa+AQUQY5AGcqSOXBOKaYGP4wDzoA/+QswUfN8sODektbPEs9Baq7LGKun5jQbNFpzwGuVYKhw==", + "license": "MIT", + "dependencies": { + "fast-safe-stringify": "^2.0.6", + "graceful-fs": "^4.1.15", + "mkdirp": "^0.5.1", + "parse-json": "^4.0.0", + "strip-bom": "^4.0.0", + "strip-json-comments": "^3.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -258,6 +329,40 @@ "wrappy": "1" } }, + "node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "license": "MIT", + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", diff --git a/action/node_modules/error-ex/LICENSE b/action/node_modules/error-ex/LICENSE new file mode 100644 index 00000000..0a5f461a --- /dev/null +++ b/action/node_modules/error-ex/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 JD Ballard + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/action/node_modules/error-ex/README.md b/action/node_modules/error-ex/README.md new file mode 100644 index 00000000..97f744af --- /dev/null +++ b/action/node_modules/error-ex/README.md @@ -0,0 +1,144 @@ +# node-error-ex [![Travis-CI.org Build Status](https://img.shields.io/travis/Qix-/node-error-ex.svg?style=flat-square)](https://travis-ci.org/Qix-/node-error-ex) [![Coveralls.io Coverage Rating](https://img.shields.io/coveralls/Qix-/node-error-ex.svg?style=flat-square)](https://coveralls.io/r/Qix-/node-error-ex) +> Easily subclass and customize new Error types + +## Examples +To include in your project: +```javascript +var errorEx = require('error-ex'); +``` + +To create an error message type with a specific name (note, that `ErrorFn.name` +will not reflect this): +```javascript +var JSONError = errorEx('JSONError'); + +var err = new JSONError('error'); +err.name; //-> JSONError +throw err; //-> JSONError: error +``` + +To add a stack line: +```javascript +var JSONError = errorEx('JSONError', {fileName: errorEx.line('in %s')}); + +var err = new JSONError('error') +err.fileName = '/a/b/c/foo.json'; +throw err; //-> (line 2)-> in /a/b/c/foo.json +``` + +To append to the error message: +```javascript +var JSONError = errorEx('JSONError', {fileName: errorEx.append('in %s')}); + +var err = new JSONError('error'); +err.fileName = '/a/b/c/foo.json'; +throw err; //-> JSONError: error in /a/b/c/foo.json +``` + +## API + +#### `errorEx([name], [properties])` +Creates a new ErrorEx error type + +- `name`: the name of the new type (appears in the error message upon throw; + defaults to `Error.name`) +- `properties`: if supplied, used as a key/value dictionary of properties to + use when building up the stack message. Keys are property names that are + looked up on the error message, and then passed to function values. + - `line`: if specified and is a function, return value is added as a stack + entry (error-ex will indent for you). Passed the property value given + the key. + - `stack`: if specified and is a function, passed the value of the property + using the key, and the raw stack lines as a second argument. Takes no + return value (but the stack can be modified directly). + - `message`: if specified and is a function, return value is used as new + `.message` value upon get. Passed the property value of the property named + by key, and the existing message is passed as the second argument as an + array of lines (suitable for multi-line messages). + +Returns a constructor (Function) that can be used just like the regular Error +constructor. + +```javascript +var errorEx = require('error-ex'); + +var BasicError = errorEx(); + +var NamedError = errorEx('NamedError'); + +// -- + +var AdvancedError = errorEx('AdvancedError', { + foo: { + line: function (value, stack) { + if (value) { + return 'bar ' + value; + } + return null; + } + } +} + +var err = new AdvancedError('hello, world'); +err.foo = 'baz'; +throw err; + +/* + AdvancedError: hello, world + bar baz + at tryReadme() (readme.js:20:1) +*/ +``` + +#### `errorEx.line(str)` +Creates a stack line using a delimiter + +> This is a helper function. It is to be used in lieu of writing a value object +> for `properties` values. + +- `str`: The string to create + - Use the delimiter `%s` to specify where in the string the value should go + +```javascript +var errorEx = require('error-ex'); + +var FileError = errorEx('FileError', {fileName: errorEx.line('in %s')}); + +var err = new FileError('problem reading file'); +err.fileName = '/a/b/c/d/foo.js'; +throw err; + +/* + FileError: problem reading file + in /a/b/c/d/foo.js + at tryReadme() (readme.js:7:1) +*/ +``` + +#### `errorEx.append(str)` +Appends to the `error.message` string + +> This is a helper function. It is to be used in lieu of writing a value object +> for `properties` values. + +- `str`: The string to append + - Use the delimiter `%s` to specify where in the string the value should go + +```javascript +var errorEx = require('error-ex'); + +var SyntaxError = errorEx('SyntaxError', {fileName: errorEx.append('in %s')}); + +var err = new SyntaxError('improper indentation'); +err.fileName = '/a/b/c/d/foo.js'; +throw err; + +/* + SyntaxError: improper indentation in /a/b/c/d/foo.js + at tryReadme() (readme.js:7:1) +*/ +``` + +## License +Licensed under the [MIT License](http://opensource.org/licenses/MIT). +You can find a copy of it in [LICENSE](LICENSE). diff --git a/action/node_modules/error-ex/index.js b/action/node_modules/error-ex/index.js new file mode 100644 index 00000000..4fb20b48 --- /dev/null +++ b/action/node_modules/error-ex/index.js @@ -0,0 +1,141 @@ +'use strict'; + +var util = require('util'); +var isArrayish = require('is-arrayish'); + +var errorEx = function errorEx(name, properties) { + if (!name || name.constructor !== String) { + properties = name || {}; + name = Error.name; + } + + var errorExError = function ErrorEXError(message) { + if (!this) { + return new ErrorEXError(message); + } + + message = message instanceof Error + ? message.message + : (message || this.message); + + Error.call(this, message); + Error.captureStackTrace(this, errorExError); + + this.name = name; + + Object.defineProperty(this, 'message', { + configurable: true, + enumerable: false, + get: function () { + var newMessage = message.split(/\r?\n/g); + + for (var key in properties) { + if (!properties.hasOwnProperty(key)) { + continue; + } + + var modifier = properties[key]; + + if ('message' in modifier) { + newMessage = modifier.message(this[key], newMessage) || newMessage; + if (!isArrayish(newMessage)) { + newMessage = [newMessage]; + } + } + } + + return newMessage.join('\n'); + }, + set: function (v) { + message = v; + } + }); + + var overwrittenStack = null; + + var stackDescriptor = Object.getOwnPropertyDescriptor(this, 'stack'); + var stackGetter = stackDescriptor.get; + var stackValue = stackDescriptor.value; + delete stackDescriptor.value; + delete stackDescriptor.writable; + + stackDescriptor.set = function (newstack) { + overwrittenStack = newstack; + }; + + stackDescriptor.get = function () { + var stack = (overwrittenStack || ((stackGetter) + ? stackGetter.call(this) + : stackValue)).split(/\r?\n+/g); + + // starting in Node 7, the stack builder caches the message. + // just replace it. + if (!overwrittenStack) { + stack[0] = this.name + ': ' + this.message; + } + + var lineCount = 1; + for (var key in properties) { + if (!properties.hasOwnProperty(key)) { + continue; + } + + var modifier = properties[key]; + + if ('line' in modifier) { + var line = modifier.line(this[key]); + if (line) { + stack.splice(lineCount++, 0, ' ' + line); + } + } + + if ('stack' in modifier) { + modifier.stack(this[key], stack); + } + } + + return stack.join('\n'); + }; + + Object.defineProperty(this, 'stack', stackDescriptor); + }; + + if (Object.setPrototypeOf) { + Object.setPrototypeOf(errorExError.prototype, Error.prototype); + Object.setPrototypeOf(errorExError, Error); + } else { + util.inherits(errorExError, Error); + } + + return errorExError; +}; + +errorEx.append = function (str, def) { + return { + message: function (v, message) { + v = v || def; + + if (v) { + message[0] += ' ' + str.replace('%s', v.toString()); + } + + return message; + } + }; +}; + +errorEx.line = function (str, def) { + return { + line: function (v) { + v = v || def; + + if (v) { + return str.replace('%s', v.toString()); + } + + return null; + } + }; +}; + +module.exports = errorEx; diff --git a/action/node_modules/error-ex/package.json b/action/node_modules/error-ex/package.json new file mode 100644 index 00000000..f3d9ae0e --- /dev/null +++ b/action/node_modules/error-ex/package.json @@ -0,0 +1,46 @@ +{ + "name": "error-ex", + "description": "Easy error subclassing and stack customization", + "version": "1.3.2", + "maintainers": [ + "Josh Junon (github.com/qix-)", + "Sindre Sorhus (sindresorhus.com)" + ], + "keywords": [ + "error", + "errors", + "extend", + "extending", + "extension", + "subclass", + "stack", + "custom" + ], + "license": "MIT", + "scripts": { + "pretest": "xo", + "test": "mocha --compilers coffee:coffee-script/register" + }, + "xo": { + "rules": { + "operator-linebreak": [ + 0 + ] + } + }, + "repository": "qix-/node-error-ex", + "files": [ + "index.js" + ], + "devDependencies": { + "coffee-script": "^1.9.3", + "coveralls": "^2.11.2", + "istanbul": "^0.3.17", + "mocha": "^2.2.5", + "should": "^7.0.1", + "xo": "^0.7.1" + }, + "dependencies": { + "is-arrayish": "^0.2.1" + } +} diff --git a/action/node_modules/fast-safe-stringify/.travis.yml b/action/node_modules/fast-safe-stringify/.travis.yml new file mode 100644 index 00000000..2b06d253 --- /dev/null +++ b/action/node_modules/fast-safe-stringify/.travis.yml @@ -0,0 +1,8 @@ +language: node_js +sudo: false +node_js: +- '4' +- '6' +- '8' +- '9' +- '10' diff --git a/action/node_modules/fast-safe-stringify/CHANGELOG.md b/action/node_modules/fast-safe-stringify/CHANGELOG.md new file mode 100644 index 00000000..55f2d082 --- /dev/null +++ b/action/node_modules/fast-safe-stringify/CHANGELOG.md @@ -0,0 +1,17 @@ +# Changelog + +## v.2.0.0 + +Features + +- Added stable-stringify (see documentation) +- Support replacer +- Support spacer +- toJSON support without forceDecirc property +- Improved performance + +Breaking changes + +- Manipulating the input value in a `toJSON` function is not possible anymore in + all cases (see documentation) +- Dropped support for e.g. IE8 and Node.js < 4 diff --git a/action/node_modules/fast-safe-stringify/LICENSE b/action/node_modules/fast-safe-stringify/LICENSE new file mode 100644 index 00000000..d310c2d1 --- /dev/null +++ b/action/node_modules/fast-safe-stringify/LICENSE @@ -0,0 +1,23 @@ +The MIT License (MIT) + +Copyright (c) 2016 David Mark Clements +Copyright (c) 2017 David Mark Clements & Matteo Collina +Copyright (c) 2018 David Mark Clements, Matteo Collina & Ruben Bridgewater + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/action/node_modules/fast-safe-stringify/benchmark.js b/action/node_modules/fast-safe-stringify/benchmark.js new file mode 100644 index 00000000..7ba5e9f5 --- /dev/null +++ b/action/node_modules/fast-safe-stringify/benchmark.js @@ -0,0 +1,137 @@ +const Benchmark = require('benchmark') +const suite = new Benchmark.Suite() +const { inspect } = require('util') +const jsonStringifySafe = require('json-stringify-safe') +const fastSafeStringify = require('./') + +const array = new Array(10).fill(0).map((_, i) => i) +const obj = { foo: array } +const circ = JSON.parse(JSON.stringify(obj)) +circ.o = { obj: circ, array } +const circGetters = JSON.parse(JSON.stringify(obj)) +Object.assign(circGetters, { get o () { return { obj: circGetters, array } } }) + +const deep = require('./package.json') +deep.deep = JSON.parse(JSON.stringify(deep)) +deep.deep.deep = JSON.parse(JSON.stringify(deep)) +deep.deep.deep.deep = JSON.parse(JSON.stringify(deep)) +deep.array = array + +const deepCirc = JSON.parse(JSON.stringify(deep)) +deepCirc.deep.deep.deep.circ = deepCirc +deepCirc.deep.deep.circ = deepCirc +deepCirc.deep.circ = deepCirc +deepCirc.array = array + +const deepCircGetters = JSON.parse(JSON.stringify(deep)) +for (let i = 0; i < 10; i++) { + deepCircGetters[i.toString()] = { + deep: { + deep: { + get circ () { return deep.deep }, + deep: { get circ () { return deep.deep.deep } } + }, + get circ () { return deep } + }, + get array () { return array } + } +} + +const deepCircNonCongifurableGetters = JSON.parse(JSON.stringify(deep)) +Object.defineProperty(deepCircNonCongifurableGetters.deep.deep.deep, 'circ', { + get: () => deepCircNonCongifurableGetters, + enumerable: true, + configurable: false +}) +Object.defineProperty(deepCircNonCongifurableGetters.deep.deep, 'circ', { + get: () => deepCircNonCongifurableGetters, + enumerable: true, + configurable: false +}) +Object.defineProperty(deepCircNonCongifurableGetters.deep, 'circ', { + get: () => deepCircNonCongifurableGetters, + enumerable: true, + configurable: false +}) +Object.defineProperty(deepCircNonCongifurableGetters, 'array', { + get: () => array, + enumerable: true, + configurable: false +}) + +suite.add('util.inspect: simple object ', function () { + inspect(obj, { showHidden: false, depth: null }) +}) +suite.add('util.inspect: circular ', function () { + inspect(circ, { showHidden: false, depth: null }) +}) +suite.add('util.inspect: circular getters ', function () { + inspect(circGetters, { showHidden: false, depth: null }) +}) +suite.add('util.inspect: deep ', function () { + inspect(deep, { showHidden: false, depth: null }) +}) +suite.add('util.inspect: deep circular ', function () { + inspect(deepCirc, { showHidden: false, depth: null }) +}) +suite.add('util.inspect: large deep circular getters ', function () { + inspect(deepCircGetters, { showHidden: false, depth: null }) +}) +suite.add('util.inspect: deep non-conf circular getters', function () { + inspect(deepCircNonCongifurableGetters, { showHidden: false, depth: null }) +}) + +suite.add('\njson-stringify-safe: simple object ', function () { + jsonStringifySafe(obj) +}) +suite.add('json-stringify-safe: circular ', function () { + jsonStringifySafe(circ) +}) +suite.add('json-stringify-safe: circular getters ', function () { + jsonStringifySafe(circGetters) +}) +suite.add('json-stringify-safe: deep ', function () { + jsonStringifySafe(deep) +}) +suite.add('json-stringify-safe: deep circular ', function () { + jsonStringifySafe(deepCirc) +}) +suite.add('json-stringify-safe: large deep circular getters ', function () { + jsonStringifySafe(deepCircGetters) +}) +suite.add('json-stringify-safe: deep non-conf circular getters', function () { + jsonStringifySafe(deepCircNonCongifurableGetters) +}) + +suite.add('\nfast-safe-stringify: simple object ', function () { + fastSafeStringify(obj) +}) +suite.add('fast-safe-stringify: circular ', function () { + fastSafeStringify(circ) +}) +suite.add('fast-safe-stringify: circular getters ', function () { + fastSafeStringify(circGetters) +}) +suite.add('fast-safe-stringify: deep ', function () { + fastSafeStringify(deep) +}) +suite.add('fast-safe-stringify: deep circular ', function () { + fastSafeStringify(deepCirc) +}) +suite.add('fast-safe-stringify: large deep circular getters ', function () { + fastSafeStringify(deepCircGetters) +}) +suite.add('fast-safe-stringify: deep non-conf circular getters', function () { + fastSafeStringify(deepCircNonCongifurableGetters) +}) + +// add listeners +suite.on('cycle', function (event) { + console.log(String(event.target)) +}) + +suite.on('complete', function () { + console.log('\nFastest is ' + this.filter('fastest').map('name')) +}) + +suite.run({ delay: 1, minSamples: 150 }) diff --git a/action/node_modules/fast-safe-stringify/index.d.ts b/action/node_modules/fast-safe-stringify/index.d.ts new file mode 100644 index 00000000..9a9b1f00 --- /dev/null +++ b/action/node_modules/fast-safe-stringify/index.d.ts @@ -0,0 +1,23 @@ +declare function stringify( + value: any, + replacer?: (key: string, value: any) => any, + space?: string | number, + options?: { depthLimit: number | undefined; edgesLimit: number | undefined } +): string; + +declare namespace stringify { + export function stable( + value: any, + replacer?: (key: string, value: any) => any, + space?: string | number, + options?: { depthLimit: number | undefined; edgesLimit: number | undefined } + ): string; + export function stableStringify( + value: any, + replacer?: (key: string, value: any) => any, + space?: string | number, + options?: { depthLimit: number | undefined; edgesLimit: number | undefined } + ): string; +} + +export default stringify; diff --git a/action/node_modules/fast-safe-stringify/index.js b/action/node_modules/fast-safe-stringify/index.js new file mode 100644 index 00000000..ecf7e519 --- /dev/null +++ b/action/node_modules/fast-safe-stringify/index.js @@ -0,0 +1,229 @@ +module.exports = stringify +stringify.default = stringify +stringify.stable = deterministicStringify +stringify.stableStringify = deterministicStringify + +var LIMIT_REPLACE_NODE = '[...]' +var CIRCULAR_REPLACE_NODE = '[Circular]' + +var arr = [] +var replacerStack = [] + +function defaultOptions () { + return { + depthLimit: Number.MAX_SAFE_INTEGER, + edgesLimit: Number.MAX_SAFE_INTEGER + } +} + +// Regular stringify +function stringify (obj, replacer, spacer, options) { + if (typeof options === 'undefined') { + options = defaultOptions() + } + + decirc(obj, '', 0, [], undefined, 0, options) + var res + try { + if (replacerStack.length === 0) { + res = JSON.stringify(obj, replacer, spacer) + } else { + res = JSON.stringify(obj, replaceGetterValues(replacer), spacer) + } + } catch (_) { + return JSON.stringify('[unable to serialize, circular reference is too complex to analyze]') + } finally { + while (arr.length !== 0) { + var part = arr.pop() + if (part.length === 4) { + Object.defineProperty(part[0], part[1], part[3]) + } else { + part[0][part[1]] = part[2] + } + } + } + return res +} + +function setReplace (replace, val, k, parent) { + var propertyDescriptor = Object.getOwnPropertyDescriptor(parent, k) + if (propertyDescriptor.get !== undefined) { + if (propertyDescriptor.configurable) { + Object.defineProperty(parent, k, { value: replace }) + arr.push([parent, k, val, propertyDescriptor]) + } else { + replacerStack.push([val, k, replace]) + } + } else { + parent[k] = replace + arr.push([parent, k, val]) + } +} + +function decirc (val, k, edgeIndex, stack, parent, depth, options) { + depth += 1 + var i + if (typeof val === 'object' && val !== null) { + for (i = 0; i < stack.length; i++) { + if (stack[i] === val) { + setReplace(CIRCULAR_REPLACE_NODE, val, k, parent) + return + } + } + + if ( + typeof options.depthLimit !== 'undefined' && + depth > options.depthLimit + ) { + setReplace(LIMIT_REPLACE_NODE, val, k, parent) + return + } + + if ( + typeof options.edgesLimit !== 'undefined' && + edgeIndex + 1 > options.edgesLimit + ) { + setReplace(LIMIT_REPLACE_NODE, val, k, parent) + return + } + + stack.push(val) + // Optimize for Arrays. Big arrays could kill the performance otherwise! + if (Array.isArray(val)) { + for (i = 0; i < val.length; i++) { + decirc(val[i], i, i, stack, val, depth, options) + } + } else { + var keys = Object.keys(val) + for (i = 0; i < keys.length; i++) { + var key = keys[i] + decirc(val[key], key, i, stack, val, depth, options) + } + } + stack.pop() + } +} + +// Stable-stringify +function compareFunction (a, b) { + if (a < b) { + return -1 + } + if (a > b) { + return 1 + } + return 0 +} + +function deterministicStringify (obj, replacer, spacer, options) { + if (typeof options === 'undefined') { + options = defaultOptions() + } + + var tmp = deterministicDecirc(obj, '', 0, [], undefined, 0, options) || obj + var res + try { + if (replacerStack.length === 0) { + res = JSON.stringify(tmp, replacer, spacer) + } else { + res = JSON.stringify(tmp, replaceGetterValues(replacer), spacer) + } + } catch (_) { + return JSON.stringify('[unable to serialize, circular reference is too complex to analyze]') + } finally { + // Ensure that we restore the object as it was. + while (arr.length !== 0) { + var part = arr.pop() + if (part.length === 4) { + Object.defineProperty(part[0], part[1], part[3]) + } else { + part[0][part[1]] = part[2] + } + } + } + return res +} + +function deterministicDecirc (val, k, edgeIndex, stack, parent, depth, options) { + depth += 1 + var i + if (typeof val === 'object' && val !== null) { + for (i = 0; i < stack.length; i++) { + if (stack[i] === val) { + setReplace(CIRCULAR_REPLACE_NODE, val, k, parent) + return + } + } + try { + if (typeof val.toJSON === 'function') { + return + } + } catch (_) { + return + } + + if ( + typeof options.depthLimit !== 'undefined' && + depth > options.depthLimit + ) { + setReplace(LIMIT_REPLACE_NODE, val, k, parent) + return + } + + if ( + typeof options.edgesLimit !== 'undefined' && + edgeIndex + 1 > options.edgesLimit + ) { + setReplace(LIMIT_REPLACE_NODE, val, k, parent) + return + } + + stack.push(val) + // Optimize for Arrays. Big arrays could kill the performance otherwise! + if (Array.isArray(val)) { + for (i = 0; i < val.length; i++) { + deterministicDecirc(val[i], i, i, stack, val, depth, options) + } + } else { + // Create a temporary object in the required way + var tmp = {} + var keys = Object.keys(val).sort(compareFunction) + for (i = 0; i < keys.length; i++) { + var key = keys[i] + deterministicDecirc(val[key], key, i, stack, val, depth, options) + tmp[key] = val[key] + } + if (typeof parent !== 'undefined') { + arr.push([parent, k, val]) + parent[k] = tmp + } else { + return tmp + } + } + stack.pop() + } +} + +// wraps replacer function to handle values we couldn't replace +// and mark them as replaced value +function replaceGetterValues (replacer) { + replacer = + typeof replacer !== 'undefined' + ? replacer + : function (k, v) { + return v + } + return function (key, val) { + if (replacerStack.length > 0) { + for (var i = 0; i < replacerStack.length; i++) { + var part = replacerStack[i] + if (part[1] === key && part[0] === val) { + val = part[2] + replacerStack.splice(i, 1) + break + } + } + } + return replacer.call(this, key, val) + } +} diff --git a/action/node_modules/fast-safe-stringify/package.json b/action/node_modules/fast-safe-stringify/package.json new file mode 100644 index 00000000..206a5919 --- /dev/null +++ b/action/node_modules/fast-safe-stringify/package.json @@ -0,0 +1,46 @@ +{ + "name": "fast-safe-stringify", + "version": "2.1.1", + "description": "Safely and quickly serialize JavaScript objects", + "keywords": [ + "stable", + "stringify", + "JSON", + "JSON.stringify", + "safe", + "serialize" + ], + "main": "index.js", + "scripts": { + "test": "standard && tap --no-esm test.js test-stable.js", + "benchmark": "node benchmark.js" + }, + "author": "David Mark Clements", + "contributors": [ + "Ruben Bridgewater", + "Matteo Collina", + "Ben Gourley", + "Gabriel Lesperance", + "Alex Liu", + "Christoph Walcher", + "Nicholas Young" + ], + "license": "MIT", + "typings": "index", + "devDependencies": { + "benchmark": "^2.1.4", + "clone": "^2.1.0", + "json-stringify-safe": "^5.0.1", + "standard": "^11.0.0", + "tap": "^12.0.0" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/davidmarkclements/fast-safe-stringify.git" + }, + "bugs": { + "url": "https://github.com/davidmarkclements/fast-safe-stringify/issues" + }, + "homepage": "https://github.com/davidmarkclements/fast-safe-stringify#readme", + "dependencies": {} +} diff --git a/action/node_modules/fast-safe-stringify/readme.md b/action/node_modules/fast-safe-stringify/readme.md new file mode 100644 index 00000000..47179c94 --- /dev/null +++ b/action/node_modules/fast-safe-stringify/readme.md @@ -0,0 +1,170 @@ +# fast-safe-stringify + +Safe and fast serialization alternative to [JSON.stringify][]. + +Gracefully handles circular structures instead of throwing in most cases. +It could return an error string if the circular object is too complex to analyze, +e.g. in case there are proxies involved. + +Provides a deterministic ("stable") version as well that will also gracefully +handle circular structures. See the example below for further information. + +## Usage + +The same as [JSON.stringify][]. + +`stringify(value[, replacer[, space[, options]]])` + +```js +const safeStringify = require('fast-safe-stringify') +const o = { a: 1 } +o.o = o + +console.log(safeStringify(o)) +// '{"a":1,"o":"[Circular]"}' +console.log(JSON.stringify(o)) +// TypeError: Converting circular structure to JSON + +function replacer(key, value) { + console.log('Key:', JSON.stringify(key), 'Value:', JSON.stringify(value)) + // Remove the circular structure + if (value === '[Circular]') { + return + } + return value +} + +// those are also defaults limits when no options object is passed into safeStringify +// configure it to lower the limit. +const options = { + depthLimit: Number.MAX_SAFE_INTEGER, + edgesLimit: Number.MAX_SAFE_INTEGER +}; + +const serialized = safeStringify(o, replacer, 2, options) +// Key: "" Value: {"a":1,"o":"[Circular]"} +// Key: "a" Value: 1 +// Key: "o" Value: "[Circular]" +console.log(serialized) +// { +// "a": 1 +// } +``` + + +Using the deterministic version also works the same: + +```js +const safeStringify = require('fast-safe-stringify') +const o = { b: 1, a: 0 } +o.o = o + +console.log(safeStringify(o)) +// '{"b":1,"a":0,"o":"[Circular]"}' +console.log(safeStringify.stableStringify(o)) +// '{"a":0,"b":1,"o":"[Circular]"}' +console.log(JSON.stringify(o)) +// TypeError: Converting circular structure to JSON +``` + +A faster and side-effect free implementation is available in the +[safe-stable-stringify][] module. However it is still considered experimental +due to a new and more complex implementation. + +### Replace strings constants + +- `[Circular]` - when same reference is found +- `[...]` - when some limit from options object is reached + +## Differences to JSON.stringify + +In general the behavior is identical to [JSON.stringify][]. The [`replacer`][] +and [`space`][] options are also available. + +A few exceptions exist to [JSON.stringify][] while using [`toJSON`][] or +[`replacer`][]: + +### Regular safe stringify + +- Manipulating a circular structure of the passed in value in a `toJSON` or the + `replacer` is not possible! It is possible for any other value and property. + +- In case a circular structure is detected and the [`replacer`][] is used it + will receive the string `[Circular]` as the argument instead of the circular + object itself. + +### Deterministic ("stable") safe stringify + +- Manipulating the input object either in a [`toJSON`][] or the [`replacer`][] + function will not have any effect on the output. The output entirely relies on + the shape the input value had at the point passed to the stringify function! + +- In case a circular structure is detected and the [`replacer`][] is used it + will receive the string `[Circular]` as the argument instead of the circular + object itself. + +A side effect free variation without these limitations can be found as well +([`safe-stable-stringify`][]). It is also faster than the current +implementation. It is still considered experimental due to a new and more +complex implementation. + +## Benchmarks + +Although not JSON, the Node.js `util.inspect` method can be used for similar +purposes (e.g. logging) and also handles circular references. + +Here we compare `fast-safe-stringify` with some alternatives: +(Lenovo T450s with a i7-5600U CPU using Node.js 8.9.4) + +```md +fast-safe-stringify: simple object x 1,121,497 ops/sec ±0.75% (97 runs sampled) +fast-safe-stringify: circular x 560,126 ops/sec ±0.64% (96 runs sampled) +fast-safe-stringify: deep x 32,472 ops/sec ±0.57% (95 runs sampled) +fast-safe-stringify: deep circular x 32,513 ops/sec ±0.80% (92 runs sampled) + +util.inspect: simple object x 272,837 ops/sec ±1.48% (90 runs sampled) +util.inspect: circular x 116,896 ops/sec ±1.19% (95 runs sampled) +util.inspect: deep x 19,382 ops/sec ±0.66% (92 runs sampled) +util.inspect: deep circular x 18,717 ops/sec ±0.63% (96 runs sampled) + +json-stringify-safe: simple object x 233,621 ops/sec ±0.97% (94 runs sampled) +json-stringify-safe: circular x 110,409 ops/sec ±1.85% (95 runs sampled) +json-stringify-safe: deep x 8,705 ops/sec ±0.87% (96 runs sampled) +json-stringify-safe: deep circular x 8,336 ops/sec ±2.20% (93 runs sampled) +``` + +For stable stringify comparisons, see the performance benchmarks in the +[`safe-stable-stringify`][] readme. + +## Protip + +Whether `fast-safe-stringify` or alternatives are used: if the use case +consists of deeply nested objects without circular references the following +pattern will give best results. +Shallow or one level nested objects on the other hand will slow down with it. +It is entirely dependant on the use case. + +```js +const stringify = require('fast-safe-stringify') + +function tryJSONStringify (obj) { + try { return JSON.stringify(obj) } catch (_) {} +} + +const serializedString = tryJSONStringify(deep) || stringify(deep) +``` + +## Acknowledgements + +Sponsored by [nearForm](http://nearform.com) + +## License + +MIT + +[`replacer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The%20replacer%20parameter +[`safe-stable-stringify`]: https://github.com/BridgeAR/safe-stable-stringify +[`space`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The%20space%20argument +[`toJSON`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#toJSON()_behavior +[benchmark]: https://github.com/epoberezkin/fast-json-stable-stringify/blob/67f688f7441010cfef91a6147280cc501701e83b/benchmark +[JSON.stringify]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify diff --git a/action/node_modules/fast-safe-stringify/test-stable.js b/action/node_modules/fast-safe-stringify/test-stable.js new file mode 100644 index 00000000..c55b95ca --- /dev/null +++ b/action/node_modules/fast-safe-stringify/test-stable.js @@ -0,0 +1,404 @@ +const test = require('tap').test +const fss = require('./').stable +const clone = require('clone') +const s = JSON.stringify +const stream = require('stream') + +test('circular reference to root', function (assert) { + const fixture = { name: 'Tywin Lannister' } + fixture.circle = fixture + const expected = s({ circle: '[Circular]', name: 'Tywin Lannister' }) + const actual = fss(fixture) + assert.equal(actual, expected) + assert.end() +}) + +test('circular getter reference to root', function (assert) { + const fixture = { + name: 'Tywin Lannister', + get circle () { + return fixture + } + } + + const expected = s({ circle: '[Circular]', name: 'Tywin Lannister' }) + const actual = fss(fixture) + assert.equal(actual, expected) + assert.end() +}) + +test('nested circular reference to root', function (assert) { + const fixture = { name: 'Tywin Lannister' } + fixture.id = { circle: fixture } + const expected = s({ id: { circle: '[Circular]' }, name: 'Tywin Lannister' }) + const actual = fss(fixture) + assert.equal(actual, expected) + assert.end() +}) + +test('child circular reference', function (assert) { + const fixture = { + name: 'Tywin Lannister', + child: { name: 'Tyrion Lannister' } + } + fixture.child.dinklage = fixture.child + const expected = s({ + child: { + dinklage: '[Circular]', + name: 'Tyrion Lannister' + }, + name: 'Tywin Lannister' + }) + const actual = fss(fixture) + assert.equal(actual, expected) + assert.end() +}) + +test('nested child circular reference', function (assert) { + const fixture = { + name: 'Tywin Lannister', + child: { name: 'Tyrion Lannister' } + } + fixture.child.actor = { dinklage: fixture.child } + const expected = s({ + child: { + actor: { dinklage: '[Circular]' }, + name: 'Tyrion Lannister' + }, + name: 'Tywin Lannister' + }) + const actual = fss(fixture) + assert.equal(actual, expected) + assert.end() +}) + +test('circular objects in an array', function (assert) { + const fixture = { name: 'Tywin Lannister' } + fixture.hand = [fixture, fixture] + const expected = s({ + hand: ['[Circular]', '[Circular]'], + name: 'Tywin Lannister' + }) + const actual = fss(fixture) + assert.equal(actual, expected) + assert.end() +}) + +test('nested circular references in an array', function (assert) { + const fixture = { + name: 'Tywin Lannister', + offspring: [{ name: 'Tyrion Lannister' }, { name: 'Cersei Lannister' }] + } + fixture.offspring[0].dinklage = fixture.offspring[0] + fixture.offspring[1].headey = fixture.offspring[1] + + const expected = s({ + name: 'Tywin Lannister', + offspring: [ + { dinklage: '[Circular]', name: 'Tyrion Lannister' }, + { headey: '[Circular]', name: 'Cersei Lannister' } + ] + }) + const actual = fss(fixture) + assert.equal(actual, expected) + assert.end() +}) + +test('circular arrays', function (assert) { + const fixture = [] + fixture.push(fixture, fixture) + const expected = s(['[Circular]', '[Circular]']) + const actual = fss(fixture) + assert.equal(actual, expected) + assert.end() +}) + +test('nested circular arrays', function (assert) { + const fixture = [] + fixture.push( + { name: 'Jon Snow', bastards: fixture }, + { name: 'Ramsay Bolton', bastards: fixture } + ) + const expected = s([ + { bastards: '[Circular]', name: 'Jon Snow' }, + { bastards: '[Circular]', name: 'Ramsay Bolton' } + ]) + const actual = fss(fixture) + assert.equal(actual, expected) + assert.end() +}) + +test('repeated non-circular references in objects', function (assert) { + const daenerys = { name: 'Daenerys Targaryen' } + const fixture = { + motherOfDragons: daenerys, + queenOfMeereen: daenerys + } + const expected = s(fixture) + const actual = fss(fixture) + assert.equal(actual, expected) + assert.end() +}) + +test('repeated non-circular references in arrays', function (assert) { + const daenerys = { name: 'Daenerys Targaryen' } + const fixture = [daenerys, daenerys] + const expected = s(fixture) + const actual = fss(fixture) + assert.equal(actual, expected) + assert.end() +}) + +test('double child circular reference', function (assert) { + // create circular reference + const child = { name: 'Tyrion Lannister' } + child.dinklage = child + + // include it twice in the fixture + const fixture = { name: 'Tywin Lannister', childA: child, childB: child } + const cloned = clone(fixture) + const expected = s({ + childA: { + dinklage: '[Circular]', + name: 'Tyrion Lannister' + }, + childB: { + dinklage: '[Circular]', + name: 'Tyrion Lannister' + }, + name: 'Tywin Lannister' + }) + const actual = fss(fixture) + assert.equal(actual, expected) + + // check if the fixture has not been modified + assert.same(fixture, cloned) + assert.end() +}) + +test('child circular reference with toJSON', function (assert) { + // Create a test object that has an overridden `toJSON` property + TestObject.prototype.toJSON = function () { + return { special: 'case' } + } + function TestObject (content) {} + + // Creating a simple circular object structure + const parentObject = {} + parentObject.childObject = new TestObject() + parentObject.childObject.parentObject = parentObject + + // Creating a simple circular object structure + const otherParentObject = new TestObject() + otherParentObject.otherChildObject = {} + otherParentObject.otherChildObject.otherParentObject = otherParentObject + + // Making sure our original tests work + assert.same(parentObject.childObject.parentObject, parentObject) + assert.same( + otherParentObject.otherChildObject.otherParentObject, + otherParentObject + ) + + // Should both be idempotent + assert.equal(fss(parentObject), '{"childObject":{"special":"case"}}') + assert.equal(fss(otherParentObject), '{"special":"case"}') + + // Therefore the following assertion should be `true` + assert.same(parentObject.childObject.parentObject, parentObject) + assert.same( + otherParentObject.otherChildObject.otherParentObject, + otherParentObject + ) + + assert.end() +}) + +test('null object', function (assert) { + const expected = s(null) + const actual = fss(null) + assert.equal(actual, expected) + assert.end() +}) + +test('null property', function (assert) { + const expected = s({ f: null }) + const actual = fss({ f: null }) + assert.equal(actual, expected) + assert.end() +}) + +test('nested child circular reference in toJSON', function (assert) { + var circle = { some: 'data' } + circle.circle = circle + var a = { + b: { + toJSON: function () { + a.b = 2 + return '[Redacted]' + } + }, + baz: { + circle, + toJSON: function () { + a.baz = circle + return '[Redacted]' + } + } + } + var o = { + a, + bar: a + } + + const expected = s({ + a: { + b: '[Redacted]', + baz: '[Redacted]' + }, + bar: { + // TODO: This is a known limitation of the current implementation. + // The ideal result would be: + // + // b: 2, + // baz: { + // circle: '[Circular]', + // some: 'data' + // } + // + b: '[Redacted]', + baz: '[Redacted]' + } + }) + const actual = fss(o) + assert.equal(actual, expected) + assert.end() +}) + +test('circular getters are restored when stringified', function (assert) { + const fixture = { + name: 'Tywin Lannister', + get circle () { + return fixture + } + } + fss(fixture) + + assert.equal(fixture.circle, fixture) + assert.end() +}) + +test('non-configurable circular getters use a replacer instead of markers', function (assert) { + const fixture = { name: 'Tywin Lannister' } + Object.defineProperty(fixture, 'circle', { + configurable: false, + get: function () { + return fixture + }, + enumerable: true + }) + + fss(fixture) + + assert.equal(fixture.circle, fixture) + assert.end() +}) + +test('getter child circular reference', function (assert) { + const fixture = { + name: 'Tywin Lannister', + child: { + name: 'Tyrion Lannister', + get dinklage () { + return fixture.child + } + }, + get self () { + return fixture + } + } + + const expected = s({ + child: { + dinklage: '[Circular]', + name: 'Tyrion Lannister' + }, + name: 'Tywin Lannister', + self: '[Circular]' + }) + const actual = fss(fixture) + assert.equal(actual, expected) + assert.end() +}) + +test('Proxy throwing', function (assert) { + assert.plan(1) + const s = new stream.PassThrough() + s.resume() + s.write('', () => { + assert.end() + }) + const actual = fss({ s, p: new Proxy({}, { get () { throw new Error('kaboom') } }) }) + assert.equal(actual, '"[unable to serialize, circular reference is too complex to analyze]"') +}) + +test('depthLimit option - will replace deep objects', function (assert) { + const fixture = { + name: 'Tywin Lannister', + child: { + name: 'Tyrion Lannister' + }, + get self () { + return fixture + } + } + + const expected = s({ + child: '[...]', + name: 'Tywin Lannister', + self: '[Circular]' + }) + const actual = fss(fixture, undefined, undefined, { + depthLimit: 1, + edgesLimit: 1 + }) + assert.equal(actual, expected) + assert.end() +}) + +test('edgesLimit option - will replace deep objects', function (assert) { + const fixture = { + object: { + 1: { test: 'test' }, + 2: { test: 'test' }, + 3: { test: 'test' }, + 4: { test: 'test' } + }, + array: [ + { test: 'test' }, + { test: 'test' }, + { test: 'test' }, + { test: 'test' } + ], + get self () { + return fixture + } + } + + const expected = s({ + array: [{ test: 'test' }, { test: 'test' }, { test: 'test' }, '[...]'], + object: { + 1: { test: 'test' }, + 2: { test: 'test' }, + 3: { test: 'test' }, + 4: '[...]' + }, + self: '[Circular]' + }) + const actual = fss(fixture, undefined, undefined, { + depthLimit: 3, + edgesLimit: 3 + }) + assert.equal(actual, expected) + assert.end() +}) diff --git a/action/node_modules/fast-safe-stringify/test.js b/action/node_modules/fast-safe-stringify/test.js new file mode 100644 index 00000000..a4170e96 --- /dev/null +++ b/action/node_modules/fast-safe-stringify/test.js @@ -0,0 +1,397 @@ +const test = require('tap').test +const fss = require('./') +const clone = require('clone') +const s = JSON.stringify +const stream = require('stream') + +test('circular reference to root', function (assert) { + const fixture = { name: 'Tywin Lannister' } + fixture.circle = fixture + const expected = s({ name: 'Tywin Lannister', circle: '[Circular]' }) + const actual = fss(fixture) + assert.equal(actual, expected) + assert.end() +}) + +test('circular getter reference to root', function (assert) { + const fixture = { + name: 'Tywin Lannister', + get circle () { + return fixture + } + } + const expected = s({ name: 'Tywin Lannister', circle: '[Circular]' }) + const actual = fss(fixture) + assert.equal(actual, expected) + assert.end() +}) + +test('nested circular reference to root', function (assert) { + const fixture = { name: 'Tywin Lannister' } + fixture.id = { circle: fixture } + const expected = s({ name: 'Tywin Lannister', id: { circle: '[Circular]' } }) + const actual = fss(fixture) + assert.equal(actual, expected) + assert.end() +}) + +test('child circular reference', function (assert) { + const fixture = { + name: 'Tywin Lannister', + child: { name: 'Tyrion Lannister' } + } + fixture.child.dinklage = fixture.child + const expected = s({ + name: 'Tywin Lannister', + child: { + name: 'Tyrion Lannister', + dinklage: '[Circular]' + } + }) + const actual = fss(fixture) + assert.equal(actual, expected) + assert.end() +}) + +test('nested child circular reference', function (assert) { + const fixture = { + name: 'Tywin Lannister', + child: { name: 'Tyrion Lannister' } + } + fixture.child.actor = { dinklage: fixture.child } + const expected = s({ + name: 'Tywin Lannister', + child: { + name: 'Tyrion Lannister', + actor: { dinklage: '[Circular]' } + } + }) + const actual = fss(fixture) + assert.equal(actual, expected) + assert.end() +}) + +test('circular objects in an array', function (assert) { + const fixture = { name: 'Tywin Lannister' } + fixture.hand = [fixture, fixture] + const expected = s({ + name: 'Tywin Lannister', + hand: ['[Circular]', '[Circular]'] + }) + const actual = fss(fixture) + assert.equal(actual, expected) + assert.end() +}) + +test('nested circular references in an array', function (assert) { + const fixture = { + name: 'Tywin Lannister', + offspring: [{ name: 'Tyrion Lannister' }, { name: 'Cersei Lannister' }] + } + fixture.offspring[0].dinklage = fixture.offspring[0] + fixture.offspring[1].headey = fixture.offspring[1] + + const expected = s({ + name: 'Tywin Lannister', + offspring: [ + { name: 'Tyrion Lannister', dinklage: '[Circular]' }, + { name: 'Cersei Lannister', headey: '[Circular]' } + ] + }) + const actual = fss(fixture) + assert.equal(actual, expected) + assert.end() +}) + +test('circular arrays', function (assert) { + const fixture = [] + fixture.push(fixture, fixture) + const expected = s(['[Circular]', '[Circular]']) + const actual = fss(fixture) + assert.equal(actual, expected) + assert.end() +}) + +test('nested circular arrays', function (assert) { + const fixture = [] + fixture.push( + { name: 'Jon Snow', bastards: fixture }, + { name: 'Ramsay Bolton', bastards: fixture } + ) + const expected = s([ + { name: 'Jon Snow', bastards: '[Circular]' }, + { name: 'Ramsay Bolton', bastards: '[Circular]' } + ]) + const actual = fss(fixture) + assert.equal(actual, expected) + assert.end() +}) + +test('repeated non-circular references in objects', function (assert) { + const daenerys = { name: 'Daenerys Targaryen' } + const fixture = { + motherOfDragons: daenerys, + queenOfMeereen: daenerys + } + const expected = s(fixture) + const actual = fss(fixture) + assert.equal(actual, expected) + assert.end() +}) + +test('repeated non-circular references in arrays', function (assert) { + const daenerys = { name: 'Daenerys Targaryen' } + const fixture = [daenerys, daenerys] + const expected = s(fixture) + const actual = fss(fixture) + assert.equal(actual, expected) + assert.end() +}) + +test('double child circular reference', function (assert) { + // create circular reference + const child = { name: 'Tyrion Lannister' } + child.dinklage = child + + // include it twice in the fixture + const fixture = { name: 'Tywin Lannister', childA: child, childB: child } + const cloned = clone(fixture) + const expected = s({ + name: 'Tywin Lannister', + childA: { + name: 'Tyrion Lannister', + dinklage: '[Circular]' + }, + childB: { + name: 'Tyrion Lannister', + dinklage: '[Circular]' + } + }) + const actual = fss(fixture) + assert.equal(actual, expected) + + // check if the fixture has not been modified + assert.same(fixture, cloned) + assert.end() +}) + +test('child circular reference with toJSON', function (assert) { + // Create a test object that has an overridden `toJSON` property + TestObject.prototype.toJSON = function () { + return { special: 'case' } + } + function TestObject (content) {} + + // Creating a simple circular object structure + const parentObject = {} + parentObject.childObject = new TestObject() + parentObject.childObject.parentObject = parentObject + + // Creating a simple circular object structure + const otherParentObject = new TestObject() + otherParentObject.otherChildObject = {} + otherParentObject.otherChildObject.otherParentObject = otherParentObject + + // Making sure our original tests work + assert.same(parentObject.childObject.parentObject, parentObject) + assert.same( + otherParentObject.otherChildObject.otherParentObject, + otherParentObject + ) + + // Should both be idempotent + assert.equal(fss(parentObject), '{"childObject":{"special":"case"}}') + assert.equal(fss(otherParentObject), '{"special":"case"}') + + // Therefore the following assertion should be `true` + assert.same(parentObject.childObject.parentObject, parentObject) + assert.same( + otherParentObject.otherChildObject.otherParentObject, + otherParentObject + ) + + assert.end() +}) + +test('null object', function (assert) { + const expected = s(null) + const actual = fss(null) + assert.equal(actual, expected) + assert.end() +}) + +test('null property', function (assert) { + const expected = s({ f: null }) + const actual = fss({ f: null }) + assert.equal(actual, expected) + assert.end() +}) + +test('nested child circular reference in toJSON', function (assert) { + const circle = { some: 'data' } + circle.circle = circle + const a = { + b: { + toJSON: function () { + a.b = 2 + return '[Redacted]' + } + }, + baz: { + circle, + toJSON: function () { + a.baz = circle + return '[Redacted]' + } + } + } + const o = { + a, + bar: a + } + + const expected = s({ + a: { + b: '[Redacted]', + baz: '[Redacted]' + }, + bar: { + b: 2, + baz: { + some: 'data', + circle: '[Circular]' + } + } + }) + const actual = fss(o) + assert.equal(actual, expected) + assert.end() +}) + +test('circular getters are restored when stringified', function (assert) { + const fixture = { + name: 'Tywin Lannister', + get circle () { + return fixture + } + } + fss(fixture) + + assert.equal(fixture.circle, fixture) + assert.end() +}) + +test('non-configurable circular getters use a replacer instead of markers', function (assert) { + const fixture = { name: 'Tywin Lannister' } + Object.defineProperty(fixture, 'circle', { + configurable: false, + get: function () { + return fixture + }, + enumerable: true + }) + + fss(fixture) + + assert.equal(fixture.circle, fixture) + assert.end() +}) + +test('getter child circular reference are replaced instead of marked', function (assert) { + const fixture = { + name: 'Tywin Lannister', + child: { + name: 'Tyrion Lannister', + get dinklage () { + return fixture.child + } + }, + get self () { + return fixture + } + } + + const expected = s({ + name: 'Tywin Lannister', + child: { + name: 'Tyrion Lannister', + dinklage: '[Circular]' + }, + self: '[Circular]' + }) + const actual = fss(fixture) + assert.equal(actual, expected) + assert.end() +}) + +test('Proxy throwing', function (assert) { + assert.plan(1) + const s = new stream.PassThrough() + s.resume() + s.write('', () => { + assert.end() + }) + const actual = fss({ s, p: new Proxy({}, { get () { throw new Error('kaboom') } }) }) + assert.equal(actual, '"[unable to serialize, circular reference is too complex to analyze]"') +}) + +test('depthLimit option - will replace deep objects', function (assert) { + const fixture = { + name: 'Tywin Lannister', + child: { + name: 'Tyrion Lannister' + }, + get self () { + return fixture + } + } + + const expected = s({ + name: 'Tywin Lannister', + child: '[...]', + self: '[Circular]' + }) + const actual = fss(fixture, undefined, undefined, { + depthLimit: 1, + edgesLimit: 1 + }) + assert.equal(actual, expected) + assert.end() +}) + +test('edgesLimit option - will replace deep objects', function (assert) { + const fixture = { + object: { + 1: { test: 'test' }, + 2: { test: 'test' }, + 3: { test: 'test' }, + 4: { test: 'test' } + }, + array: [ + { test: 'test' }, + { test: 'test' }, + { test: 'test' }, + { test: 'test' } + ], + get self () { + return fixture + } + } + + const expected = s({ + object: { + 1: { test: 'test' }, + 2: { test: 'test' }, + 3: { test: 'test' }, + 4: '[...]' + }, + array: [{ test: 'test' }, { test: 'test' }, { test: 'test' }, '[...]'], + self: '[Circular]' + }) + const actual = fss(fixture, undefined, undefined, { + depthLimit: 3, + edgesLimit: 3 + }) + assert.equal(actual, expected) + assert.end() +}) diff --git a/action/node_modules/graceful-fs/LICENSE b/action/node_modules/graceful-fs/LICENSE new file mode 100644 index 00000000..e906a25a --- /dev/null +++ b/action/node_modules/graceful-fs/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) 2011-2022 Isaac Z. Schlueter, Ben Noordhuis, and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/action/node_modules/graceful-fs/README.md b/action/node_modules/graceful-fs/README.md new file mode 100644 index 00000000..82d6e4da --- /dev/null +++ b/action/node_modules/graceful-fs/README.md @@ -0,0 +1,143 @@ +# graceful-fs + +graceful-fs functions as a drop-in replacement for the fs module, +making various improvements. + +The improvements are meant to normalize behavior across different +platforms and environments, and to make filesystem access more +resilient to errors. + +## Improvements over [fs module](https://nodejs.org/api/fs.html) + +* Queues up `open` and `readdir` calls, and retries them once + something closes if there is an EMFILE error from too many file + descriptors. +* fixes `lchmod` for Node versions prior to 0.6.2. +* implements `fs.lutimes` if possible. Otherwise it becomes a noop. +* ignores `EINVAL` and `EPERM` errors in `chown`, `fchown` or + `lchown` if the user isn't root. +* makes `lchmod` and `lchown` become noops, if not available. +* retries reading a file if `read` results in EAGAIN error. + +On Windows, it retries renaming a file for up to one second if `EACCESS` +or `EPERM` error occurs, likely because antivirus software has locked +the directory. + +## USAGE + +```javascript +// use just like fs +var fs = require('graceful-fs') + +// now go and do stuff with it... +fs.readFile('some-file-or-whatever', (err, data) => { + // Do stuff here. +}) +``` + +## Sync methods + +This module cannot intercept or handle `EMFILE` or `ENFILE` errors from sync +methods. If you use sync methods which open file descriptors then you are +responsible for dealing with any errors. + +This is a known limitation, not a bug. + +## Global Patching + +If you want to patch the global fs module (or any other fs-like +module) you can do this: + +```javascript +// Make sure to read the caveat below. +var realFs = require('fs') +var gracefulFs = require('graceful-fs') +gracefulFs.gracefulify(realFs) +``` + +This should only ever be done at the top-level application layer, in +order to delay on EMFILE errors from any fs-using dependencies. You +should **not** do this in a library, because it can cause unexpected +delays in other parts of the program. + +## Changes + +This module is fairly stable at this point, and used by a lot of +things. That being said, because it implements a subtle behavior +change in a core part of the node API, even modest changes can be +extremely breaking, and the versioning is thus biased towards +bumping the major when in doubt. + +The main change between major versions has been switching between +providing a fully-patched `fs` module vs monkey-patching the node core +builtin, and the approach by which a non-monkey-patched `fs` was +created. + +The goal is to trade `EMFILE` errors for slower fs operations. So, if +you try to open a zillion files, rather than crashing, `open` +operations will be queued up and wait for something else to `close`. + +There are advantages to each approach. Monkey-patching the fs means +that no `EMFILE` errors can possibly occur anywhere in your +application, because everything is using the same core `fs` module, +which is patched. However, it can also obviously cause undesirable +side-effects, especially if the module is loaded multiple times. + +Implementing a separate-but-identical patched `fs` module is more +surgical (and doesn't run the risk of patching multiple times), but +also imposes the challenge of keeping in sync with the core module. + +The current approach loads the `fs` module, and then creates a +lookalike object that has all the same methods, except a few that are +patched. It is safe to use in all versions of Node from 0.8 through +7.0. + +### v4 + +* Do not monkey-patch the fs module. This module may now be used as a + drop-in dep, and users can opt into monkey-patching the fs builtin + if their app requires it. + +### v3 + +* Monkey-patch fs, because the eval approach no longer works on recent + node. +* fixed possible type-error throw if rename fails on windows +* verify that we *never* get EMFILE errors +* Ignore ENOSYS from chmod/chown +* clarify that graceful-fs must be used as a drop-in + +### v2.1.0 + +* Use eval rather than monkey-patching fs. +* readdir: Always sort the results +* win32: requeue a file if error has an OK status + +### v2.0 + +* A return to monkey patching +* wrap process.cwd + +### v1.1 + +* wrap readFile +* Wrap fs.writeFile. +* readdir protection +* Don't clobber the fs builtin +* Handle fs.read EAGAIN errors by trying again +* Expose the curOpen counter +* No-op lchown/lchmod if not implemented +* fs.rename patch only for win32 +* Patch fs.rename to handle AV software on Windows +* Close #4 Chown should not fail on einval or eperm if non-root +* Fix isaacs/fstream#1 Only wrap fs one time +* Fix #3 Start at 1024 max files, then back off on EMFILE +* lutimes that doens't blow up on Linux +* A full on-rewrite using a queue instead of just swallowing the EMFILE error +* Wrap Read/Write streams as well + +### 1.0 + +* Update engines for node 0.6 +* Be lstat-graceful on Windows +* first diff --git a/action/node_modules/graceful-fs/clone.js b/action/node_modules/graceful-fs/clone.js new file mode 100644 index 00000000..dff3cc8c --- /dev/null +++ b/action/node_modules/graceful-fs/clone.js @@ -0,0 +1,23 @@ +'use strict' + +module.exports = clone + +var getPrototypeOf = Object.getPrototypeOf || function (obj) { + return obj.__proto__ +} + +function clone (obj) { + if (obj === null || typeof obj !== 'object') + return obj + + if (obj instanceof Object) + var copy = { __proto__: getPrototypeOf(obj) } + else + var copy = Object.create(null) + + Object.getOwnPropertyNames(obj).forEach(function (key) { + Object.defineProperty(copy, key, Object.getOwnPropertyDescriptor(obj, key)) + }) + + return copy +} diff --git a/action/node_modules/graceful-fs/graceful-fs.js b/action/node_modules/graceful-fs/graceful-fs.js new file mode 100644 index 00000000..8d5b89e4 --- /dev/null +++ b/action/node_modules/graceful-fs/graceful-fs.js @@ -0,0 +1,448 @@ +var fs = require('fs') +var polyfills = require('./polyfills.js') +var legacy = require('./legacy-streams.js') +var clone = require('./clone.js') + +var util = require('util') + +/* istanbul ignore next - node 0.x polyfill */ +var gracefulQueue +var previousSymbol + +/* istanbul ignore else - node 0.x polyfill */ +if (typeof Symbol === 'function' && typeof Symbol.for === 'function') { + gracefulQueue = Symbol.for('graceful-fs.queue') + // This is used in testing by future versions + previousSymbol = Symbol.for('graceful-fs.previous') +} else { + gracefulQueue = '___graceful-fs.queue' + previousSymbol = '___graceful-fs.previous' +} + +function noop () {} + +function publishQueue(context, queue) { + Object.defineProperty(context, gracefulQueue, { + get: function() { + return queue + } + }) +} + +var debug = noop +if (util.debuglog) + debug = util.debuglog('gfs4') +else if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) + debug = function() { + var m = util.format.apply(util, arguments) + m = 'GFS4: ' + m.split(/\n/).join('\nGFS4: ') + console.error(m) + } + +// Once time initialization +if (!fs[gracefulQueue]) { + // This queue can be shared by multiple loaded instances + var queue = global[gracefulQueue] || [] + publishQueue(fs, queue) + + // Patch fs.close/closeSync to shared queue version, because we need + // to retry() whenever a close happens *anywhere* in the program. + // This is essential when multiple graceful-fs instances are + // in play at the same time. + fs.close = (function (fs$close) { + function close (fd, cb) { + return fs$close.call(fs, fd, function (err) { + // This function uses the graceful-fs shared queue + if (!err) { + resetQueue() + } + + if (typeof cb === 'function') + cb.apply(this, arguments) + }) + } + + Object.defineProperty(close, previousSymbol, { + value: fs$close + }) + return close + })(fs.close) + + fs.closeSync = (function (fs$closeSync) { + function closeSync (fd) { + // This function uses the graceful-fs shared queue + fs$closeSync.apply(fs, arguments) + resetQueue() + } + + Object.defineProperty(closeSync, previousSymbol, { + value: fs$closeSync + }) + return closeSync + })(fs.closeSync) + + if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) { + process.on('exit', function() { + debug(fs[gracefulQueue]) + require('assert').equal(fs[gracefulQueue].length, 0) + }) + } +} + +if (!global[gracefulQueue]) { + publishQueue(global, fs[gracefulQueue]); +} + +module.exports = patch(clone(fs)) +if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs.__patched) { + module.exports = patch(fs) + fs.__patched = true; +} + +function patch (fs) { + // Everything that references the open() function needs to be in here + polyfills(fs) + fs.gracefulify = patch + + fs.createReadStream = createReadStream + fs.createWriteStream = createWriteStream + var fs$readFile = fs.readFile + fs.readFile = readFile + function readFile (path, options, cb) { + if (typeof options === 'function') + cb = options, options = null + + return go$readFile(path, options, cb) + + function go$readFile (path, options, cb, startTime) { + return fs$readFile(path, options, function (err) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$readFile, [path, options, cb], err, startTime || Date.now(), Date.now()]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + } + }) + } + } + + var fs$writeFile = fs.writeFile + fs.writeFile = writeFile + function writeFile (path, data, options, cb) { + if (typeof options === 'function') + cb = options, options = null + + return go$writeFile(path, data, options, cb) + + function go$writeFile (path, data, options, cb, startTime) { + return fs$writeFile(path, data, options, function (err) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$writeFile, [path, data, options, cb], err, startTime || Date.now(), Date.now()]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + } + }) + } + } + + var fs$appendFile = fs.appendFile + if (fs$appendFile) + fs.appendFile = appendFile + function appendFile (path, data, options, cb) { + if (typeof options === 'function') + cb = options, options = null + + return go$appendFile(path, data, options, cb) + + function go$appendFile (path, data, options, cb, startTime) { + return fs$appendFile(path, data, options, function (err) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$appendFile, [path, data, options, cb], err, startTime || Date.now(), Date.now()]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + } + }) + } + } + + var fs$copyFile = fs.copyFile + if (fs$copyFile) + fs.copyFile = copyFile + function copyFile (src, dest, flags, cb) { + if (typeof flags === 'function') { + cb = flags + flags = 0 + } + return go$copyFile(src, dest, flags, cb) + + function go$copyFile (src, dest, flags, cb, startTime) { + return fs$copyFile(src, dest, flags, function (err) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$copyFile, [src, dest, flags, cb], err, startTime || Date.now(), Date.now()]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + } + }) + } + } + + var fs$readdir = fs.readdir + fs.readdir = readdir + var noReaddirOptionVersions = /^v[0-5]\./ + function readdir (path, options, cb) { + if (typeof options === 'function') + cb = options, options = null + + var go$readdir = noReaddirOptionVersions.test(process.version) + ? function go$readdir (path, options, cb, startTime) { + return fs$readdir(path, fs$readdirCallback( + path, options, cb, startTime + )) + } + : function go$readdir (path, options, cb, startTime) { + return fs$readdir(path, options, fs$readdirCallback( + path, options, cb, startTime + )) + } + + return go$readdir(path, options, cb) + + function fs$readdirCallback (path, options, cb, startTime) { + return function (err, files) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([ + go$readdir, + [path, options, cb], + err, + startTime || Date.now(), + Date.now() + ]) + else { + if (files && files.sort) + files.sort() + + if (typeof cb === 'function') + cb.call(this, err, files) + } + } + } + } + + if (process.version.substr(0, 4) === 'v0.8') { + var legStreams = legacy(fs) + ReadStream = legStreams.ReadStream + WriteStream = legStreams.WriteStream + } + + var fs$ReadStream = fs.ReadStream + if (fs$ReadStream) { + ReadStream.prototype = Object.create(fs$ReadStream.prototype) + ReadStream.prototype.open = ReadStream$open + } + + var fs$WriteStream = fs.WriteStream + if (fs$WriteStream) { + WriteStream.prototype = Object.create(fs$WriteStream.prototype) + WriteStream.prototype.open = WriteStream$open + } + + Object.defineProperty(fs, 'ReadStream', { + get: function () { + return ReadStream + }, + set: function (val) { + ReadStream = val + }, + enumerable: true, + configurable: true + }) + Object.defineProperty(fs, 'WriteStream', { + get: function () { + return WriteStream + }, + set: function (val) { + WriteStream = val + }, + enumerable: true, + configurable: true + }) + + // legacy names + var FileReadStream = ReadStream + Object.defineProperty(fs, 'FileReadStream', { + get: function () { + return FileReadStream + }, + set: function (val) { + FileReadStream = val + }, + enumerable: true, + configurable: true + }) + var FileWriteStream = WriteStream + Object.defineProperty(fs, 'FileWriteStream', { + get: function () { + return FileWriteStream + }, + set: function (val) { + FileWriteStream = val + }, + enumerable: true, + configurable: true + }) + + function ReadStream (path, options) { + if (this instanceof ReadStream) + return fs$ReadStream.apply(this, arguments), this + else + return ReadStream.apply(Object.create(ReadStream.prototype), arguments) + } + + function ReadStream$open () { + var that = this + open(that.path, that.flags, that.mode, function (err, fd) { + if (err) { + if (that.autoClose) + that.destroy() + + that.emit('error', err) + } else { + that.fd = fd + that.emit('open', fd) + that.read() + } + }) + } + + function WriteStream (path, options) { + if (this instanceof WriteStream) + return fs$WriteStream.apply(this, arguments), this + else + return WriteStream.apply(Object.create(WriteStream.prototype), arguments) + } + + function WriteStream$open () { + var that = this + open(that.path, that.flags, that.mode, function (err, fd) { + if (err) { + that.destroy() + that.emit('error', err) + } else { + that.fd = fd + that.emit('open', fd) + } + }) + } + + function createReadStream (path, options) { + return new fs.ReadStream(path, options) + } + + function createWriteStream (path, options) { + return new fs.WriteStream(path, options) + } + + var fs$open = fs.open + fs.open = open + function open (path, flags, mode, cb) { + if (typeof mode === 'function') + cb = mode, mode = null + + return go$open(path, flags, mode, cb) + + function go$open (path, flags, mode, cb, startTime) { + return fs$open(path, flags, mode, function (err, fd) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$open, [path, flags, mode, cb], err, startTime || Date.now(), Date.now()]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + } + }) + } + } + + return fs +} + +function enqueue (elem) { + debug('ENQUEUE', elem[0].name, elem[1]) + fs[gracefulQueue].push(elem) + retry() +} + +// keep track of the timeout between retry() calls +var retryTimer + +// reset the startTime and lastTime to now +// this resets the start of the 60 second overall timeout as well as the +// delay between attempts so that we'll retry these jobs sooner +function resetQueue () { + var now = Date.now() + for (var i = 0; i < fs[gracefulQueue].length; ++i) { + // entries that are only a length of 2 are from an older version, don't + // bother modifying those since they'll be retried anyway. + if (fs[gracefulQueue][i].length > 2) { + fs[gracefulQueue][i][3] = now // startTime + fs[gracefulQueue][i][4] = now // lastTime + } + } + // call retry to make sure we're actively processing the queue + retry() +} + +function retry () { + // clear the timer and remove it to help prevent unintended concurrency + clearTimeout(retryTimer) + retryTimer = undefined + + if (fs[gracefulQueue].length === 0) + return + + var elem = fs[gracefulQueue].shift() + var fn = elem[0] + var args = elem[1] + // these items may be unset if they were added by an older graceful-fs + var err = elem[2] + var startTime = elem[3] + var lastTime = elem[4] + + // if we don't have a startTime we have no way of knowing if we've waited + // long enough, so go ahead and retry this item now + if (startTime === undefined) { + debug('RETRY', fn.name, args) + fn.apply(null, args) + } else if (Date.now() - startTime >= 60000) { + // it's been more than 60 seconds total, bail now + debug('TIMEOUT', fn.name, args) + var cb = args.pop() + if (typeof cb === 'function') + cb.call(null, err) + } else { + // the amount of time between the last attempt and right now + var sinceAttempt = Date.now() - lastTime + // the amount of time between when we first tried, and when we last tried + // rounded up to at least 1 + var sinceStart = Math.max(lastTime - startTime, 1) + // backoff. wait longer than the total time we've been retrying, but only + // up to a maximum of 100ms + var desiredDelay = Math.min(sinceStart * 1.2, 100) + // it's been long enough since the last retry, do it again + if (sinceAttempt >= desiredDelay) { + debug('RETRY', fn.name, args) + fn.apply(null, args.concat([startTime])) + } else { + // if we can't do this job yet, push it to the end of the queue + // and let the next iteration check again + fs[gracefulQueue].push(elem) + } + } + + // schedule our next run if one isn't already scheduled + if (retryTimer === undefined) { + retryTimer = setTimeout(retry, 0) + } +} diff --git a/action/node_modules/graceful-fs/legacy-streams.js b/action/node_modules/graceful-fs/legacy-streams.js new file mode 100644 index 00000000..d617b50f --- /dev/null +++ b/action/node_modules/graceful-fs/legacy-streams.js @@ -0,0 +1,118 @@ +var Stream = require('stream').Stream + +module.exports = legacy + +function legacy (fs) { + return { + ReadStream: ReadStream, + WriteStream: WriteStream + } + + function ReadStream (path, options) { + if (!(this instanceof ReadStream)) return new ReadStream(path, options); + + Stream.call(this); + + var self = this; + + this.path = path; + this.fd = null; + this.readable = true; + this.paused = false; + + this.flags = 'r'; + this.mode = 438; /*=0666*/ + this.bufferSize = 64 * 1024; + + options = options || {}; + + // Mixin options into this + var keys = Object.keys(options); + for (var index = 0, length = keys.length; index < length; index++) { + var key = keys[index]; + this[key] = options[key]; + } + + if (this.encoding) this.setEncoding(this.encoding); + + if (this.start !== undefined) { + if ('number' !== typeof this.start) { + throw TypeError('start must be a Number'); + } + if (this.end === undefined) { + this.end = Infinity; + } else if ('number' !== typeof this.end) { + throw TypeError('end must be a Number'); + } + + if (this.start > this.end) { + throw new Error('start must be <= end'); + } + + this.pos = this.start; + } + + if (this.fd !== null) { + process.nextTick(function() { + self._read(); + }); + return; + } + + fs.open(this.path, this.flags, this.mode, function (err, fd) { + if (err) { + self.emit('error', err); + self.readable = false; + return; + } + + self.fd = fd; + self.emit('open', fd); + self._read(); + }) + } + + function WriteStream (path, options) { + if (!(this instanceof WriteStream)) return new WriteStream(path, options); + + Stream.call(this); + + this.path = path; + this.fd = null; + this.writable = true; + + this.flags = 'w'; + this.encoding = 'binary'; + this.mode = 438; /*=0666*/ + this.bytesWritten = 0; + + options = options || {}; + + // Mixin options into this + var keys = Object.keys(options); + for (var index = 0, length = keys.length; index < length; index++) { + var key = keys[index]; + this[key] = options[key]; + } + + if (this.start !== undefined) { + if ('number' !== typeof this.start) { + throw TypeError('start must be a Number'); + } + if (this.start < 0) { + throw new Error('start must be >= zero'); + } + + this.pos = this.start; + } + + this.busy = false; + this._queue = []; + + if (this.fd === null) { + this._open = fs.open; + this._queue.push([this._open, this.path, this.flags, this.mode, undefined]); + this.flush(); + } + } +} diff --git a/action/node_modules/graceful-fs/package.json b/action/node_modules/graceful-fs/package.json new file mode 100644 index 00000000..87babf02 --- /dev/null +++ b/action/node_modules/graceful-fs/package.json @@ -0,0 +1,53 @@ +{ + "name": "graceful-fs", + "description": "A drop-in replacement for fs, making various improvements.", + "version": "4.2.11", + "repository": { + "type": "git", + "url": "https://github.com/isaacs/node-graceful-fs" + }, + "main": "graceful-fs.js", + "directories": { + "test": "test" + }, + "scripts": { + "preversion": "npm test", + "postversion": "npm publish", + "postpublish": "git push origin --follow-tags", + "test": "nyc --silent node test.js | tap -c -", + "posttest": "nyc report" + }, + "keywords": [ + "fs", + "module", + "reading", + "retry", + "retries", + "queue", + "error", + "errors", + "handling", + "EMFILE", + "EAGAIN", + "EINVAL", + "EPERM", + "EACCESS" + ], + "license": "ISC", + "devDependencies": { + "import-fresh": "^2.0.0", + "mkdirp": "^0.5.0", + "rimraf": "^2.2.8", + "tap": "^16.3.4" + }, + "files": [ + "fs.js", + "graceful-fs.js", + "legacy-streams.js", + "polyfills.js", + "clone.js" + ], + "tap": { + "reporter": "classic" + } +} diff --git a/action/node_modules/graceful-fs/polyfills.js b/action/node_modules/graceful-fs/polyfills.js new file mode 100644 index 00000000..453f1a9e --- /dev/null +++ b/action/node_modules/graceful-fs/polyfills.js @@ -0,0 +1,355 @@ +var constants = require('constants') + +var origCwd = process.cwd +var cwd = null + +var platform = process.env.GRACEFUL_FS_PLATFORM || process.platform + +process.cwd = function() { + if (!cwd) + cwd = origCwd.call(process) + return cwd +} +try { + process.cwd() +} catch (er) {} + +// This check is needed until node.js 12 is required +if (typeof process.chdir === 'function') { + var chdir = process.chdir + process.chdir = function (d) { + cwd = null + chdir.call(process, d) + } + if (Object.setPrototypeOf) Object.setPrototypeOf(process.chdir, chdir) +} + +module.exports = patch + +function patch (fs) { + // (re-)implement some things that are known busted or missing. + + // lchmod, broken prior to 0.6.2 + // back-port the fix here. + if (constants.hasOwnProperty('O_SYMLINK') && + process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) { + patchLchmod(fs) + } + + // lutimes implementation, or no-op + if (!fs.lutimes) { + patchLutimes(fs) + } + + // https://github.com/isaacs/node-graceful-fs/issues/4 + // Chown should not fail on einval or eperm if non-root. + // It should not fail on enosys ever, as this just indicates + // that a fs doesn't support the intended operation. + + fs.chown = chownFix(fs.chown) + fs.fchown = chownFix(fs.fchown) + fs.lchown = chownFix(fs.lchown) + + fs.chmod = chmodFix(fs.chmod) + fs.fchmod = chmodFix(fs.fchmod) + fs.lchmod = chmodFix(fs.lchmod) + + fs.chownSync = chownFixSync(fs.chownSync) + fs.fchownSync = chownFixSync(fs.fchownSync) + fs.lchownSync = chownFixSync(fs.lchownSync) + + fs.chmodSync = chmodFixSync(fs.chmodSync) + fs.fchmodSync = chmodFixSync(fs.fchmodSync) + fs.lchmodSync = chmodFixSync(fs.lchmodSync) + + fs.stat = statFix(fs.stat) + fs.fstat = statFix(fs.fstat) + fs.lstat = statFix(fs.lstat) + + fs.statSync = statFixSync(fs.statSync) + fs.fstatSync = statFixSync(fs.fstatSync) + fs.lstatSync = statFixSync(fs.lstatSync) + + // if lchmod/lchown do not exist, then make them no-ops + if (fs.chmod && !fs.lchmod) { + fs.lchmod = function (path, mode, cb) { + if (cb) process.nextTick(cb) + } + fs.lchmodSync = function () {} + } + if (fs.chown && !fs.lchown) { + fs.lchown = function (path, uid, gid, cb) { + if (cb) process.nextTick(cb) + } + fs.lchownSync = function () {} + } + + // on Windows, A/V software can lock the directory, causing this + // to fail with an EACCES or EPERM if the directory contains newly + // created files. Try again on failure, for up to 60 seconds. + + // Set the timeout this long because some Windows Anti-Virus, such as Parity + // bit9, may lock files for up to a minute, causing npm package install + // failures. Also, take care to yield the scheduler. Windows scheduling gives + // CPU to a busy looping process, which can cause the program causing the lock + // contention to be starved of CPU by node, so the contention doesn't resolve. + if (platform === "win32") { + fs.rename = typeof fs.rename !== 'function' ? fs.rename + : (function (fs$rename) { + function rename (from, to, cb) { + var start = Date.now() + var backoff = 0; + fs$rename(from, to, function CB (er) { + if (er + && (er.code === "EACCES" || er.code === "EPERM" || er.code === "EBUSY") + && Date.now() - start < 60000) { + setTimeout(function() { + fs.stat(to, function (stater, st) { + if (stater && stater.code === "ENOENT") + fs$rename(from, to, CB); + else + cb(er) + }) + }, backoff) + if (backoff < 100) + backoff += 10; + return; + } + if (cb) cb(er) + }) + } + if (Object.setPrototypeOf) Object.setPrototypeOf(rename, fs$rename) + return rename + })(fs.rename) + } + + // if read() returns EAGAIN, then just try it again. + fs.read = typeof fs.read !== 'function' ? fs.read + : (function (fs$read) { + function read (fd, buffer, offset, length, position, callback_) { + var callback + if (callback_ && typeof callback_ === 'function') { + var eagCounter = 0 + callback = function (er, _, __) { + if (er && er.code === 'EAGAIN' && eagCounter < 10) { + eagCounter ++ + return fs$read.call(fs, fd, buffer, offset, length, position, callback) + } + callback_.apply(this, arguments) + } + } + return fs$read.call(fs, fd, buffer, offset, length, position, callback) + } + + // This ensures `util.promisify` works as it does for native `fs.read`. + if (Object.setPrototypeOf) Object.setPrototypeOf(read, fs$read) + return read + })(fs.read) + + fs.readSync = typeof fs.readSync !== 'function' ? fs.readSync + : (function (fs$readSync) { return function (fd, buffer, offset, length, position) { + var eagCounter = 0 + while (true) { + try { + return fs$readSync.call(fs, fd, buffer, offset, length, position) + } catch (er) { + if (er.code === 'EAGAIN' && eagCounter < 10) { + eagCounter ++ + continue + } + throw er + } + } + }})(fs.readSync) + + function patchLchmod (fs) { + fs.lchmod = function (path, mode, callback) { + fs.open( path + , constants.O_WRONLY | constants.O_SYMLINK + , mode + , function (err, fd) { + if (err) { + if (callback) callback(err) + return + } + // prefer to return the chmod error, if one occurs, + // but still try to close, and report closing errors if they occur. + fs.fchmod(fd, mode, function (err) { + fs.close(fd, function(err2) { + if (callback) callback(err || err2) + }) + }) + }) + } + + fs.lchmodSync = function (path, mode) { + var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK, mode) + + // prefer to return the chmod error, if one occurs, + // but still try to close, and report closing errors if they occur. + var threw = true + var ret + try { + ret = fs.fchmodSync(fd, mode) + threw = false + } finally { + if (threw) { + try { + fs.closeSync(fd) + } catch (er) {} + } else { + fs.closeSync(fd) + } + } + return ret + } + } + + function patchLutimes (fs) { + if (constants.hasOwnProperty("O_SYMLINK") && fs.futimes) { + fs.lutimes = function (path, at, mt, cb) { + fs.open(path, constants.O_SYMLINK, function (er, fd) { + if (er) { + if (cb) cb(er) + return + } + fs.futimes(fd, at, mt, function (er) { + fs.close(fd, function (er2) { + if (cb) cb(er || er2) + }) + }) + }) + } + + fs.lutimesSync = function (path, at, mt) { + var fd = fs.openSync(path, constants.O_SYMLINK) + var ret + var threw = true + try { + ret = fs.futimesSync(fd, at, mt) + threw = false + } finally { + if (threw) { + try { + fs.closeSync(fd) + } catch (er) {} + } else { + fs.closeSync(fd) + } + } + return ret + } + + } else if (fs.futimes) { + fs.lutimes = function (_a, _b, _c, cb) { if (cb) process.nextTick(cb) } + fs.lutimesSync = function () {} + } + } + + function chmodFix (orig) { + if (!orig) return orig + return function (target, mode, cb) { + return orig.call(fs, target, mode, function (er) { + if (chownErOk(er)) er = null + if (cb) cb.apply(this, arguments) + }) + } + } + + function chmodFixSync (orig) { + if (!orig) return orig + return function (target, mode) { + try { + return orig.call(fs, target, mode) + } catch (er) { + if (!chownErOk(er)) throw er + } + } + } + + + function chownFix (orig) { + if (!orig) return orig + return function (target, uid, gid, cb) { + return orig.call(fs, target, uid, gid, function (er) { + if (chownErOk(er)) er = null + if (cb) cb.apply(this, arguments) + }) + } + } + + function chownFixSync (orig) { + if (!orig) return orig + return function (target, uid, gid) { + try { + return orig.call(fs, target, uid, gid) + } catch (er) { + if (!chownErOk(er)) throw er + } + } + } + + function statFix (orig) { + if (!orig) return orig + // Older versions of Node erroneously returned signed integers for + // uid + gid. + return function (target, options, cb) { + if (typeof options === 'function') { + cb = options + options = null + } + function callback (er, stats) { + if (stats) { + if (stats.uid < 0) stats.uid += 0x100000000 + if (stats.gid < 0) stats.gid += 0x100000000 + } + if (cb) cb.apply(this, arguments) + } + return options ? orig.call(fs, target, options, callback) + : orig.call(fs, target, callback) + } + } + + function statFixSync (orig) { + if (!orig) return orig + // Older versions of Node erroneously returned signed integers for + // uid + gid. + return function (target, options) { + var stats = options ? orig.call(fs, target, options) + : orig.call(fs, target) + if (stats) { + if (stats.uid < 0) stats.uid += 0x100000000 + if (stats.gid < 0) stats.gid += 0x100000000 + } + return stats; + } + } + + // ENOSYS means that the fs doesn't support the op. Just ignore + // that, because it doesn't matter. + // + // if there's no getuid, or if getuid() is something other + // than 0, and the error is EINVAL or EPERM, then just ignore + // it. + // + // This specific case is a silent failure in cp, install, tar, + // and most other unix tools that manage permissions. + // + // When running as root, or if other types of errors are + // encountered, then it's strict. + function chownErOk (er) { + if (!er) + return true + + if (er.code === "ENOSYS") + return true + + var nonroot = !process.getuid || process.getuid() !== 0 + if (nonroot) { + if (er.code === "EINVAL" || er.code === "EPERM") + return true + } + + return false + } +} diff --git a/action/node_modules/is-arrayish/.editorconfig b/action/node_modules/is-arrayish/.editorconfig new file mode 100644 index 00000000..4c017f8a --- /dev/null +++ b/action/node_modules/is-arrayish/.editorconfig @@ -0,0 +1,18 @@ +root = true + +[*] +indent_style = tab +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.coffee] +indent_style = space + +[{package.json,*.yml}] +indent_style = space +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false diff --git a/action/node_modules/is-arrayish/.istanbul.yml b/action/node_modules/is-arrayish/.istanbul.yml new file mode 100644 index 00000000..19fbec32 --- /dev/null +++ b/action/node_modules/is-arrayish/.istanbul.yml @@ -0,0 +1,4 @@ +instrumentation: + excludes: + - test.js + - test/**/* diff --git a/action/node_modules/is-arrayish/.npmignore b/action/node_modules/is-arrayish/.npmignore new file mode 100644 index 00000000..8d5eacb3 --- /dev/null +++ b/action/node_modules/is-arrayish/.npmignore @@ -0,0 +1,5 @@ +/coverage/ +/test.js +/test/ +*.sw[a-p] +/node_modules/ diff --git a/action/node_modules/is-arrayish/.travis.yml b/action/node_modules/is-arrayish/.travis.yml new file mode 100644 index 00000000..5a042435 --- /dev/null +++ b/action/node_modules/is-arrayish/.travis.yml @@ -0,0 +1,17 @@ +language: node_js + +script: + - node_modules/.bin/istanbul cover node_modules/.bin/_mocha -- --compilers coffee:coffee-script/register + - cat coverage/lcov.info | node_modules/.bin/coveralls +node_js: + - "0.10" + - "0.11" + - "0.12" + - "iojs" +os: + - linux + - osx + +notifications: + slack: + secure: oOt8QGzdrPDsTMcyahtIq5Q+0U1iwfgJgFCxBLsomQ0bpIMn+y5m4viJydA2UinHPGc944HS3LMZS9iKQyv+DjTgbhUyNXqeVjtxCwRe37f5rKQlXVvdfmjHk2kln4H8DcK3r5Qd/+2hd9BeMsp2GImTrkRSud1CZQlhhe5IgZOboSoWpGVMMy1iazWT06tAtiB2LRVhmsdUaFZDWAhGZ+UAvCPf+mnBOAylIj+U0GDrofhfTi25RK0gddG2f/p2M1HCu49O6wECGWkt2hVei233DkNJyLLLJVcvmhf+aXkV5TjMyaoxh/HdcV4DrA7KvYuWmWWKsINa9hlwAsdd/FYmJ6PjRkKWas2JoQ1C+qOzDxyQvn3CaUZFKD99pdsq0rBBZujqXQKZZ/hWb/CE74BI6fKmqQkiEPaD/7uADj04FEg6HVBZaMCyauOaK5b3VC97twbALZ1qVxYV6mU+zSEvnUbpnjjvRO0fSl9ZHA+rzkW73kX3GmHY0wAozEZbSy7QLuZlQ2QtHmBLr+APaGMdL1sFF9qFfzqKy0WDbSE0WS6hpAEJpTsjYmeBrnI8UmK3m++iEgyQPvZoH9LhUT+ek7XIfHZMe04BmC6wuO24/RfpmR6bQK9VMarFCYlBiWxg/z30vkP0KTpUi3o/cqFm7/Noxc0i2LVqM3E0Sy4= diff --git a/action/node_modules/is-arrayish/LICENSE b/action/node_modules/is-arrayish/LICENSE new file mode 100644 index 00000000..0a5f461a --- /dev/null +++ b/action/node_modules/is-arrayish/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 JD Ballard + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/action/node_modules/is-arrayish/README.md b/action/node_modules/is-arrayish/README.md new file mode 100644 index 00000000..7d360724 --- /dev/null +++ b/action/node_modules/is-arrayish/README.md @@ -0,0 +1,16 @@ +# node-is-arrayish [![Travis-CI.org Build Status](https://img.shields.io/travis/Qix-/node-is-arrayish.svg?style=flat-square)](https://travis-ci.org/Qix-/node-is-arrayish) [![Coveralls.io Coverage Rating](https://img.shields.io/coveralls/Qix-/node-is-arrayish.svg?style=flat-square)](https://coveralls.io/r/Qix-/node-is-arrayish) +> Determines if an object can be used like an Array + +## Example +```javascript +var isArrayish = require('is-arrayish'); + +isArrayish([]); // true +isArrayish({__proto__: []}); // true +isArrayish({}); // false +isArrayish({length:10}); // false +``` + +## License +Licensed under the [MIT License](http://opensource.org/licenses/MIT). +You can find a copy of it in [LICENSE](LICENSE). diff --git a/action/node_modules/is-arrayish/index.js b/action/node_modules/is-arrayish/index.js new file mode 100644 index 00000000..5b971868 --- /dev/null +++ b/action/node_modules/is-arrayish/index.js @@ -0,0 +1,10 @@ +'use strict'; + +module.exports = function isArrayish(obj) { + if (!obj) { + return false; + } + + return obj instanceof Array || Array.isArray(obj) || + (obj.length >= 0 && obj.splice instanceof Function); +}; diff --git a/action/node_modules/is-arrayish/package.json b/action/node_modules/is-arrayish/package.json new file mode 100644 index 00000000..8b2d1c30 --- /dev/null +++ b/action/node_modules/is-arrayish/package.json @@ -0,0 +1,34 @@ +{ + "name": "is-arrayish", + "description": "Determines if an object can be used as an array", + "version": "0.2.1", + "author": "Qix (http://github.com/qix-)", + "keywords": [ + "is", + "array", + "duck", + "type", + "arrayish", + "similar", + "proto", + "prototype", + "type" + ], + "license": "MIT", + "scripts": { + "pretest": "xo", + "test": "mocha --compilers coffee:coffee-script/register" + }, + "repository": { + "type": "git", + "url": "https://github.com/qix-/node-is-arrayish.git" + }, + "devDependencies": { + "coffee-script": "^1.9.3", + "coveralls": "^2.11.2", + "istanbul": "^0.3.17", + "mocha": "^2.2.5", + "should": "^7.0.1", + "xo": "^0.6.1" + } +} diff --git a/action/node_modules/json-parse-better-errors/CHANGELOG.md b/action/node_modules/json-parse-better-errors/CHANGELOG.md new file mode 100644 index 00000000..b1d212de --- /dev/null +++ b/action/node_modules/json-parse-better-errors/CHANGELOG.md @@ -0,0 +1,46 @@ +# Change Log + +All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. + + +## [1.0.2](https://github.com/zkat/json-parse-better-errors/compare/v1.0.1...v1.0.2) (2018-03-30) + + +### Bug Fixes + +* **messages:** More friendly messages for non-string ([#1](https://github.com/zkat/json-parse-better-errors/issues/1)) ([a476d42](https://github.com/zkat/json-parse-better-errors/commit/a476d42)) + + + + +## [1.0.1](https://github.com/zkat/json-parse-better-errors/compare/v1.0.0...v1.0.1) (2017-08-16) + + +### Bug Fixes + +* **license:** oops. Forgot to update license.md ([efe2958](https://github.com/zkat/json-parse-better-errors/commit/efe2958)) + + + + +# 1.0.0 (2017-08-15) + + +### Features + +* **init:** Initial Commit ([562c977](https://github.com/zkat/json-parse-better-errors/commit/562c977)) + + +### BREAKING CHANGES + +* **init:** This is the first commit! + + + + +# 0.1.0 (2017-08-15) + + +### Features + +* **init:** Initial Commit ([9dd1a19](https://github.com/zkat/json-parse-better-errors/commit/9dd1a19)) diff --git a/action/node_modules/json-parse-better-errors/LICENSE.md b/action/node_modules/json-parse-better-errors/LICENSE.md new file mode 100644 index 00000000..c51842cc --- /dev/null +++ b/action/node_modules/json-parse-better-errors/LICENSE.md @@ -0,0 +1,7 @@ +Copyright 2017 Kat Marchán + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/action/node_modules/json-parse-better-errors/README.md b/action/node_modules/json-parse-better-errors/README.md new file mode 100644 index 00000000..a1f0f0a5 --- /dev/null +++ b/action/node_modules/json-parse-better-errors/README.md @@ -0,0 +1,46 @@ +# json-parse-better-errors [![npm version](https://img.shields.io/npm/v/json-parse-better-errors.svg)](https://npm.im/json-parse-better-errors) [![license](https://img.shields.io/npm/l/json-parse-better-errors.svg)](https://npm.im/json-parse-better-errors) [![Travis](https://img.shields.io/travis/zkat/json-parse-better-errors.svg)](https://travis-ci.org/zkat/json-parse-better-errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/github/zkat/json-parse-better-errors?svg=true)](https://ci.appveyor.com/project/zkat/json-parse-better-errors) [![Coverage Status](https://coveralls.io/repos/github/zkat/json-parse-better-errors/badge.svg?branch=latest)](https://coveralls.io/github/zkat/json-parse-better-errors?branch=latest) + +[`json-parse-better-errors`](https://github.com/zkat/json-parse-better-errors) is a Node.js library for +getting nicer errors out of `JSON.parse()`, including context and position of the parse errors. + +## Install + +`$ npm install --save json-parse-better-errors` + +## Table of Contents + +* [Example](#example) +* [Features](#features) +* [Contributing](#contributing) +* [API](#api) + * [`parse`](#parse) + +### Example + +```javascript +const parseJson = require('json-parse-better-errors') + +parseJson('"foo"') +parseJson('garbage') // more useful error message +``` + +### Features + +* Like JSON.parse, but the errors are better. + +### Contributing + +The npm team enthusiastically welcomes contributions and project participation! There's a bunch of things you can do if you want to contribute! The [Contributor Guide](CONTRIBUTING.md) has all the information you need for everything from reporting bugs to contributing entire new features. Please don't hesitate to jump in if you'd like to, or even ask us questions if something isn't clear. + +All participants and maintainers in this project are expected to follow [Code of Conduct](CODE_OF_CONDUCT.md), and just generally be excellent to each other. + +Please refer to the [Changelog](CHANGELOG.md) for project history details, too. + +Happy hacking! + +### API + +#### `> parse(txt, ?reviver, ?context=20)` + +Works just like `JSON.parse`, but will include a bit more information when an +error happens. diff --git a/action/node_modules/json-parse-better-errors/index.js b/action/node_modules/json-parse-better-errors/index.js new file mode 100644 index 00000000..14644c2f --- /dev/null +++ b/action/node_modules/json-parse-better-errors/index.js @@ -0,0 +1,38 @@ +'use strict' + +module.exports = parseJson +function parseJson (txt, reviver, context) { + context = context || 20 + try { + return JSON.parse(txt, reviver) + } catch (e) { + if (typeof txt !== 'string') { + const isEmptyArray = Array.isArray(txt) && txt.length === 0 + const errorMessage = 'Cannot parse ' + + (isEmptyArray ? 'an empty array' : String(txt)) + throw new TypeError(errorMessage) + } + const syntaxErr = e.message.match(/^Unexpected token.*position\s+(\d+)/i) + const errIdx = syntaxErr + ? +syntaxErr[1] + : e.message.match(/^Unexpected end of JSON.*/i) + ? txt.length - 1 + : null + if (errIdx != null) { + const start = errIdx <= context + ? 0 + : errIdx - context + const end = errIdx + context >= txt.length + ? txt.length + : errIdx + context + e.message += ` while parsing near '${ + start === 0 ? '' : '...' + }${txt.slice(start, end)}${ + end === txt.length ? '' : '...' + }'` + } else { + e.message += ` while parsing '${txt.slice(0, context * 2)}'` + } + throw e + } +} diff --git a/action/node_modules/json-parse-better-errors/package.json b/action/node_modules/json-parse-better-errors/package.json new file mode 100644 index 00000000..c4c2c20a --- /dev/null +++ b/action/node_modules/json-parse-better-errors/package.json @@ -0,0 +1,45 @@ +{ + "name": "json-parse-better-errors", + "version": "1.0.2", + "description": "JSON.parse with context information on error", + "main": "index.js", + "files": [ + "*.js" + ], + "scripts": { + "prerelease": "npm t", + "postrelease": "npm publish && git push --follow-tags", + "pretest": "standard", + "release": "standard-version -s", + "test": "tap -J --coverage test/*.js", + "update-coc": "weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'", + "update-contrib": "weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'" + }, + "repository": "https://github.com/zkat/json-parse-better-errors", + "keywords": [ + "JSON", + "parser" + ], + "author": { + "name": "Kat Marchán", + "email": "kzm@zkat.tech", + "twitter": "maybekatz" + }, + "license": "MIT", + "devDependencies": { + "nyc": "^10.3.2", + "standard": "^9.0.2", + "standard-version": "^4.1.0", + "tap": "^10.3.3", + "weallbehave": "^1.2.0", + "weallcontribute": "^1.0.8" + }, + "config": { + "nyc": { + "exclude": [ + "node_modules/**", + "test/**" + ] + } + } +} diff --git a/action/node_modules/jsonc/LICENSE b/action/node_modules/jsonc/LICENSE new file mode 100644 index 00000000..9f201e85 --- /dev/null +++ b/action/node_modules/jsonc/LICENSE @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2019, Onur Yıldırım . All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/action/node_modules/jsonc/README.md b/action/node_modules/jsonc/README.md new file mode 100644 index 00000000..900af4f1 --- /dev/null +++ b/action/node_modules/jsonc/README.md @@ -0,0 +1,97 @@ +# jsonc + +[![build-status](https://img.shields.io/travis/onury/jsonc.svg?branch=master&style=flat-square)](https://travis-ci.org/onury/jsonc) +[![coverage-status](https://img.shields.io/coveralls/github/onury/jsonc/master.svg?style=flat-square)](https://coveralls.io/github/onury/jsonc?branch=master) +[![npm](http://img.shields.io/npm/v/jsonc.svg?style=flat-square)](https://www.npmjs.com/package/jsonc) +[![release](https://img.shields.io/github/release/onury/jsonc.svg?style=flat-square)](https://github.com/onury/jsonc) +[![dependencies](https://david-dm.org/onury/jsonc.svg?style=flat-square)](https://david-dm.org/onury/jsonc) +[![license](http://img.shields.io/npm/l/jsonc.svg?style=flat-square)](https://github.com/onury/jsonc/blob/master/LICENSE) +[![maintained](https://img.shields.io/maintenance/yes/2019.svg?style=flat-square)](https://github.com/onury/jsonc/graphs/punch-card) + +> © 2019, Onur Yıldırım ([@onury](https://github.com/onury)). MIT License. + +Everything you need in JSON land. + +`npm i jsonc` + +## Features + +- Parse JSON with comments. +- Stringify objects with circular references. +- Safely parse / stringify without try/catch blocks. +- Read and auto-parse JSON files gracefully, sync or async (with promises). +- Auto-stringify and write JSON files gracefully, sync or async (with promises). +- Strips UTF-8 BOM. +- Log objects as JSON (without worrying about errors). +- Uglify/beautify JSON strings. +- More helpful JSON errors. +- Friendly API. +- TypeScript support. + +## Usage + +See the concise [API reference][docs-api]. + +```js +const jsonc = require('jsonc'); +// or +import { jsonc } from 'jsonc'; +``` + +This is safe for JSON with comments: +```js +jsonc.parse('// comment\n{"data": /* comment */ "value"}\n'); // » { data: 'value' } +``` + +And this is safe for circular references: +```js +const obj = { x: 1 }; +obj.y = obj; // circular +jsonc.stringify(obj); // » { x: 1, y: '[Circular]' } +``` + +But this is seriously safe: +```js +// safe version of every method +const jsonc = require('jsonc').safe; +// or +import { safe as jsonc } from 'jsonc'; + +const [err, result] = jsonc.parse('[invalid JSON}'); +if (err) { + console.log(`Failed to parse JSON: ${err.message}`); +} else { + console.log(result); +} +``` + +## Documentation + +See the concise [API reference][docs-api]. + +## Change Log + +- **v2.0.0** (2019-06-17) + + Requires Node.js v8 or newer. + + Updated dependencies. + + +- **v1.1.0** (2018-11-22) + + Fixed an issue where TypeScript compiler would complain about `'declare' modifier`. + + Improved typings for safe methods. + + Updated core dependencies. + + +- **v1.0.0** (2018-10-18) + + Initial release. + + +## License +MIT. + + +[docs-api]:https://onury.io/jsonc/api +[strip-json-comments]:https://github.com/sindresorhus/strip-json-comments +[json-stringify-safe]:https://github.com/isaacs/json-stringify-safe +[parse-json]:https://github.com/sindresorhus/parse-json +[fs-extra]:https://www.npmjs.com/package/fs-extra diff --git a/action/node_modules/jsonc/index.js b/action/node_modules/jsonc/index.js new file mode 100644 index 00000000..626471b0 --- /dev/null +++ b/action/node_modules/jsonc/index.js @@ -0,0 +1,5 @@ +var jsonc = require('./lib/jsonc').jsonc; +module.exports = jsonc; +// adding circular ref to allow easy importing in both ES5/6 and TS projects +module.exports.jsonc = jsonc; +module.exports.safe = jsonc.safe; \ No newline at end of file diff --git a/action/node_modules/jsonc/lib/helper.d.ts b/action/node_modules/jsonc/lib/helper.d.ts new file mode 100644 index 00000000..8226931a --- /dev/null +++ b/action/node_modules/jsonc/lib/helper.d.ts @@ -0,0 +1,19 @@ +import * as mkdirp from 'mkdirp'; +import { IConfig, IStringifyOptions, Replacer } from './interfaces'; +declare const helper: { + isObject(o: any): boolean; + isPrimitive(value: any): boolean; + strLog(value: any, pretty: boolean): string; + getLogger(config: IConfig, pretty: boolean): Function; + getStringifyOptions(options: IStringifyOptions | Replacer, space: string | number): IStringifyOptions; + fs: any; + mkdirp: typeof mkdirp; + promise: { + readFile: any; + writeFile: any; + mkdirp: any; + }; + safeSync(fn: (...args: any[]) => T): (...args: any[]) => [U, T]; + safeAsync(promise: Promise): Promise<[U, T]>; +}; +export { helper }; diff --git a/action/node_modules/jsonc/lib/helper.js b/action/node_modules/jsonc/lib/helper.js new file mode 100644 index 00000000..def2ccfc --- /dev/null +++ b/action/node_modules/jsonc/lib/helper.js @@ -0,0 +1,118 @@ +"use strict"; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +// dep modules +var fast_safe_stringify_1 = require("fast-safe-stringify"); +var fs = require("graceful-fs"); +var mkdirp = require("mkdirp"); +// vars +var oproto = Object.prototype; +// simple promisification. this won't work for callbacks with more than 2 +// args. +function promisify(fn) { + return function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + return new Promise(function (resolve, reject) { + fn.apply(void 0, args.concat([function (err, result) { + if (err) { + reject(err); + } + else { + resolve(result); + } + }])); + }); + }; +} +var defaultStringifyOpts = { + replacer: null, + space: 0, + handleCircular: true +}; +var helper = { + isObject: function (o) { + return oproto.toString.call(o) === '[object Object]'; + }, + isPrimitive: function (value) { + var t = typeof value; + return value === null + || value === undefined + || (t !== 'function' && t !== 'object'); + }, + strLog: function (value, pretty) { + if (helper.isPrimitive(value)) + return value; + var s = pretty ? ' ' : null; + return fast_safe_stringify_1.default(value, null, s); + }, + getLogger: function (config, pretty) { + return function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + var stream = config.stream; + var msg = args.map(function (arg) { + if (arg instanceof Error) { + stream = config.streamErr; + return arg.stack + /* istanbul ignore next */ + || arg.message + /* istanbul ignore next */ + || String(arg); + } + return helper.strLog(arg, pretty); + }).join(' '); + stream.write(msg + '\n'); + }; + }, + getStringifyOptions: function (options, space) { + if (helper.isObject(options)) { + return __assign({}, defaultStringifyOpts, options); // as IStringifyOptions + } + if (typeof options === 'function' || Array.isArray(options)) { + return __assign({}, defaultStringifyOpts, { replacer: options, space: space }); + } + return __assign({}, defaultStringifyOpts, { space: space }); + }, + fs: fs, + mkdirp: mkdirp, + promise: { + readFile: promisify(fs.readFile), + writeFile: promisify(fs.writeFile), + mkdirp: promisify(mkdirp) + }, + safeSync: function (fn) { + return function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + try { + return [null, fn.apply(void 0, args)]; + } + catch (err) { + return [err, undefined]; + } + }; + }, + safeAsync: function (promise) { + return promise + .then(function (data) { return [null, data]; }) + .catch(function (err) { return [err, undefined]; }); + } +}; +exports.helper = helper; diff --git a/action/node_modules/jsonc/lib/interfaces.d.ts b/action/node_modules/jsonc/lib/interfaces.d.ts new file mode 100644 index 00000000..0317c983 --- /dev/null +++ b/action/node_modules/jsonc/lib/interfaces.d.ts @@ -0,0 +1,24 @@ +/// +export declare type Reviver = (key: string, value: any) => any; +export declare type Replacer = (key: string, value: any) => any | string[] | number[]; +export interface IParseOptions { + reviver?: Reviver; + stripComments?: boolean; +} +export interface IStringifyOptions { + replacer?: Replacer; + space?: string | number; + handleCircular?: boolean; +} +export interface IReadOptions extends IParseOptions { +} +export interface IWriteOptions { + mode?: number; + autoPath?: boolean; + replacer?: Replacer; + space?: string | number; +} +export interface IConfig { + stream?: NodeJS.WriteStream; + streamErr?: NodeJS.WriteStream; +} diff --git a/action/node_modules/jsonc/lib/interfaces.js b/action/node_modules/jsonc/lib/interfaces.js new file mode 100644 index 00000000..c8ad2e54 --- /dev/null +++ b/action/node_modules/jsonc/lib/interfaces.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/action/node_modules/jsonc/lib/jsonc.d.ts b/action/node_modules/jsonc/lib/jsonc.d.ts new file mode 100644 index 00000000..ea54cc68 --- /dev/null +++ b/action/node_modules/jsonc/lib/jsonc.d.ts @@ -0,0 +1,357 @@ +import { IConfig, IParseOptions, IReadOptions, IStringifyOptions, IWriteOptions, Replacer, Reviver } from './interfaces'; +import { jsoncSafe } from './jsonc.safe'; +/** + * JSON utility class that can handle comments and circular references; and + * other extra functionality. + * @class + * @author Onur Yıldırım + * @license MIT + * @see {@link https://github.com/onury/jsonc|GitHub Repo} + * @see {@link https://github.com/onury/jsonc#related-modules|Related Modules} + * + * @example + * const jsonc = require('jsonc'); + * // or + * import { jsonc } from 'jsonc'; + * + * const result = jsonc.parse('// comments\n{ "key": "value" }'); + * console.log(result); // { key: "value" } + */ +declare class jsonc { + /** @private */ + private static _; + /** + * Configures `jsonc` object. + * + * @param {IConfig} cfg - Configurations. + * @param {NodeJS.WriteStream} [stream] - Stream to write logs to. This is + * used with `.log()` and `.logp()` methods. + * @param {NodeJS.WriteStream} [streamErr] - Stream to write error logs to. + * This is used with `.log()` and `.logp()` methods. + * + * @example + * // Output logs to stdout but logs containing errors to a file. + * jsonc.config({ + * stream: process.stdout, + * streamErr: fs.createWriteStream('path/to/log.txt') + * }); + * jsonc.log({ info: 'this is logged to console' }); + * jsonc.log(new Error('this is logged to file')); + */ + static config(cfg: IConfig): void; + /** + * Stringifies and logs the given arguments to console. This will + * automatically handle circular references; so it won't throw. + * + * If an `Error` instance is passed, it will log the `.stack` property on + * the instance, without stringifying the object. + * + * @param {...any[]} [args] - Arguments to be logged. + * @returns {void} + */ + static log(...args: any[]): void; + /** + * Pretty version of `log()` method. Stringifies and logs the given + * arguments to console, with indents. This will automatically handle + * circular references; so it won't throw. + * + * If an `Error` instance is passed, it will log the `.stack` property on + * the instance, without stringifying the object. + * + * @param {...any[]} [args] - Arguments to be logged. + * @returns {void} + */ + static logp(...args: any[]): void; + /** + * Parses the given JSON string into a JavaScript object. The input string + * can include comments. + * + * @param {string} str - JSON string to be parsed. + * @param {IParseOptions|Reviver} [options] - Either a parse options + * object or a reviver function. + * @param {Reviver} [options.reviver] - A function that can filter + * and transform the results. It receives each of the keys and values, and + * its return value is used instead of the original value. If it returns + * what it received, then the structure is not modified. If it returns + * `undefined` then the member is deleted. + * @param {Boolean} [options.stripComments=true] - Whether to strip + * comments from the JSON string. Note that it will throw if this is set to + * `false` and the string includes comments. + * + * @returns {any} - Parsed value. + * + * @throws {JSONError} - If JSON string is not valid. Note that any + * comments within JSON are removed by default; so this will not throw for + * comments unless you explicitly set `stripComments` to `false`. + * + * @example + * const parsed = jsonc.parse('// comments\n{"success":true}\n'); + * console.log(parsed); // { success: true } + */ + static parse(str: string, options?: IParseOptions | Reviver): any; + /** + * Outputs a JSON string from the given JavaScript object. + * + * @param {*} value - JavaScript value to be stringified. + * @param {IStringifyOptions|Replacer} [options] - Stringify options or a + * replacer. + * @param {Replacer} [options.replacer] - Determines how object values are + * stringified for objects. It can be a function or an array of strings or + * numbers. + * @param {string|number} [options.space] - Specifies the indentation of + * nested structures. If it is omitted, the text will be packed without + * extra whitespace. If it is a number, it will specify the number of + * spaces to indent at each level. If it is a string (such as `"\t"` or + * `" "`), it contains the characters used to indent at each level. + * @param {string|number} [space] - This takes effect if second argument is + * the `replacer` or a falsy value. This is for supporting the signature of + * native `JSON.stringify()` method. + * @param {boolean} [options.handleCircular=true] - Whether to handle + * circular references (if any) by replacing their values with the string + * `"[Circular]"`. You can also use a replacer function to replace or + * remove circular references instead. + * + * @returns {string} - JSON string. + * + * @throws {Error} - If there are any circular references within the + * original input. In this case, use `jsonc.safe.stringify()` method + * instead. + * + * @example + * const obj = { key: 'value' }; + * console.log(jsonc.stringify(obj)); // '{"key":"value"}' + * + * // pretty output with indents + * let pretty = jsonc.stringify(obj, null, 2); + * // equivalent to: + * pretty = jsonc.stringify(obj, { reviver: null, space: 2 }); + * if (!err) console.log(pretty); + * // { + * // "key": "value" + * // } + */ + static stringify(value: any, optionsOrReplacer?: IStringifyOptions | Replacer, space?: string | number): string; + /** + * Specifies whether the given string has well-formed JSON structure. + * + * Note that, not all JSON-parsable strings are considered well-formed JSON + * structures. JSON is built on two structures; a collection of name/value + * pairs (object) or an ordered list of values (array). + * + * For example, `JSON.parse('true')` will parse successfully but + * `jsonc.isJSON('true')` will return `false` since it has no object or + * array structure. + * + * @param {string} str - String to be validated. + * @param {boolean} [allowComments=false] - Whether comments should be + * considered valid. + * + * @returns {boolean} + * + * @example + * jsonc.isJSON('{"x":1}'); // true + * jsonc.isJSON('true'); // false + * jsonc.isJSON('[1, false, null]'); // true + * jsonc.isJSON('string'); // false + * jsonc.isJSON('null'); // false + */ + static isJSON(str: string, allowComments?: boolean): boolean; + /** + * Strips comments from the given JSON string. + * + * @param {string} str - JSON string. + * @param {boolean} [whitespace=false] - Whether to replace comments with + * whitespace instead of stripping them entirely. + * + * @returns {string} - Valid JSON string. + * + * @example + * const str = jsonc.stripComments('// comments\n{"key":"value"}'); + * console.log(str); // '\n{"key":"value"}' + */ + static stripComments(str: string, whitespace?: boolean): string; + /** + * Uglifies the given JSON string. + * + * @param {string} str - JSON string to be uglified. + * @returns {string} - Uglified JSON string. + * + * @example + * const pretty = ` + * { + * // comments... + * "key": "value" + * } + * `; + * const ugly = jsonc.uglify(pretty); + * console.log(ugly); // '{"key":"value"}' + */ + static uglify(str: string): string; + /** + * Beautifies the given JSON string. Note that this will remove comments, + * if any. + * + * @param {string} str - JSON string to be beautified. + * @param {string|number} [space=2] Specifies the indentation of nested + * structures. If it is omitted, the text will be packed without extra + * whitespace. If it is a number, it will specify the number of spaces to + * indent at each level. If it is a string (such as "\t" or " "), it + * contains the characters used to indent at each level. + * + * @returns {string} - Beautified JSON string. + * + * @example + * const ugly = '{"key":"value"}'; + * const pretty = jsonc.beautify(ugly); + * console.log(pretty); + * // { + * // "key": "value" + * // } + */ + static beautify(str: string, space?: string | number): string; + /** + * Normalizes the given value by stringifying and parsing it back to a + * Javascript object. + * + * @param {any} value + * @param {Replacer} [replacer] - Determines how object values are + * normalized for objects. It can be a function or an array of strings. + * + * @returns {any} - Normalized object. + * + * @example + * const c = new SomeClass(); + * console.log(c.constructor.name); // "SomeClass" + * const normalized = jsonc.normalize(c); + * console.log(normalized.constructor.name); // "Object" + */ + static normalize(value: any, replacer?: Replacer): any; + /** + * Asynchronously reads a JSON file, strips comments and UTF-8 BOM and + * parses the JSON content. + * + * @param {string} filePath - Path to JSON file. + * @param {Function|IReadOptions} [options] - Read options. + * @param {Function} [options.reviver] - A function that can filter and + * transform the results. It receives each of the keys and values, and its + * return value is used instead of the original value. If it returns what + * it received, then the structure is not modified. If it returns undefined + * then the member is deleted. + * @param {boolean} [options.stripComments=true] - Whether to strip + * comments from the JSON string. Note that it will throw if this is set to + * `false` and the string includes comments. + * + * @returns {Promise} - Promise of the parsed JSON content as a + * JavaScript object. + * + * @example Using async/await (async () => {try {const + * obj = await jsonc.read('path/to/file.json'); console.log(typeof obj); // + * "object"} catch (err) {console.log('Failed to read JSON file'); + * } + * })(); + * + * @example Using promises + * jsonc.read('path/to/file.json') .then(obj => {console.log(typeof obj); + * // "object" + * }) + * .catch(err => { + * console.log('Failed to read JSON file'); + * }); + */ + static read(filePath: string, options?: IReadOptions): Promise; + /** + * Synchronously reads a JSON file, strips UTF-8 BOM and parses the JSON + * content. + * + * @param {string} filePath - Path to JSON file. + * @param {Function|IReadOptions} [options] - Read options. + * @param {Function} [options.reviver] - A function that can filter and + * transform the results. It receives each of the keys and values, and its + * return value is used instead of the original value. If it returns what + * it received, then the structure is not modified. If it returns undefined + * then the member is deleted. + * @param {boolean} [options.stripComments=true] - Whether to strip + * comments from the JSON string. Note that it will throw if this is set to + * `false` and the string includes comments. + * + * @returns {any} - Parsed JSON content as a JavaScript object. + * + * @example + * const obj = jsonc.readSync('path/to/file.json'); + * // use try/catch block to handle errors. or better, use the safe version. + * console.log(typeof obj); // "object" + */ + static readSync(filePath: string, options?: IReadOptions): any; + /** + * Asynchronously writes a JSON file from the given JavaScript object. + * + * @param {string} filePath - Path to JSON file to be written. + * @param {any} data - Data to be stringified into JSON. + * @param {IWriteOptions} [options] - Write options. + * @param {Replacer} [options.replacer] - Determines how object values are + * stringified for objects. It can be a function or an array of strings. + * @param {string|number} [options.space] - Specifies the indentation of + * nested structures. If it is omitted, the text will be packed without + * extra whitespace. If it is a number, it will specify the number of + * spaces to indent at each level. If it is a string (such as "\t" or + * " "), it contains the characters used to indent at each level. + * @param {number} [options.mode=438] - FileSystem permission mode to be used when + * writing the file. Default is `438` (`0666` in octal). + * @param {boolean} [options.autoPath=true] - Specifies whether to create path + * directories if they don't exist. This will throw if set to `false` and + * path does not exist. + * + * @returns {Promise} - Always resolves with `true`, if no errors occur. + * + * @example Using async/await + * (async () => { + * try { + * await jsonc.write('path/to/file.json', data); + * console.log('Successfully wrote JSON file'); + * } catch (err) { + * console.log('Failed to write JSON file'); + * } + * })(); + * + * @example Using promises + * jsonc.write('path/to/file.json', data) + * .then(success => { + * console.log('Successfully wrote JSON file'); + * }) + * .catch(err => { + * console.log('Failed to write JSON file'); + * }); + */ + static write(filePath: string, data: any, options?: IWriteOptions): Promise; + /** + * Synchronously writes a JSON file from the given JavaScript object. + * + * @param {string} filePath - Path to JSON file to be written. + * @param {any} data - Data to be stringified into JSON. + * @param {IWriteOptions} [options] - Write options. + * @param {Replacer} [options.replacer] - Determines how object values are + * stringified for objects. It can be a function or an array of strings. + * @param {string|number} [options.space] - Specifies the indentation of + * nested structures. If it is omitted, the text will be packed without + * extra whitespace. If it is a number, it will specify the number of + * spaces to indent at each level. If it is a string (such as "\t" or + * " "), it contains the characters used to indent at each level. + * @param {number} [options.mode=438] - FileSystem permission mode to be used when + * writing the file. Default is `438` (`0666` in octal). + * @param {boolean} [options.autoPath=true] - Specifies whether to create path + * directories if they don't exist. This will throw if set to `false` and + * path does not exist. + * + * @returns {boolean} - Always returns `true`, if no errors occur. + * + * @example + * const success = jsonc.writeSync('path/to/file.json'); + * // this will always return true. use try/catch block to handle errors. or better, use the safe version. + * console.log('Successfully wrote JSON file'); + */ + static writeSync(filePath: string, data: any, options?: IWriteOptions): boolean; +} +declare namespace jsonc { + const safe: typeof jsoncSafe; +} +export { jsonc }; diff --git a/action/node_modules/jsonc/lib/jsonc.js b/action/node_modules/jsonc/lib/jsonc.js new file mode 100644 index 00000000..785058fc --- /dev/null +++ b/action/node_modules/jsonc/lib/jsonc.js @@ -0,0 +1,527 @@ +"use strict"; +/* tslint:disable:class-name no-require-imports no-default-export max-line-length interface-name max-classes-per-file max-file-line-count */ +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +// core modules +var path = require("path"); +// dep modules +var fast_safe_stringify_1 = require("fast-safe-stringify"); +var parseJson = require("parse-json"); +var stripBOM = require("strip-bom"); +var stripJsonComments = require("strip-json-comments"); +// own modules +var helper_1 = require("./helper"); +var jsonc_safe_1 = require("./jsonc.safe"); +// constants, variables +var fs = helper_1.helper.fs, mkdirp = helper_1.helper.mkdirp, promise = helper_1.helper.promise; +/** + * JSON utility class that can handle comments and circular references; and + * other extra functionality. + * @class + * @author Onur Yıldırım + * @license MIT + * @see {@link https://github.com/onury/jsonc|GitHub Repo} + * @see {@link https://github.com/onury/jsonc#related-modules|Related Modules} + * + * @example + * const jsonc = require('jsonc'); + * // or + * import { jsonc } from 'jsonc'; + * + * const result = jsonc.parse('// comments\n{ "key": "value" }'); + * console.log(result); // { key: "value" } + */ +var jsonc = /** @class */ (function () { + function jsonc() { + } + /** + * Configures `jsonc` object. + * + * @param {IConfig} cfg - Configurations. + * @param {NodeJS.WriteStream} [stream] - Stream to write logs to. This is + * used with `.log()` and `.logp()` methods. + * @param {NodeJS.WriteStream} [streamErr] - Stream to write error logs to. + * This is used with `.log()` and `.logp()` methods. + * + * @example + * // Output logs to stdout but logs containing errors to a file. + * jsonc.config({ + * stream: process.stdout, + * streamErr: fs.createWriteStream('path/to/log.txt') + * }); + * jsonc.log({ info: 'this is logged to console' }); + * jsonc.log(new Error('this is logged to file')); + */ + jsonc.config = function (cfg) { + var conf = __assign({ stream: process.stdout, streamErr: process.stderr }, (cfg || {})); + jsonc._ = { + logger: helper_1.helper.getLogger(conf, false), + prettyLogger: helper_1.helper.getLogger(conf, true) + }; + }; + /** + * Stringifies and logs the given arguments to console. This will + * automatically handle circular references; so it won't throw. + * + * If an `Error` instance is passed, it will log the `.stack` property on + * the instance, without stringifying the object. + * + * @param {...any[]} [args] - Arguments to be logged. + * @returns {void} + */ + jsonc.log = function () { + var _a; + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + (_a = jsonc._).logger.apply(_a, args); + }; + /** + * Pretty version of `log()` method. Stringifies and logs the given + * arguments to console, with indents. This will automatically handle + * circular references; so it won't throw. + * + * If an `Error` instance is passed, it will log the `.stack` property on + * the instance, without stringifying the object. + * + * @param {...any[]} [args] - Arguments to be logged. + * @returns {void} + */ + jsonc.logp = function () { + var _a; + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + (_a = jsonc._).prettyLogger.apply(_a, args); + }; + /** + * Parses the given JSON string into a JavaScript object. The input string + * can include comments. + * + * @param {string} str - JSON string to be parsed. + * @param {IParseOptions|Reviver} [options] - Either a parse options + * object or a reviver function. + * @param {Reviver} [options.reviver] - A function that can filter + * and transform the results. It receives each of the keys and values, and + * its return value is used instead of the original value. If it returns + * what it received, then the structure is not modified. If it returns + * `undefined` then the member is deleted. + * @param {Boolean} [options.stripComments=true] - Whether to strip + * comments from the JSON string. Note that it will throw if this is set to + * `false` and the string includes comments. + * + * @returns {any} - Parsed value. + * + * @throws {JSONError} - If JSON string is not valid. Note that any + * comments within JSON are removed by default; so this will not throw for + * comments unless you explicitly set `stripComments` to `false`. + * + * @example + * const parsed = jsonc.parse('// comments\n{"success":true}\n'); + * console.log(parsed); // { success: true } + */ + jsonc.parse = function (str, options) { + var opts = typeof options === 'function' + ? { reviver: options } + : (options || {}); + if (opts.stripComments !== false) + str = stripJsonComments(str, { whitespace: false }); + return parseJson(str, opts.reviver); + }; + /** + * Outputs a JSON string from the given JavaScript object. + * + * @param {*} value - JavaScript value to be stringified. + * @param {IStringifyOptions|Replacer} [options] - Stringify options or a + * replacer. + * @param {Replacer} [options.replacer] - Determines how object values are + * stringified for objects. It can be a function or an array of strings or + * numbers. + * @param {string|number} [options.space] - Specifies the indentation of + * nested structures. If it is omitted, the text will be packed without + * extra whitespace. If it is a number, it will specify the number of + * spaces to indent at each level. If it is a string (such as `"\t"` or + * `" "`), it contains the characters used to indent at each level. + * @param {string|number} [space] - This takes effect if second argument is + * the `replacer` or a falsy value. This is for supporting the signature of + * native `JSON.stringify()` method. + * @param {boolean} [options.handleCircular=true] - Whether to handle + * circular references (if any) by replacing their values with the string + * `"[Circular]"`. You can also use a replacer function to replace or + * remove circular references instead. + * + * @returns {string} - JSON string. + * + * @throws {Error} - If there are any circular references within the + * original input. In this case, use `jsonc.safe.stringify()` method + * instead. + * + * @example + * const obj = { key: 'value' }; + * console.log(jsonc.stringify(obj)); // '{"key":"value"}' + * + * // pretty output with indents + * let pretty = jsonc.stringify(obj, null, 2); + * // equivalent to: + * pretty = jsonc.stringify(obj, { reviver: null, space: 2 }); + * if (!err) console.log(pretty); + * // { + * // "key": "value" + * // } + */ + jsonc.stringify = function (value, optionsOrReplacer, space) { + var opts = helper_1.helper.getStringifyOptions(optionsOrReplacer, space); + return opts.handleCircular + ? fast_safe_stringify_1.default(value, opts.replacer, opts.space) + : JSON.stringify(value, opts.replacer, opts.space); + }; + /** + * Specifies whether the given string has well-formed JSON structure. + * + * Note that, not all JSON-parsable strings are considered well-formed JSON + * structures. JSON is built on two structures; a collection of name/value + * pairs (object) or an ordered list of values (array). + * + * For example, `JSON.parse('true')` will parse successfully but + * `jsonc.isJSON('true')` will return `false` since it has no object or + * array structure. + * + * @param {string} str - String to be validated. + * @param {boolean} [allowComments=false] - Whether comments should be + * considered valid. + * + * @returns {boolean} + * + * @example + * jsonc.isJSON('{"x":1}'); // true + * jsonc.isJSON('true'); // false + * jsonc.isJSON('[1, false, null]'); // true + * jsonc.isJSON('string'); // false + * jsonc.isJSON('null'); // false + */ + jsonc.isJSON = function (str, allowComments) { + if (allowComments === void 0) { allowComments = false; } + if (typeof str !== 'string') + return false; + var _a = jsonc.safe.parse(str, { stripComments: allowComments }), err = _a[0], result = _a[1]; + return !err && (helper_1.helper.isObject(result) || Array.isArray(result)); + }; + /** + * Strips comments from the given JSON string. + * + * @param {string} str - JSON string. + * @param {boolean} [whitespace=false] - Whether to replace comments with + * whitespace instead of stripping them entirely. + * + * @returns {string} - Valid JSON string. + * + * @example + * const str = jsonc.stripComments('// comments\n{"key":"value"}'); + * console.log(str); // '\n{"key":"value"}' + */ + jsonc.stripComments = function (str, whitespace) { + if (whitespace === void 0) { whitespace = false; } + return stripJsonComments(str, { whitespace: whitespace }); + }; + /** + * Uglifies the given JSON string. + * + * @param {string} str - JSON string to be uglified. + * @returns {string} - Uglified JSON string. + * + * @example + * const pretty = ` + * { + * // comments... + * "key": "value" + * } + * `; + * const ugly = jsonc.uglify(pretty); + * console.log(ugly); // '{"key":"value"}' + */ + jsonc.uglify = function (str) { + return jsonc.stringify(jsonc.parse(str, { stripComments: true })); + }; + /** + * Beautifies the given JSON string. Note that this will remove comments, + * if any. + * + * @param {string} str - JSON string to be beautified. + * @param {string|number} [space=2] Specifies the indentation of nested + * structures. If it is omitted, the text will be packed without extra + * whitespace. If it is a number, it will specify the number of spaces to + * indent at each level. If it is a string (such as "\t" or " "), it + * contains the characters used to indent at each level. + * + * @returns {string} - Beautified JSON string. + * + * @example + * const ugly = '{"key":"value"}'; + * const pretty = jsonc.beautify(ugly); + * console.log(pretty); + * // { + * // "key": "value" + * // } + */ + jsonc.beautify = function (str, space) { + if (space === void 0) { space = 2; } + if (!space) + space = 2; + return jsonc.stringify(jsonc.parse(str), { space: space }); + }; + /** + * Normalizes the given value by stringifying and parsing it back to a + * Javascript object. + * + * @param {any} value + * @param {Replacer} [replacer] - Determines how object values are + * normalized for objects. It can be a function or an array of strings. + * + * @returns {any} - Normalized object. + * + * @example + * const c = new SomeClass(); + * console.log(c.constructor.name); // "SomeClass" + * const normalized = jsonc.normalize(c); + * console.log(normalized.constructor.name); // "Object" + */ + jsonc.normalize = function (value, replacer) { + return jsonc.parse(jsonc.stringify(value, { replacer: replacer })); + }; + /** + * Asynchronously reads a JSON file, strips comments and UTF-8 BOM and + * parses the JSON content. + * + * @param {string} filePath - Path to JSON file. + * @param {Function|IReadOptions} [options] - Read options. + * @param {Function} [options.reviver] - A function that can filter and + * transform the results. It receives each of the keys and values, and its + * return value is used instead of the original value. If it returns what + * it received, then the structure is not modified. If it returns undefined + * then the member is deleted. + * @param {boolean} [options.stripComments=true] - Whether to strip + * comments from the JSON string. Note that it will throw if this is set to + * `false` and the string includes comments. + * + * @returns {Promise} - Promise of the parsed JSON content as a + * JavaScript object. + * + * @example Using async/await (async () => {try {const + * obj = await jsonc.read('path/to/file.json'); console.log(typeof obj); // + * "object"} catch (err) {console.log('Failed to read JSON file'); + * } + * })(); + * + * @example Using promises + * jsonc.read('path/to/file.json') .then(obj => {console.log(typeof obj); + * // "object" + * }) + * .catch(err => { + * console.log('Failed to read JSON file'); + * }); + */ + jsonc.read = function (filePath, options) { + return __awaiter(this, void 0, void 0, function () { + var opts, data; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + opts = __assign({ reviver: null, stripComments: true }, (options || {})); + return [4 /*yield*/, promise.readFile(filePath, 'utf8')]; + case 1: + data = _a.sent(); + if (opts.stripComments !== false) + data = stripJsonComments(data); + return [2 /*return*/, parseJson(stripBOM(data), opts.reviver, filePath)]; + } + }); + }); + }; + /** + * Synchronously reads a JSON file, strips UTF-8 BOM and parses the JSON + * content. + * + * @param {string} filePath - Path to JSON file. + * @param {Function|IReadOptions} [options] - Read options. + * @param {Function} [options.reviver] - A function that can filter and + * transform the results. It receives each of the keys and values, and its + * return value is used instead of the original value. If it returns what + * it received, then the structure is not modified. If it returns undefined + * then the member is deleted. + * @param {boolean} [options.stripComments=true] - Whether to strip + * comments from the JSON string. Note that it will throw if this is set to + * `false` and the string includes comments. + * + * @returns {any} - Parsed JSON content as a JavaScript object. + * + * @example + * const obj = jsonc.readSync('path/to/file.json'); + * // use try/catch block to handle errors. or better, use the safe version. + * console.log(typeof obj); // "object" + */ + jsonc.readSync = function (filePath, options) { + var opts = __assign({ reviver: null, stripComments: true }, (options || {})); + var data = fs.readFileSync(filePath, 'utf8'); + if (opts.stripComments !== false) + data = stripJsonComments(data); + return parseJson(stripBOM(data), opts.reviver, filePath); + }; + /** + * Asynchronously writes a JSON file from the given JavaScript object. + * + * @param {string} filePath - Path to JSON file to be written. + * @param {any} data - Data to be stringified into JSON. + * @param {IWriteOptions} [options] - Write options. + * @param {Replacer} [options.replacer] - Determines how object values are + * stringified for objects. It can be a function or an array of strings. + * @param {string|number} [options.space] - Specifies the indentation of + * nested structures. If it is omitted, the text will be packed without + * extra whitespace. If it is a number, it will specify the number of + * spaces to indent at each level. If it is a string (such as "\t" or + * " "), it contains the characters used to indent at each level. + * @param {number} [options.mode=438] - FileSystem permission mode to be used when + * writing the file. Default is `438` (`0666` in octal). + * @param {boolean} [options.autoPath=true] - Specifies whether to create path + * directories if they don't exist. This will throw if set to `false` and + * path does not exist. + * + * @returns {Promise} - Always resolves with `true`, if no errors occur. + * + * @example Using async/await + * (async () => { + * try { + * await jsonc.write('path/to/file.json', data); + * console.log('Successfully wrote JSON file'); + * } catch (err) { + * console.log('Failed to write JSON file'); + * } + * })(); + * + * @example Using promises + * jsonc.write('path/to/file.json', data) + * .then(success => { + * console.log('Successfully wrote JSON file'); + * }) + * .catch(err => { + * console.log('Failed to write JSON file'); + * }); + */ + jsonc.write = function (filePath, data, options) { + return __awaiter(this, void 0, void 0, function () { + var opts, content; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + opts = __assign({ replacer: null, space: 0, mode: 438, autoPath: true }, (options || {})); + if (!opts.autoPath) return [3 /*break*/, 2]; + return [4 /*yield*/, promise.mkdirp(path.dirname(filePath), { fs: fs })]; + case 1: + _a.sent(); + _a.label = 2; + case 2: + content = JSON.stringify(data, opts.replacer, opts.space); + return [4 /*yield*/, promise.writeFile(filePath, content + "\n", { + mode: opts.mode, + encoding: 'utf8' + })]; + case 3: + _a.sent(); + return [2 /*return*/, true]; + } + }); + }); + }; + /** + * Synchronously writes a JSON file from the given JavaScript object. + * + * @param {string} filePath - Path to JSON file to be written. + * @param {any} data - Data to be stringified into JSON. + * @param {IWriteOptions} [options] - Write options. + * @param {Replacer} [options.replacer] - Determines how object values are + * stringified for objects. It can be a function or an array of strings. + * @param {string|number} [options.space] - Specifies the indentation of + * nested structures. If it is omitted, the text will be packed without + * extra whitespace. If it is a number, it will specify the number of + * spaces to indent at each level. If it is a string (such as "\t" or + * " "), it contains the characters used to indent at each level. + * @param {number} [options.mode=438] - FileSystem permission mode to be used when + * writing the file. Default is `438` (`0666` in octal). + * @param {boolean} [options.autoPath=true] - Specifies whether to create path + * directories if they don't exist. This will throw if set to `false` and + * path does not exist. + * + * @returns {boolean} - Always returns `true`, if no errors occur. + * + * @example + * const success = jsonc.writeSync('path/to/file.json'); + * // this will always return true. use try/catch block to handle errors. or better, use the safe version. + * console.log('Successfully wrote JSON file'); + */ + jsonc.writeSync = function (filePath, data, options) { + var opts = __assign({ replacer: null, space: 0, mode: 438, autoPath: true }, (options || {})); + if (opts.autoPath) + mkdirp.sync(path.dirname(filePath), { fs: fs }); + var content = JSON.stringify(data, opts.replacer, opts.space); + fs.writeFileSync(filePath, content + "\n", { + mode: opts.mode, + encoding: 'utf8' + }); + return true; + }; + return jsonc; +}()); +exports.jsonc = jsonc; +// default configuration +jsonc.config(null); +/* istanbul ignore next */ +(function (jsonc) { + jsonc.safe = jsonc_safe_1.jsoncSafe; +})(jsonc || (jsonc = {})); +exports.jsonc = jsonc; diff --git a/action/node_modules/jsonc/lib/jsonc.safe.d.ts b/action/node_modules/jsonc/lib/jsonc.safe.d.ts new file mode 100644 index 00000000..37686829 --- /dev/null +++ b/action/node_modules/jsonc/lib/jsonc.safe.d.ts @@ -0,0 +1,451 @@ +import { IConfig, IParseOptions, IReadOptions, IStringifyOptions, IWriteOptions, Replacer, Reviver } from './interfaces'; +/** + * Class that provides safe versions of `jsonc` methods. Safe methods provide a + * way to easily handle errors without throwing; so that you don't need to use + * try/catch blocks. + * + * Each method (except a few such as `.isJSON`), will return an array with the + * first item being the `Error` instance caught. If successful, second item + * will be the result. + * @name jsonc.safe + * @class + * + * @example + * const { safe } = require('jsonc'); + * // or + * import { safe as jsonc } from 'jsonc'; + * + * const [err, result] = jsonc.parse('[invalid JSON}'); + * if (err) { + * console.log(`Failed to parse JSON: ${err.message}`); + * } else { + * console.log(result); + * } + */ +declare class jsoncSafe { + /** + * Configures `jsonc` object. + * + *
This method is added for convenience. Works the same as `jsonc.config()`.
+ * + * @name jsonc.safe.config + * @function + * + * @param {IConfig} cfg - Configurations. + * @param {NodeJS.WriteStream} [stream] - Stream to write logs to. This is + * used with `.log()` and `.logp()` methods. + * @param {NodeJS.WriteStream} [streamErr] - Stream to write error logs to. + * This is used with `.log()` and `.logp()` methods. + * + * @example + * import { safe as jsonc } from 'jsonc'; + * // Output logs to stdout but logs containing errors to a file. + * jsonc.config({ + * stream: process.stdout, + * streamErr: fs.createWriteStream('path/to/log.txt') + * }); + * jsonc.log({ info: 'this is logged to console' }); + * jsonc.log(new Error('this is logged to file')); + */ + static config(cfg: IConfig): void; + /** + * Stringifies and logs the given arguments to console. This will + * automatically handle circular references; so it won't throw. + * + * If an `Error` instance is passed, it will log the `.stack` property on + * the instance, without stringifying the object. + * + *
This method is added for convenience. Works the same as `jsonc.log()`.
+ * @name jsonc.safe.log + * @function + * + * @param {...any[]} [args] - Arguments to be logged. + * @returns {void} + */ + static log(...args: any[]): void; + /** + * Pretty version of `log()` method. Stringifies and logs the given + * arguments to console, with indents. This will automatically handle + * circular references; so it won't throw. + * + * If an `Error` instance is passed, it will log the `.stack` property on + * the instance, without stringifying the object. + * + *
This method is added for convenience. Works the same as `jsonc.logp()`.
+ * @name jsonc.safe.logp + * @function + * + * @param {...any[]} [args] - Arguments to be logged. + * @returns {void} + */ + static logp(...args: any[]): void; + /** + * Safe version of `jsonc.parse()`. Parses the given string into a + * JavaScript object. + * @name jsonc.safe.parse + * @function + * + * @param {string} str - JSON string to be parsed. + * @param {IParseOptions|Reviver} [options] - Either a parse options + * object or a reviver function. + * @param {Reviver} [options.reviver] - A function that can filter and + * transform the results. It receives each of the keys and values, and + * its return value is used instead of the original value. If it + * returns what it received, then the structure is not modified. If it + * returns `undefined` then the member is deleted. + * @param {boolean} [options.stripComments=true] - Whether to strip + * comments from the JSON string. Note that it will return the first + * parameter as an error if this is set to `false` and the string + * includes comments. + * + * @returns {Array} - Safe methods return an array with the + * first item being the `Error` instance caught. If successful, second + * item will be the result: `[Error, any]` + * + * @example + * import { safe as jsonc } from 'jsonc'; + * const [err, result] = jsonc.parse('--invalid JSON--'); + * if (err) { + * console.log('Failed to parse JSON: ' + err.message); + * } else { + * console.log(result); + * } + */ + static parse(str: string, options?: IParseOptions | Reviver): [Error, undefined] | [null, any]; + /** + * Safe version of `jsonc.stringify()`. Stringifies the given + * JavaScript object. The input object can have circular references + * which will return the string `"[Circular]"` for each circular + * reference, by default. You can use a replacer function to replace or + * remove circular references instead. + * @name jsonc.safe.stringify + * @function + * + * @param {*} value - JavaScript value to be stringified. + * @param {IStringifyOptions|Replacer} [options] - Stringify options or + * a replacer. + * @param {Replacer} [options.replacer] - Determines how object values + * are stringified for objects. It can be an array of strings or + * numbers; or a function with the following signature: `(key: string, + * value: any) => any`. + * @param {string|number} [options.space] - Specifies the indentation + * of nested structures. If it is omitted, the text will be packed + * without extra whitespace. If it is a number, it will specify the + * number of spaces to indent at each level. If it is a string (such as + * `"\t"` or `" "`), it contains the characters used to indent at + * each level. + * @param {boolean} [options.handleCircular=true] - Whether to handle + * circular references (if any) by replacing their values with the + * string `"[Circular]"`. You can also use a replacer function to + * replace or remove circular references instead. + * @param {string|number} [space] - This takes effect if second + * argument is the `replacer` or a falsy value. Included for supporting + * the signature of native `JSON.stringify()` method. + * + * @returns {Array} - Safe methods return an array with the + * first item being the `Error` instance caught. If successful, second + * item will be the result: `[Error, string]` + * + * @example + * import { safe as jsonc } from 'jsonc'; + * const obj = { key: 'value' }; + * let [err, str] = jsonc.stringify(obj); + * if (!err) console.log(str); // '{"key":"value"}' + * + * // pretty output with indents + * let [err, pretty] = jsonc.stringify(obj, null, 2); + * // equivalent to: + * [err, pretty] = jsonc.stringify(obj, { reviver: null, space: 2 }); + * if (!err) console.log(pretty); + * // { + * // "key": "value" + * // } + */ + static stringify(value: any, option?: IStringifyOptions): [Error, undefined] | [null, string]; + static stringify(value: any, replacer: Replacer, space?: string | number): [Error, undefined] | [null, string]; + /** + * Specifies whether the given string has well-formed JSON structure. + * + * Note that, not all JSON-parsable strings are considered well-formed JSON + * structures. JSON is built on two structures; a collection of name/value + * pairs (object) or an ordered list of values (array). + * + * For example, `JSON.parse('true')` will parse successfully but + * `jsonc.isJSON('true')` will return `false` since it has no object or + * array structure. + * + *
This method is added for convenience. Works the same as + * `jsonc.isJSON()`.
+ * @name jsonc.safe.isJSON + * @function + * + * @param {string} str - String to be validated. + * @param {boolean} [allowComments=false] - Whether comments should be + * considered valid. + * + * @returns {boolean} + * + * @example + * import { safe as jsonc } from 'jsonc'; + * jsonc.isJSON('{"x":1}'); // true + * jsonc.isJSON('true'); // false + * jsonc.isJSON('[1, false, null]'); // true + * jsonc.isJSON('string'); // false + * jsonc.isJSON('null'); // false + */ + static isJSON(str: string, allowComments?: boolean): boolean; + /** + * Strips comments from the given JSON string. + * @name jsonc.safe.stripComments + * @function + * + * @param {string} str - JSON string. + * @param {boolean} [whitespace=false] - Whether to replace comments + * with whitespace instead of stripping them entirely. + * + * @returns {Array} - Safe methods return an array with the + * first item being the `Error` instance caught. If successful, second + * item will be the result: `[Error, string]` + * + * @example + * import { safe as jsonc } from 'jsonc'; + * const [err, str] = jsonc.stripComments('// comments\n{"key":"value"}'); + * if (!err) console.log(str); // '\n{"key":"value"}' + */ + static stripComments(str: string, whitespace?: boolean): [Error, undefined] | [null, string]; + /** + * Safe version of `jsonc.uglify()`. Uglifies the given JSON string. + * @name jsonc.safe.uglify + * @function + * + * @param {string} str - JSON string to be uglified. + * + * @returns {Array} - Safe methods return an array with the + * first item being the `Error` instance caught. If successful, second + * item will be the result: `[Error, string]` + * + * @example + * import { safe as jsonc } from 'jsonc'; + * const pretty = ` + * { + * // comments... + * "key": "value" + * } + * `; + * const [err, ugly] = jsonc.uglify(pretty); + * if (!err) console.log(ugly); // '{"key":"value"}' + */ + static uglify(str: string): [Error, undefined] | [null, string]; + /** + * Safe version of `jsonc.beautify()`. Beautifies the given JSON + * string. Note that this will remove comments, if any. + * @name jsonc.safe.beautify + * @function + * + * @param {string} str - JSON string to be beautified. + * @param {string|number} [space=2] Specifies the indentation of nested + * structures. If it is omitted, the text will be packed without extra + * whitespace. If it is a number, it will specify the number of spaces + * to indent at each level. If it is a string (such as "\t" or + * " "), it contains the characters used to indent at each level. + * + * @returns {Array} - Safe methods return an array with the + * first item being the `Error` instance caught. If successful, second + * item will be the result: `[Error, string]` + * + * @example + * import { safe as jsonc } from 'jsonc'; + * const ugly = '{"key":"value"}'; + * const [err, pretty] = jsonc.beautify(ugly); + * if (!err) console.log(pretty); + * // { + * // "key": "value" + * // } + */ + static beautify(str: string, space?: string | number): [Error, undefined] | [null, string]; + /** + * Safe version of `jsonc.normalize()`. Normalizes the given value by + * stringifying and parsing it back to a Javascript object. + * @name jsonc.safe.normalize + * @function + * + * @param {any} value + * @param {Replacer} [replacer] - Determines how object values are + * normalized for objects. It can be a function or an array of strings. + * + * @returns {Array} - Safe methods return an array with the + * first item being the `Error` instance caught. If successful, second + * item will be the result: `[Error, any]` + * + * @example + * import { safe as jsonc } from 'jsonc'; + * const c = new SomeClass(); + * console.log(c.constructor.name); // "SomeClass" + * const [err, normalized] = jsonc.normalize(c); + * if (err) { + * console.log('Failed to normalize: ' + err.message); + * } else { + * console.log(normalized.constructor.name); // "Object" + * } + */ + static normalize(value: any, replacer?: Replacer): [Error, undefined] | [null, any]; + /** + * Safe version of `jsonc.read()`. Asynchronously reads a JSON file, + * strips comments and UTF-8 BOM and parses the JSON content. + * @name jsonc.safe.read + * @function + * + * @param {string} filePath - Path to JSON file. + * @param {Function|IReadOptions} [options] - Read options. + * @param {Function} [options.reviver] - A function that can filter and + * transform the results. It receives each of the keys and values, and + * its return value is used instead of the original value. If it + * returns what it received, then the structure is not modified. If it + * returns undefined then the member is deleted. + * @param {boolean} [options.stripComments=true] - Whether to strip + * comments from the JSON string. Note that it will fail if this is + * set to `false` and the string includes comments. + * + * @returns {Promise} - Safe methods return an array with + * the first item being the `Error` instance caught. If successful, + * second item will be the result: `Promise<[Error, any]>` + * + * @example Using async/await (recommended) + * import { safe as jsonc } from 'jsonc'; + * (async () => { + * const [err, obj] = await jsonc.read('path/to/file.json'); + * if (err) { + * console.log('Failed to read JSON file'); + * } catch (err) { + * console.log(typeof obj); // "object" + * } + * })(); + * + * @example Using promises + * import { safe as jsonc } from 'jsonc'; + * jsonc.read('path/to/file.json') + * .then([err, obj] => { + * if (err) { + * console.log('Failed to read JSON file'); + * } else { + * console.log(typeof obj); // "object" + * } + * }) + * // .catch(err => {}); // this is never invoked when safe version is used. + */ + static read(filePath: string, options?: IReadOptions): Promise<[Error, undefined] | [null, any]>; + /** + * Safe version of `jsonc.readSync()`. Synchronously reads a JSON file, + * strips UTF-8 BOM and parses the JSON content. + * @name jsonc.safe.readSync + * @function + * + * @param {string} filePath - Path to JSON file. + * @param {Function|IReadOptions} [options] - Read options. + * @param {Function} [options.reviver] - A function that can filter and + * transform the results. It receives each of the keys and values, and + * its return value is used instead of the original value. If it + * returns what it received, then the structure is not modified. If it + * returns undefined then the member is deleted. + * @param {boolean} [options.stripComments=true] - Whether to strip + * comments from the JSON string. Note that it will fail if this is + * set to `false` and the string includes comments. + * + * @returns {Array} - Safe methods return an array with + * the first item being the `Error` instance caught. If successful, + * second item will be the result: `[Error, any]` + * + * @example + * import { safe as jsonc } from 'jsonc'; + * const [err, obj] = jsonc.readSync('path/to/file.json'); + * if (!err) console.log(typeof obj); // "object" + */ + static readSync(filePath: string, options?: IReadOptions): [Error, undefined] | [null, any]; + /** + * Safe version of `jsonc.write()`. Asynchronously writes a JSON file + * from the given JavaScript object. + * @name jsonc.safe.write + * @function + * + * @param {string} filePath - Path to JSON file to be written. + * @param {any} data - Data to be stringified into JSON. + * @param {IWriteOptions} [options] - Write options. + * @param {Replacer} [options.replacer] - Determines how object values + * are stringified for objects. It can be a function or an array of + * strings. + * @param {string|number} [options.space] - Specifies the indentation + * of nested structures. If it is omitted, the text will be packed + * without extra whitespace. If it is a number, it will specify the + * number of spaces to indent at each level. If it is a string (such as + * "\t" or " "), it contains the characters used to indent at each + * level. + * @param {number} [options.mode=438] - FileSystem permission mode to + * be used when writing the file. Default is `438` (`0666` in octal). + * @param {boolean} [options.autoPath=true] - Specifies whether to + * create path directories if they don't exist. This will throw if set + * to `false` and path does not exist. + * + * @returns {Promise} - Safe methods return an array with the + * first item being the `Error` instance caught. If successful, + * second item will be the result: `Promise<[Error, boolean]>` + * + * @example Using async/await (recommended) + * import { safe as jsonc } from 'jsonc'; + * (async () => { + * const [err, success] = await jsonc.write('path/to/file.json', data); + * if (err) { + * console.log('Failed to read JSON file'); + * } else { + * console.log('Successfully wrote JSON file'); + * } + * })(); + * + * @example Using promises + * import { safe as jsonc } from 'jsonc'; + * jsonc.write('path/to/file.json', data) + * .then([err, obj] => { + * if (err) { + * console.log('Failed to read JSON file'); + * } else { + * console.log('Successfully wrote JSON file'); + * } + * }) + * // .catch(err => {}); // this is never invoked when safe version is used. + */ + static write(filePath: string, data: any, options?: IWriteOptions): Promise<[Error, undefined] | [null, boolean]>; + /** + * Safe version of `jsonc.writeSync()`. Synchronously writes a JSON + * file from the given JavaScript object. + * @name jsonc.safe.writeSync + * @function + * + * @param {string} filePath - Path to JSON file to be written. + * @param {any} data - Data to be stringified into JSON. + * @param {IWriteOptions} [options] - Write options. + * @param {Replacer} [options.replacer] - Determines how object values + * are stringified for objects. It can be a function or an array of + * strings. + * @param {string|number} [options.space] - Specifies the indentation + * of nested structures. If it is omitted, the text will be packed + * without extra whitespace. If it is a number, it will specify the + * number of spaces to indent at each level. If it is a string (such as + * "\t" or " "), it contains the characters used to indent at each + * level. + * @param {number} [options.mode=438] - FileSystem permission mode to + * be used when writing the file. Default is `438` (`0666` in octal). + * @param {boolean} [options.autoPath=true] - Specifies whether to + * create path directories if they don't exist. This will throw if set + * to `false` and path does not exist. + * + * @returns {Array} - Safe methods return an array with the + * first item being the `Error` instance caught. If successful, second + * item will be the result: `[Error, boolean]` + * + * @example + * import { safe as jsonc } from 'jsonc'; + * const [err, obj] = jsonc.writeSync('path/to/file.json'); + * if (!err) console.log(typeof obj); // "object" + */ + static writeSync(filePath: string, data: any, options?: IWriteOptions): [Error, undefined] | [null, boolean]; +} +export { jsoncSafe }; diff --git a/action/node_modules/jsonc/lib/jsonc.safe.js b/action/node_modules/jsonc/lib/jsonc.safe.js new file mode 100644 index 00000000..a85c1f21 --- /dev/null +++ b/action/node_modules/jsonc/lib/jsonc.safe.js @@ -0,0 +1,460 @@ +"use strict"; +/* tslint:disable:class-name no-require-imports no-default-export max-line-length interface-name max-classes-per-file max-file-line-count */ +Object.defineProperty(exports, "__esModule", { value: true }); +// core modules +// dep modules +var fast_safe_stringify_1 = require("fast-safe-stringify"); +var stripJsonComments = require("strip-json-comments"); +// own modules +var helper_1 = require("./helper"); +var jsonc_1 = require("./jsonc"); +// constants, variables +var safeSync = helper_1.helper.safeSync, safeAsync = helper_1.helper.safeAsync; +/** + * Class that provides safe versions of `jsonc` methods. Safe methods provide a + * way to easily handle errors without throwing; so that you don't need to use + * try/catch blocks. + * + * Each method (except a few such as `.isJSON`), will return an array with the + * first item being the `Error` instance caught. If successful, second item + * will be the result. + * @name jsonc.safe + * @class + * + * @example + * const { safe } = require('jsonc'); + * // or + * import { safe as jsonc } from 'jsonc'; + * + * const [err, result] = jsonc.parse('[invalid JSON}'); + * if (err) { + * console.log(`Failed to parse JSON: ${err.message}`); + * } else { + * console.log(result); + * } + */ +var jsoncSafe = /** @class */ (function () { + function jsoncSafe() { + } + /** + * Configures `jsonc` object. + * + *
This method is added for convenience. Works the same as `jsonc.config()`.
+ * + * @name jsonc.safe.config + * @function + * + * @param {IConfig} cfg - Configurations. + * @param {NodeJS.WriteStream} [stream] - Stream to write logs to. This is + * used with `.log()` and `.logp()` methods. + * @param {NodeJS.WriteStream} [streamErr] - Stream to write error logs to. + * This is used with `.log()` and `.logp()` methods. + * + * @example + * import { safe as jsonc } from 'jsonc'; + * // Output logs to stdout but logs containing errors to a file. + * jsonc.config({ + * stream: process.stdout, + * streamErr: fs.createWriteStream('path/to/log.txt') + * }); + * jsonc.log({ info: 'this is logged to console' }); + * jsonc.log(new Error('this is logged to file')); + */ + jsoncSafe.config = function (cfg) { + jsonc_1.jsonc.config(cfg); + }; + /** + * Stringifies and logs the given arguments to console. This will + * automatically handle circular references; so it won't throw. + * + * If an `Error` instance is passed, it will log the `.stack` property on + * the instance, without stringifying the object. + * + *
This method is added for convenience. Works the same as `jsonc.log()`.
+ * @name jsonc.safe.log + * @function + * + * @param {...any[]} [args] - Arguments to be logged. + * @returns {void} + */ + jsoncSafe.log = function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + jsonc_1.jsonc.log.apply(jsonc_1.jsonc, args); + }; + /** + * Pretty version of `log()` method. Stringifies and logs the given + * arguments to console, with indents. This will automatically handle + * circular references; so it won't throw. + * + * If an `Error` instance is passed, it will log the `.stack` property on + * the instance, without stringifying the object. + * + *
This method is added for convenience. Works the same as `jsonc.logp()`.
+ * @name jsonc.safe.logp + * @function + * + * @param {...any[]} [args] - Arguments to be logged. + * @returns {void} + */ + jsoncSafe.logp = function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + jsonc_1.jsonc.logp.apply(jsonc_1.jsonc, args); + }; + /** + * Safe version of `jsonc.parse()`. Parses the given string into a + * JavaScript object. + * @name jsonc.safe.parse + * @function + * + * @param {string} str - JSON string to be parsed. + * @param {IParseOptions|Reviver} [options] - Either a parse options + * object or a reviver function. + * @param {Reviver} [options.reviver] - A function that can filter and + * transform the results. It receives each of the keys and values, and + * its return value is used instead of the original value. If it + * returns what it received, then the structure is not modified. If it + * returns `undefined` then the member is deleted. + * @param {boolean} [options.stripComments=true] - Whether to strip + * comments from the JSON string. Note that it will return the first + * parameter as an error if this is set to `false` and the string + * includes comments. + * + * @returns {Array} - Safe methods return an array with the + * first item being the `Error` instance caught. If successful, second + * item will be the result: `[Error, any]` + * + * @example + * import { safe as jsonc } from 'jsonc'; + * const [err, result] = jsonc.parse('--invalid JSON--'); + * if (err) { + * console.log('Failed to parse JSON: ' + err.message); + * } else { + * console.log(result); + * } + */ + jsoncSafe.parse = function (str, options) { + return safeSync(jsonc_1.jsonc.parse)(str, options); + }; + jsoncSafe.stringify = function (value, optionsOrReplacer, space) { + var opts = helper_1.helper.getStringifyOptions(optionsOrReplacer, space); + try { + return [null, fast_safe_stringify_1.default(value, opts.replacer, opts.space)]; + } + catch (err) { + return [err, undefined]; + } + }; + /** + * Specifies whether the given string has well-formed JSON structure. + * + * Note that, not all JSON-parsable strings are considered well-formed JSON + * structures. JSON is built on two structures; a collection of name/value + * pairs (object) or an ordered list of values (array). + * + * For example, `JSON.parse('true')` will parse successfully but + * `jsonc.isJSON('true')` will return `false` since it has no object or + * array structure. + * + *
This method is added for convenience. Works the same as + * `jsonc.isJSON()`.
+ * @name jsonc.safe.isJSON + * @function + * + * @param {string} str - String to be validated. + * @param {boolean} [allowComments=false] - Whether comments should be + * considered valid. + * + * @returns {boolean} + * + * @example + * import { safe as jsonc } from 'jsonc'; + * jsonc.isJSON('{"x":1}'); // true + * jsonc.isJSON('true'); // false + * jsonc.isJSON('[1, false, null]'); // true + * jsonc.isJSON('string'); // false + * jsonc.isJSON('null'); // false + */ + jsoncSafe.isJSON = function (str, allowComments) { + if (allowComments === void 0) { allowComments = false; } + return jsonc_1.jsonc.isJSON(str, allowComments); + }; + /** + * Strips comments from the given JSON string. + * @name jsonc.safe.stripComments + * @function + * + * @param {string} str - JSON string. + * @param {boolean} [whitespace=false] - Whether to replace comments + * with whitespace instead of stripping them entirely. + * + * @returns {Array} - Safe methods return an array with the + * first item being the `Error` instance caught. If successful, second + * item will be the result: `[Error, string]` + * + * @example + * import { safe as jsonc } from 'jsonc'; + * const [err, str] = jsonc.stripComments('// comments\n{"key":"value"}'); + * if (!err) console.log(str); // '\n{"key":"value"}' + */ + jsoncSafe.stripComments = function (str, whitespace) { + if (whitespace === void 0) { whitespace = false; } + return safeSync(stripJsonComments)(str, { whitespace: whitespace }); + }; + /** + * Safe version of `jsonc.uglify()`. Uglifies the given JSON string. + * @name jsonc.safe.uglify + * @function + * + * @param {string} str - JSON string to be uglified. + * + * @returns {Array} - Safe methods return an array with the + * first item being the `Error` instance caught. If successful, second + * item will be the result: `[Error, string]` + * + * @example + * import { safe as jsonc } from 'jsonc'; + * const pretty = ` + * { + * // comments... + * "key": "value" + * } + * `; + * const [err, ugly] = jsonc.uglify(pretty); + * if (!err) console.log(ugly); // '{"key":"value"}' + */ + jsoncSafe.uglify = function (str) { + return safeSync(jsonc_1.jsonc.uglify)(str); + }; + /** + * Safe version of `jsonc.beautify()`. Beautifies the given JSON + * string. Note that this will remove comments, if any. + * @name jsonc.safe.beautify + * @function + * + * @param {string} str - JSON string to be beautified. + * @param {string|number} [space=2] Specifies the indentation of nested + * structures. If it is omitted, the text will be packed without extra + * whitespace. If it is a number, it will specify the number of spaces + * to indent at each level. If it is a string (such as "\t" or + * " "), it contains the characters used to indent at each level. + * + * @returns {Array} - Safe methods return an array with the + * first item being the `Error` instance caught. If successful, second + * item will be the result: `[Error, string]` + * + * @example + * import { safe as jsonc } from 'jsonc'; + * const ugly = '{"key":"value"}'; + * const [err, pretty] = jsonc.beautify(ugly); + * if (!err) console.log(pretty); + * // { + * // "key": "value" + * // } + */ + jsoncSafe.beautify = function (str, space) { + if (space === void 0) { space = 2; } + return safeSync(jsonc_1.jsonc.beautify)(str, space); + }; + /** + * Safe version of `jsonc.normalize()`. Normalizes the given value by + * stringifying and parsing it back to a Javascript object. + * @name jsonc.safe.normalize + * @function + * + * @param {any} value + * @param {Replacer} [replacer] - Determines how object values are + * normalized for objects. It can be a function or an array of strings. + * + * @returns {Array} - Safe methods return an array with the + * first item being the `Error` instance caught. If successful, second + * item will be the result: `[Error, any]` + * + * @example + * import { safe as jsonc } from 'jsonc'; + * const c = new SomeClass(); + * console.log(c.constructor.name); // "SomeClass" + * const [err, normalized] = jsonc.normalize(c); + * if (err) { + * console.log('Failed to normalize: ' + err.message); + * } else { + * console.log(normalized.constructor.name); // "Object" + * } + */ + jsoncSafe.normalize = function (value, replacer) { + return safeSync(jsonc_1.jsonc.normalize)(value, replacer); + }; + /** + * Safe version of `jsonc.read()`. Asynchronously reads a JSON file, + * strips comments and UTF-8 BOM and parses the JSON content. + * @name jsonc.safe.read + * @function + * + * @param {string} filePath - Path to JSON file. + * @param {Function|IReadOptions} [options] - Read options. + * @param {Function} [options.reviver] - A function that can filter and + * transform the results. It receives each of the keys and values, and + * its return value is used instead of the original value. If it + * returns what it received, then the structure is not modified. If it + * returns undefined then the member is deleted. + * @param {boolean} [options.stripComments=true] - Whether to strip + * comments from the JSON string. Note that it will fail if this is + * set to `false` and the string includes comments. + * + * @returns {Promise} - Safe methods return an array with + * the first item being the `Error` instance caught. If successful, + * second item will be the result: `Promise<[Error, any]>` + * + * @example Using async/await (recommended) + * import { safe as jsonc } from 'jsonc'; + * (async () => { + * const [err, obj] = await jsonc.read('path/to/file.json'); + * if (err) { + * console.log('Failed to read JSON file'); + * } catch (err) { + * console.log(typeof obj); // "object" + * } + * })(); + * + * @example Using promises + * import { safe as jsonc } from 'jsonc'; + * jsonc.read('path/to/file.json') + * .then([err, obj] => { + * if (err) { + * console.log('Failed to read JSON file'); + * } else { + * console.log(typeof obj); // "object" + * } + * }) + * // .catch(err => {}); // this is never invoked when safe version is used. + */ + jsoncSafe.read = function (filePath, options) { + return safeAsync(jsonc_1.jsonc.read(filePath, options)); + }; + /** + * Safe version of `jsonc.readSync()`. Synchronously reads a JSON file, + * strips UTF-8 BOM and parses the JSON content. + * @name jsonc.safe.readSync + * @function + * + * @param {string} filePath - Path to JSON file. + * @param {Function|IReadOptions} [options] - Read options. + * @param {Function} [options.reviver] - A function that can filter and + * transform the results. It receives each of the keys and values, and + * its return value is used instead of the original value. If it + * returns what it received, then the structure is not modified. If it + * returns undefined then the member is deleted. + * @param {boolean} [options.stripComments=true] - Whether to strip + * comments from the JSON string. Note that it will fail if this is + * set to `false` and the string includes comments. + * + * @returns {Array} - Safe methods return an array with + * the first item being the `Error` instance caught. If successful, + * second item will be the result: `[Error, any]` + * + * @example + * import { safe as jsonc } from 'jsonc'; + * const [err, obj] = jsonc.readSync('path/to/file.json'); + * if (!err) console.log(typeof obj); // "object" + */ + jsoncSafe.readSync = function (filePath, options) { + return safeSync(jsonc_1.jsonc.readSync)(filePath, options); + }; + /** + * Safe version of `jsonc.write()`. Asynchronously writes a JSON file + * from the given JavaScript object. + * @name jsonc.safe.write + * @function + * + * @param {string} filePath - Path to JSON file to be written. + * @param {any} data - Data to be stringified into JSON. + * @param {IWriteOptions} [options] - Write options. + * @param {Replacer} [options.replacer] - Determines how object values + * are stringified for objects. It can be a function or an array of + * strings. + * @param {string|number} [options.space] - Specifies the indentation + * of nested structures. If it is omitted, the text will be packed + * without extra whitespace. If it is a number, it will specify the + * number of spaces to indent at each level. If it is a string (such as + * "\t" or " "), it contains the characters used to indent at each + * level. + * @param {number} [options.mode=438] - FileSystem permission mode to + * be used when writing the file. Default is `438` (`0666` in octal). + * @param {boolean} [options.autoPath=true] - Specifies whether to + * create path directories if they don't exist. This will throw if set + * to `false` and path does not exist. + * + * @returns {Promise} - Safe methods return an array with the + * first item being the `Error` instance caught. If successful, + * second item will be the result: `Promise<[Error, boolean]>` + * + * @example Using async/await (recommended) + * import { safe as jsonc } from 'jsonc'; + * (async () => { + * const [err, success] = await jsonc.write('path/to/file.json', data); + * if (err) { + * console.log('Failed to read JSON file'); + * } else { + * console.log('Successfully wrote JSON file'); + * } + * })(); + * + * @example Using promises + * import { safe as jsonc } from 'jsonc'; + * jsonc.write('path/to/file.json', data) + * .then([err, obj] => { + * if (err) { + * console.log('Failed to read JSON file'); + * } else { + * console.log('Successfully wrote JSON file'); + * } + * }) + * // .catch(err => {}); // this is never invoked when safe version is used. + */ + jsoncSafe.write = function (filePath, data, options) { + return safeAsync(jsonc_1.jsonc.write(filePath, data, options)); + }; + /** + * Safe version of `jsonc.writeSync()`. Synchronously writes a JSON + * file from the given JavaScript object. + * @name jsonc.safe.writeSync + * @function + * + * @param {string} filePath - Path to JSON file to be written. + * @param {any} data - Data to be stringified into JSON. + * @param {IWriteOptions} [options] - Write options. + * @param {Replacer} [options.replacer] - Determines how object values + * are stringified for objects. It can be a function or an array of + * strings. + * @param {string|number} [options.space] - Specifies the indentation + * of nested structures. If it is omitted, the text will be packed + * without extra whitespace. If it is a number, it will specify the + * number of spaces to indent at each level. If it is a string (such as + * "\t" or " "), it contains the characters used to indent at each + * level. + * @param {number} [options.mode=438] - FileSystem permission mode to + * be used when writing the file. Default is `438` (`0666` in octal). + * @param {boolean} [options.autoPath=true] - Specifies whether to + * create path directories if they don't exist. This will throw if set + * to `false` and path does not exist. + * + * @returns {Array} - Safe methods return an array with the + * first item being the `Error` instance caught. If successful, second + * item will be the result: `[Error, boolean]` + * + * @example + * import { safe as jsonc } from 'jsonc'; + * const [err, obj] = jsonc.writeSync('path/to/file.json'); + * if (!err) console.log(typeof obj); // "object" + */ + jsoncSafe.writeSync = function (filePath, data, options) { + return safeSync(jsonc_1.jsonc.writeSync)(filePath, data, options); + }; + return jsoncSafe; +}()); +exports.jsoncSafe = jsoncSafe; diff --git a/action/node_modules/jsonc/package.json b/action/node_modules/jsonc/package.json new file mode 100644 index 00000000..a48aa006 --- /dev/null +++ b/action/node_modules/jsonc/package.json @@ -0,0 +1,102 @@ +{ + "name": "jsonc", + "version": "2.0.0", + "description": "Everything you need in JSON land. Parse JSON with comments, stringify objects with circular references, etc...", + "author": "Onur Yıldırım ", + "license": "MIT", + "homepage": "https://onury.io/jsonc", + "repository": "onury/jsonc", + "main": "index.js", + "files": [ + "lib", + "index.js", + "LICENSE" + ], + "types": "./lib/jsonc.d.ts", + "engines": { + "node": ">=8" + }, + "scripts": { + "clean": "rimraf ./lib", + "build": "npm run clean && npm run cover && mkdirp ./lib && tsc", + "test": "jest --verbose --no-cache", + "cover": "jest --coverage --verbose --no-cache", + "coveralls": "cat ./test/coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js -v", + "report": "open ./test/coverage/lcov-report/index.html", + "docs": "docma -c ./docma.json" + }, + "jest": { + "testEnvironment": "node", + "globals": { + "ts-jest": { + "diagnostics": false + } + }, + "roots": [ + "/src", + "/lib", + "/test" + ], + "transform": { + "^.+\\.tsx?$": "ts-jest" + }, + "testRegex": "(/test/.*|(\\.|/)(test|spec))\\.tsx?$", + "moduleFileExtensions": [ + "ts", + "tsx", + "js", + "json" + ], + "testPathIgnorePatterns": [ + "/backup/", + "/helpers/", + "/coverage/" + ], + "collectCoverageFrom": [ + "src/**/*.ts", + "!src/interfaces.ts" + ], + "coverageDirectory": "./test/coverage" + }, + "keywords": [ + "json", + "object", + "notation", + "safe", + "stringify", + "parse", + "read-file", + "write-file", + "comments", + "circular", + "cyclic", + "console", + "log", + "uglify", + "beautify", + "typescript" + ], + "dependencies": { + "fast-safe-stringify": "^2.0.6", + "graceful-fs": "^4.1.15", + "mkdirp": "^0.5.1", + "parse-json": "^4.0.0", + "strip-bom": "^4.0.0", + "strip-json-comments": "^3.0.1" + }, + "devDependencies": { + "@types/jest": "^24.0.15", + "@types/mkdirp": "^0.5.2", + "@types/node": "^12.0.8", + "@types/parse-json": "^4.0.0", + "@types/strip-bom": "^4.0.1", + "@types/strip-json-comments": "0.0.30", + "coveralls": "^3.0.4", + "docma": "^3.2.2", + "jest": "^24.8.0", + "jest-cli": "^24.8.0", + "rimraf": "^2.6.3", + "ts-jest": "^24.0.2", + "typescript": "^3.5.2" + } +} diff --git a/action/node_modules/minimist/.eslintrc b/action/node_modules/minimist/.eslintrc new file mode 100644 index 00000000..bd1a5e04 --- /dev/null +++ b/action/node_modules/minimist/.eslintrc @@ -0,0 +1,29 @@ +{ + "root": true, + + "extends": "@ljharb/eslint-config/node/0.4", + + "rules": { + "array-element-newline": 0, + "complexity": 0, + "func-style": [2, "declaration"], + "max-lines-per-function": 0, + "max-nested-callbacks": 1, + "max-statements-per-line": 1, + "max-statements": 0, + "multiline-comment-style": 0, + "no-continue": 1, + "no-param-reassign": 1, + "no-restricted-syntax": 1, + "object-curly-newline": 0, + }, + + "overrides": [ + { + "files": "test/**", + "rules": { + "camelcase": 0, + }, + }, + ] +} diff --git a/action/node_modules/minimist/.github/FUNDING.yml b/action/node_modules/minimist/.github/FUNDING.yml new file mode 100644 index 00000000..a9366222 --- /dev/null +++ b/action/node_modules/minimist/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: [ljharb] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: npm/minimist +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/action/node_modules/minimist/.nycrc b/action/node_modules/minimist/.nycrc new file mode 100644 index 00000000..55c3d293 --- /dev/null +++ b/action/node_modules/minimist/.nycrc @@ -0,0 +1,14 @@ +{ + "all": true, + "check-coverage": false, + "reporter": ["text-summary", "text", "html", "json"], + "lines": 86, + "statements": 85.93, + "functions": 82.43, + "branches": 76.06, + "exclude": [ + "coverage", + "example", + "test" + ] +} diff --git a/action/node_modules/minimist/CHANGELOG.md b/action/node_modules/minimist/CHANGELOG.md new file mode 100644 index 00000000..c9a1e15e --- /dev/null +++ b/action/node_modules/minimist/CHANGELOG.md @@ -0,0 +1,298 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [v1.2.8](https://github.com/minimistjs/minimist/compare/v1.2.7...v1.2.8) - 2023-02-09 + +### Merged + +- [Fix] Fix long option followed by single dash [`#17`](https://github.com/minimistjs/minimist/pull/17) +- [Tests] Remove duplicate test [`#12`](https://github.com/minimistjs/minimist/pull/12) +- [Fix] opt.string works with multiple aliases [`#10`](https://github.com/minimistjs/minimist/pull/10) + +### Fixed + +- [Fix] Fix long option followed by single dash (#17) [`#15`](https://github.com/minimistjs/minimist/issues/15) +- [Tests] Remove duplicate test (#12) [`#8`](https://github.com/minimistjs/minimist/issues/8) +- [Fix] Fix long option followed by single dash [`#15`](https://github.com/minimistjs/minimist/issues/15) +- [Fix] opt.string works with multiple aliases (#10) [`#9`](https://github.com/minimistjs/minimist/issues/9) +- [Fix] Fix handling of short option with non-trivial equals [`#5`](https://github.com/minimistjs/minimist/issues/5) +- [Tests] Remove duplicate test [`#8`](https://github.com/minimistjs/minimist/issues/8) +- [Fix] opt.string works with multiple aliases [`#9`](https://github.com/minimistjs/minimist/issues/9) + +### Commits + +- Merge tag 'v0.2.3' [`a026794`](https://github.com/minimistjs/minimist/commit/a0267947c7870fc5847cf2d437fbe33f392767da) +- [eslint] fix indentation and whitespace [`5368ca4`](https://github.com/minimistjs/minimist/commit/5368ca4147e974138a54cc0dc4cea8f756546b70) +- [eslint] fix indentation and whitespace [`e5f5067`](https://github.com/minimistjs/minimist/commit/e5f5067259ceeaf0b098d14bec910f87e58708c7) +- [eslint] more cleanup [`62fde7d`](https://github.com/minimistjs/minimist/commit/62fde7d935f83417fb046741531a9e2346a36976) +- [eslint] more cleanup [`36ac5d0`](https://github.com/minimistjs/minimist/commit/36ac5d0d95e4947d074e5737d94814034ca335d1) +- [meta] add `auto-changelog` [`73923d2`](https://github.com/minimistjs/minimist/commit/73923d223553fca08b1ba77e3fbc2a492862ae4c) +- [actions] add reusable workflows [`d80727d`](https://github.com/minimistjs/minimist/commit/d80727df77bfa9e631044d7f16368d8f09242c91) +- [eslint] add eslint; rules to enable later are warnings [`48bc06a`](https://github.com/minimistjs/minimist/commit/48bc06a1b41f00e9cdf183db34f7a51ba70e98d4) +- [eslint] fix indentation [`34b0f1c`](https://github.com/minimistjs/minimist/commit/34b0f1ccaa45183c3c4f06a91f9b405180a6f982) +- [readme] rename and add badges [`5df0fe4`](https://github.com/minimistjs/minimist/commit/5df0fe49211bd09a3636f8686a7cb3012c3e98f0) +- [Dev Deps] switch from `covert` to `nyc` [`a48b128`](https://github.com/minimistjs/minimist/commit/a48b128fdb8d427dfb20a15273f83e38d97bef07) +- [Dev Deps] update `covert`, `tape`; remove unnecessary `tap` [`f0fb958`](https://github.com/minimistjs/minimist/commit/f0fb958e9a1fe980cdffc436a211b0bda58f621b) +- [meta] create FUNDING.yml; add `funding` in package.json [`3639e0c`](https://github.com/minimistjs/minimist/commit/3639e0c819359a366387e425ab6eabf4c78d3caa) +- [meta] use `npmignore` to autogenerate an npmignore file [`be2e038`](https://github.com/minimistjs/minimist/commit/be2e038c342d8333b32f0fde67a0026b79c8150e) +- Only apps should have lockfiles [`282b570`](https://github.com/minimistjs/minimist/commit/282b570e7489d01b03f2d6d3dabf79cd3e5f84cf) +- isConstructorOrProto adapted from PR [`ef9153f`](https://github.com/minimistjs/minimist/commit/ef9153fc52b6cea0744b2239921c5dcae4697f11) +- [Dev Deps] update `@ljharb/eslint-config`, `aud` [`098873c`](https://github.com/minimistjs/minimist/commit/098873c213cdb7c92e55ae1ef5aa1af3a8192a79) +- [Dev Deps] update `@ljharb/eslint-config`, `aud` [`3124ed3`](https://github.com/minimistjs/minimist/commit/3124ed3e46306301ebb3c834874ce0241555c2c4) +- [meta] add `safe-publish-latest` [`4b927de`](https://github.com/minimistjs/minimist/commit/4b927de696d561c636b4f43bf49d4597cb36d6d6) +- [Tests] add `aud` in `posttest` [`b32d9bd`](https://github.com/minimistjs/minimist/commit/b32d9bd0ab340f4e9f8c3a97ff2a4424f25fab8c) +- [meta] update repo URLs [`f9fdfc0`](https://github.com/minimistjs/minimist/commit/f9fdfc032c54884d9a9996a390c63cd0719bbe1a) +- [actions] Avoid 0.6 tests due to build failures [`ba92fe6`](https://github.com/minimistjs/minimist/commit/ba92fe6ebbdc0431cca9a2ea8f27beb492f5e4ec) +- [Dev Deps] update `tape` [`950eaa7`](https://github.com/minimistjs/minimist/commit/950eaa74f112e04d23e9c606c67472c46739b473) +- [Dev Deps] add missing `npmignore` dev dep [`3226afa`](https://github.com/minimistjs/minimist/commit/3226afaf09e9d127ca369742437fe6e88f752d6b) +- Merge tag 'v0.2.2' [`980d7ac`](https://github.com/minimistjs/minimist/commit/980d7ac61a0b4bd552711251ac107d506b23e41f) + +## [v1.2.7](https://github.com/minimistjs/minimist/compare/v1.2.6...v1.2.7) - 2022-10-10 + +### Commits + +- [meta] add `auto-changelog` [`0ebf4eb`](https://github.com/minimistjs/minimist/commit/0ebf4ebcd5f7787a5524d31a849ef41316b83c3c) +- [actions] add reusable workflows [`e115b63`](https://github.com/minimistjs/minimist/commit/e115b63fa9d3909f33b00a2db647ff79068388de) +- [eslint] add eslint; rules to enable later are warnings [`f58745b`](https://github.com/minimistjs/minimist/commit/f58745b9bb84348e1be72af7dbba5840c7c13013) +- [Dev Deps] switch from `covert` to `nyc` [`ab03356`](https://github.com/minimistjs/minimist/commit/ab033567b9c8b31117cb026dc7f1e592ce455c65) +- [readme] rename and add badges [`236f4a0`](https://github.com/minimistjs/minimist/commit/236f4a07e4ebe5ee44f1496ec6974991ab293ffd) +- [meta] create FUNDING.yml; add `funding` in package.json [`783a49b`](https://github.com/minimistjs/minimist/commit/783a49bfd47e8335d3098a8cac75662cf71eb32a) +- [meta] use `npmignore` to autogenerate an npmignore file [`f81ece6`](https://github.com/minimistjs/minimist/commit/f81ece6aaec2fa14e69ff4f1e0407a8c4e2635a2) +- Only apps should have lockfiles [`56cad44`](https://github.com/minimistjs/minimist/commit/56cad44c7f879b9bb5ec18fcc349308024a89bfc) +- [Dev Deps] update `covert`, `tape`; remove unnecessary `tap` [`49c5f9f`](https://github.com/minimistjs/minimist/commit/49c5f9fb7e6a92db9eb340cc679de92fb3aacded) +- [Tests] add `aud` in `posttest` [`228ae93`](https://github.com/minimistjs/minimist/commit/228ae938f3cd9db9dfd8bd7458b076a7b2aef280) +- [meta] add `safe-publish-latest` [`01fc23f`](https://github.com/minimistjs/minimist/commit/01fc23f5104f85c75059972e01dd33796ab529ff) +- [meta] update repo URLs [`6b164c7`](https://github.com/minimistjs/minimist/commit/6b164c7d68e0b6bf32f894699effdfb7c63041dd) + +## [v1.2.6](https://github.com/minimistjs/minimist/compare/v1.2.5...v1.2.6) - 2022-03-21 + +### Commits + +- test from prototype pollution PR [`bc8ecee`](https://github.com/minimistjs/minimist/commit/bc8ecee43875261f4f17eb20b1243d3ed15e70eb) +- isConstructorOrProto adapted from PR [`c2b9819`](https://github.com/minimistjs/minimist/commit/c2b981977fa834b223b408cfb860f933c9811e4d) +- security notice for additional prototype pollution issue [`ef88b93`](https://github.com/minimistjs/minimist/commit/ef88b9325f77b5ee643ccfc97e2ebda577e4c4e2) + +## [v1.2.5](https://github.com/minimistjs/minimist/compare/v1.2.4...v1.2.5) - 2020-03-12 + +## [v1.2.4](https://github.com/minimistjs/minimist/compare/v1.2.3...v1.2.4) - 2020-03-11 + +### Commits + +- security notice [`4cf1354`](https://github.com/minimistjs/minimist/commit/4cf1354839cb972e38496d35e12f806eea92c11f) +- additional test for constructor prototype pollution [`1043d21`](https://github.com/minimistjs/minimist/commit/1043d212c3caaf871966e710f52cfdf02f9eea4b) + +## [v1.2.3](https://github.com/minimistjs/minimist/compare/v1.2.2...v1.2.3) - 2020-03-10 + +### Commits + +- more failing proto pollution tests [`13c01a5`](https://github.com/minimistjs/minimist/commit/13c01a5327736903704984b7f65616b8476850cc) +- even more aggressive checks for protocol pollution [`38a4d1c`](https://github.com/minimistjs/minimist/commit/38a4d1caead72ef99e824bb420a2528eec03d9ab) + +## [v1.2.2](https://github.com/minimistjs/minimist/compare/v1.2.1...v1.2.2) - 2020-03-10 + +### Commits + +- failing test for protocol pollution [`0efed03`](https://github.com/minimistjs/minimist/commit/0efed0340ec8433638758f7ca0c77cb20a0bfbab) +- cleanup [`67d3722`](https://github.com/minimistjs/minimist/commit/67d3722413448d00a62963d2d30c34656a92d7e2) +- console.dir -> console.log [`47acf72`](https://github.com/minimistjs/minimist/commit/47acf72c715a630bf9ea013867f47f1dd69dfc54) +- don't assign onto __proto__ [`63e7ed0`](https://github.com/minimistjs/minimist/commit/63e7ed05aa4b1889ec2f3b196426db4500cbda94) + +## [v1.2.1](https://github.com/minimistjs/minimist/compare/v1.2.0...v1.2.1) - 2020-03-10 + +### Merged + +- move the `opts['--']` example back where it belongs [`#63`](https://github.com/minimistjs/minimist/pull/63) + +### Commits + +- add test [`6be5dae`](https://github.com/minimistjs/minimist/commit/6be5dae35a32a987bcf4137fcd6c19c5200ee909) +- fix bad boolean regexp [`ac3fc79`](https://github.com/minimistjs/minimist/commit/ac3fc796e63b95128fdbdf67ea7fad71bd59aa76) + +## [v1.2.0](https://github.com/minimistjs/minimist/compare/v1.1.3...v1.2.0) - 2015-08-24 + +### Commits + +- failing -k=v short test [`63416b8`](https://github.com/minimistjs/minimist/commit/63416b8cd1d0d70e4714564cce465a36e4dd26d7) +- kv short fix [`6bbe145`](https://github.com/minimistjs/minimist/commit/6bbe14529166245e86424f220a2321442fe88dc3) +- failing kv short test [`f72ab7f`](https://github.com/minimistjs/minimist/commit/f72ab7f4572adc52902c9b6873cc969192f01b10) +- fixed kv test [`f5a48c3`](https://github.com/minimistjs/minimist/commit/f5a48c3e50e40ca54f00c8e84de4b4d6e9897fa8) +- enforce space between arg key and value [`86b321a`](https://github.com/minimistjs/minimist/commit/86b321affe648a8e016c095a4f0efa9d9074f502) + +## [v1.1.3](https://github.com/minimistjs/minimist/compare/v1.1.2...v1.1.3) - 2015-08-06 + +### Commits + +- add failing test - boolean alias array [`0fa3c5b`](https://github.com/minimistjs/minimist/commit/0fa3c5b3dd98551ddecf5392831b4c21211743fc) +- fix boolean values with multiple aliases [`9c0a6e7`](https://github.com/minimistjs/minimist/commit/9c0a6e7de25a273b11bbf9a7464f0bd833779795) + +## [v1.1.2](https://github.com/minimistjs/minimist/compare/v1.1.1...v1.1.2) - 2015-07-22 + +### Commits + +- Convert boolean arguments to boolean values [`8f3dc27`](https://github.com/minimistjs/minimist/commit/8f3dc27cf833f1d54671b6d0bcb55c2fe19672a9) +- use non-ancient npm, node 0.12 and iojs [`61ed1d0`](https://github.com/minimistjs/minimist/commit/61ed1d034b9ec7282764ce76f3992b1a0b4906ae) +- an older npm for 0.8 [`25cf778`](https://github.com/minimistjs/minimist/commit/25cf778b1220e7838a526832ad6972f75244054f) + +## [v1.1.1](https://github.com/minimistjs/minimist/compare/v1.1.0...v1.1.1) - 2015-03-10 + +### Commits + +- check that they type of a value is a boolean, not just that it is currently set to a boolean [`6863198`](https://github.com/minimistjs/minimist/commit/6863198e36139830ff1f20ffdceaddd93f2c1db9) +- upgrade tape, fix type issues from old tape version [`806712d`](https://github.com/minimistjs/minimist/commit/806712df91604ed02b8e39aa372b84aea659ee34) +- test for setting a boolean to a null default [`8c444fe`](https://github.com/minimistjs/minimist/commit/8c444fe89384ded7d441c120915ea60620b01dd3) +- if the previous value was a boolean, without an default (or with an alias) don't make an array either [`e5f419a`](https://github.com/minimistjs/minimist/commit/e5f419a3b5b3bc3f9e5ac71b7040621af70ed2dd) + +## [v1.1.0](https://github.com/minimistjs/minimist/compare/v1.0.0...v1.1.0) - 2014-08-10 + +### Commits + +- add support for handling "unknown" options not registered with the parser. [`6f3cc5d`](https://github.com/minimistjs/minimist/commit/6f3cc5d4e84524932a6ef2ce3592acc67cdd4383) +- reformat package.json [`02ed371`](https://github.com/minimistjs/minimist/commit/02ed37115194d3697ff358e8e25e5e66bab1d9f8) +- coverage script [`e5531ba`](https://github.com/minimistjs/minimist/commit/e5531ba0479da3b8138d3d8cac545d84ccb1c8df) +- extra fn to get 100% coverage again [`a6972da`](https://github.com/minimistjs/minimist/commit/a6972da89e56bf77642f8ec05a13b6558db93498) + +## [v1.0.0](https://github.com/minimistjs/minimist/compare/v0.2.3...v1.0.0) - 2014-08-10 + +### Commits + +- added stopEarly option [`471c7e4`](https://github.com/minimistjs/minimist/commit/471c7e4a7e910fc7ad8f9df850a186daf32c64e9) +- fix list [`fef6ae7`](https://github.com/minimistjs/minimist/commit/fef6ae79c38b9dc1c49569abb7cd04eb965eac5e) + +## [v0.2.3](https://github.com/minimistjs/minimist/compare/v0.2.2...v0.2.3) - 2023-02-09 + +### Merged + +- [Fix] Fix long option followed by single dash [`#17`](https://github.com/minimistjs/minimist/pull/17) +- [Tests] Remove duplicate test [`#12`](https://github.com/minimistjs/minimist/pull/12) +- [Fix] opt.string works with multiple aliases [`#10`](https://github.com/minimistjs/minimist/pull/10) + +### Fixed + +- [Fix] Fix long option followed by single dash (#17) [`#15`](https://github.com/minimistjs/minimist/issues/15) +- [Tests] Remove duplicate test (#12) [`#8`](https://github.com/minimistjs/minimist/issues/8) +- [Fix] opt.string works with multiple aliases (#10) [`#9`](https://github.com/minimistjs/minimist/issues/9) + +### Commits + +- [eslint] fix indentation and whitespace [`e5f5067`](https://github.com/minimistjs/minimist/commit/e5f5067259ceeaf0b098d14bec910f87e58708c7) +- [eslint] more cleanup [`36ac5d0`](https://github.com/minimistjs/minimist/commit/36ac5d0d95e4947d074e5737d94814034ca335d1) +- [eslint] fix indentation [`34b0f1c`](https://github.com/minimistjs/minimist/commit/34b0f1ccaa45183c3c4f06a91f9b405180a6f982) +- isConstructorOrProto adapted from PR [`ef9153f`](https://github.com/minimistjs/minimist/commit/ef9153fc52b6cea0744b2239921c5dcae4697f11) +- [Dev Deps] update `@ljharb/eslint-config`, `aud` [`098873c`](https://github.com/minimistjs/minimist/commit/098873c213cdb7c92e55ae1ef5aa1af3a8192a79) +- [Dev Deps] add missing `npmignore` dev dep [`3226afa`](https://github.com/minimistjs/minimist/commit/3226afaf09e9d127ca369742437fe6e88f752d6b) + +## [v0.2.2](https://github.com/minimistjs/minimist/compare/v0.2.1...v0.2.2) - 2022-10-10 + +### Commits + +- [meta] add `auto-changelog` [`73923d2`](https://github.com/minimistjs/minimist/commit/73923d223553fca08b1ba77e3fbc2a492862ae4c) +- [actions] add reusable workflows [`d80727d`](https://github.com/minimistjs/minimist/commit/d80727df77bfa9e631044d7f16368d8f09242c91) +- [eslint] add eslint; rules to enable later are warnings [`48bc06a`](https://github.com/minimistjs/minimist/commit/48bc06a1b41f00e9cdf183db34f7a51ba70e98d4) +- [readme] rename and add badges [`5df0fe4`](https://github.com/minimistjs/minimist/commit/5df0fe49211bd09a3636f8686a7cb3012c3e98f0) +- [Dev Deps] switch from `covert` to `nyc` [`a48b128`](https://github.com/minimistjs/minimist/commit/a48b128fdb8d427dfb20a15273f83e38d97bef07) +- [Dev Deps] update `covert`, `tape`; remove unnecessary `tap` [`f0fb958`](https://github.com/minimistjs/minimist/commit/f0fb958e9a1fe980cdffc436a211b0bda58f621b) +- [meta] create FUNDING.yml; add `funding` in package.json [`3639e0c`](https://github.com/minimistjs/minimist/commit/3639e0c819359a366387e425ab6eabf4c78d3caa) +- [meta] use `npmignore` to autogenerate an npmignore file [`be2e038`](https://github.com/minimistjs/minimist/commit/be2e038c342d8333b32f0fde67a0026b79c8150e) +- Only apps should have lockfiles [`282b570`](https://github.com/minimistjs/minimist/commit/282b570e7489d01b03f2d6d3dabf79cd3e5f84cf) +- [meta] add `safe-publish-latest` [`4b927de`](https://github.com/minimistjs/minimist/commit/4b927de696d561c636b4f43bf49d4597cb36d6d6) +- [Tests] add `aud` in `posttest` [`b32d9bd`](https://github.com/minimistjs/minimist/commit/b32d9bd0ab340f4e9f8c3a97ff2a4424f25fab8c) +- [meta] update repo URLs [`f9fdfc0`](https://github.com/minimistjs/minimist/commit/f9fdfc032c54884d9a9996a390c63cd0719bbe1a) + +## [v0.2.1](https://github.com/minimistjs/minimist/compare/v0.2.0...v0.2.1) - 2020-03-12 + +## [v0.2.0](https://github.com/minimistjs/minimist/compare/v0.1.0...v0.2.0) - 2014-06-19 + +### Commits + +- support all-boolean mode [`450a97f`](https://github.com/minimistjs/minimist/commit/450a97f6e2bc85c7a4a13185c19a818d9a5ebe69) + +## [v0.1.0](https://github.com/minimistjs/minimist/compare/v0.0.10...v0.1.0) - 2014-05-12 + +### Commits + +- Provide a mechanism to segregate -- arguments [`ce4a1e6`](https://github.com/minimistjs/minimist/commit/ce4a1e63a7e8d5ab88d2a3768adefa6af98a445a) +- documented argv['--'] [`14db0e6`](https://github.com/minimistjs/minimist/commit/14db0e6dbc6d2b9e472adaa54dad7004b364634f) +- Adding a test-case for notFlags segregation [`715c1e3`](https://github.com/minimistjs/minimist/commit/715c1e3714be223f998f6c537af6b505f0236c16) + +## [v0.0.10](https://github.com/minimistjs/minimist/compare/v0.0.9...v0.0.10) - 2014-05-11 + +### Commits + +- dedicated boolean test [`46e448f`](https://github.com/minimistjs/minimist/commit/46e448f9f513cfeb2bcc8b688b9b47ba1e515c2b) +- dedicated num test [`9bf2d36`](https://github.com/minimistjs/minimist/commit/9bf2d36f1d3b8795be90b8f7de0a937f098aa394) +- aliased values treated as strings [`1ab743b`](https://github.com/minimistjs/minimist/commit/1ab743bad4484d69f1259bed42f9531de01119de) +- cover the case of already numbers, at 100% coverage [`b2bb044`](https://github.com/minimistjs/minimist/commit/b2bb04436599d77a2ce029e8e555e25b3aa55d13) +- another test for higher coverage [`3662624`](https://github.com/minimistjs/minimist/commit/3662624be976d5489d486a856849c048d13be903) + +## [v0.0.9](https://github.com/minimistjs/minimist/compare/v0.0.8...v0.0.9) - 2014-05-08 + +### Commits + +- Eliminate `longest` fn. [`824f642`](https://github.com/minimistjs/minimist/commit/824f642038d1b02ede68b6261d1d65163390929a) + +## [v0.0.8](https://github.com/minimistjs/minimist/compare/v0.0.7...v0.0.8) - 2014-02-20 + +### Commits + +- return '' if flag is string and empty [`fa63ed4`](https://github.com/minimistjs/minimist/commit/fa63ed4651a4ef4eefddce34188e0d98d745a263) +- handle joined single letters [`66c248f`](https://github.com/minimistjs/minimist/commit/66c248f0241d4d421d193b022e9e365f11178534) + +## [v0.0.7](https://github.com/minimistjs/minimist/compare/v0.0.6...v0.0.7) - 2014-02-08 + +### Commits + +- another swap of .test for .match [`d1da408`](https://github.com/minimistjs/minimist/commit/d1da40819acbe846d89a5c02721211e3c1260dde) + +## [v0.0.6](https://github.com/minimistjs/minimist/compare/v0.0.5...v0.0.6) - 2014-02-08 + +### Commits + +- use .test() instead of .match() to not crash on non-string values in the arguments array [`7e0d1ad`](https://github.com/minimistjs/minimist/commit/7e0d1add8c9e5b9b20a4d3d0f9a94d824c578da1) + +## [v0.0.5](https://github.com/minimistjs/minimist/compare/v0.0.4...v0.0.5) - 2013-09-18 + +### Commits + +- Improve '--' handling. [`b11822c`](https://github.com/minimistjs/minimist/commit/b11822c09cc9d2460f30384d12afc0b953c037a4) + +## [v0.0.4](https://github.com/minimistjs/minimist/compare/v0.0.3...v0.0.4) - 2013-09-17 + +## [v0.0.3](https://github.com/minimistjs/minimist/compare/v0.0.2...v0.0.3) - 2013-09-12 + +### Commits + +- failing test for single dash preceeding a double dash [`b465514`](https://github.com/minimistjs/minimist/commit/b465514b82c9ae28972d714facd951deb2ad762b) +- fix for the dot test [`6a095f1`](https://github.com/minimistjs/minimist/commit/6a095f1d364c8fab2d6753d2291a0649315d297a) + +## [v0.0.2](https://github.com/minimistjs/minimist/compare/v0.0.1...v0.0.2) - 2013-08-28 + +### Commits + +- allow dotted aliases & defaults [`321c33e`](https://github.com/minimistjs/minimist/commit/321c33e755485faaeb44eeb1c05d33b2e0a5a7c4) +- use a better version of ff [`e40f611`](https://github.com/minimistjs/minimist/commit/e40f61114cf7be6f7947f7b3eed345853a67dbbb) + +## [v0.0.1](https://github.com/minimistjs/minimist/compare/v0.0.0...v0.0.1) - 2013-06-25 + +### Commits + +- remove trailing commas [`6ff0fa0`](https://github.com/minimistjs/minimist/commit/6ff0fa055064f15dbe06d50b89d5173a6796e1db) + +## v0.0.0 - 2013-06-25 + +### Commits + +- half of the parse test ported [`3079326`](https://github.com/minimistjs/minimist/commit/307932601325087de6cf94188eb798ffc4f3088a) +- stripped down code and a passing test from optimist [`7cced88`](https://github.com/minimistjs/minimist/commit/7cced88d82e399d1a03ed23eb667f04d3f320d10) +- ported parse tests completely over [`9448754`](https://github.com/minimistjs/minimist/commit/944875452e0820df6830b1408c26a0f7d3e1db04) +- docs, package.json [`a5bf46a`](https://github.com/minimistjs/minimist/commit/a5bf46ac9bb3bd114a9c340276c62c1091e538d5) +- move more short tests into short.js [`503edb5`](https://github.com/minimistjs/minimist/commit/503edb5c41d89c0d40831ee517154fc13b0f18b9) +- default bool test was wrong, not the code [`1b9f5db`](https://github.com/minimistjs/minimist/commit/1b9f5db4741b49962846081b68518de824992097) +- passing long tests ripped out of parse.js [`7972c4a`](https://github.com/minimistjs/minimist/commit/7972c4aff1f4803079e1668006658e2a761a0428) +- badges [`84c0370`](https://github.com/minimistjs/minimist/commit/84c037063664d42878aace715fe6572ce01b6f3b) +- all the tests now ported, some failures [`64239ed`](https://github.com/minimistjs/minimist/commit/64239edfe92c711c4eb0da254fcdfad2a5fdb605) +- failing short test [`f8a5341`](https://github.com/minimistjs/minimist/commit/f8a534112dd1138d2fad722def56a848480c446f) +- fixed the numeric test [`6b034f3`](https://github.com/minimistjs/minimist/commit/6b034f37c79342c60083ed97fd222e16928aac51) diff --git a/action/node_modules/minimist/LICENSE b/action/node_modules/minimist/LICENSE new file mode 100644 index 00000000..ee27ba4b --- /dev/null +++ b/action/node_modules/minimist/LICENSE @@ -0,0 +1,18 @@ +This software is released under the MIT license: + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/action/node_modules/minimist/README.md b/action/node_modules/minimist/README.md new file mode 100644 index 00000000..74da3234 --- /dev/null +++ b/action/node_modules/minimist/README.md @@ -0,0 +1,121 @@ +# minimist [![Version Badge][npm-version-svg]][package-url] + +[![github actions][actions-image]][actions-url] +[![coverage][codecov-image]][codecov-url] +[![License][license-image]][license-url] +[![Downloads][downloads-image]][downloads-url] + +[![npm badge][npm-badge-png]][package-url] + +parse argument options + +This module is the guts of optimist's argument parser without all the +fanciful decoration. + +# example + +``` js +var argv = require('minimist')(process.argv.slice(2)); +console.log(argv); +``` + +``` +$ node example/parse.js -a beep -b boop +{ _: [], a: 'beep', b: 'boop' } +``` + +``` +$ node example/parse.js -x 3 -y 4 -n5 -abc --beep=boop foo bar baz +{ + _: ['foo', 'bar', 'baz'], + x: 3, + y: 4, + n: 5, + a: true, + b: true, + c: true, + beep: 'boop' +} +``` + +# security + +Previous versions had a prototype pollution bug that could cause privilege +escalation in some circumstances when handling untrusted user input. + +Please use version 1.2.6 or later: + +* https://security.snyk.io/vuln/SNYK-JS-MINIMIST-2429795 (version <=1.2.5) +* https://snyk.io/vuln/SNYK-JS-MINIMIST-559764 (version <=1.2.3) + +# methods + +``` js +var parseArgs = require('minimist') +``` + +## var argv = parseArgs(args, opts={}) + +Return an argument object `argv` populated with the array arguments from `args`. + +`argv._` contains all the arguments that didn't have an option associated with +them. + +Numeric-looking arguments will be returned as numbers unless `opts.string` or +`opts.boolean` is set for that argument name. + +Any arguments after `'--'` will not be parsed and will end up in `argv._`. + +options can be: + +* `opts.string` - a string or array of strings argument names to always treat as +strings +* `opts.boolean` - a boolean, string or array of strings to always treat as +booleans. if `true` will treat all double hyphenated arguments without equal signs +as boolean (e.g. affects `--foo`, not `-f` or `--foo=bar`) +* `opts.alias` - an object mapping string names to strings or arrays of string +argument names to use as aliases +* `opts.default` - an object mapping string argument names to default values +* `opts.stopEarly` - when true, populate `argv._` with everything after the +first non-option +* `opts['--']` - when true, populate `argv._` with everything before the `--` +and `argv['--']` with everything after the `--`. Here's an example: + + ``` + > require('./')('one two three -- four five --six'.split(' '), { '--': true }) + { + _: ['one', 'two', 'three'], + '--': ['four', 'five', '--six'] + } + ``` + + Note that with `opts['--']` set, parsing for arguments still stops after the + `--`. + +* `opts.unknown` - a function which is invoked with a command line parameter not +defined in the `opts` configuration object. If the function returns `false`, the +unknown option is not added to `argv`. + +# install + +With [npm](https://npmjs.org) do: + +``` +npm install minimist +``` + +# license + +MIT + +[package-url]: https://npmjs.org/package/minimist +[npm-version-svg]: https://versionbadg.es/minimistjs/minimist.svg +[npm-badge-png]: https://nodei.co/npm/minimist.png?downloads=true&stars=true +[license-image]: https://img.shields.io/npm/l/minimist.svg +[license-url]: LICENSE +[downloads-image]: https://img.shields.io/npm/dm/minimist.svg +[downloads-url]: https://npm-stat.com/charts.html?package=minimist +[codecov-image]: https://codecov.io/gh/minimistjs/minimist/branch/main/graphs/badge.svg +[codecov-url]: https://app.codecov.io/gh/minimistjs/minimist/ +[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/minimistjs/minimist +[actions-url]: https://github.com/minimistjs/minimist/actions diff --git a/action/node_modules/minimist/example/parse.js b/action/node_modules/minimist/example/parse.js new file mode 100644 index 00000000..9d90ffb2 --- /dev/null +++ b/action/node_modules/minimist/example/parse.js @@ -0,0 +1,4 @@ +'use strict'; + +var argv = require('../')(process.argv.slice(2)); +console.log(argv); diff --git a/action/node_modules/minimist/index.js b/action/node_modules/minimist/index.js new file mode 100644 index 00000000..f020f394 --- /dev/null +++ b/action/node_modules/minimist/index.js @@ -0,0 +1,263 @@ +'use strict'; + +function hasKey(obj, keys) { + var o = obj; + keys.slice(0, -1).forEach(function (key) { + o = o[key] || {}; + }); + + var key = keys[keys.length - 1]; + return key in o; +} + +function isNumber(x) { + if (typeof x === 'number') { return true; } + if ((/^0x[0-9a-f]+$/i).test(x)) { return true; } + return (/^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/).test(x); +} + +function isConstructorOrProto(obj, key) { + return (key === 'constructor' && typeof obj[key] === 'function') || key === '__proto__'; +} + +module.exports = function (args, opts) { + if (!opts) { opts = {}; } + + var flags = { + bools: {}, + strings: {}, + unknownFn: null, + }; + + if (typeof opts.unknown === 'function') { + flags.unknownFn = opts.unknown; + } + + if (typeof opts.boolean === 'boolean' && opts.boolean) { + flags.allBools = true; + } else { + [].concat(opts.boolean).filter(Boolean).forEach(function (key) { + flags.bools[key] = true; + }); + } + + var aliases = {}; + + function aliasIsBoolean(key) { + return aliases[key].some(function (x) { + return flags.bools[x]; + }); + } + + Object.keys(opts.alias || {}).forEach(function (key) { + aliases[key] = [].concat(opts.alias[key]); + aliases[key].forEach(function (x) { + aliases[x] = [key].concat(aliases[key].filter(function (y) { + return x !== y; + })); + }); + }); + + [].concat(opts.string).filter(Boolean).forEach(function (key) { + flags.strings[key] = true; + if (aliases[key]) { + [].concat(aliases[key]).forEach(function (k) { + flags.strings[k] = true; + }); + } + }); + + var defaults = opts.default || {}; + + var argv = { _: [] }; + + function argDefined(key, arg) { + return (flags.allBools && (/^--[^=]+$/).test(arg)) + || flags.strings[key] + || flags.bools[key] + || aliases[key]; + } + + function setKey(obj, keys, value) { + var o = obj; + for (var i = 0; i < keys.length - 1; i++) { + var key = keys[i]; + if (isConstructorOrProto(o, key)) { return; } + if (o[key] === undefined) { o[key] = {}; } + if ( + o[key] === Object.prototype + || o[key] === Number.prototype + || o[key] === String.prototype + ) { + o[key] = {}; + } + if (o[key] === Array.prototype) { o[key] = []; } + o = o[key]; + } + + var lastKey = keys[keys.length - 1]; + if (isConstructorOrProto(o, lastKey)) { return; } + if ( + o === Object.prototype + || o === Number.prototype + || o === String.prototype + ) { + o = {}; + } + if (o === Array.prototype) { o = []; } + if (o[lastKey] === undefined || flags.bools[lastKey] || typeof o[lastKey] === 'boolean') { + o[lastKey] = value; + } else if (Array.isArray(o[lastKey])) { + o[lastKey].push(value); + } else { + o[lastKey] = [o[lastKey], value]; + } + } + + function setArg(key, val, arg) { + if (arg && flags.unknownFn && !argDefined(key, arg)) { + if (flags.unknownFn(arg) === false) { return; } + } + + var value = !flags.strings[key] && isNumber(val) + ? Number(val) + : val; + setKey(argv, key.split('.'), value); + + (aliases[key] || []).forEach(function (x) { + setKey(argv, x.split('.'), value); + }); + } + + Object.keys(flags.bools).forEach(function (key) { + setArg(key, defaults[key] === undefined ? false : defaults[key]); + }); + + var notFlags = []; + + if (args.indexOf('--') !== -1) { + notFlags = args.slice(args.indexOf('--') + 1); + args = args.slice(0, args.indexOf('--')); + } + + for (var i = 0; i < args.length; i++) { + var arg = args[i]; + var key; + var next; + + if ((/^--.+=/).test(arg)) { + // Using [\s\S] instead of . because js doesn't support the + // 'dotall' regex modifier. See: + // http://stackoverflow.com/a/1068308/13216 + var m = arg.match(/^--([^=]+)=([\s\S]*)$/); + key = m[1]; + var value = m[2]; + if (flags.bools[key]) { + value = value !== 'false'; + } + setArg(key, value, arg); + } else if ((/^--no-.+/).test(arg)) { + key = arg.match(/^--no-(.+)/)[1]; + setArg(key, false, arg); + } else if ((/^--.+/).test(arg)) { + key = arg.match(/^--(.+)/)[1]; + next = args[i + 1]; + if ( + next !== undefined + && !(/^(-|--)[^-]/).test(next) + && !flags.bools[key] + && !flags.allBools + && (aliases[key] ? !aliasIsBoolean(key) : true) + ) { + setArg(key, next, arg); + i += 1; + } else if ((/^(true|false)$/).test(next)) { + setArg(key, next === 'true', arg); + i += 1; + } else { + setArg(key, flags.strings[key] ? '' : true, arg); + } + } else if ((/^-[^-]+/).test(arg)) { + var letters = arg.slice(1, -1).split(''); + + var broken = false; + for (var j = 0; j < letters.length; j++) { + next = arg.slice(j + 2); + + if (next === '-') { + setArg(letters[j], next, arg); + continue; + } + + if ((/[A-Za-z]/).test(letters[j]) && next[0] === '=') { + setArg(letters[j], next.slice(1), arg); + broken = true; + break; + } + + if ( + (/[A-Za-z]/).test(letters[j]) + && (/-?\d+(\.\d*)?(e-?\d+)?$/).test(next) + ) { + setArg(letters[j], next, arg); + broken = true; + break; + } + + if (letters[j + 1] && letters[j + 1].match(/\W/)) { + setArg(letters[j], arg.slice(j + 2), arg); + broken = true; + break; + } else { + setArg(letters[j], flags.strings[letters[j]] ? '' : true, arg); + } + } + + key = arg.slice(-1)[0]; + if (!broken && key !== '-') { + if ( + args[i + 1] + && !(/^(-|--)[^-]/).test(args[i + 1]) + && !flags.bools[key] + && (aliases[key] ? !aliasIsBoolean(key) : true) + ) { + setArg(key, args[i + 1], arg); + i += 1; + } else if (args[i + 1] && (/^(true|false)$/).test(args[i + 1])) { + setArg(key, args[i + 1] === 'true', arg); + i += 1; + } else { + setArg(key, flags.strings[key] ? '' : true, arg); + } + } + } else { + if (!flags.unknownFn || flags.unknownFn(arg) !== false) { + argv._.push(flags.strings._ || !isNumber(arg) ? arg : Number(arg)); + } + if (opts.stopEarly) { + argv._.push.apply(argv._, args.slice(i + 1)); + break; + } + } + } + + Object.keys(defaults).forEach(function (k) { + if (!hasKey(argv, k.split('.'))) { + setKey(argv, k.split('.'), defaults[k]); + + (aliases[k] || []).forEach(function (x) { + setKey(argv, x.split('.'), defaults[k]); + }); + } + }); + + if (opts['--']) { + argv['--'] = notFlags.slice(); + } else { + notFlags.forEach(function (k) { + argv._.push(k); + }); + } + + return argv; +}; diff --git a/action/node_modules/minimist/package.json b/action/node_modules/minimist/package.json new file mode 100644 index 00000000..c10a3344 --- /dev/null +++ b/action/node_modules/minimist/package.json @@ -0,0 +1,75 @@ +{ + "name": "minimist", + "version": "1.2.8", + "description": "parse argument options", + "main": "index.js", + "devDependencies": { + "@ljharb/eslint-config": "^21.0.1", + "aud": "^2.0.2", + "auto-changelog": "^2.4.0", + "eslint": "=8.8.0", + "in-publish": "^2.0.1", + "npmignore": "^0.3.0", + "nyc": "^10.3.2", + "safe-publish-latest": "^2.0.0", + "tape": "^5.6.3" + }, + "scripts": { + "prepack": "npmignore --auto --commentLines=auto", + "prepublishOnly": "safe-publish-latest", + "prepublish": "not-in-publish || npm run prepublishOnly", + "lint": "eslint --ext=js,mjs .", + "pretest": "npm run lint", + "tests-only": "nyc tape 'test/**/*.js'", + "test": "npm run tests-only", + "posttest": "aud --production", + "version": "auto-changelog && git add CHANGELOG.md", + "postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\"" + }, + "testling": { + "files": "test/*.js", + "browsers": [ + "ie/6..latest", + "ff/5", + "firefox/latest", + "chrome/10", + "chrome/latest", + "safari/5.1", + "safari/latest", + "opera/12" + ] + }, + "repository": { + "type": "git", + "url": "git://github.com/minimistjs/minimist.git" + }, + "homepage": "https://github.com/minimistjs/minimist", + "keywords": [ + "argv", + "getopt", + "parser", + "optimist" + ], + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + }, + "license": "MIT", + "auto-changelog": { + "output": "CHANGELOG.md", + "template": "keepachangelog", + "unreleased": false, + "commitLimit": false, + "backfillLimit": false, + "hideCredit": true + }, + "publishConfig": { + "ignore": [ + ".github/workflows" + ] + } +} diff --git a/action/node_modules/minimist/test/all_bool.js b/action/node_modules/minimist/test/all_bool.js new file mode 100644 index 00000000..befa0c99 --- /dev/null +++ b/action/node_modules/minimist/test/all_bool.js @@ -0,0 +1,34 @@ +'use strict'; + +var parse = require('../'); +var test = require('tape'); + +test('flag boolean true (default all --args to boolean)', function (t) { + var argv = parse(['moo', '--honk', 'cow'], { + boolean: true, + }); + + t.deepEqual(argv, { + honk: true, + _: ['moo', 'cow'], + }); + + t.deepEqual(typeof argv.honk, 'boolean'); + t.end(); +}); + +test('flag boolean true only affects double hyphen arguments without equals signs', function (t) { + var argv = parse(['moo', '--honk', 'cow', '-p', '55', '--tacos=good'], { + boolean: true, + }); + + t.deepEqual(argv, { + honk: true, + tacos: 'good', + p: 55, + _: ['moo', 'cow'], + }); + + t.deepEqual(typeof argv.honk, 'boolean'); + t.end(); +}); diff --git a/action/node_modules/minimist/test/bool.js b/action/node_modules/minimist/test/bool.js new file mode 100644 index 00000000..e58d47e4 --- /dev/null +++ b/action/node_modules/minimist/test/bool.js @@ -0,0 +1,177 @@ +'use strict'; + +var parse = require('../'); +var test = require('tape'); + +test('flag boolean default false', function (t) { + var argv = parse(['moo'], { + boolean: ['t', 'verbose'], + default: { verbose: false, t: false }, + }); + + t.deepEqual(argv, { + verbose: false, + t: false, + _: ['moo'], + }); + + t.deepEqual(typeof argv.verbose, 'boolean'); + t.deepEqual(typeof argv.t, 'boolean'); + t.end(); + +}); + +test('boolean groups', function (t) { + var argv = parse(['-x', '-z', 'one', 'two', 'three'], { + boolean: ['x', 'y', 'z'], + }); + + t.deepEqual(argv, { + x: true, + y: false, + z: true, + _: ['one', 'two', 'three'], + }); + + t.deepEqual(typeof argv.x, 'boolean'); + t.deepEqual(typeof argv.y, 'boolean'); + t.deepEqual(typeof argv.z, 'boolean'); + t.end(); +}); +test('boolean and alias with chainable api', function (t) { + var aliased = ['-h', 'derp']; + var regular = ['--herp', 'derp']; + var aliasedArgv = parse(aliased, { + boolean: 'herp', + alias: { h: 'herp' }, + }); + var propertyArgv = parse(regular, { + boolean: 'herp', + alias: { h: 'herp' }, + }); + var expected = { + herp: true, + h: true, + _: ['derp'], + }; + + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.end(); +}); + +test('boolean and alias with options hash', function (t) { + var aliased = ['-h', 'derp']; + var regular = ['--herp', 'derp']; + var opts = { + alias: { h: 'herp' }, + boolean: 'herp', + }; + var aliasedArgv = parse(aliased, opts); + var propertyArgv = parse(regular, opts); + var expected = { + herp: true, + h: true, + _: ['derp'], + }; + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.end(); +}); + +test('boolean and alias array with options hash', function (t) { + var aliased = ['-h', 'derp']; + var regular = ['--herp', 'derp']; + var alt = ['--harp', 'derp']; + var opts = { + alias: { h: ['herp', 'harp'] }, + boolean: 'h', + }; + var aliasedArgv = parse(aliased, opts); + var propertyArgv = parse(regular, opts); + var altPropertyArgv = parse(alt, opts); + var expected = { + harp: true, + herp: true, + h: true, + _: ['derp'], + }; + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.same(altPropertyArgv, expected); + t.end(); +}); + +test('boolean and alias using explicit true', function (t) { + var aliased = ['-h', 'true']; + var regular = ['--herp', 'true']; + var opts = { + alias: { h: 'herp' }, + boolean: 'h', + }; + var aliasedArgv = parse(aliased, opts); + var propertyArgv = parse(regular, opts); + var expected = { + herp: true, + h: true, + _: [], + }; + + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.end(); +}); + +// regression, see https://github.com/substack/node-optimist/issues/71 +test('boolean and --x=true', function (t) { + var parsed = parse(['--boool', '--other=true'], { + boolean: 'boool', + }); + + t.same(parsed.boool, true); + t.same(parsed.other, 'true'); + + parsed = parse(['--boool', '--other=false'], { + boolean: 'boool', + }); + + t.same(parsed.boool, true); + t.same(parsed.other, 'false'); + t.end(); +}); + +test('boolean --boool=true', function (t) { + var parsed = parse(['--boool=true'], { + default: { + boool: false, + }, + boolean: ['boool'], + }); + + t.same(parsed.boool, true); + t.end(); +}); + +test('boolean --boool=false', function (t) { + var parsed = parse(['--boool=false'], { + default: { + boool: true, + }, + boolean: ['boool'], + }); + + t.same(parsed.boool, false); + t.end(); +}); + +test('boolean using something similar to true', function (t) { + var opts = { boolean: 'h' }; + var result = parse(['-h', 'true.txt'], opts); + var expected = { + h: true, + _: ['true.txt'], + }; + + t.same(result, expected); + t.end(); +}); diff --git a/action/node_modules/minimist/test/dash.js b/action/node_modules/minimist/test/dash.js new file mode 100644 index 00000000..70788177 --- /dev/null +++ b/action/node_modules/minimist/test/dash.js @@ -0,0 +1,43 @@ +'use strict'; + +var parse = require('../'); +var test = require('tape'); + +test('-', function (t) { + t.plan(6); + t.deepEqual(parse(['-n', '-']), { n: '-', _: [] }); + t.deepEqual(parse(['--nnn', '-']), { nnn: '-', _: [] }); + t.deepEqual(parse(['-']), { _: ['-'] }); + t.deepEqual(parse(['-f-']), { f: '-', _: [] }); + t.deepEqual( + parse(['-b', '-'], { boolean: 'b' }), + { b: true, _: ['-'] } + ); + t.deepEqual( + parse(['-s', '-'], { string: 's' }), + { s: '-', _: [] } + ); +}); + +test('-a -- b', function (t) { + t.plan(2); + t.deepEqual(parse(['-a', '--', 'b']), { a: true, _: ['b'] }); + t.deepEqual(parse(['--a', '--', 'b']), { a: true, _: ['b'] }); +}); + +test('move arguments after the -- into their own `--` array', function (t) { + t.plan(1); + t.deepEqual( + parse(['--name', 'John', 'before', '--', 'after'], { '--': true }), + { name: 'John', _: ['before'], '--': ['after'] } + ); +}); + +test('--- option value', function (t) { + // A multi-dash value is largely an edge case, but check the behaviour is as expected, + // and in particular the same for short option and long option (as made consistent in Jan 2023). + t.plan(2); + t.deepEqual(parse(['-n', '---']), { n: '---', _: [] }); + t.deepEqual(parse(['--nnn', '---']), { nnn: '---', _: [] }); +}); + diff --git a/action/node_modules/minimist/test/default_bool.js b/action/node_modules/minimist/test/default_bool.js new file mode 100644 index 00000000..4e9f6250 --- /dev/null +++ b/action/node_modules/minimist/test/default_bool.js @@ -0,0 +1,37 @@ +'use strict'; + +var test = require('tape'); +var parse = require('../'); + +test('boolean default true', function (t) { + var argv = parse([], { + boolean: 'sometrue', + default: { sometrue: true }, + }); + t.equal(argv.sometrue, true); + t.end(); +}); + +test('boolean default false', function (t) { + var argv = parse([], { + boolean: 'somefalse', + default: { somefalse: false }, + }); + t.equal(argv.somefalse, false); + t.end(); +}); + +test('boolean default to null', function (t) { + var argv = parse([], { + boolean: 'maybe', + default: { maybe: null }, + }); + t.equal(argv.maybe, null); + + var argvLong = parse(['--maybe'], { + boolean: 'maybe', + default: { maybe: null }, + }); + t.equal(argvLong.maybe, true); + t.end(); +}); diff --git a/action/node_modules/minimist/test/dotted.js b/action/node_modules/minimist/test/dotted.js new file mode 100644 index 00000000..126ff033 --- /dev/null +++ b/action/node_modules/minimist/test/dotted.js @@ -0,0 +1,24 @@ +'use strict'; + +var parse = require('../'); +var test = require('tape'); + +test('dotted alias', function (t) { + var argv = parse(['--a.b', '22'], { default: { 'a.b': 11 }, alias: { 'a.b': 'aa.bb' } }); + t.equal(argv.a.b, 22); + t.equal(argv.aa.bb, 22); + t.end(); +}); + +test('dotted default', function (t) { + var argv = parse('', { default: { 'a.b': 11 }, alias: { 'a.b': 'aa.bb' } }); + t.equal(argv.a.b, 11); + t.equal(argv.aa.bb, 11); + t.end(); +}); + +test('dotted default with no alias', function (t) { + var argv = parse('', { default: { 'a.b': 11 } }); + t.equal(argv.a.b, 11); + t.end(); +}); diff --git a/action/node_modules/minimist/test/kv_short.js b/action/node_modules/minimist/test/kv_short.js new file mode 100644 index 00000000..6d1b53a7 --- /dev/null +++ b/action/node_modules/minimist/test/kv_short.js @@ -0,0 +1,32 @@ +'use strict'; + +var parse = require('../'); +var test = require('tape'); + +test('short -k=v', function (t) { + t.plan(1); + + var argv = parse(['-b=123']); + t.deepEqual(argv, { b: 123, _: [] }); +}); + +test('multi short -k=v', function (t) { + t.plan(1); + + var argv = parse(['-a=whatever', '-b=robots']); + t.deepEqual(argv, { a: 'whatever', b: 'robots', _: [] }); +}); + +test('short with embedded equals -k=a=b', function (t) { + t.plan(1); + + var argv = parse(['-k=a=b']); + t.deepEqual(argv, { k: 'a=b', _: [] }); +}); + +test('short with later equals like -ab=c', function (t) { + t.plan(1); + + var argv = parse(['-ab=c']); + t.deepEqual(argv, { a: true, b: 'c', _: [] }); +}); diff --git a/action/node_modules/minimist/test/long.js b/action/node_modules/minimist/test/long.js new file mode 100644 index 00000000..9fef51f1 --- /dev/null +++ b/action/node_modules/minimist/test/long.js @@ -0,0 +1,33 @@ +'use strict'; + +var test = require('tape'); +var parse = require('../'); + +test('long opts', function (t) { + t.deepEqual( + parse(['--bool']), + { bool: true, _: [] }, + 'long boolean' + ); + t.deepEqual( + parse(['--pow', 'xixxle']), + { pow: 'xixxle', _: [] }, + 'long capture sp' + ); + t.deepEqual( + parse(['--pow=xixxle']), + { pow: 'xixxle', _: [] }, + 'long capture eq' + ); + t.deepEqual( + parse(['--host', 'localhost', '--port', '555']), + { host: 'localhost', port: 555, _: [] }, + 'long captures sp' + ); + t.deepEqual( + parse(['--host=localhost', '--port=555']), + { host: 'localhost', port: 555, _: [] }, + 'long captures eq' + ); + t.end(); +}); diff --git a/action/node_modules/minimist/test/num.js b/action/node_modules/minimist/test/num.js new file mode 100644 index 00000000..074393ec --- /dev/null +++ b/action/node_modules/minimist/test/num.js @@ -0,0 +1,38 @@ +'use strict'; + +var parse = require('../'); +var test = require('tape'); + +test('nums', function (t) { + var argv = parse([ + '-x', '1234', + '-y', '5.67', + '-z', '1e7', + '-w', '10f', + '--hex', '0xdeadbeef', + '789', + ]); + t.deepEqual(argv, { + x: 1234, + y: 5.67, + z: 1e7, + w: '10f', + hex: 0xdeadbeef, + _: [789], + }); + t.deepEqual(typeof argv.x, 'number'); + t.deepEqual(typeof argv.y, 'number'); + t.deepEqual(typeof argv.z, 'number'); + t.deepEqual(typeof argv.w, 'string'); + t.deepEqual(typeof argv.hex, 'number'); + t.deepEqual(typeof argv._[0], 'number'); + t.end(); +}); + +test('already a number', function (t) { + var argv = parse(['-x', 1234, 789]); + t.deepEqual(argv, { x: 1234, _: [789] }); + t.deepEqual(typeof argv.x, 'number'); + t.deepEqual(typeof argv._[0], 'number'); + t.end(); +}); diff --git a/action/node_modules/minimist/test/parse.js b/action/node_modules/minimist/test/parse.js new file mode 100644 index 00000000..65d9d909 --- /dev/null +++ b/action/node_modules/minimist/test/parse.js @@ -0,0 +1,209 @@ +'use strict'; + +var parse = require('../'); +var test = require('tape'); + +test('parse args', function (t) { + t.deepEqual( + parse(['--no-moo']), + { moo: false, _: [] }, + 'no' + ); + t.deepEqual( + parse(['-v', 'a', '-v', 'b', '-v', 'c']), + { v: ['a', 'b', 'c'], _: [] }, + 'multi' + ); + t.end(); +}); + +test('comprehensive', function (t) { + t.deepEqual( + parse([ + '--name=meowmers', 'bare', '-cats', 'woo', + '-h', 'awesome', '--multi=quux', + '--key', 'value', + '-b', '--bool', '--no-meep', '--multi=baz', + '--', '--not-a-flag', 'eek', + ]), + { + c: true, + a: true, + t: true, + s: 'woo', + h: 'awesome', + b: true, + bool: true, + key: 'value', + multi: ['quux', 'baz'], + meep: false, + name: 'meowmers', + _: ['bare', '--not-a-flag', 'eek'], + } + ); + t.end(); +}); + +test('flag boolean', function (t) { + var argv = parse(['-t', 'moo'], { boolean: 't' }); + t.deepEqual(argv, { t: true, _: ['moo'] }); + t.deepEqual(typeof argv.t, 'boolean'); + t.end(); +}); + +test('flag boolean value', function (t) { + var argv = parse(['--verbose', 'false', 'moo', '-t', 'true'], { + boolean: ['t', 'verbose'], + default: { verbose: true }, + }); + + t.deepEqual(argv, { + verbose: false, + t: true, + _: ['moo'], + }); + + t.deepEqual(typeof argv.verbose, 'boolean'); + t.deepEqual(typeof argv.t, 'boolean'); + t.end(); +}); + +test('newlines in params', function (t) { + var args = parse(['-s', 'X\nX']); + t.deepEqual(args, { _: [], s: 'X\nX' }); + + // reproduce in bash: + // VALUE="new + // line" + // node program.js --s="$VALUE" + args = parse(['--s=X\nX']); + t.deepEqual(args, { _: [], s: 'X\nX' }); + t.end(); +}); + +test('strings', function (t) { + var s = parse(['-s', '0001234'], { string: 's' }).s; + t.equal(s, '0001234'); + t.equal(typeof s, 'string'); + + var x = parse(['-x', '56'], { string: 'x' }).x; + t.equal(x, '56'); + t.equal(typeof x, 'string'); + t.end(); +}); + +test('stringArgs', function (t) { + var s = parse([' ', ' '], { string: '_' })._; + t.same(s.length, 2); + t.same(typeof s[0], 'string'); + t.same(s[0], ' '); + t.same(typeof s[1], 'string'); + t.same(s[1], ' '); + t.end(); +}); + +test('empty strings', function (t) { + var s = parse(['-s'], { string: 's' }).s; + t.equal(s, ''); + t.equal(typeof s, 'string'); + + var str = parse(['--str'], { string: 'str' }).str; + t.equal(str, ''); + t.equal(typeof str, 'string'); + + var letters = parse(['-art'], { + string: ['a', 't'], + }); + + t.equal(letters.a, ''); + t.equal(letters.r, true); + t.equal(letters.t, ''); + + t.end(); +}); + +test('string and alias', function (t) { + var x = parse(['--str', '000123'], { + string: 's', + alias: { s: 'str' }, + }); + + t.equal(x.str, '000123'); + t.equal(typeof x.str, 'string'); + t.equal(x.s, '000123'); + t.equal(typeof x.s, 'string'); + + var y = parse(['-s', '000123'], { + string: 'str', + alias: { str: 's' }, + }); + + t.equal(y.str, '000123'); + t.equal(typeof y.str, 'string'); + t.equal(y.s, '000123'); + t.equal(typeof y.s, 'string'); + + var z = parse(['-s123'], { + alias: { str: ['s', 'S'] }, + string: ['str'], + }); + + t.deepEqual( + z, + { _: [], s: '123', S: '123', str: '123' }, + 'opt.string works with multiple aliases' + ); + t.end(); +}); + +test('slashBreak', function (t) { + t.same( + parse(['-I/foo/bar/baz']), + { I: '/foo/bar/baz', _: [] } + ); + t.same( + parse(['-xyz/foo/bar/baz']), + { x: true, y: true, z: '/foo/bar/baz', _: [] } + ); + t.end(); +}); + +test('alias', function (t) { + var argv = parse(['-f', '11', '--zoom', '55'], { + alias: { z: 'zoom' }, + }); + t.equal(argv.zoom, 55); + t.equal(argv.z, argv.zoom); + t.equal(argv.f, 11); + t.end(); +}); + +test('multiAlias', function (t) { + var argv = parse(['-f', '11', '--zoom', '55'], { + alias: { z: ['zm', 'zoom'] }, + }); + t.equal(argv.zoom, 55); + t.equal(argv.z, argv.zoom); + t.equal(argv.z, argv.zm); + t.equal(argv.f, 11); + t.end(); +}); + +test('nested dotted objects', function (t) { + var argv = parse([ + '--foo.bar', '3', '--foo.baz', '4', + '--foo.quux.quibble', '5', '--foo.quux.o_O', + '--beep.boop', + ]); + + t.same(argv.foo, { + bar: 3, + baz: 4, + quux: { + quibble: 5, + o_O: true, + }, + }); + t.same(argv.beep, { boop: true }); + t.end(); +}); diff --git a/action/node_modules/minimist/test/parse_modified.js b/action/node_modules/minimist/test/parse_modified.js new file mode 100644 index 00000000..32965d13 --- /dev/null +++ b/action/node_modules/minimist/test/parse_modified.js @@ -0,0 +1,11 @@ +'use strict'; + +var parse = require('../'); +var test = require('tape'); + +test('parse with modifier functions', function (t) { + t.plan(1); + + var argv = parse(['-b', '123'], { boolean: 'b' }); + t.deepEqual(argv, { b: true, _: [123] }); +}); diff --git a/action/node_modules/minimist/test/proto.js b/action/node_modules/minimist/test/proto.js new file mode 100644 index 00000000..6e629dd3 --- /dev/null +++ b/action/node_modules/minimist/test/proto.js @@ -0,0 +1,64 @@ +'use strict'; + +/* eslint no-proto: 0 */ + +var parse = require('../'); +var test = require('tape'); + +test('proto pollution', function (t) { + var argv = parse(['--__proto__.x', '123']); + t.equal({}.x, undefined); + t.equal(argv.__proto__.x, undefined); + t.equal(argv.x, undefined); + t.end(); +}); + +test('proto pollution (array)', function (t) { + var argv = parse(['--x', '4', '--x', '5', '--x.__proto__.z', '789']); + t.equal({}.z, undefined); + t.deepEqual(argv.x, [4, 5]); + t.equal(argv.x.z, undefined); + t.equal(argv.x.__proto__.z, undefined); + t.end(); +}); + +test('proto pollution (number)', function (t) { + var argv = parse(['--x', '5', '--x.__proto__.z', '100']); + t.equal({}.z, undefined); + t.equal((4).z, undefined); + t.equal(argv.x, 5); + t.equal(argv.x.z, undefined); + t.end(); +}); + +test('proto pollution (string)', function (t) { + var argv = parse(['--x', 'abc', '--x.__proto__.z', 'def']); + t.equal({}.z, undefined); + t.equal('...'.z, undefined); + t.equal(argv.x, 'abc'); + t.equal(argv.x.z, undefined); + t.end(); +}); + +test('proto pollution (constructor)', function (t) { + var argv = parse(['--constructor.prototype.y', '123']); + t.equal({}.y, undefined); + t.equal(argv.y, undefined); + t.end(); +}); + +test('proto pollution (constructor function)', function (t) { + var argv = parse(['--_.concat.constructor.prototype.y', '123']); + function fnToBeTested() {} + t.equal(fnToBeTested.y, undefined); + t.equal(argv.y, undefined); + t.end(); +}); + +// powered by snyk - https://github.com/backstage/backstage/issues/10343 +test('proto pollution (constructor function) snyk', function (t) { + var argv = parse('--_.constructor.constructor.prototype.foo bar'.split(' ')); + t.equal(function () {}.foo, undefined); + t.equal(argv.y, undefined); + t.end(); +}); diff --git a/action/node_modules/minimist/test/short.js b/action/node_modules/minimist/test/short.js new file mode 100644 index 00000000..4a7b8438 --- /dev/null +++ b/action/node_modules/minimist/test/short.js @@ -0,0 +1,69 @@ +'use strict'; + +var parse = require('../'); +var test = require('tape'); + +test('numeric short args', function (t) { + t.plan(2); + t.deepEqual(parse(['-n123']), { n: 123, _: [] }); + t.deepEqual( + parse(['-123', '456']), + { 1: true, 2: true, 3: 456, _: [] } + ); +}); + +test('short', function (t) { + t.deepEqual( + parse(['-b']), + { b: true, _: [] }, + 'short boolean' + ); + t.deepEqual( + parse(['foo', 'bar', 'baz']), + { _: ['foo', 'bar', 'baz'] }, + 'bare' + ); + t.deepEqual( + parse(['-cats']), + { c: true, a: true, t: true, s: true, _: [] }, + 'group' + ); + t.deepEqual( + parse(['-cats', 'meow']), + { c: true, a: true, t: true, s: 'meow', _: [] }, + 'short group next' + ); + t.deepEqual( + parse(['-h', 'localhost']), + { h: 'localhost', _: [] }, + 'short capture' + ); + t.deepEqual( + parse(['-h', 'localhost', '-p', '555']), + { h: 'localhost', p: 555, _: [] }, + 'short captures' + ); + t.end(); +}); + +test('mixed short bool and capture', function (t) { + t.same( + parse(['-h', 'localhost', '-fp', '555', 'script.js']), + { + f: true, p: 555, h: 'localhost', + _: ['script.js'], + } + ); + t.end(); +}); + +test('short and long', function (t) { + t.deepEqual( + parse(['-h', 'localhost', '-fp', '555', 'script.js']), + { + f: true, p: 555, h: 'localhost', + _: ['script.js'], + } + ); + t.end(); +}); diff --git a/action/node_modules/minimist/test/stop_early.js b/action/node_modules/minimist/test/stop_early.js new file mode 100644 index 00000000..52a6a919 --- /dev/null +++ b/action/node_modules/minimist/test/stop_early.js @@ -0,0 +1,17 @@ +'use strict'; + +var parse = require('../'); +var test = require('tape'); + +test('stops parsing on the first non-option when stopEarly is set', function (t) { + var argv = parse(['--aaa', 'bbb', 'ccc', '--ddd'], { + stopEarly: true, + }); + + t.deepEqual(argv, { + aaa: 'bbb', + _: ['ccc', '--ddd'], + }); + + t.end(); +}); diff --git a/action/node_modules/minimist/test/unknown.js b/action/node_modules/minimist/test/unknown.js new file mode 100644 index 00000000..4f2e0ca4 --- /dev/null +++ b/action/node_modules/minimist/test/unknown.js @@ -0,0 +1,104 @@ +'use strict'; + +var parse = require('../'); +var test = require('tape'); + +test('boolean and alias is not unknown', function (t) { + var unknown = []; + function unknownFn(arg) { + unknown.push(arg); + return false; + } + var aliased = ['-h', 'true', '--derp', 'true']; + var regular = ['--herp', 'true', '-d', 'true']; + var opts = { + alias: { h: 'herp' }, + boolean: 'h', + unknown: unknownFn, + }; + parse(aliased, opts); + parse(regular, opts); + + t.same(unknown, ['--derp', '-d']); + t.end(); +}); + +test('flag boolean true any double hyphen argument is not unknown', function (t) { + var unknown = []; + function unknownFn(arg) { + unknown.push(arg); + return false; + } + var argv = parse(['--honk', '--tacos=good', 'cow', '-p', '55'], { + boolean: true, + unknown: unknownFn, + }); + t.same(unknown, ['--tacos=good', 'cow', '-p']); + t.same(argv, { + honk: true, + _: [], + }); + t.end(); +}); + +test('string and alias is not unknown', function (t) { + var unknown = []; + function unknownFn(arg) { + unknown.push(arg); + return false; + } + var aliased = ['-h', 'hello', '--derp', 'goodbye']; + var regular = ['--herp', 'hello', '-d', 'moon']; + var opts = { + alias: { h: 'herp' }, + string: 'h', + unknown: unknownFn, + }; + parse(aliased, opts); + parse(regular, opts); + + t.same(unknown, ['--derp', '-d']); + t.end(); +}); + +test('default and alias is not unknown', function (t) { + var unknown = []; + function unknownFn(arg) { + unknown.push(arg); + return false; + } + var aliased = ['-h', 'hello']; + var regular = ['--herp', 'hello']; + var opts = { + default: { h: 'bar' }, + alias: { h: 'herp' }, + unknown: unknownFn, + }; + parse(aliased, opts); + parse(regular, opts); + + t.same(unknown, []); + t.end(); + unknownFn(); // exercise fn for 100% coverage +}); + +test('value following -- is not unknown', function (t) { + var unknown = []; + function unknownFn(arg) { + unknown.push(arg); + return false; + } + var aliased = ['--bad', '--', 'good', 'arg']; + var opts = { + '--': true, + unknown: unknownFn, + }; + var argv = parse(aliased, opts); + + t.same(unknown, ['--bad']); + t.same(argv, { + '--': ['good', 'arg'], + _: [], + }); + t.end(); +}); diff --git a/action/node_modules/minimist/test/whitespace.js b/action/node_modules/minimist/test/whitespace.js new file mode 100644 index 00000000..4fdaf1d3 --- /dev/null +++ b/action/node_modules/minimist/test/whitespace.js @@ -0,0 +1,10 @@ +'use strict'; + +var parse = require('../'); +var test = require('tape'); + +test('whitespace should be whitespace', function (t) { + t.plan(1); + var x = parse(['-x', '\t']).x; + t.equal(x, '\t'); +}); diff --git a/action/node_modules/mkdirp/LICENSE b/action/node_modules/mkdirp/LICENSE new file mode 100644 index 00000000..432d1aeb --- /dev/null +++ b/action/node_modules/mkdirp/LICENSE @@ -0,0 +1,21 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/action/node_modules/mkdirp/bin/cmd.js b/action/node_modules/mkdirp/bin/cmd.js new file mode 100755 index 00000000..d95de15a --- /dev/null +++ b/action/node_modules/mkdirp/bin/cmd.js @@ -0,0 +1,33 @@ +#!/usr/bin/env node + +var mkdirp = require('../'); +var minimist = require('minimist'); +var fs = require('fs'); + +var argv = minimist(process.argv.slice(2), { + alias: { m: 'mode', h: 'help' }, + string: [ 'mode' ] +}); +if (argv.help) { + fs.createReadStream(__dirname + '/usage.txt').pipe(process.stdout); + return; +} + +var paths = argv._.slice(); +var mode = argv.mode ? parseInt(argv.mode, 8) : undefined; + +(function next () { + if (paths.length === 0) return; + var p = paths.shift(); + + if (mode === undefined) mkdirp(p, cb) + else mkdirp(p, mode, cb) + + function cb (err) { + if (err) { + console.error(err.message); + process.exit(1); + } + else next(); + } +})(); diff --git a/action/node_modules/mkdirp/bin/usage.txt b/action/node_modules/mkdirp/bin/usage.txt new file mode 100644 index 00000000..f952aa2c --- /dev/null +++ b/action/node_modules/mkdirp/bin/usage.txt @@ -0,0 +1,12 @@ +usage: mkdirp [DIR1,DIR2..] {OPTIONS} + + Create each supplied directory including any necessary parent directories that + don't yet exist. + + If the directory already exists, do nothing. + +OPTIONS are: + + -m, --mode If a directory needs to be created, set the mode as an octal + permission string. + diff --git a/action/node_modules/mkdirp/index.js b/action/node_modules/mkdirp/index.js new file mode 100644 index 00000000..0890ac3b --- /dev/null +++ b/action/node_modules/mkdirp/index.js @@ -0,0 +1,102 @@ +var path = require('path'); +var fs = require('fs'); +var _0777 = parseInt('0777', 8); + +module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; + +function mkdirP (p, opts, f, made) { + if (typeof opts === 'function') { + f = opts; + opts = {}; + } + else if (!opts || typeof opts !== 'object') { + opts = { mode: opts }; + } + + var mode = opts.mode; + var xfs = opts.fs || fs; + + if (mode === undefined) { + mode = _0777 + } + if (!made) made = null; + + var cb = f || /* istanbul ignore next */ function () {}; + p = path.resolve(p); + + xfs.mkdir(p, mode, function (er) { + if (!er) { + made = made || p; + return cb(null, made); + } + switch (er.code) { + case 'ENOENT': + /* istanbul ignore if */ + if (path.dirname(p) === p) return cb(er); + mkdirP(path.dirname(p), opts, function (er, made) { + /* istanbul ignore if */ + if (er) cb(er, made); + else mkdirP(p, opts, cb, made); + }); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + xfs.stat(p, function (er2, stat) { + // if the stat fails, then that's super weird. + // let the original error be the failure reason. + if (er2 || !stat.isDirectory()) cb(er, made) + else cb(null, made); + }); + break; + } + }); +} + +mkdirP.sync = function sync (p, opts, made) { + if (!opts || typeof opts !== 'object') { + opts = { mode: opts }; + } + + var mode = opts.mode; + var xfs = opts.fs || fs; + + if (mode === undefined) { + mode = _0777 + } + if (!made) made = null; + + p = path.resolve(p); + + try { + xfs.mkdirSync(p, mode); + made = made || p; + } + catch (err0) { + switch (err0.code) { + case 'ENOENT' : + made = sync(path.dirname(p), opts, made); + sync(p, opts, made); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + var stat; + try { + stat = xfs.statSync(p); + } + catch (err1) /* istanbul ignore next */ { + throw err0; + } + /* istanbul ignore if */ + if (!stat.isDirectory()) throw err0; + break; + } + } + + return made; +}; diff --git a/action/node_modules/mkdirp/package.json b/action/node_modules/mkdirp/package.json new file mode 100644 index 00000000..951e58da --- /dev/null +++ b/action/node_modules/mkdirp/package.json @@ -0,0 +1,33 @@ +{ + "name": "mkdirp", + "description": "Recursively mkdir, like `mkdir -p`", + "version": "0.5.6", + "publishConfig": { + "tag": "legacy" + }, + "author": "James Halliday (http://substack.net)", + "main": "index.js", + "keywords": [ + "mkdir", + "directory" + ], + "repository": { + "type": "git", + "url": "https://github.com/substack/node-mkdirp.git" + }, + "scripts": { + "test": "tap test/*.js" + }, + "dependencies": { + "minimist": "^1.2.6" + }, + "devDependencies": { + "tap": "^16.0.1" + }, + "bin": "bin/cmd.js", + "license": "MIT", + "files": [ + "bin", + "index.js" + ] +} diff --git a/action/node_modules/mkdirp/readme.markdown b/action/node_modules/mkdirp/readme.markdown new file mode 100644 index 00000000..fc314bfb --- /dev/null +++ b/action/node_modules/mkdirp/readme.markdown @@ -0,0 +1,100 @@ +# mkdirp + +Like `mkdir -p`, but in node.js! + +[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp) + +# example + +## pow.js + +```js +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') +}); +``` + +Output + +``` +pow! +``` + +And now /tmp/foo/bar/baz exists, huzzah! + +# methods + +```js +var mkdirp = require('mkdirp'); +``` + +## mkdirp(dir, opts, cb) + +Create a new directory and any necessary subdirectories at `dir` with octal +permission string `opts.mode`. If `opts` is a non-object, it will be treated as +the `opts.mode`. + +If `opts.mode` isn't specified, it defaults to `0777`. + +`cb(err, made)` fires with the error or the first directory `made` +that had to be created, if any. + +You can optionally pass in an alternate `fs` implementation by passing in +`opts.fs`. Your implementation should have `opts.fs.mkdir(path, mode, cb)` and +`opts.fs.stat(path, cb)`. + +## mkdirp.sync(dir, opts) + +Synchronously create a new directory and any necessary subdirectories at `dir` +with octal permission string `opts.mode`. If `opts` is a non-object, it will be +treated as the `opts.mode`. + +If `opts.mode` isn't specified, it defaults to `0777`. + +Returns the first directory that had to be created, if any. + +You can optionally pass in an alternate `fs` implementation by passing in +`opts.fs`. Your implementation should have `opts.fs.mkdirSync(path, mode)` and +`opts.fs.statSync(path)`. + +# usage + +This package also ships with a `mkdirp` command. + +``` +usage: mkdirp [DIR1,DIR2..] {OPTIONS} + + Create each supplied directory including any necessary parent directories that + don't yet exist. + + If the directory already exists, do nothing. + +OPTIONS are: + + -m, --mode If a directory needs to be created, set the mode as an octal + permission string. + +``` + +# install + +With [npm](http://npmjs.org) do: + +``` +npm install mkdirp +``` + +to get the library, or + +``` +npm install -g mkdirp +``` + +to get the command. + +# license + +MIT diff --git a/action/node_modules/parse-json/index.js b/action/node_modules/parse-json/index.js new file mode 100644 index 00000000..16f42b4a --- /dev/null +++ b/action/node_modules/parse-json/index.js @@ -0,0 +1,33 @@ +'use strict'; +const errorEx = require('error-ex'); +const fallback = require('json-parse-better-errors'); + +const JSONError = errorEx('JSONError', { + fileName: errorEx.append('in %s') +}); + +module.exports = (input, reviver, filename) => { + if (typeof reviver === 'string') { + filename = reviver; + reviver = null; + } + + try { + try { + return JSON.parse(input, reviver); + } catch (err) { + fallback(input, reviver); + + throw err; + } + } catch (err) { + err.message = err.message.replace(/\n/g, ''); + + const jsonErr = new JSONError(err); + if (filename) { + jsonErr.fileName = filename; + } + + throw jsonErr; + } +}; diff --git a/action/node_modules/parse-json/license b/action/node_modules/parse-json/license new file mode 100644 index 00000000..e7af2f77 --- /dev/null +++ b/action/node_modules/parse-json/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/action/node_modules/parse-json/package.json b/action/node_modules/parse-json/package.json new file mode 100644 index 00000000..7aca6ede --- /dev/null +++ b/action/node_modules/parse-json/package.json @@ -0,0 +1,43 @@ +{ + "name": "parse-json", + "version": "4.0.0", + "description": "Parse JSON with more helpful errors", + "license": "MIT", + "repository": "sindresorhus/parse-json", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=4" + }, + "scripts": { + "test": "xo && nyc ava" + }, + "files": [ + "index.js", + "vendor" + ], + "keywords": [ + "parse", + "json", + "graceful", + "error", + "message", + "humanize", + "friendly", + "helpful", + "string", + "str" + ], + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "devDependencies": { + "ava": "*", + "nyc": "^11.2.1", + "xo": "*" + } +} diff --git a/action/node_modules/parse-json/readme.md b/action/node_modules/parse-json/readme.md new file mode 100644 index 00000000..2976e347 --- /dev/null +++ b/action/node_modules/parse-json/readme.md @@ -0,0 +1,83 @@ +# parse-json [![Build Status](https://travis-ci.org/sindresorhus/parse-json.svg?branch=master)](https://travis-ci.org/sindresorhus/parse-json) + +> Parse JSON with more helpful errors + + +## Install + +``` +$ npm install parse-json +``` + + +## Usage + +```js +const parseJson = require('parse-json'); +const json = '{\n\t"foo": true,\n}'; + + +JSON.parse(json); +/* +undefined:3 +} +^ +SyntaxError: Unexpected token } +*/ + + +parseJson(json); +/* +JSONError: Trailing comma in object at 3:1 +} +^ +*/ + + +parseJson(json, 'foo.json'); +/* +JSONError: Trailing comma in object in foo.json:3:1 +} +^ +*/ + + +// You can also add the filename at a later point +try { + parseJson(json); +} catch (err) { + err.fileName = 'foo.json'; + throw err; +} +/* +JSONError: Trailing comma in object in foo.json:3:1 +} +^ +*/ +``` + +## API + +### parseJson(input, [reviver], [filename]) + +#### input + +Type: `string` + +#### reviver + +Type: `Function` + +Prescribes how the value originally produced by parsing is transformed, before being returned. See [`JSON.parse` docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Using_the_reviver_parameter +) for more. + +#### filename + +Type: `string` + +Filename displayed in the error message. + + +## License + +MIT © [Sindre Sorhus](https://sindresorhus.com) diff --git a/action/node_modules/strip-bom/index.d.ts b/action/node_modules/strip-bom/index.d.ts new file mode 100644 index 00000000..8f2a5248 --- /dev/null +++ b/action/node_modules/strip-bom/index.d.ts @@ -0,0 +1,14 @@ +/** +Strip UTF-8 [byte order mark](https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8) (BOM) from a string. + +@example +``` +import stripBom = require('strip-bom'); + +stripBom('\uFEFFunicorn'); +//=> 'unicorn' +``` +*/ +declare function stripBom(string: string): string; + +export = stripBom; diff --git a/action/node_modules/strip-bom/index.js b/action/node_modules/strip-bom/index.js new file mode 100644 index 00000000..82f91754 --- /dev/null +++ b/action/node_modules/strip-bom/index.js @@ -0,0 +1,15 @@ +'use strict'; + +module.exports = string => { + if (typeof string !== 'string') { + throw new TypeError(`Expected a string, got ${typeof string}`); + } + + // Catches EFBBBF (UTF-8 BOM) because the buffer-to-string + // conversion translates it to FEFF (UTF-16 BOM) + if (string.charCodeAt(0) === 0xFEFF) { + return string.slice(1); + } + + return string; +}; diff --git a/action/node_modules/strip-bom/license b/action/node_modules/strip-bom/license new file mode 100644 index 00000000..e7af2f77 --- /dev/null +++ b/action/node_modules/strip-bom/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/action/node_modules/strip-bom/package.json b/action/node_modules/strip-bom/package.json new file mode 100644 index 00000000..f96ba34f --- /dev/null +++ b/action/node_modules/strip-bom/package.json @@ -0,0 +1,42 @@ +{ + "name": "strip-bom", + "version": "4.0.0", + "description": "Strip UTF-8 byte order mark (BOM) from a string", + "license": "MIT", + "repository": "sindresorhus/strip-bom", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && ava && tsd" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "strip", + "bom", + "byte", + "order", + "mark", + "unicode", + "utf8", + "utf-8", + "remove", + "delete", + "trim", + "text", + "string" + ], + "devDependencies": { + "ava": "^1.4.1", + "tsd": "^0.7.2", + "xo": "^0.24.0" + } +} diff --git a/action/node_modules/strip-bom/readme.md b/action/node_modules/strip-bom/readme.md new file mode 100644 index 00000000..e826851f --- /dev/null +++ b/action/node_modules/strip-bom/readme.md @@ -0,0 +1,54 @@ +# strip-bom [![Build Status](https://travis-ci.org/sindresorhus/strip-bom.svg?branch=master)](https://travis-ci.org/sindresorhus/strip-bom) + +> Strip UTF-8 [byte order mark](https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8) (BOM) from a string + +From Wikipedia: + +> The Unicode Standard permits the BOM in UTF-8, but does not require nor recommend its use. Byte order has no meaning in UTF-8. + +--- + +
+ + Get professional support for 'strip-bom' with a Tidelift subscription + +
+ + Tidelift helps make open source sustainable for maintainers while giving companies
assurances about security, maintenance, and licensing for their dependencies. +
+
+ +--- + +## Install + +``` +$ npm install strip-bom +``` + + +## Usage + +```js +const stripBom = require('strip-bom'); + +stripBom('\uFEFFunicorn'); +//=> 'unicorn' +``` + + +## Security + +To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure. + + +## Related + +- [strip-bom-cli](https://github.com/sindresorhus/strip-bom-cli) - CLI for this module +- [strip-bom-buf](https://github.com/sindresorhus/strip-bom-buf) - Buffer version of this module +- [strip-bom-stream](https://github.com/sindresorhus/strip-bom-stream) - Stream version of this module + + +## License + +MIT © [Sindre Sorhus](https://sindresorhus.com) diff --git a/action/node_modules/strip-json-comments/index.d.ts b/action/node_modules/strip-json-comments/index.d.ts new file mode 100644 index 00000000..28ba3c8a --- /dev/null +++ b/action/node_modules/strip-json-comments/index.d.ts @@ -0,0 +1,36 @@ +declare namespace stripJsonComments { + interface Options { + /** + Replace comments with whitespace instead of stripping them entirely. + + @default true + */ + readonly whitespace?: boolean; + } +} + +/** +Strip comments from JSON. Lets you use comments in your JSON files! + +It will replace single-line comments `//` and multi-line comments `/**\/` with whitespace. This allows JSON error positions to remain as close as possible to the original source. + +@param jsonString - Accepts a string with JSON. +@returns A JSON string without comments. + +@example +``` +const json = `{ + // Rainbows + "unicorn": "cake" +}`; + +JSON.parse(stripJsonComments(json)); +//=> {unicorn: 'cake'} +``` +*/ +declare function stripJsonComments( + jsonString: string, + options?: stripJsonComments.Options +): string; + +export = stripJsonComments; diff --git a/action/node_modules/strip-json-comments/index.js b/action/node_modules/strip-json-comments/index.js new file mode 100644 index 00000000..bb00b38b --- /dev/null +++ b/action/node_modules/strip-json-comments/index.js @@ -0,0 +1,77 @@ +'use strict'; +const singleComment = Symbol('singleComment'); +const multiComment = Symbol('multiComment'); +const stripWithoutWhitespace = () => ''; +const stripWithWhitespace = (string, start, end) => string.slice(start, end).replace(/\S/g, ' '); + +const isEscaped = (jsonString, quotePosition) => { + let index = quotePosition - 1; + let backslashCount = 0; + + while (jsonString[index] === '\\') { + index -= 1; + backslashCount += 1; + } + + return Boolean(backslashCount % 2); +}; + +module.exports = (jsonString, options = {}) => { + if (typeof jsonString !== 'string') { + throw new TypeError(`Expected argument \`jsonString\` to be a \`string\`, got \`${typeof jsonString}\``); + } + + const strip = options.whitespace === false ? stripWithoutWhitespace : stripWithWhitespace; + + let insideString = false; + let insideComment = false; + let offset = 0; + let result = ''; + + for (let i = 0; i < jsonString.length; i++) { + const currentCharacter = jsonString[i]; + const nextCharacter = jsonString[i + 1]; + + if (!insideComment && currentCharacter === '"') { + const escaped = isEscaped(jsonString, i); + if (!escaped) { + insideString = !insideString; + } + } + + if (insideString) { + continue; + } + + if (!insideComment && currentCharacter + nextCharacter === '//') { + result += jsonString.slice(offset, i); + offset = i; + insideComment = singleComment; + i++; + } else if (insideComment === singleComment && currentCharacter + nextCharacter === '\r\n') { + i++; + insideComment = false; + result += strip(jsonString, offset, i); + offset = i; + continue; + } else if (insideComment === singleComment && currentCharacter === '\n') { + insideComment = false; + result += strip(jsonString, offset, i); + offset = i; + } else if (!insideComment && currentCharacter + nextCharacter === '/*') { + result += jsonString.slice(offset, i); + offset = i; + insideComment = multiComment; + i++; + continue; + } else if (insideComment === multiComment && currentCharacter + nextCharacter === '*/') { + i++; + insideComment = false; + result += strip(jsonString, offset, i + 1); + offset = i + 1; + continue; + } + } + + return result + (insideComment ? strip(jsonString.slice(offset)) : jsonString.slice(offset)); +}; diff --git a/action/node_modules/strip-json-comments/license b/action/node_modules/strip-json-comments/license new file mode 100644 index 00000000..fa7ceba3 --- /dev/null +++ b/action/node_modules/strip-json-comments/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (https://sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/action/node_modules/strip-json-comments/package.json b/action/node_modules/strip-json-comments/package.json new file mode 100644 index 00000000..ce7875aa --- /dev/null +++ b/action/node_modules/strip-json-comments/package.json @@ -0,0 +1,47 @@ +{ + "name": "strip-json-comments", + "version": "3.1.1", + "description": "Strip comments from JSON. Lets you use comments in your JSON files!", + "license": "MIT", + "repository": "sindresorhus/strip-json-comments", + "funding": "https://github.com/sponsors/sindresorhus", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "https://sindresorhus.com" + }, + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && ava && tsd", + "bench": "matcha benchmark.js" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "json", + "strip", + "comments", + "remove", + "delete", + "trim", + "multiline", + "parse", + "config", + "configuration", + "settings", + "util", + "env", + "environment", + "jsonc" + ], + "devDependencies": { + "ava": "^1.4.1", + "matcha": "^0.7.0", + "tsd": "^0.7.2", + "xo": "^0.24.0" + } +} diff --git a/action/node_modules/strip-json-comments/readme.md b/action/node_modules/strip-json-comments/readme.md new file mode 100644 index 00000000..cc542e50 --- /dev/null +++ b/action/node_modules/strip-json-comments/readme.md @@ -0,0 +1,78 @@ +# strip-json-comments [![Build Status](https://travis-ci.com/sindresorhus/strip-json-comments.svg?branch=master)](https://travis-ci.com/github/sindresorhus/strip-json-comments) + +> Strip comments from JSON. Lets you use comments in your JSON files! + +This is now possible: + +```js +{ + // Rainbows + "unicorn": /* ❤ */ "cake" +} +``` + +It will replace single-line comments `//` and multi-line comments `/**/` with whitespace. This allows JSON error positions to remain as close as possible to the original source. + +Also available as a [Gulp](https://github.com/sindresorhus/gulp-strip-json-comments)/[Grunt](https://github.com/sindresorhus/grunt-strip-json-comments)/[Broccoli](https://github.com/sindresorhus/broccoli-strip-json-comments) plugin. + +## Install + +``` +$ npm install strip-json-comments +``` + +## Usage + +```js +const json = `{ + // Rainbows + "unicorn": /* ❤ */ "cake" +}`; + +JSON.parse(stripJsonComments(json)); +//=> {unicorn: 'cake'} +``` + +## API + +### stripJsonComments(jsonString, options?) + +#### jsonString + +Type: `string` + +Accepts a string with JSON and returns a string without comments. + +#### options + +Type: `object` + +##### whitespace + +Type: `boolean`\ +Default: `true` + +Replace comments with whitespace instead of stripping them entirely. + +## Benchmark + +``` +$ npm run bench +``` + +## Related + +- [strip-json-comments-cli](https://github.com/sindresorhus/strip-json-comments-cli) - CLI for this module +- [strip-css-comments](https://github.com/sindresorhus/strip-css-comments) - Strip comments from CSS + +--- + +
+ + Get professional support for this package with a Tidelift subscription + +
+ + Tidelift helps make open source sustainable for maintainers while giving companies
assurances about security, maintenance, and licensing for their dependencies. +
+
diff --git a/action/package-lock.json b/action/package-lock.json index 0780f883..118b3b15 100644 --- a/action/package-lock.json +++ b/action/package-lock.json @@ -4,12 +4,12 @@ "requires": true, "packages": { "": { - "name": "action", "dependencies": { "@actions/core": "^1.10.0", "@actions/github": "^5.1.1", "@deno/shim-deno": "^0.19.2", "formdata-polyfill": "^4.0.10", + "jsonc": "^2.0.0", "undici": "^5.11.0" } }, @@ -174,6 +174,21 @@ "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "license": "MIT" + }, "node_modules/fetch-blob": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.4.tgz", @@ -207,6 +222,18 @@ "node": ">=12.20.0" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, "node_modules/is-plain-object": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", @@ -223,6 +250,50 @@ "node": ">=16" } }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "license": "MIT" + }, + "node_modules/jsonc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jsonc/-/jsonc-2.0.0.tgz", + "integrity": "sha512-B281bLCT2TRMQa+AQUQY5AGcqSOXBOKaYGP4wDzoA/+QswUfN8sODektbPEs9Baq7LGKun5jQbNFpzwGuVYKhw==", + "license": "MIT", + "dependencies": { + "fast-safe-stringify": "^2.0.6", + "graceful-fs": "^4.1.15", + "mkdirp": "^0.5.1", + "parse-json": "^4.0.0", + "strip-bom": "^4.0.0", + "strip-json-comments": "^3.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -268,6 +339,40 @@ "wrappy": "1" } }, + "node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "license": "MIT", + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -500,6 +605,19 @@ "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" + }, "fetch-blob": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.4.tgz", @@ -517,6 +635,16 @@ "fetch-blob": "^3.1.2" } }, + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, "is-plain-object": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", @@ -527,6 +655,37 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==" }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + }, + "jsonc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jsonc/-/jsonc-2.0.0.tgz", + "integrity": "sha512-B281bLCT2TRMQa+AQUQY5AGcqSOXBOKaYGP4wDzoA/+QswUfN8sODektbPEs9Baq7LGKun5jQbNFpzwGuVYKhw==", + "requires": { + "fast-safe-stringify": "^2.0.6", + "graceful-fs": "^4.1.15", + "mkdirp": "^0.5.1", + "parse-json": "^4.0.0", + "strip-bom": "^4.0.0", + "strip-json-comments": "^3.0.1" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "requires": { + "minimist": "^1.2.6" + } + }, "node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -548,6 +707,25 @@ "wrappy": "1" } }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==" + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" + }, "tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", diff --git a/action/package.json b/action/package.json index c2303dbf..778ea3a8 100644 --- a/action/package.json +++ b/action/package.json @@ -5,6 +5,7 @@ "@actions/github": "^5.1.1", "@deno/shim-deno": "^0.19.2", "formdata-polyfill": "^4.0.10", + "jsonc": "^2.0.0", "undici": "^5.11.0" } } From 79bf2f4c701536632cfb967d6c21c48688b18f04 Mon Sep 17 00:00:00 2001 From: Simon Lecoq <22963968+lowlighter@users.noreply.github.com> Date: Thu, 19 Dec 2024 01:12:28 +0000 Subject: [PATCH 02/10] continue --- .github/workflows/test.yml | 4 ++++ action/index.js | 6 +++--- action/tests/with-deno-config/deno.jsonc | 9 +++++++++ action/tests/with-deno-config/hello.ts | 11 +++++++++++ 4 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 action/tests/with-deno-config/deno.jsonc create mode 100644 action/tests/with-deno-config/hello.ts diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5043756c..39d59e5d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -81,3 +81,7 @@ jobs: project: happy-rat-64 root: action/tests entrypoint: "data:,Deno.serve(() => new Response())" + - name: Deploy with deno.jsonc file + uses: ./ + with: + root: action/tests/with-deno-config diff --git a/action/index.js b/action/index.js index b8498f34..01de20fa 100644 --- a/action/index.js +++ b/action/index.js @@ -21,11 +21,12 @@ const ORIGIN = process.env.DEPLOY_API_ENDPOINT ?? "https://dash.deno.com"; async function main() { // Try to resolve and parse a deno config file + const cwd = resolve(process.cwd(), core.getInput("root", {})); let denoConfig = core.getInput("deno-config", {}); let denoConfigHasDeployInfo = false; const denoParsedConfig = {}; for (let path of [denoConfig, "deno.json", "deno.jsonc"]) { - path = resolve(process.cwd(), path); + path = resolve(cwd, path); if (existsSync(path)) { denoConfig = path; break; @@ -55,7 +56,7 @@ async function main() { // This lets user use deno.jsonc files as import-map since jsonc is not directly supported if (denoParsedConfig.imports) { core.info(`The configuration file has a "imports" field`); - denoParsedConfig.importMap = path.join(tmpdir(), "importMap.json"); + denoParsedConfig.importMap = resolve(tmpdir(), "importMap.json"); await writeFile( denoParsedConfig.importMap, JSON.stringify({ imports: denoParsedConfig.imports }), @@ -75,7 +76,6 @@ async function main() { core.getMultilineInput("include", {}); const exclude = denoParsedConfig.deploy?.exclude || core.getMultilineInput("exclude", {}); - const cwd = resolve(process.cwd(), core.getInput("root", {})); if (github.context.eventName === "pull_request") { const pr = github.context.payload.pull_request; diff --git a/action/tests/with-deno-config/deno.jsonc b/action/tests/with-deno-config/deno.jsonc new file mode 100644 index 00000000..36a5b864 --- /dev/null +++ b/action/tests/with-deno-config/deno.jsonc @@ -0,0 +1,9 @@ +{ + "deploy": { + "project": "happy-rat-64", + "entrypoint": "deno-config/hello.ts" + }, + "imports": { + "std/": "https://deno.land/std@0.128.0/" + } +} diff --git a/action/tests/with-deno-config/hello.ts b/action/tests/with-deno-config/hello.ts new file mode 100644 index 00000000..805c71ca --- /dev/null +++ b/action/tests/with-deno-config/hello.ts @@ -0,0 +1,11 @@ +import { serve } from "std/http/server.ts"; + +async function handler(_req: Request) { + const text = await Deno.readTextFile(new URL(import.meta.url)); + return new Response(text, { + headers: { "content-type": "text/plain; charset=utf8" }, + }); +} + +console.log("Listening on http://localhost:8000"); +serve(handler); From 0af6f6a136dfd759fc30e64820e63de40d60562b Mon Sep 17 00:00:00 2001 From: Simon Lecoq <22963968+lowlighter@users.noreply.github.com> Date: Thu, 19 Dec 2024 01:15:06 +0000 Subject: [PATCH 03/10] fix --- action/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action/index.js b/action/index.js index 01de20fa..31e7baab 100644 --- a/action/index.js +++ b/action/index.js @@ -25,7 +25,7 @@ async function main() { let denoConfig = core.getInput("deno-config", {}); let denoConfigHasDeployInfo = false; const denoParsedConfig = {}; - for (let path of [denoConfig, "deno.json", "deno.jsonc"]) { + for (let path of [denoConfig, "deno.json", "deno.jsonc"].filter(Boolean)) { path = resolve(cwd, path); if (existsSync(path)) { denoConfig = path; From 5165b44ef4da9dbbceaa06670e81d2d54f14501c Mon Sep 17 00:00:00 2001 From: Simon Lecoq <22963968+lowlighter@users.noreply.github.com> Date: Thu, 19 Dec 2024 01:23:09 +0000 Subject: [PATCH 04/10] test --- .github/workflows/test.yml | 20 +++++++++++--------- action.yml | 12 ++++++------ 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 39d59e5d..dd6af8bd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,41 +13,43 @@ jobs: permissions: id-token: write contents: read + env: + PROJECT_NAME: test-deployctl-fork # happy-rat-64 steps: - name: Checkout repository uses: actions/checkout@v3 - name: Deploy to Deno Deploy uses: ./ with: - project: happy-rat-64 + project: ${{ env.PROJECT_NAME }} root: action/tests entrypoint: hello.ts import-map: ./import_map.json - name: Deploy with single include uses: ./ with: - project: happy-rat-64 + project: ${{ env.PROJECT_NAME }} root: action/tests entrypoint: include_exclude.ts include: include_exclude.ts - name: Deploy with comma-separated include uses: ./ with: - project: happy-rat-64 + project: ${{ env.PROJECT_NAME }} root: action entrypoint: tests/include_exclude.ts include: foo, tests/include_exclude.ts,bar - name: Deploy with comma-separated exclude uses: ./ with: - project: happy-rat-64 + project: ${{ env.PROJECT_NAME }} root: action/tests entrypoint: include_exclude.ts exclude: import_bomb1,import_bomb2 - name: Deploy with multiline exclude uses: ./ with: - project: happy-rat-64 + project: ${{ env.PROJECT_NAME }} root: action/tests entrypoint: include_exclude.ts exclude: | @@ -56,7 +58,7 @@ jobs: - name: Deploy combine include and exclude uses: ./ with: - project: happy-rat-64 + project: ${{ env.PROJECT_NAME }} root: action entrypoint: tests/include_exclude.ts include: tests @@ -66,19 +68,19 @@ jobs: - name: Always exclude node_modules directory uses: ./ with: - project: happy-rat-64 + project: ${{ env.PROJECT_NAME }} root: action/tests/always_exclude_node_modules entrypoint: main.ts - name: Always exclude nested node_modules directory uses: ./ with: - project: happy-rat-64 + project: ${{ env.PROJECT_NAME }} root: action/tests entrypoint: always_exclude_node_modules/main.ts - name: data URL entrypoint uses: ./ with: - project: happy-rat-64 + project: ${{ env.PROJECT_NAME }} root: action/tests entrypoint: "data:,Deno.serve(() => new Response())" - name: Deploy with deno.jsonc file diff --git a/action.yml b/action.yml index 3fae2e03..8bb1c852 100644 --- a/action.yml +++ b/action.yml @@ -8,22 +8,22 @@ branding: inputs: deno-config: - description: The path to a local Deno config file (deno.json and deno.jsonc are auto-discovered). If it contains a "deploy" field, other inputs will default to its content. + description: The path to a deno config file (deno.json and deno.jsonc are auto-discovered) required: false project: - description: The name or ID of the project to deploy (required if when not set in Deno config) + description: The name or ID of the project to deploy (required, defaults to "deploy.project" of deno config if present) required: false entrypoint: - description: The path or URL to the entrypoint file (required if when not set in Deno config) + description: The path or URL to the entrypoint file (required, defaults to "deploy.entrypoint" of deno config if present) required: false import-map: - description: The path or URL to an import map file + description: The path or URL to an import map file (defaults to "importMap" or auto-generated from "imports" of deno config if present) required: false include: - description: Only upload files that match this pattern (multiline and/or comma-separated) + description: Only upload files that match this pattern (multiline and/or comma-separated, defaults to "deploy.exclude" of deno config if present) required: false exclude: - description: Exclude files that match this pattern (multiline and/or comma-separated) + description: Exclude files that match this pattern (multiline and/or comma-separated, defaults to "deploy.exclude" of deno config if present) required: false root: description: The path to the directory containing the code and assets to upload From 3f9b4c3655e28880a49de18287c50503d28e758e Mon Sep 17 00:00:00 2001 From: Simon Lecoq <22963968+lowlighter@users.noreply.github.com> Date: Thu, 19 Dec 2024 01:27:32 +0000 Subject: [PATCH 05/10] test --- .github/workflows/test.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index dd6af8bd..d43f35d9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -83,7 +83,11 @@ jobs: project: ${{ env.PROJECT_NAME }} root: action/tests entrypoint: "data:,Deno.serve(() => new Response())" + - name: "Setup test: Deploy with deno.jsonc file" + run: sed -i 's/\$PROJECT_NAME/${{ env.PROJECT_NAME }}/g' action/tests/with-deno-config/deno.jsonc - name: Deploy with deno.jsonc file uses: ./ with: root: action/tests/with-deno-config + - name: "Cleanup test: Deploy with deno.jsonc file" + run: git checkout action/tests/with-deno-config/deno.jsonc From 7aa8dc5e1392265ebd36fe4959eceafbe19f3a4a Mon Sep 17 00:00:00 2001 From: Simon Lecoq <22963968+lowlighter@users.noreply.github.com> Date: Thu, 19 Dec 2024 01:28:28 +0000 Subject: [PATCH 06/10] test --- .github/workflows/test.yml | 16 ++++++++-------- action/tests/with-deno-config/deno.jsonc | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d43f35d9..fa1e5995 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,6 +25,14 @@ jobs: root: action/tests entrypoint: hello.ts import-map: ./import_map.json + - name: "Setup test: Deploy to Deno Deploy with deno.jsonc file" + run: sed -i 's/\$PROJECT_NAME/${{ env.PROJECT_NAME }}/g' action/tests/with-deno-config/deno.jsonc + - name: Deploy to Deno Deploy with deno.jsonc file + uses: ./ + with: + root: action/tests/with-deno-config + - name: "Cleanup test: Deploy to Deno Deploy with deno.jsonc file" + run: git checkout action/tests/with-deno-config/deno.jsonc - name: Deploy with single include uses: ./ with: @@ -83,11 +91,3 @@ jobs: project: ${{ env.PROJECT_NAME }} root: action/tests entrypoint: "data:,Deno.serve(() => new Response())" - - name: "Setup test: Deploy with deno.jsonc file" - run: sed -i 's/\$PROJECT_NAME/${{ env.PROJECT_NAME }}/g' action/tests/with-deno-config/deno.jsonc - - name: Deploy with deno.jsonc file - uses: ./ - with: - root: action/tests/with-deno-config - - name: "Cleanup test: Deploy with deno.jsonc file" - run: git checkout action/tests/with-deno-config/deno.jsonc diff --git a/action/tests/with-deno-config/deno.jsonc b/action/tests/with-deno-config/deno.jsonc index 36a5b864..20abf3c8 100644 --- a/action/tests/with-deno-config/deno.jsonc +++ b/action/tests/with-deno-config/deno.jsonc @@ -1,7 +1,7 @@ { "deploy": { - "project": "happy-rat-64", - "entrypoint": "deno-config/hello.ts" + "project": "$PROJECT_NAME", + "entrypoint": "hello.ts" }, "imports": { "std/": "https://deno.land/std@0.128.0/" From b593177f1cf2969c3bea776b57b03a73542b4b2a Mon Sep 17 00:00:00 2001 From: Simon Lecoq <22963968+lowlighter@users.noreply.github.com> Date: Thu, 19 Dec 2024 01:35:58 +0000 Subject: [PATCH 07/10] test --- action.yml | 6 +++++- action/index.js | 9 +++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/action.yml b/action.yml index 8bb1c852..3b888761 100644 --- a/action.yml +++ b/action.yml @@ -17,8 +17,12 @@ inputs: description: The path or URL to the entrypoint file (required, defaults to "deploy.entrypoint" of deno config if present) required: false import-map: - description: The path or URL to an import map file (defaults to "importMap" or auto-generated from "imports" of deno config if present) + description: The path or URL to an import map file (defaults to "importMap" of deno config if present) required: false + import-map-autogen-temp: + description: If "imports" is present in deno config, the path to store the auto-generated import map (relative to root, overrides the "importMap" valud of deno config if present) + required: false + default: ".importMap.generated.json" include: description: Only upload files that match this pattern (multiline and/or comma-separated, defaults to "deploy.exclude" of deno config if present) required: false diff --git a/action/index.js b/action/index.js index 31e7baab..3b7aabdd 100644 --- a/action/index.js +++ b/action/index.js @@ -12,7 +12,6 @@ import { } from "./deps.js"; import process from "node:process"; import { jsonc } from "jsonc"; -import { tmpdir } from "node:os"; import { existsSync } from "node:fs"; import { readFile, writeFile } from "node:fs/promises"; @@ -56,11 +55,17 @@ async function main() { // This lets user use deno.jsonc files as import-map since jsonc is not directly supported if (denoParsedConfig.imports) { core.info(`The configuration file has a "imports" field`); - denoParsedConfig.importMap = resolve(tmpdir(), "importMap.json"); + denoParsedConfig.importMap = resolve( + root, + core.getInput("import-map-autogen-temp", {}), + ); await writeFile( denoParsedConfig.importMap, JSON.stringify({ imports: denoParsedConfig.imports }), ); + core.info( + `Created temporary import map in ${denoParsedConfig.importMap}`, + ); } } From de0a1818ac2921b30013968c9aac21fc942eef40 Mon Sep 17 00:00:00 2001 From: Simon Lecoq <22963968+lowlighter@users.noreply.github.com> Date: Thu, 19 Dec 2024 01:37:11 +0000 Subject: [PATCH 08/10] fix --- action/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action/index.js b/action/index.js index 3b7aabdd..55760ac3 100644 --- a/action/index.js +++ b/action/index.js @@ -56,7 +56,7 @@ async function main() { if (denoParsedConfig.imports) { core.info(`The configuration file has a "imports" field`); denoParsedConfig.importMap = resolve( - root, + cwd, core.getInput("import-map-autogen-temp", {}), ); await writeFile( From 514b033f89a590b9915d130c64acdc0c887d01a3 Mon Sep 17 00:00:00 2001 From: Simon Lecoq <22963968+lowlighter@users.noreply.github.com> Date: Thu, 19 Dec 2024 01:45:35 +0000 Subject: [PATCH 09/10] continue --- action.yml | 20 ++++++++++---------- action/README.md | 17 +++++++++++++++++ 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/action.yml b/action.yml index 3b888761..a26564fb 100644 --- a/action.yml +++ b/action.yml @@ -8,30 +8,30 @@ branding: inputs: deno-config: - description: The path to a deno config file (deno.json and deno.jsonc are auto-discovered) + description: The path to a deno config file that will populate other inputs (optional, deno.json and deno.jsonc are auto-discovered) required: false project: - description: The name or ID of the project to deploy (required, defaults to "deploy.project" of deno config if present) + description: The name or ID of the project to deploy (required) required: false entrypoint: - description: The path or URL to the entrypoint file (required, defaults to "deploy.entrypoint" of deno config if present) + description: The path or URL to the entrypoint file (required) required: false import-map: - description: The path or URL to an import map file (defaults to "importMap" of deno config if present) + description: The path or URL to an import map file required: false - import-map-autogen-temp: - description: If "imports" is present in deno config, the path to store the auto-generated import map (relative to root, overrides the "importMap" valud of deno config if present) - required: false - default: ".importMap.generated.json" include: - description: Only upload files that match this pattern (multiline and/or comma-separated, defaults to "deploy.exclude" of deno config if present) + description: Only upload files that match this pattern (multiline and/or comma-separated) required: false exclude: - description: Exclude files that match this pattern (multiline and/or comma-separated, defaults to "deploy.exclude" of deno config if present) + description: Exclude files that match this pattern (multiline and/or comma-separated) required: false root: description: The path to the directory containing the code and assets to upload required: false + import-map-autogen-temp: + description: The path to store the auto-generated import map if deno config file is present (relative to root) + required: false + default: ".importMap.generated.json" outputs: deployment-id: diff --git a/action/README.md b/action/README.md index 24444b9b..e66c49f9 100644 --- a/action/README.md +++ b/action/README.md @@ -49,14 +49,22 @@ jobs: - name: Deploy to Deno Deploy uses: denoland/deployctl@v1 with: + # Path to the deno config file + # Auto-discovered from the root directory if it is named "deno.json" or "deno.jsonc". + # If present, other inputs will defaults to their value in the config file. + # Optional. + deno-config: + # Name of the project on Deno Deploy # Required. + # Defaults to "deploy.project" of deno config file if present. project: # Entrypoint location executed by Deno Deploy # The entrypoint can be a relative path or an absolute URL. # If it is a relative path, it will be resolved relative to the `root` directory. # Required. + # Defaults to "deploy.entrypoint" of deno config file if present. entrypoint: # Root directory to deploy @@ -67,17 +75,26 @@ jobs: # Filter which files to include in the deployment # It supports a single file, multiple files separated by a comma or by a newline # Optional. + # Defaults to "include" of deno config file if present. include: # Filter which files to exclude in the deployment # It supports a single file, multiple files separated by a comma or by a newline # Optional. + # Defaults to "exclude" of deno config file if present. exclude: # Location of an import map # Must be relative to root directory # Optional. + # Defaults to "importMap" of deno config file if present. import-map: + + # Location of the auto-generated import map if the deno config file contains + # an "imports" field (allowing support for jsonc config files). + # Relative to root directory + # Optional. + import-map-autogen-temp: ``` ## Examples From 16a33b37811ae3b0378c310142040031bb2aa52d Mon Sep 17 00:00:00 2001 From: Simon Lecoq <22963968+lowlighter@users.noreply.github.com> Date: Thu, 19 Dec 2024 01:48:28 +0000 Subject: [PATCH 10/10] fix --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fa1e5995..4c94a5c8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,7 +14,7 @@ jobs: id-token: write contents: read env: - PROJECT_NAME: test-deployctl-fork # happy-rat-64 + PROJECT_NAME: happy-rat-64 steps: - name: Checkout repository uses: actions/checkout@v3