├── .husky ├── .gitignore └── pre-commit ├── .prettierrc.yml ├── .prettierignore ├── .vscode ├── settings.json └── tasks.json ├── examples ├── bundle │ ├── echo.js │ ├── .yarnrc.yml │ ├── .gitignore │ ├── src │ │ └── cli.ts │ ├── tsconfig.json │ ├── package.json │ └── yarn.lock ├── foo.ts ├── dice.ts ├── simple.ts ├── cat.ts ├── pretty.ts ├── pizza.ts ├── repl.ts ├── calculator.ts ├── errors.ts └── types.ts ├── tests ├── unit │ ├── option.spec.ts │ ├── __snapshots__ │ │ └── command.spec.ts.snap │ ├── autocomplete.spec.ts │ ├── utils.spec.ts │ ├── argument.spec.ts │ ├── program.spec.ts │ ├── history.spec.ts │ └── command.spec.ts ├── smoke │ ├── cjs │ │ ├── package.json │ │ └── index.cjs │ ├── esm │ │ ├── package.json │ │ └── index.mjs │ └── run.sh └── types │ ├── program.test-d.ts │ └── command.test-d.ts ├── jest.config.js ├── tsconfig.build.json ├── src ├── index.ts ├── utils.ts ├── autocompleter.ts ├── option.ts ├── history.ts ├── argument.ts ├── baseArg.ts ├── repl.ts ├── prompter.ts ├── command.ts └── program.ts ├── .gitignore ├── .github ├── workflows │ ├── dependency-review.yml │ ├── format-check.yml │ ├── dependabot-automerge.yml │ ├── release.yml │ ├── update-node-versions.yml │ ├── codeql.yml │ └── ci.yml └── dependabot.yml ├── .yarnrc.yml ├── .devcontainer └── devcontainer.json ├── tsconfig.json ├── .releaserc.json ├── TODO.md ├── LICENSE ├── package.json ├── README.md ├── CHANGELOG.md └── .yarn └── plugins └── @yarnpkg └── plugin-typescript.cjs /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /.prettierrc.yml: -------------------------------------------------------------------------------- 1 | proseWrap: always 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # yarn 2 | .yarn 3 | 4 | # artifacts 5 | dist/ -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib" 3 | } 4 | -------------------------------------------------------------------------------- /examples/bundle/echo.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require("./dist/cli").default.run(); 4 | -------------------------------------------------------------------------------- /examples/bundle/.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | 3 | yarnPath: .yarn/releases/yarn-3.0.2.cjs 4 | -------------------------------------------------------------------------------- /examples/bundle/.gitignore: -------------------------------------------------------------------------------- 1 | .yarn/* 2 | !.yarn/patches 3 | !.yarn/releases 4 | !.yarn/plugins 5 | !.yarn/sdks 6 | !.yarn/versions 7 | .pnp.* 8 | 9 | node_modules/ 10 | 11 | dist/ 12 | echo.exe 13 | -------------------------------------------------------------------------------- /tests/unit/option.spec.ts: -------------------------------------------------------------------------------- 1 | import { option, Option } from "../../src/index.js"; 2 | 3 | test("option should return new Option object", () => { 4 | expect(option("test")).toBeInstanceOf(Option); 5 | }); 6 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import("ts-jest").JestConfigWithTsJest} */ 2 | 3 | export default { 4 | preset: "ts-jest/presets/default-esm", 5 | moduleNameMapper: { 6 | "^(\\.{1,2}/.*)\\.js$": "$1", 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /tests/smoke/cjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bandersnatch-smoke-test-cjs", 3 | "scripts": { 4 | "test": "node index.cjs" 5 | }, 6 | "dependencies": { 7 | "bandersnatch": "^1.9.2" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/foo.ts: -------------------------------------------------------------------------------- 1 | import { command, program } from "../src/index.js"; 2 | 3 | const foo = command("foo") 4 | .description('Outputs "bar".') 5 | .action(() => console.log("bar")); 6 | 7 | program().default(foo).run(); 8 | -------------------------------------------------------------------------------- /tests/smoke/esm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bandersnatch-smoke-test-esm", 3 | "type": "module", 4 | "scripts": { 5 | "test": "node index.mjs" 6 | }, 7 | "dependencies": { 8 | "bandersnatch": "^1.9.2" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["src"], 4 | "compilerOptions": { 5 | "rootDir": "src", 6 | "noEmit": false, 7 | "declaration": true, 8 | "declarationDir": "dist/types" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn todos && git add TODO.md 5 | yarn prettier --write TODO.md && git add TODO.md 6 | yarn doctoc && git add README.md 7 | yarn prettier --write README.md && git add README.md 8 | yarn lint-staged 9 | -------------------------------------------------------------------------------- /tests/smoke/esm/index.mjs: -------------------------------------------------------------------------------- 1 | import { command, program } from "bandersnatch"; 2 | 3 | const app = program(); 4 | 5 | app.default( 6 | command("echo") 7 | .argument("arg1") 8 | .action((args) => console.log(args.arg1)), 9 | ); 10 | 11 | app.run(); 12 | -------------------------------------------------------------------------------- /tests/unit/__snapshots__/command.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`handler is required 1`] = `[Error: No handler defined for this command.]`; 4 | 5 | exports[`variadic argument must be last 1`] = `"Can't add more arguments."`; 6 | -------------------------------------------------------------------------------- /tests/smoke/cjs/index.cjs: -------------------------------------------------------------------------------- 1 | const { command, program } = require("bandersnatch"); 2 | 3 | const app = program(); 4 | 5 | app.default( 6 | command("echo") 7 | .argument("arg1") 8 | .action((args) => console.log(args.arg1)), 9 | ); 10 | 11 | app.run(); 12 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./argument.js"; 2 | export * from "./autocompleter.js"; 3 | export * from "./command.js"; 4 | export * from "./history.js"; 5 | export * from "./option.js"; 6 | export * from "./program.js"; 7 | export * from "./repl.js"; 8 | export * from "./utils.js"; 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # node 2 | node_modules/ 3 | dist/ 4 | coverage/ 5 | tests/smoke/*/yarn.lock 6 | 7 | # yarn 8 | **/.pnp.* 9 | **/.yarn/* 10 | !**/.yarn/patches 11 | !**/.yarn/plugins 12 | !**/.yarn/releases 13 | !**/.yarn/sdks 14 | !**/.yarn/versions 15 | # artifacts 16 | /dist 17 | /types 18 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | // See https://github.com/then/is-promise/blob/master/index.js 2 | export function isPromise(obj: any): obj is Promise { 3 | return ( 4 | !!obj && 5 | (typeof obj === "object" || typeof obj === "function") && 6 | typeof obj.then === "function" 7 | ); 8 | } 9 | -------------------------------------------------------------------------------- /examples/bundle/src/cli.ts: -------------------------------------------------------------------------------- 1 | import { program, command } from "bandersnatch"; 2 | 3 | export default program().default( 4 | command("echo") 5 | .description("Echo something in the terminal") 6 | .argument("words", { description: "Say some kind words", variadic: true }) 7 | .action(console.log), 8 | ); 9 | -------------------------------------------------------------------------------- /.github/workflows/dependency-review.yml: -------------------------------------------------------------------------------- 1 | name: dependency-review 2 | 3 | on: 4 | pull_request: 5 | 6 | permissions: 7 | contents: read 8 | 9 | jobs: 10 | dependency-review: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: actions/dependency-review-action@v4 15 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "npm", 6 | "script": "watch", 7 | "problemMatcher": ["$tsc-watch"], 8 | "group": "build", 9 | "label": "npm: watch", 10 | "detail": "tsc --watch", 11 | "isBackground": true 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | 3 | npmPublishAccess: public 4 | 5 | plugins: 6 | - path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs 7 | spec: "@yarnpkg/plugin-interactive-tools" 8 | - path: .yarn/plugins/@yarnpkg/plugin-typescript.cjs 9 | spec: "@yarnpkg/plugin-typescript" 10 | 11 | yarnPath: .yarn/releases/yarn-3.5.0.cjs 12 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Node.js & TypeScript", 3 | "image": "mcr.microsoft.com/devcontainers/typescript-node:16-bullseye", 4 | "features": {}, 5 | "forwardPorts": [], 6 | "postCreateCommand": "yarn install && yarn husky install", 7 | "customizations": { 8 | "vscode": { 9 | "extensions": ["esbenp.prettier-vscode", "redhat.vscode-yaml"] 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/bundle/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["./src"], 3 | "compilerOptions": { 4 | "target": "es2017", 5 | "module": "commonjs", 6 | "lib": ["es2017"], 7 | "declaration": true, 8 | "outDir": "dist", 9 | "rootDir": "src", 10 | "strict": true, 11 | "allowSyntheticDefaultImports": true, 12 | "esModuleInterop": true, 13 | "moduleResolution": "node" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.github/workflows/format-check.yml: -------------------------------------------------------------------------------- 1 | name: format-check 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | 9 | jobs: 10 | format-check: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: actions/setup-node@v4 15 | with: 16 | node-version: lts/* 17 | cache: yarn 18 | - run: yarn install 19 | - run: yarn format:check 20 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Node 18 + ESM + Strictest", 4 | "include": ["src", "tests", "examples"], 5 | "compilerOptions": { 6 | "rootDir": ".", 7 | "noEmit": true, 8 | "target": "es2017", 9 | "module": "es6", 10 | "lib": ["es2017"], 11 | "allowSyntheticDefaultImports": true, 12 | "moduleResolution": "node", 13 | "esModuleInterop": true, 14 | "strict": true 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/dice.ts: -------------------------------------------------------------------------------- 1 | import { command, program } from "../src/index.js"; 2 | 3 | async function rng(bounds: [number, number]) { 4 | const [min, max] = bounds; 5 | return Math.floor(Math.random() * (max - min + 1)) + min; 6 | } 7 | 8 | const dice = program().add( 9 | command("roll") 10 | .option("min", { default: 1 }) 11 | .option("max", { default: 6 }) 12 | .action(async (args) => { 13 | console.log(await rng([args.min, args.max])); 14 | }), 15 | ); 16 | 17 | dice.runOrRepl(); 18 | -------------------------------------------------------------------------------- /examples/simple.ts: -------------------------------------------------------------------------------- 1 | import { command, program } from "../src/index.js"; 2 | 3 | const echo = command("concat") 4 | .description("Concatenate input") 5 | .argument("input", { 6 | description: "List of inputs to concatenate", 7 | variadic: true, 8 | }) 9 | .option("delimiter", { 10 | type: "string", 11 | alias: "d", 12 | default: " ", 13 | }) 14 | .action((args) => { 15 | console.log(args.input.join(args.delimiter)); 16 | }); 17 | 18 | program().default(echo).run(); 19 | -------------------------------------------------------------------------------- /.github/workflows/dependabot-automerge.yml: -------------------------------------------------------------------------------- 1 | name: dependabot-automerge 2 | 3 | on: 4 | pull_request: 5 | 6 | permissions: 7 | pull-requests: write 8 | contents: write 9 | 10 | jobs: 11 | dependabot-automerge: 12 | runs-on: ubuntu-latest 13 | if: ${{ github.actor == 'dependabot[bot]' }} 14 | steps: 15 | - run: gh pr merge --auto --squash "$PR_URL" 16 | env: 17 | PR_URL: ${{ github.event.pull_request.html_url }} 18 | GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} 19 | -------------------------------------------------------------------------------- /.releaserc.json: -------------------------------------------------------------------------------- 1 | { 2 | "branches": ["main"], 3 | "plugins": [ 4 | "@semantic-release/commit-analyzer", 5 | "@semantic-release/release-notes-generator", 6 | "@semantic-release/changelog", 7 | "semantic-release-yarn", 8 | "@semantic-release/github", 9 | [ 10 | "@semantic-release/git", 11 | { 12 | "assets": ["CHANGELOG.md", "package.json"], 13 | "message": "chore(release): ${nextRelease.version}\n\n${nextRelease.notes}\n\n[skip ci]" 14 | } 15 | ] 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /examples/bundle/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "echo", 3 | "description": "", 4 | "version": "1.0.0", 5 | "bin": "echo.js", 6 | "files": [ 7 | "dist" 8 | ], 9 | "scripts": { 10 | "prepublishOnly": "yarn build", 11 | "build": "tsc", 12 | "bundle": "yarn build && pkg -t host ." 13 | }, 14 | "author": "", 15 | "license": "MIT", 16 | "dependencies": { 17 | "bandersnatch": "^1.9.2" 18 | }, 19 | "devDependencies": { 20 | "pkg": "^5.5.2", 21 | "typescript": "^5.0.3" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/cat.ts: -------------------------------------------------------------------------------- 1 | import { readFileSync } from "fs"; 2 | import { command, program } from "../src/index.js"; 3 | 4 | const cat = command("cat") 5 | .description("Concatenate files") 6 | .argument("files", { variadic: true, default: [] }) 7 | .action(({ files }) => 8 | console.log( 9 | files.reduce((str, file) => str + readFileSync(file, "utf8"), ""), 10 | ), 11 | ); 12 | 13 | program() 14 | .default(cat) 15 | .run() 16 | .catch((err) => { 17 | console.error(`There was a problem running this command:\n${String(err)}`); 18 | process.exit(1); 19 | }); 20 | -------------------------------------------------------------------------------- /examples/pretty.ts: -------------------------------------------------------------------------------- 1 | import { command, program } from "../src/index.js"; 2 | 3 | const app = program() 4 | .description("JSON pretty printer") 5 | .default( 6 | command() 7 | .description("Raw JSON input as string") 8 | .argument("json") 9 | .option("color", { 10 | description: "Enables colorized output", 11 | type: "boolean", 12 | }) 13 | .action(async (args) => { 14 | const json = JSON.parse(args.json); 15 | args.color 16 | ? console.dir(json) 17 | : console.log(JSON.stringify(json, undefined, 4)); 18 | }), 19 | ); 20 | 21 | app.runOrRepl(); 22 | -------------------------------------------------------------------------------- /tests/unit/autocomplete.spec.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Autocompleter, 3 | autocompleter as createAutocompleter, 4 | command, 5 | program as createProgram, 6 | } from "../../src/index.js"; 7 | 8 | test("autocompleter should return new Autocompleter object", () => { 9 | const program = createProgram(); 10 | expect(createAutocompleter(program)).toBeInstanceOf(Autocompleter); 11 | }); 12 | 13 | test("autocompleter should complete commands", () => { 14 | const program = createProgram().add(command("test")); 15 | const autocompleter = createAutocompleter(program); 16 | expect(autocompleter.completions(["t"])).resolves.toContain("test"); 17 | }); 18 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: / 5 | schedule: 6 | interval: weekly 7 | commit-message: 8 | prefix: fix 9 | prefix-development: chore 10 | include: scope 11 | - package-ecosystem: npm 12 | directory: /examples/bundle 13 | schedule: 14 | interval: weekly 15 | - package-ecosystem: npm 16 | directory: /tests/smoke/cjs 17 | schedule: 18 | interval: weekly 19 | - package-ecosystem: npm 20 | directory: /tests/smoke/esm 21 | schedule: 22 | interval: weekly 23 | - package-ecosystem: github-actions 24 | directory: / 25 | schedule: 26 | interval: weekly 27 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: release 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - main 8 | 9 | jobs: 10 | release: 11 | concurrency: 12 | group: ${{ github.workflow }}-${{ github.ref }} 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v4 16 | with: 17 | persist-credentials: false 18 | - uses: actions/setup-node@v4 19 | with: 20 | node-version: lts/* 21 | cache: yarn 22 | - run: yarn install 23 | - run: yarn build 24 | - run: yarn release 25 | env: 26 | GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} 27 | YARN_NPM_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 28 | -------------------------------------------------------------------------------- /.github/workflows/update-node-versions.yml: -------------------------------------------------------------------------------- 1 | name: update-node-versions 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: "30 7 * * 0" 7 | 8 | jobs: 9 | update-node-versions: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v4 13 | - uses: hongaar/update-node-versions@v2 14 | - uses: peter-evans/create-pull-request@v6 15 | with: 16 | title: "feat: update node.js versions" 17 | body: | 18 | Automated changes by [update-node-versions](https://github.com/hongaar/update-node-versions) GitHub action 19 | 20 | BREAKING CHANGE: This updates the supported node.js versions 21 | token: ${{ secrets.GH_TOKEN }} 22 | -------------------------------------------------------------------------------- /tests/types/program.test-d.ts: -------------------------------------------------------------------------------- 1 | import { expectType } from "tsd"; 2 | import { command } from "../../src/command"; 3 | import { Program, program } from "../../src/program"; 4 | import { Repl } from "../../src/repl"; 5 | 6 | const app = program(); 7 | 8 | expectType(app); 9 | 10 | // Chainable methods 11 | expectType(app.description("foo")); 12 | expectType(app.prompt("foo")); 13 | expectType(app.add(command())); 14 | expectType(app.default(command())); 15 | expectType(app.on("run", () => {})); 16 | 17 | // Run methods 18 | expectType>(app.run("foo")); 19 | expectType>(app.run(["foo", "bar"])); 20 | expectType>(app.run()); 21 | expectType(app.repl()); 22 | expectType>(app.runOrRepl()); 23 | 24 | // Getters 25 | expectType(app.isRepl()); 26 | expectType(app.isRepl()); 27 | -------------------------------------------------------------------------------- /examples/pizza.ts: -------------------------------------------------------------------------------- 1 | import { command, program } from "../src/index.js"; 2 | 3 | const cmd = command() 4 | .argument("address", { 5 | prompt: "Your address", 6 | }) 7 | .option("name", { 8 | description: "Your name", 9 | default: "anonymous", 10 | prompt: true, 11 | }) 12 | .option("size", { 13 | description: "Choose pizza size", 14 | choices: ["small", "medium", "large"] as const, 15 | default: "medium", 16 | prompt: true, 17 | }) 18 | .option("toppings", { 19 | description: "Pick some toppings", 20 | choices: ["mozzarella", "pepperoni", "veggies"] as const, 21 | default: ["mozzarella"], 22 | prompt: true, 23 | }) 24 | .option("confirmed", { 25 | description: "Order pizza?", 26 | default: true, 27 | prompt: true, 28 | }) 29 | .action((args) => { 30 | console.log(args); 31 | }); 32 | 33 | program().description("Order food").default(cmd).run(); 34 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: codeql 2 | 3 | on: 4 | push: 5 | branches: ["main"] 6 | pull_request: 7 | branches: ["main"] 8 | schedule: 9 | - cron: "25 22 * * 3" 10 | 11 | jobs: 12 | analyze: 13 | runs-on: ubuntu-latest 14 | permissions: 15 | actions: read 16 | contents: read 17 | security-events: write 18 | 19 | strategy: 20 | fail-fast: false 21 | matrix: 22 | language: [javascript] 23 | 24 | steps: 25 | - name: checkout 26 | uses: actions/checkout@v4 27 | 28 | - name: initialize 29 | uses: github/codeql-action/init@v3 30 | with: 31 | languages: ${{ matrix.language }} 32 | queries: +security-and-quality 33 | 34 | - name: autobuild 35 | uses: github/codeql-action/autobuild@v3 36 | 37 | - name: analysis 38 | uses: github/codeql-action/analyze@v3 39 | with: 40 | category: "/language:${{ matrix.language }}" 41 | -------------------------------------------------------------------------------- /tests/unit/utils.spec.ts: -------------------------------------------------------------------------------- 1 | import { isPromise } from "../../src/index.js"; 2 | 3 | test("isPromise should return true for promises", () => { 4 | expect(isPromise(Promise.resolve())).toBe(true); 5 | const rejected = Promise.reject(); 6 | expect(isPromise(rejected)).toBe(true); 7 | expect(isPromise(new Promise(() => {}))).toBe(true); 8 | // Cleanup 9 | rejected.catch(() => {}); 10 | }); 11 | 12 | test("isPromise should return true for promise-like objects", () => { 13 | expect(isPromise({ then: () => {} })).toBe(true); 14 | const promiseFn = () => {}; 15 | promiseFn.then = () => {}; 16 | expect(isPromise(promiseFn)).toBe(true); 17 | }); 18 | 19 | test("isPromise should return false for non-promises", () => { 20 | expect(isPromise(true)).toBe(false); 21 | expect(isPromise("string")).toBe(false); 22 | expect(isPromise(42)).toBe(false); 23 | expect(isPromise([])).toBe(false); 24 | expect(isPromise({})).toBe(false); 25 | expect(isPromise(() => {})).toBe(false); 26 | }); 27 | -------------------------------------------------------------------------------- /tests/smoke/run.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cwd=$(dirname "$0") 4 | targets=( cjs esm ) 5 | status=0 6 | 7 | for target in "${targets[@]}" 8 | do 9 | 10 | echo "==== Testing $target build ====" 11 | 12 | pushd "$cwd/$target" > /dev/null 13 | echo "▶️ Installing..." 14 | touch yarn.lock 15 | yarn install --no-immutable > /dev/null 16 | echo "▶️ Copying dist..." 17 | rm -rf "./node_modules/bandersnatch/dist" 18 | cp -r "../../../dist" "./node_modules/bandersnatch" 19 | cp "../../../package.json" "./node_modules/bandersnatch" 20 | yarn install --no-immutable > /dev/null 21 | echo "▶️ Running test script..." 22 | actual=$(yarn test ok 2>&1) 23 | expected=ok 24 | if [ "$actual" = "$expected" ]; then 25 | echo "✅" 26 | else 27 | echo "❌" 28 | echo -e "\nExpected:\n\n$expected" 29 | echo -e "\nActual:\n\n$actual\n" 30 | status=1 31 | fi 32 | popd > /dev/null 33 | 34 | done 35 | 36 | exit $status 37 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | ### TODOs 2 | 3 | | Filename | line # | TODO | 4 | | :------------------------------------- | :----: | :----------------------------------------------------- | 5 | | [src/baseArg.ts](src/baseArg.ts#L93) | 93 | See if we can add this to autocompleter | 6 | | [src/command.ts](src/command.ts#L276) | 276 | coerce all types and remove coerce option from baseArg | 7 | | [src/command.ts](src/command.ts#L291) | 291 | Upgrade to native async handlers in yarn 17 | 8 | | [src/prompter.ts](src/prompter.ts#L14) | 14 | Wait for upstream change to import types from enquirer | 9 | 10 | ### FIXMEs 11 | 12 | | Filename | line # | FIXME | 13 | | :------------------------------------------------------------------ | :----: | :----------------------------------------------------------------- | 14 | | [tests/types/command.test-d.ts](tests/types/command.test-d.ts#L127) | 127 | unspecified options are omitted by yargs but are always present in | 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2022 Joram van den Boezem 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /src/autocompleter.ts: -------------------------------------------------------------------------------- 1 | import { Program } from "./program.js"; 2 | import { isPromise } from "./utils.js"; 3 | 4 | export function autocompleter(program: Program) { 5 | return new Autocompleter(program); 6 | } 7 | 8 | export class Autocompleter { 9 | constructor(private program: Program) {} 10 | 11 | completions(argv: string[]) { 12 | return this.yargsCompletions(argv); 13 | } 14 | 15 | private yargsCompletions(argv: string[]) { 16 | return new Promise((resolve, reject) => { 17 | // We need to override 'strip-dashed' to make sure yargs can find the 18 | // '--get-yargs-completions' option. 19 | const yargs = this.program.createYargsInstance({ "strip-dashed": false }); 20 | 21 | // yargs.getCompletion() doesn't work for our use case. 22 | yargs.parse( 23 | ["$0", "--get-yargs-completions", "$0", ...argv], 24 | {}, 25 | (err, argv, output) => { 26 | // We don't use yargs 17 promise style argv 27 | if (isPromise(argv)) { 28 | throw new Error("argv is of unexpected type"); 29 | } 30 | 31 | if (argv.getYargsCompletions) { 32 | resolve(output ? output.split("\n") : []); 33 | } 34 | }, 35 | ); 36 | }); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tests/unit/argument.spec.ts: -------------------------------------------------------------------------------- 1 | import { argument, Argument } from "../../src/index.js"; 2 | 3 | test("argument should return new Argument object", () => { 4 | expect(argument("test")).toBeInstanceOf(Argument); 5 | }); 6 | 7 | test("getName", () => { 8 | expect(argument("test").getName()).toBe("test"); 9 | }); 10 | 11 | test("getDescription", () => { 12 | expect(argument("test", { description: "foo" }).getDescription()).toBe("foo"); 13 | }); 14 | 15 | test("getOptions", () => { 16 | expect(argument("test", { type: "number" }).getOptions().type).toBe("number"); 17 | }); 18 | 19 | test("required argument", () => { 20 | expect(argument("test").toCommand()).toBe(""); 21 | }); 22 | 23 | test("optional argument", () => { 24 | expect(argument("test", { optional: true }).toCommand()).toBe("[test]"); 25 | }); 26 | 27 | test("variadic argument", () => { 28 | expect(argument("test", { variadic: true }).toCommand()).toBe("[test..]"); 29 | }); 30 | 31 | test("promptable argument", () => { 32 | const arg1 = argument("test", { description: "foo", prompt: true }); 33 | expect(arg1.getPrompt()).toBe("foo"); 34 | 35 | const arg2 = argument("test", { prompt: true }); 36 | expect(arg2.getPrompt()).toBe("test"); 37 | 38 | const arg3 = argument("test", { prompt: "bar" }); 39 | expect(arg3.getPrompt()).toBe("bar"); 40 | }); 41 | -------------------------------------------------------------------------------- /examples/repl.ts: -------------------------------------------------------------------------------- 1 | import { command, program } from "../src/index.js"; 2 | 3 | let url: string | null = null; 4 | 5 | const app = program(); 6 | 7 | app 8 | .add( 9 | command("connect") 10 | .description("Connect to a server") 11 | .argument("host", { 12 | default: "example.com", 13 | prompt: true, 14 | }) 15 | .argument("port", { 16 | default: 443, 17 | prompt: true, 18 | }) 19 | .argument("tls", { 20 | default: true, 21 | prompt: true, 22 | }) 23 | .option("protocol", { 24 | default: "http", 25 | choices: ["http", "ftp", "imap", "ldap", "pop3"] as const, 26 | }) 27 | .option("timeout", { 28 | default: 60, 29 | }) 30 | .action(async ({ host, port, tls, protocol, timeout }) => { 31 | url = `${protocol}${tls && "s"}://${host}:${port}`; 32 | console.log(`Connecting to ${url} (timeout set to ${timeout}s)...`); 33 | app.options.prompt = `${host} > `; 34 | }), 35 | ) 36 | .add( 37 | command("disconnect") 38 | .description("Disconnect from a server") 39 | .action(async () => { 40 | if (!url) { 41 | throw new Error("Not connected"); 42 | } 43 | 44 | console.log(`Disconnecting from ${url}...`); 45 | app.options.prompt = "> "; 46 | url = null; 47 | }), 48 | ); 49 | 50 | app.runOrRepl(); 51 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | 9 | jobs: 10 | test: 11 | runs-on: ubuntu-latest 12 | strategy: 13 | matrix: 14 | node-version: 15 | - 18 16 | - 20 17 | - 22 18 | steps: 19 | - uses: actions/checkout@v4 20 | - uses: actions/setup-node@v4 21 | with: 22 | node-version: ${{ matrix.node-version }} 23 | cache: yarn 24 | - run: yarn install 25 | - run: yarn build 26 | - run: yarn test 27 | - uses: actions/upload-artifact@v4 28 | with: 29 | name: dist-${{ matrix.node-version }} 30 | path: dist 31 | 32 | coverage: 33 | needs: test 34 | runs-on: ubuntu-latest 35 | strategy: 36 | matrix: 37 | node-version: 38 | - 22 39 | steps: 40 | - uses: actions/checkout@v4 41 | - uses: actions/setup-node@v4 42 | with: 43 | node-version: ${{ matrix.node-version }} 44 | cache: yarn 45 | - run: yarn install 46 | - uses: actions/download-artifact@v4 47 | with: 48 | name: dist-${{ matrix.node-version }} 49 | path: dist 50 | - uses: paambaati/codeclimate-action@v6.0.0 51 | env: 52 | CC_TEST_REPORTER_ID: e1a2f8ecd90c13810c302d9cdfb4a26a5b79666e899c4f353e558416c168da0d 53 | with: 54 | coverageCommand: yarn test:unit --coverage 55 | -------------------------------------------------------------------------------- /examples/calculator.ts: -------------------------------------------------------------------------------- 1 | import { argument, command, program } from "../src/index.js"; 2 | 3 | type Args = { number: number[] }; 4 | 5 | const number = argument("number", { type: "number", variadic: true }); 6 | 7 | const makeOutput = 8 | (op: string, initial = (args: Args) => 0) => 9 | (args: Args) => 10 | args.number.reduce( 11 | (sum, arg) => eval(`${sum} ${op} ${arg}`), 12 | initial(args), 13 | ); 14 | 15 | program() 16 | .description("calculator") 17 | .add( 18 | command(["add"]) 19 | .description("Add one or more numbers to 0") 20 | .add(number) 21 | .action(makeOutput("+")), 22 | ) 23 | .add( 24 | command(["sub", "subtract"]) 25 | .description("Subtract one or more numbers from 0") 26 | .add(number) 27 | .action(makeOutput("-")), 28 | ) 29 | .add( 30 | command(["mul", "multiply"]) 31 | .description("Multiply one or more numbers from 1") 32 | .add(number) 33 | .action(makeOutput("*", () => 1)), 34 | ) 35 | .add( 36 | command(["div", "divide"]) 37 | .description("Divide two or more numbers in order") 38 | .add(number) 39 | .action(makeOutput("/", (args) => args.number[0] * args.number[0])), 40 | ) 41 | .add( 42 | command(["pow", "power"]) 43 | .description("Raise numbers to a power in order") 44 | .add(number) 45 | .action(makeOutput("**", () => 1)), 46 | ) 47 | .runOrRepl() 48 | .then(console.log) 49 | .catch(console.error); 50 | -------------------------------------------------------------------------------- /src/option.ts: -------------------------------------------------------------------------------- 1 | import { Argv, Options as BaseOptions } from "yargs"; 2 | import { BaseArg, BaseArgOptions } from "./baseArg.js"; 3 | 4 | // We ignore some not-so-common use cases from the type to make using this 5 | // library easier. They could still be used at runtime but won't be documented 6 | // here. 7 | type IgnoreOptions = 8 | | "array" 9 | | "boolean" 10 | | "conflicts" 11 | | "config" 12 | | "configParser" 13 | | "count" 14 | | "defaultDescription" 15 | | "demand" 16 | | "demandOption" 17 | | "deprecate" 18 | | "desc" 19 | | "describe" 20 | | "global" 21 | | "group" 22 | | "hidden" 23 | | "implies" 24 | | "nargs" 25 | | "normalize" 26 | | "number" 27 | | "require" 28 | | "requiresArg" 29 | | "skipValidation" 30 | | "string" 31 | | "implies"; 32 | 33 | export interface OptionOptions 34 | extends Omit, 35 | BaseArgOptions { 36 | required?: true; 37 | } 38 | 39 | export function option(name: string) { 40 | return new Option(name); 41 | } 42 | 43 | export class Option extends BaseArg { 44 | protected options: OptionOptions = {}; 45 | 46 | constructor(name: string, options?: OptionOptions) { 47 | super(name); 48 | 49 | this.configure(options || {}); 50 | } 51 | 52 | configure(options: OptionOptions) { 53 | this.options = options; 54 | 55 | return this; 56 | } 57 | 58 | /** 59 | * Calls the option() method on the passed in yargs instance and returns 60 | * it. See http://yargs.js.org/docs/#api-positionalkey-opt 61 | */ 62 | toYargs(yargs: Argv) { 63 | return yargs.option(this.name, BaseArg.getYargsOptions(this.options)); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/history.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | import os from "os"; 3 | import { REPLServer } from "repl"; 4 | import { Program } from "./program.js"; 5 | 6 | export const HISTSIZE = 500; 7 | 8 | /** 9 | * Create new history instance. 10 | */ 11 | export function history(program: Program) { 12 | return new History(program); 13 | } 14 | 15 | export class History { 16 | private path: string; 17 | 18 | constructor(private program: Program) { 19 | this.path = this.program.options.historyFile!; 20 | 21 | this.program.on("run", (command) => this.push(command)); 22 | } 23 | 24 | /** 25 | * Add a new entry to the history file. 26 | */ 27 | public push(entry: string | readonly string[]) { 28 | if (Array.isArray(entry)) { 29 | entry = entry.join(" "); 30 | } 31 | 32 | // Truncate if needed and if possible 33 | try { 34 | const historyContents = fs.readFileSync(this.path, "utf8").split(os.EOL); 35 | if (historyContents.length > HISTSIZE) { 36 | fs.writeFileSync( 37 | this.path, 38 | historyContents.slice(historyContents.length - HISTSIZE).join(os.EOL), 39 | "utf8", 40 | ); 41 | } 42 | } catch (err) {} 43 | 44 | fs.appendFileSync(this.path, entry + os.EOL); 45 | } 46 | 47 | /** 48 | * Read the history file and hydrate the REPL server history. 49 | */ 50 | public hydrateReplServer(server: REPLServer) { 51 | // @ts-ignore 52 | if (typeof server.history !== "object") { 53 | return; 54 | } 55 | 56 | try { 57 | fs.readFileSync(this.path, "utf-8") 58 | .split(os.EOL) 59 | .reverse() 60 | .filter((line) => line.trim()) 61 | // @ts-ignore 62 | .map((line) => server.history.push(line)); 63 | } catch (err) { 64 | // Ignore history file read errors 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /tests/unit/program.spec.ts: -------------------------------------------------------------------------------- 1 | import mockArgv from "mock-argv"; 2 | import { command, program, Program, Repl } from "../../src/index.js"; 3 | 4 | jest.mock("../../src/repl", () => { 5 | return { 6 | repl: jest.fn().mockImplementation(() => { 7 | return new MockedRepl(); 8 | }), 9 | Repl: jest.fn().mockImplementation(() => { 10 | return MockedRepl; 11 | }), 12 | }; 13 | }); 14 | 15 | // Repl mock 16 | const replStartFn = jest.fn(); 17 | class MockedRepl { 18 | start = replStartFn; 19 | attachHistory = jest.fn(); 20 | } 21 | 22 | beforeEach(() => { 23 | const MockedRepl = jest.mocked(Repl); 24 | MockedRepl.mockClear(); 25 | }); 26 | 27 | test("program should return new Program object", () => { 28 | expect(program()).toBeInstanceOf(Program); 29 | }); 30 | 31 | test("program executes command", async () => { 32 | const app = program().add( 33 | command("test").action(() => { 34 | return "foo"; 35 | }), 36 | ); 37 | await expect(app.run("test")).resolves.toBe("foo"); 38 | }); 39 | 40 | test("program executes argv", async () => { 41 | await mockArgv(["test"], async () => { 42 | const app = program().add( 43 | command("test").action(() => { 44 | return "foo"; 45 | }), 46 | ); 47 | await expect(app.run()).resolves.toBe("foo"); 48 | }); 49 | }); 50 | 51 | test("program passes parserConfiguration", async () => { 52 | await mockArgv(["test", "--test-field", "1"], async () => { 53 | const app = program({ parserConfiguration: { "strip-dashed": true } }).add( 54 | command("test") 55 | .option("test-field") 56 | .action((args) => { 57 | return JSON.stringify(args); 58 | }), 59 | ); 60 | await expect(app.run()).resolves.toBe('{"testField":1}'); 61 | }); 62 | }); 63 | 64 | test("program starts repl", async () => { 65 | const app = program(); 66 | expect(app.repl()).toBeInstanceOf(MockedRepl); 67 | expect(replStartFn).toHaveBeenCalled(); 68 | }); 69 | -------------------------------------------------------------------------------- /examples/errors.ts: -------------------------------------------------------------------------------- 1 | import { command, program } from "../src/index.js"; 2 | 3 | const app = program(); 4 | 5 | const syncOk = command("sync") 6 | .description("Print sync message") 7 | .action(() => "ok/sync"); 8 | 9 | const asyncOk = command("async") 10 | .description("Print async message") 11 | .action(async () => "ok/async"); 12 | 13 | const syncNok = command("sync") 14 | .description("Throw sync error") 15 | .action(() => { 16 | throw new Error("nok/sync"); 17 | }); 18 | 19 | const asyncNok = command("async") 20 | .description("Throw async error") 21 | .action(async () => { 22 | throw new Error("nok/async"); 23 | }); 24 | 25 | const syncValidation = command("sync") 26 | .description("Test validation error with sync handler") 27 | .argument("required") 28 | .action(() => "call without arguments"); 29 | 30 | const asyncValidation = command("async") 31 | .description("Test validation error with async handler") 32 | .argument("required") 33 | .action(async () => "call without arguments"); 34 | 35 | const noHandler = command("no_handler").description( 36 | "Test missing command handler", 37 | ); 38 | 39 | // Say bye 40 | const success = (resolved: unknown) => console.log("resolved:", resolved); 41 | 42 | // Print error message only (omit stack trace) and exit with a meaningful status 43 | const fail = (error: any) => { 44 | console.error("rejected:", String(error)); 45 | 46 | if (!app.isRepl()) { 47 | process.exit(42); 48 | } 49 | }; 50 | 51 | app 52 | .add( 53 | command("ok") 54 | .description("Print message to stdout from handler") 55 | .add(syncOk) 56 | .add(asyncOk), 57 | ) 58 | .add( 59 | command("nok") 60 | .description("Throw various errors") 61 | .add(syncNok) 62 | .add(asyncNok), 63 | ) 64 | .add( 65 | command("validation") 66 | .description("Validation errors") 67 | .add(syncValidation) 68 | .add(asyncValidation), 69 | ) 70 | .add(noHandler) 71 | .runOrRepl() 72 | .then(success) 73 | .catch(fail); 74 | -------------------------------------------------------------------------------- /src/argument.ts: -------------------------------------------------------------------------------- 1 | import { Argv, PositionalOptions } from "yargs"; 2 | import { BaseArg, BaseArgOptions } from "./baseArg.js"; 3 | 4 | // We ignore some not-so-common use cases from the type to make using this 5 | // library easier. They could still be used at runtime but won't be documented 6 | // here. 7 | type IgnoreOptions = 8 | | "array" 9 | | "conflicts" 10 | | "demandOption" 11 | | "desc" 12 | | "describe" 13 | | "implies" 14 | | "normalize"; 15 | 16 | export interface ArgumentOptions 17 | extends Omit, 18 | BaseArgOptions { 19 | optional?: true; 20 | variadic?: true; 21 | } 22 | 23 | export function argument(name: string, options?: ArgumentOptions) { 24 | return new Argument(name, options); 25 | } 26 | 27 | export const defaultOptions: ArgumentOptions = { type: "string" }; 28 | 29 | export class Argument extends BaseArg { 30 | protected options: ArgumentOptions = {}; 31 | 32 | constructor(name: string, options?: ArgumentOptions) { 33 | super(name); 34 | 35 | this.configure(options || {}); 36 | } 37 | 38 | configure(options: ArgumentOptions) { 39 | this.options = { type: "string", ...options }; 40 | 41 | if (this.isPromptable()) { 42 | this.options = { optional: true, ...this.options }; 43 | } 44 | 45 | return this; 46 | } 47 | 48 | isOptional() { 49 | return this.options.optional; 50 | } 51 | 52 | isVariadic() { 53 | return this.options.variadic; 54 | } 55 | 56 | /** 57 | * Returns the formatted positional argument to be used in a command. See 58 | * https://github.com/yargs/yargs/blob/master/docs/advanced.md#positional-arguments 59 | */ 60 | toCommand() { 61 | if (this.isVariadic()) { 62 | return `[${this.name}..]`; 63 | } 64 | if (this.isOptional()) { 65 | return `[${this.name}]`; 66 | } 67 | return `<${this.name}>`; 68 | } 69 | 70 | /** 71 | * Calls the positional() method on the passed in yargs instance and returns 72 | * it. See http://yargs.js.org/docs/#api-positionalkey-opt 73 | */ 74 | toYargs(yargs: Argv) { 75 | return yargs.positional(this.name, BaseArg.getYargsOptions(this.options)); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /tests/unit/history.spec.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | import os from "os"; 3 | import path from "path"; 4 | import { 5 | command, 6 | history, 7 | History, 8 | HISTSIZE, 9 | program, 10 | } from "../../src/index.js"; 11 | 12 | // https://stackoverflow.com/a/52560084/938297 13 | function tmpFile( 14 | name = "tmp_file", 15 | data = "", 16 | encoding: BufferEncoding = "utf8", 17 | ) { 18 | return new Promise((resolve, reject) => { 19 | const tempPath = path.join(os.tmpdir(), "bandersnatch-"); 20 | fs.mkdtemp(tempPath, (err, folder) => { 21 | if (err) return reject(err); 22 | 23 | const file_name = path.join(folder, name); 24 | 25 | fs.writeFile(file_name, data, encoding, (error_file) => { 26 | if (error_file) return reject(error_file); 27 | 28 | resolve(file_name); 29 | }); 30 | }); 31 | }); 32 | } 33 | 34 | test("history should return new History object", () => { 35 | const app = program(); 36 | 37 | expect(history(app)).toBeInstanceOf(History); 38 | }); 39 | 40 | test("commands should end up in history file", async () => { 41 | const historyFile = await tmpFile("history_file"); 42 | const app = program({ historyFile }).add(command("test").action(() => {})); 43 | 44 | await app.run("test"); 45 | 46 | expect(fs.readFileSync(historyFile, "utf8")).toBe("test" + os.EOL); 47 | }); 48 | 49 | test("history file should be truncated", async () => { 50 | const historyFile = await tmpFile( 51 | "history_file", 52 | [...Array(HISTSIZE).keys()].join(os.EOL) + os.EOL, 53 | ); 54 | const app = program({ historyFile }).add(command("test").action(() => {})); 55 | 56 | await app.run("test"); 57 | 58 | expect(fs.readFileSync(historyFile, "utf8")).toBe( 59 | [...Array(HISTSIZE).keys()].slice(1).join(os.EOL) + 60 | os.EOL + 61 | "test" + 62 | os.EOL, 63 | ); 64 | }); 65 | 66 | test("commands should not end up in history file when disabled", async () => { 67 | const historyFile = await tmpFile("history_file"); 68 | const app = program({ historyFile: null }).add( 69 | command("test").action(() => {}), 70 | ); 71 | 72 | await app.run("test"); 73 | 74 | expect(fs.readFileSync(historyFile, "utf8")).toBe(""); 75 | }); 76 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bandersnatch", 3 | "version": "2.0.1", 4 | "description": "Simple TypeScript CLI / REPL framework", 5 | "keywords": [ 6 | "cli", 7 | "args", 8 | "argv", 9 | "parser", 10 | "terminal", 11 | "console", 12 | "program", 13 | "command", 14 | "argument", 15 | "option" 16 | ], 17 | "repository": "github:hongaar/bandersnatch", 18 | "license": "MIT", 19 | "author": "Joram van den Boezem ", 20 | "sideEffects": false, 21 | "type": "module", 22 | "exports": { 23 | "types": "./dist/types/index.d.ts", 24 | "import": "./dist/esm/index.js", 25 | "require": "./dist/cjs/index.cjs" 26 | }, 27 | "main": "dist/cjs/index.cjs", 28 | "types": "dist/types/index.d.ts", 29 | "files": [ 30 | "dist" 31 | ], 32 | "scripts": { 33 | "build": "yarn clean && yarn build:cjs && yarn build:esm", 34 | "build:cjs": "tsc --project tsconfig.build.json --module commonjs --outDir dist/cjs && yarn convert-extension cjs dist/cjs/ && rm dist/cjs/*.map", 35 | "build:esm": "tsc --project tsconfig.build.json --module es6 --outDir dist/esm", 36 | "clean": "rm -rf dist", 37 | "doctoc": "doctoc README.md", 38 | "format": "yarn format:code && yarn format:toc && yarn format:todos", 39 | "format:check": "prettier --check --ignore-unknown .", 40 | "format:code": "prettier --write --ignore-unknown .", 41 | "format:toc": "doctoc README.md", 42 | "format:todos": "leasot --exit-nicely --reporter markdown --ignore \"**/node_modules\" \"**/*.ts\" > TODO.md", 43 | "release": "semantic-release", 44 | "start": "node --loader ts-node/esm", 45 | "test": "yarn test:unit && yarn test:types && yarn test:smoke", 46 | "test:smoke": "./tests/smoke/run.sh", 47 | "test:types": "tsd", 48 | "test:unit": "jest", 49 | "watch:cjs": "yarn build:cjs --watch", 50 | "watch:esm": "yarn build:esm --watch" 51 | }, 52 | "lint-staged": { 53 | "*": "prettier --write --ignore-unknown" 54 | }, 55 | "dependencies": { 56 | "@types/yargs": "17.0.32", 57 | "enquirer": "^2.3.6", 58 | "string-argv": "^0.3.1", 59 | "typed-emitter": "^2.1.0", 60 | "yargs": "^17.5.1" 61 | }, 62 | "devDependencies": { 63 | "@semantic-release/changelog": "6.0.3", 64 | "@semantic-release/git": "10.0.1", 65 | "@types/jest": "29.5.12", 66 | "@types/node": "20.12.7", 67 | "convert-extension": "0.3.0", 68 | "doctoc": "2.2.1", 69 | "husky": "9.0.11", 70 | "jest": "29.7.0", 71 | "leasot": "13.3.0", 72 | "lint-staged": "15.2.2", 73 | "mock-argv": "2.0.8", 74 | "prettier": "3.2.5", 75 | "semantic-release": "23.0.8", 76 | "semantic-release-yarn": "3.0.2", 77 | "ts-jest": "29.1.2", 78 | "ts-node": "10.9.2", 79 | "tsd": "0.31.0", 80 | "typescript": "5.4.5" 81 | }, 82 | "packageManager": "yarn@3.5.0", 83 | "engines": { 84 | "node": ">=18" 85 | }, 86 | "moker": { 87 | "plugins": [ 88 | "typescript", 89 | "github-actions", 90 | "todos", 91 | "doctoc", 92 | "husky", 93 | "jest", 94 | "lint-staged", 95 | "prettier", 96 | "semantic-release", 97 | "dependabot", 98 | "devcontainer" 99 | ] 100 | }, 101 | "tsd": { 102 | "directory": "tests/types" 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /examples/types.ts: -------------------------------------------------------------------------------- 1 | import { command, program } from "../src/index.js"; 2 | 3 | function printArgs(args: T) { 4 | console.log("Args are", args); 5 | } 6 | 7 | /** 8 | * Keep in mind that argument/option types are not validated at runtime. 9 | * For example, when providing a default value with type boolean, it can be set 10 | * to a string value at runtime. 11 | */ 12 | 13 | const string = command("string") 14 | .argument("arg1", { description: "Required string argument" }) 15 | .argument("arg2", { optional: true, description: "Optional string argument" }) 16 | .argument("arg3", { variadic: true, description: "Variadic string argument" }) 17 | .option("opt1", { type: "string", description: "String option" }) 18 | .option("opt2", { 19 | default: "foo", 20 | description: "String option with default", 21 | }) 22 | .action(printArgs); 23 | 24 | const number = command("number") 25 | .argument("arg1", { type: "number", description: "Required number argument" }) 26 | .argument("arg2", { 27 | type: "number", 28 | optional: true, 29 | description: "Optional number argument", 30 | }) 31 | .argument("arg3", { 32 | type: "number", 33 | variadic: true, 34 | description: "Variadic number argument", 35 | }) 36 | .option("opt1", { type: "number", description: "Number option" }) 37 | .option("opt2", { default: 100, description: "Number option with default" }) 38 | .action(printArgs); 39 | 40 | const boolean = command("boolean") 41 | .argument("arg1", { 42 | type: "boolean", 43 | description: "Required boolean argument", 44 | }) 45 | .argument("arg2", { 46 | type: "boolean", 47 | optional: true, 48 | description: "Optional boolean argument", 49 | }) 50 | .argument("arg3", { 51 | type: "boolean", 52 | variadic: true, 53 | description: "Variadic boolean argument", 54 | }) 55 | .option("opt1", { type: "boolean", description: "Boolean option" }) 56 | .option("opt2", { 57 | default: false, 58 | description: "Boolean option with default", 59 | }) 60 | .action(printArgs); 61 | 62 | const choices = command("choices") 63 | .argument("arg", { 64 | description: "Argument with choices", 65 | choices: ["foo", "bar"] as const, 66 | }) 67 | .option("opt", { 68 | description: "Option with choices", 69 | choices: ["option1", "option2"] as const, 70 | default: "option3", 71 | }) 72 | .action(printArgs); 73 | 74 | const defaultValues = command("default") 75 | .argument("arg", { 76 | description: "Optional argument with default value", 77 | default: 5, 78 | optional: true, 79 | }) 80 | .option("opt", { description: "Default value", default: true }) 81 | .action(printArgs); 82 | 83 | const constraints = command("constraint") 84 | .argument("arg", { 85 | description: "Required argument", 86 | }) 87 | .argument("optionalArg", { 88 | description: "Required argument", 89 | optional: true, 90 | }) 91 | .option("opt", { description: "Required option", required: true }) 92 | .option("opt1a", { 93 | description: "Also requires option 1a", 94 | requires: "opt1b", 95 | }) 96 | .option("opt1b", { 97 | description: "Also requires option 1b", 98 | requires: "opt1a", 99 | }) 100 | .option("opt2", { description: "Forbids option 1a", excludes: "opt1a" }) 101 | .option("opt3", { 102 | description: "Also requires optionalArg", 103 | requires: "optionalArg", 104 | }) 105 | 106 | .action(printArgs); 107 | 108 | const app = program() 109 | .description("All argument and option types") 110 | .add(string) 111 | .add(number) 112 | .add(boolean) 113 | .add(choices) 114 | .add(defaultValues) 115 | .add(constraints); 116 | 117 | app.runOrRepl(); 118 | -------------------------------------------------------------------------------- /src/baseArg.ts: -------------------------------------------------------------------------------- 1 | import type { InferredOptionType, Options, PositionalOptions } from "yargs"; 2 | import type { ArgumentOptions } from "./argument.js"; 3 | import type { OptionOptions } from "./option.js"; 4 | 5 | export interface BaseArgOptions { 6 | prompt?: true | string; 7 | requires?: string | string[]; 8 | excludes?: string | string[]; 9 | } 10 | 11 | // prettier-ignore 12 | export type InferArgType = 13 | // Default number 14 | O extends { default: number } ? number : 15 | // Optional number 16 | O extends { type: 'number', optional: true } ? number | undefined : 17 | // Variadic number 18 | O extends { type: 'number', variadic: true } ? Array : 19 | // Number 20 | O extends { type: 'number' } ? number : 21 | // Default boolean 22 | O extends { default: boolean } ? boolean : 23 | // Optional boolean 24 | O extends { type: 'boolean', optional: true } ? boolean | undefined : 25 | // Variadic boolean 26 | O extends { type: 'boolean', variadic: true } ? Array : 27 | // Boolean 28 | O extends { type: 'boolean' } ? boolean : 29 | // Choices with array type 30 | O extends { choices: ReadonlyArray; type: 'array' } ? C[] : 31 | // Choices with array default 32 | O extends { choices: ReadonlyArray, default: ReadonlyArray } ? C[] : 33 | // Choices, variadic 34 | O extends { choices: ReadonlyArray; variadic: true } ? C[] : 35 | // Choices, optional 36 | O extends { choices: ReadonlyArray, optional: true } ? C | undefined : 37 | // Prefer choices over default 38 | O extends { choices: ReadonlyArray } ? C : 39 | // Default string 40 | O extends { default: string } ? string : 41 | // Optional string 42 | O extends { optional: true } ? string | undefined : 43 | // Variadic string 44 | O extends { variadic: true } ? Array : 45 | // Allow fallback type 46 | unknown extends InferredOptionType ? F : 47 | // Base type from yargs 48 | InferredOptionType 49 | 50 | export class BaseArg { 51 | protected name: string; 52 | protected options: ArgumentOptions | OptionOptions = {}; 53 | 54 | constructor(name: string) { 55 | this.name = name; 56 | } 57 | 58 | /** 59 | * Set the argument/option description. 60 | */ 61 | public description(description: string) { 62 | this.options.description = description; 63 | return this; 64 | } 65 | 66 | /** 67 | * Whether this argument/option can be interactive. 68 | */ 69 | isPromptable() { 70 | return !!this.options.prompt; 71 | } 72 | 73 | /** 74 | * Returns the prompt line. 75 | */ 76 | getPrompt() { 77 | return typeof this.options.prompt === "string" 78 | ? this.options.prompt 79 | : this.options.description 80 | ? this.options.description 81 | : this.name; 82 | } 83 | 84 | /** 85 | * Get default value, if specified. 86 | */ 87 | getDefault() { 88 | return this.options.default; 89 | } 90 | 91 | /** 92 | * Get possible values, is specified. 93 | * @todo See if we can add this to autocompleter 94 | */ 95 | getChoices() { 96 | return this.options.choices; 97 | } 98 | 99 | /** 100 | * Get type, is specified. 101 | */ 102 | getType() { 103 | return this.options.type; 104 | } 105 | 106 | /** 107 | * Returns the argument/option identifier. 108 | */ 109 | getName() { 110 | return this.name; 111 | } 112 | 113 | /** 114 | * Returns the argument/option description. 115 | */ 116 | getDescription() { 117 | return this.options.description; 118 | } 119 | 120 | /** 121 | * Returns the argument/option options. 122 | */ 123 | getOptions() { 124 | return this.options; 125 | } 126 | 127 | protected static getYargsOptions(options: T) { 128 | const { requires, excludes, ...rest } = options; 129 | 130 | return { 131 | implies: requires, 132 | conflicts: excludes, 133 | ...rest, 134 | }; 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/repl.ts: -------------------------------------------------------------------------------- 1 | import { CompleterResult } from "readline"; 2 | import nodeRepl, { REPLServer } from "repl"; 3 | import { parseArgsStringToArgv } from "string-argv"; 4 | import { Context } from "vm"; 5 | import { autocompleter, Autocompleter } from "./autocompleter.js"; 6 | import { History } from "./history.js"; 7 | import { Program } from "./program.js"; 8 | 9 | /** 10 | * Create new REPL instance. 11 | */ 12 | export function repl(program: Program) { 13 | return new Repl(program); 14 | } 15 | 16 | export class Repl { 17 | private server?: REPLServer; 18 | private history?: History; 19 | private autocompleter: Autocompleter; 20 | 21 | private successHandler: (value?: unknown) => void = () => {}; 22 | private errorHandler: (reason?: any) => void = (reason) => 23 | console.error(reason); 24 | 25 | constructor(private program: Program) { 26 | this.autocompleter = autocompleter(program); 27 | 28 | // Stop the server to avoid eval'ing stdin from prompts 29 | this.program.on("run", () => { 30 | this.stop(); 31 | }); 32 | } 33 | 34 | attachHistory(history: History) { 35 | this.history = history; 36 | } 37 | 38 | /** 39 | * Start the REPL server. This method may change at any time, not 40 | * intended for public use. 41 | * 42 | * @private 43 | */ 44 | public async start() { 45 | this.server = nodeRepl.start({ 46 | prompt: this.program.options.prompt, 47 | eval: this.eval.bind(this), 48 | completer: this.completer.bind(this), 49 | ignoreUndefined: true, 50 | }); 51 | 52 | // Setup history 53 | this.history?.hydrateReplServer(this.server); 54 | 55 | // Fixes bug with hidden cursor after enquirer prompt, this is identical to 56 | // the enquirer method Prompt.cursorShow() 57 | process.stdout.write(`\u001b[?25h`); 58 | } 59 | 60 | public stop() { 61 | this.server?.close(); 62 | } 63 | 64 | /** 65 | * Emulates promise.then, but saves the callback instead to be executed on 66 | * each command which resolves. 67 | */ 68 | public then(cb: (value?: unknown) => void) { 69 | this.successHandler = cb; 70 | return this; 71 | } 72 | 73 | /** 74 | * Emulates promise.catch, but saves the callback instead to be executed on 75 | * each command which rejects. 76 | */ 77 | public catch(cb: (reason?: any) => void) { 78 | this.errorHandler = cb; 79 | return this; 80 | } 81 | 82 | /** 83 | * Invokes the autocompleter and passes results to the REPL server. 84 | */ 85 | private async completer( 86 | line: string, 87 | cb: (err?: null | Error, result?: CompleterResult) => void, 88 | ) { 89 | function addSpace(str: string) { 90 | return `${str} `; 91 | } 92 | const argv = parseArgsStringToArgv(line); 93 | const current = argv.slice(-1).toString(); 94 | const completions = (await this.autocompleter.completions(argv)).map( 95 | addSpace, 96 | ); 97 | let hits = completions.filter((completion) => 98 | completion.startsWith(current), 99 | ); 100 | 101 | // Show all completions if none found 102 | cb(null, [hits.length ? hits : completions, current]); 103 | } 104 | 105 | /** 106 | * Uses the bandersnatch program to run commands received by the REPL server. 107 | */ 108 | private async eval( 109 | line: string, 110 | context: Context, 111 | file: string, 112 | cb: (err: Error | null, result: any) => void, 113 | ) { 114 | try { 115 | const result = await this.program.run(line.trim()); 116 | this.successHandler(result); 117 | } catch (error) { 118 | this.errorHandler(error); 119 | } 120 | 121 | // Since we stop the server when a command is executed (by listening to the 122 | // 'run' event in the constructor), we need to start a new instance when the 123 | // command is finished. 124 | this.start(); 125 | 126 | // The result passed to this function is printed by the Node REPL server, 127 | // but we don't want to use that, so we pass undefined instead. 128 | cb(null, undefined); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /tests/unit/command.spec.ts: -------------------------------------------------------------------------------- 1 | import Enquirer from "enquirer"; 2 | import { command, Command, program } from "../../src/index.js"; 3 | 4 | jest.mock("enquirer", () => { 5 | return { 6 | prompt: jest.fn(), 7 | }; 8 | }); 9 | 10 | const prompt = Enquirer.prompt as jest.Mock; 11 | 12 | let outputSpy: jest.MockInstance; 13 | let errorSpy: jest.MockInstance; 14 | 15 | beforeEach(() => { 16 | outputSpy = jest.spyOn(console, "log").mockImplementation(() => {}); 17 | errorSpy = jest.spyOn(console, "error").mockImplementation(() => {}); 18 | prompt.mockClear(); 19 | }); 20 | 21 | afterEach(() => { 22 | outputSpy.mockRestore(); 23 | errorSpy.mockRestore(); 24 | }); 25 | 26 | test("command should return new Command object", () => { 27 | expect(command("test")).toBeInstanceOf(Command); 28 | }); 29 | 30 | test("with description", async () => { 31 | const cmd = command("test").description("foo description"); 32 | await program().add(cmd).run("help"); 33 | expect(outputSpy.mock.calls[0][0]).toContain("foo description"); 34 | }); 35 | 36 | test("variadic argument must be last", () => { 37 | const cmd = command("test").argument("var", { variadic: true }); 38 | expect(() => { 39 | cmd.argument("reg"); 40 | }).toThrowErrorMatchingSnapshot(); 41 | }); 42 | 43 | test("handler is required", async () => { 44 | let error; 45 | try { 46 | await program().add(command("test")).run("test"); 47 | } catch (err) { 48 | error = err; 49 | } 50 | expect(error).toMatchSnapshot(); 51 | }); 52 | 53 | test("sync handler should be executed", (done) => { 54 | const cmd = command("test").action(() => { 55 | done(); 56 | }); 57 | const app = program().add(cmd); 58 | app.run("test"); 59 | }); 60 | 61 | test("async handler should be executed", async () => { 62 | let handled = false; 63 | const cmd = command("test").action(async () => { 64 | handled = true; 65 | }); 66 | const app = program().add(cmd); 67 | await app.run("test"); 68 | expect(handled).toBeTruthy(); 69 | }); 70 | 71 | test("hidden", async () => { 72 | const foo = command("foo").hidden(); 73 | await program().add(foo).run("help"); 74 | expect(outputSpy.mock.calls[0][0]).not.toContain("foo"); 75 | }); 76 | 77 | // Argument tests 78 | test("default argument", async () => { 79 | const cmd = command("test") 80 | .argument("foo") 81 | .action((args) => { 82 | expect(args.foo).toBe("bar"); 83 | }); 84 | await program().add(cmd).run("test bar"); 85 | }); 86 | 87 | test("argument with description", async () => { 88 | const cmd = command("test").argument("foo").description("bar description"); 89 | await program().add(cmd).run("test --help"); 90 | expect(outputSpy.mock.calls[0][0]).toContain("bar description"); 91 | }); 92 | 93 | test("prompt for argument", async () => { 94 | prompt.mockReturnValueOnce(Promise.resolve({ foo: "bar" })); 95 | const cmd = command("test") 96 | .argument("foo", { prompt: true }) 97 | .action((args) => { 98 | expect(args.foo).toBe("bar"); 99 | }); 100 | await program().add(cmd).run("test"); 101 | expect(prompt).toHaveBeenCalled(); 102 | }); 103 | 104 | // Option tests 105 | test("default option", async () => { 106 | const cmd = command("test") 107 | .option("foo") 108 | .action((args) => { 109 | expect(args.foo).toBe("bar"); 110 | }); 111 | await program().add(cmd).run("test --foo bar"); 112 | }); 113 | 114 | test("option with description", async () => { 115 | const cmd = command("test").option("foo").description("bar description"); 116 | await program().add(cmd).run("test --help"); 117 | }); 118 | 119 | test("prompt for option", async () => { 120 | prompt.mockReturnValueOnce(Promise.resolve({ foo: "bar" })); 121 | const cmd = command("test") 122 | .option("foo", { prompt: true }) 123 | .action((args) => { 124 | expect(args.foo).toBe("bar"); 125 | }); 126 | await program().add(cmd).run("test"); 127 | expect(prompt).toHaveBeenCalled(); 128 | }); 129 | 130 | // Sub-command tests 131 | test("sub-commands", async () => { 132 | const subCmd = command("sub") 133 | .argument("foo") 134 | .action((args) => { 135 | expect(args.foo).toBe("bar"); 136 | }); 137 | const cmd = command("test").add(subCmd); 138 | await program().add(cmd).run("test sub bar"); 139 | }); 140 | -------------------------------------------------------------------------------- /tests/types/command.test-d.ts: -------------------------------------------------------------------------------- 1 | import { expectType } from "tsd"; 2 | import { Command, command } from "../../src/command"; 3 | 4 | const cmd = command(); 5 | 6 | expectType(cmd); 7 | 8 | // Chainable methods 9 | expectType(cmd.description("foo")); 10 | expectType(cmd.hidden()); 11 | expectType(cmd.add(cmd)); 12 | expectType(cmd.default()); 13 | expectType(cmd.action(() => {})); 14 | 15 | // String argument types 16 | cmd.argument("foo").action((args) => { 17 | // No options 18 | expectType<{ foo: string }>(args); 19 | }); 20 | cmd.argument("foo", { default: "bar" }).action((args) => { 21 | // With default 22 | expectType<{ foo: string }>(args); 23 | }); 24 | cmd.argument("foo", { variadic: true }).action((args) => { 25 | // Variadic 26 | expectType<{ foo: string[] }>(args); 27 | }); 28 | cmd.argument("foo", { optional: true }).action((args) => { 29 | // Optional 30 | expectType<{ foo: string | undefined }>(args); 31 | }); 32 | cmd.argument("foo", { optional: true, default: "bar" }).action((args) => { 33 | // Optional with default 34 | expectType<{ foo: string }>(args); 35 | }); 36 | cmd.argument("foo", { choices: ["bar", "baz"] as const }).action((args) => { 37 | // Enum 38 | expectType<{ foo: "bar" | "baz" }>(args); 39 | }); 40 | cmd 41 | .argument("foo", { choices: ["bar", "baz"] as const, optional: true }) 42 | .action((args) => { 43 | // Optional enum 44 | expectType<{ foo: "bar" | "baz" | undefined }>(args); 45 | }); 46 | cmd 47 | .argument("foo", { choices: ["bar", "baz"] as const, variadic: true }) 48 | .action((args) => { 49 | // Variadic enum 50 | expectType<{ foo: ("bar" | "baz")[] }>(args); 51 | }); 52 | 53 | // Numeric argument types 54 | cmd.argument("foo", { type: "number" }).action((args) => { 55 | // No options 56 | expectType<{ foo: number }>(args); 57 | }); 58 | cmd.argument("foo", { type: "number", default: 100 }).action((args) => { 59 | // With default 60 | expectType<{ foo: number }>(args); 61 | }); 62 | cmd.argument("foo", { default: 100 }).action((args) => { 63 | // Inferred from default 64 | expectType<{ foo: number }>(args); 65 | }); 66 | cmd.argument("foo", { type: "number", optional: true }).action((args) => { 67 | // Optional 68 | expectType<{ foo: number | undefined }>(args); 69 | }); 70 | cmd 71 | .argument("foo", { type: "number", optional: true, default: 100 }) 72 | .action((args) => { 73 | // Optional with default 74 | expectType<{ foo: number }>(args); 75 | }); 76 | cmd.argument("foo", { optional: true, default: 100 }).action((args) => { 77 | // Optional inferred from default 78 | expectType<{ foo: number }>(args); 79 | }); 80 | 81 | // Boolean argument types 82 | cmd.argument("foo", { type: "boolean" }).action((args) => { 83 | // No options 84 | expectType<{ foo: boolean }>(args); 85 | }); 86 | cmd.argument("foo", { type: "boolean", default: false }).action((args) => { 87 | // With default 88 | expectType<{ foo: boolean }>(args); 89 | }); 90 | cmd.argument("foo", { default: false }).action((args) => { 91 | // Inferred from default 92 | expectType<{ foo: boolean }>(args); 93 | }); 94 | cmd.argument("foo", { type: "boolean", optional: true }).action((args) => { 95 | // Optional 96 | expectType<{ foo: boolean | undefined }>(args); 97 | }); 98 | cmd 99 | .argument("foo", { type: "boolean", optional: true, default: false }) 100 | .action((args) => { 101 | // Optional with default 102 | expectType<{ foo: boolean }>(args); 103 | }); 104 | cmd.argument("foo", { optional: true, default: false }).action((args) => { 105 | // Optional inferred from default 106 | expectType<{ foo: boolean }>(args); 107 | }); 108 | 109 | // String option types 110 | cmd.option("foo").action((args) => { 111 | // Default type 112 | expectType<{ foo: unknown }>(args); 113 | }); 114 | cmd.option("foo", { type: "string" }).action((args) => { 115 | // Explicit string type 116 | expectType<{ foo: string | undefined }>(args); 117 | }); 118 | cmd.option("foo", { default: "string" }).action((args) => { 119 | // Implicit string type 120 | expectType<{ foo: string }>(args); 121 | }); 122 | cmd.option("foo", { type: "string", required: true }).action((args) => { 123 | // Required explicit string type 124 | expectType<{ foo: string }>(args); 125 | }); 126 | 127 | // @fixme: unspecified options are omitted by yargs but are always present in 128 | // the args. 129 | -------------------------------------------------------------------------------- /src/prompter.ts: -------------------------------------------------------------------------------- 1 | import Enquirer from "enquirer"; 2 | import { Argument } from "./argument.js"; 3 | import { Option } from "./option.js"; 4 | 5 | /** 6 | * Workaround for "The requested module 'enquirer' is a CommonJS module, which 7 | * may not support all module.exports as named exports." 8 | */ 9 | const prompt = Enquirer.prompt; 10 | 11 | /** 12 | * Extract PromptOptions from exported Enquirer types, since types are not 13 | * exported natively. 14 | * @todo Wait for upstream change to import types from enquirer 15 | * @link https://github.com/enquirer/enquirer/pull/258 16 | */ 17 | type EnquirerQuestion = Extract< 18 | Parameters[0], 19 | { initial?: any } 20 | >; 21 | 22 | // Another workaround: we need to add the `limit` option to ArrayPromptOptions. 23 | type ArrayPromptOptions = Extract & { 24 | limit?: number; 25 | }; 26 | 27 | type Question = EnquirerQuestion | ArrayPromptOptions; 28 | 29 | /** 30 | * Creates a new prompter instance 31 | */ 32 | export function prompter(baseArgs: Array, args: T) { 33 | return new Prompter(baseArgs, args); 34 | } 35 | 36 | export class Prompter { 37 | constructor( 38 | private baseArgs: Array, 39 | private args: T, 40 | ) {} 41 | 42 | public async prompt() { 43 | const questions = this.getQuestions(this.args); 44 | 45 | // Short circuit if there are no questions to ask. 46 | if (!questions.length) { 47 | return this.args; 48 | } 49 | 50 | // Ask questions and merge with passed in args. 51 | const answers = await prompt(questions); 52 | 53 | return { 54 | ...this.args, 55 | ...answers, 56 | }; 57 | } 58 | 59 | private getSelectLimit() { 60 | // Never more than what fits on the screen (+ some padding) or 20 61 | return Math.min(process.stdout.rows - 3, 20); 62 | } 63 | 64 | /** 65 | * Returns an array of arguments and options which should be prompted, because 66 | * they are promptable (`isPromptable()` returned true) and they are not 67 | * provided in the args passed in to this function. 68 | */ 69 | private getQuestions(args: T) { 70 | // If we need to prompt for things, fill questions array 71 | return this.baseArgs.reduce((questions, arg) => { 72 | const name = arg.getName(); 73 | const defaultValue = arg.getDefault(); 74 | const isPromptable = arg.isPromptable(); 75 | const presentInArgs = Object.constructor.hasOwnProperty.call(args, name); 76 | const isDefault = 77 | presentInArgs && 78 | typeof defaultValue !== "undefined" && 79 | defaultValue == (args as any)[name]; 80 | 81 | // We're going to assume that if an argument/option still has its default 82 | // value and it is promptable, it should get a prompt. 83 | if (isPromptable && (!presentInArgs || isDefault)) { 84 | // Detect the type of question we need to ask 85 | switch (true) { 86 | case typeof arg.getChoices() !== "undefined" && 87 | (arg.getType() === "array" || Array.isArray(defaultValue)): 88 | // Use checkbox question type 89 | questions.push({ 90 | name, 91 | type: "multiselect", 92 | message: arg.getPrompt(), 93 | initial: defaultValue, 94 | choices: arg.getChoices() as string[], 95 | limit: this.getSelectLimit(), 96 | }); 97 | break; 98 | 99 | case typeof arg.getChoices() !== "undefined": 100 | // Use list question type 101 | questions.push({ 102 | name, 103 | type: "autocomplete", 104 | message: arg.getPrompt(), 105 | initial: defaultValue, 106 | choices: arg.getChoices() as string[], 107 | limit: this.getSelectLimit(), 108 | }); 109 | break; 110 | 111 | case arg.getType() === "boolean" || typeof defaultValue === "boolean": 112 | // Use confirm question type 113 | questions.push({ 114 | name, 115 | type: "confirm", 116 | message: arg.getPrompt(), 117 | initial: defaultValue, 118 | }); 119 | break; 120 | 121 | default: 122 | // Use input question type as default 123 | questions.push({ 124 | name, 125 | type: "input", 126 | message: arg.getPrompt(), 127 | initial: defaultValue, 128 | }); 129 | } 130 | } 131 | 132 | return questions; 133 | }, [] as Question[]); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/command.ts: -------------------------------------------------------------------------------- 1 | import { ArgumentsCamelCase, Argv, CommandModule } from "yargs"; 2 | import { Argument, ArgumentOptions } from "./argument.js"; 3 | import { InferArgType } from "./baseArg.js"; 4 | import { Option, OptionOptions } from "./option.js"; 5 | import { prompter } from "./prompter.js"; 6 | 7 | export type YargsArguments = ArgumentsCamelCase; 8 | 9 | type CommandOptions = { 10 | /** 11 | * Command description. Can also be set by calling 12 | * `command(...).description(...)`. 13 | * 14 | * Defaults to `undefined`. 15 | */ 16 | description?: string; 17 | 18 | /** 19 | * When set to true, creates a hidden command not visible in autocomplete or 20 | * help output. Can also be set by calling `command(...).hidden()`. 21 | * 22 | * Default to `false`. 23 | */ 24 | hidden?: boolean; 25 | }; 26 | 27 | type CommandRunner = (command: string) => Promise; 28 | 29 | export interface HandlerFn { 30 | (args: T, commandRunner: CommandRunner): Promise | any; 31 | } 32 | 33 | function isArgument(obj: Argument | Option | Command): obj is Argument { 34 | return obj instanceof Argument; 35 | } 36 | 37 | function isOption(obj: Argument | Option | Command): obj is Option { 38 | return obj instanceof Option; 39 | } 40 | 41 | function isCommand(obj: Argument | Option | Command): obj is Command { 42 | return obj instanceof Command; 43 | } 44 | 45 | /** 46 | * Creates a new command, which can be added to a program. 47 | */ 48 | export function command( 49 | command?: string | string[], 50 | options: CommandOptions = {}, 51 | ) { 52 | return new Command(command, options); 53 | } 54 | 55 | export class Command { 56 | private args: (Argument | Option | Command)[] = []; 57 | private handler?: HandlerFn; 58 | private parent?: Command; 59 | 60 | constructor( 61 | private command?: string | string[], 62 | private options: CommandOptions = {}, 63 | ) {} 64 | 65 | /** 66 | * Set the command description. 67 | */ 68 | public description(description: string) { 69 | this.options.description = description; 70 | return this; 71 | } 72 | 73 | /** 74 | * Marks the command as hidden, i.e. not visible in autocomplete or help 75 | * output. 76 | */ 77 | public hidden() { 78 | this.options.hidden = true; 79 | return this; 80 | } 81 | 82 | /** 83 | * Adds a new positional argument to the command. 84 | * This is shorthand for `.add(argument(...))` 85 | */ 86 | public argument( 87 | name: K, 88 | options?: O, 89 | ) { 90 | this.add(new Argument(name, options)); 91 | 92 | return this as unknown as Command< 93 | T & { [key in K]: InferArgType } 94 | >; 95 | } 96 | 97 | /** 98 | * Adds a new option to the command. 99 | * This is shorthand for `.add(option(...))` 100 | */ 101 | public option( 102 | name: K, 103 | options?: O, 104 | ) { 105 | this.add(new Option(name, options)); 106 | 107 | return this as unknown as Command }>; 108 | } 109 | 110 | /** 111 | * This is the base method for adding arguments, options and commands, but it 112 | * doesn't provide type hints. Use `.argument()` and `.option()` instead. 113 | */ 114 | public add(obj: Argument | Option | Command) { 115 | if (isArgument(obj)) { 116 | // If last argument is variadic, we should not add more arguments. See 117 | // https://github.com/yargs/yargs/blob/master/docs/advanced.md#variadic-positional-arguments 118 | const allArguments = this.getArguments(); 119 | const lastArgument = allArguments[allArguments.length - 1]; 120 | 121 | if (lastArgument && lastArgument.isVariadic()) { 122 | throw new Error("Can't add more arguments."); 123 | } 124 | 125 | this.args.push(obj); 126 | } else if (isOption(obj)) { 127 | this.args.push(obj); 128 | } else if (isCommand(obj)) { 129 | obj.setParentCommand(this); 130 | this.args.push(obj); 131 | } else { 132 | console.log("add", { obj, command: this }); 133 | throw new Error("Not implemented."); 134 | } 135 | 136 | return this; 137 | } 138 | 139 | /** 140 | * Mark as the default command. 141 | */ 142 | public default() { 143 | this.command = "$0"; 144 | return this; 145 | } 146 | 147 | /** 148 | * Provide a function to execute when this command is invoked. 149 | */ 150 | public action(fn: HandlerFn) { 151 | this.handler = fn; 152 | return this; 153 | } 154 | 155 | /** 156 | * Set the parent command. This method may change at any time, not 157 | * intended for public use. 158 | * 159 | * @private 160 | */ 161 | public setParentCommand(parentCommand: Command) { 162 | this.parent = parentCommand; 163 | } 164 | 165 | private getArguments() { 166 | return this.args.filter(isArgument); 167 | } 168 | 169 | private getOptions() { 170 | return this.args.filter(isOption); 171 | } 172 | 173 | private getCommands() { 174 | return this.args.filter(isCommand); 175 | } 176 | 177 | /** 178 | * Returns a fully qualified command name (including parent command names). 179 | */ 180 | private getFqn(): string { 181 | if (!this.command) { 182 | throw new Error("Can't get command FQN for default commands."); 183 | } 184 | 185 | const command = Array.isArray(this.command) 186 | ? this.command[0] 187 | : this.command; 188 | 189 | if (this.parent) { 190 | return `${this.parent.getFqn()} ${command}`; 191 | } 192 | 193 | return command; 194 | } 195 | 196 | /** 197 | * Calls the command() method on the passed in yargs instance and returns it. 198 | * Takes command runner. 199 | * See https://github.com/yargs/yargs/blob/master/docs/advanced.md#providing-a-command-module 200 | */ 201 | public toYargs(yargs: Argv, commandRunner: CommandRunner) { 202 | return yargs.command(this.toModule(commandRunner)); 203 | } 204 | 205 | /** 206 | * Returns a yargs module for this command. Takes command runner, which is 207 | * passed down to getHandler and getBuilder functions. 208 | */ 209 | private toModule(commandRunner: CommandRunner) { 210 | const module: CommandModule<{}, T> = { 211 | command: this.toYargsCommand(), 212 | aliases: [], 213 | describe: this.options.hidden ? false : this.options.description || "", 214 | builder: this.getBuilder(commandRunner), 215 | // @ts-ignore Our handler returns a different type than void 216 | handler: this.getHandler(commandRunner), 217 | }; 218 | return module; 219 | } 220 | 221 | /** 222 | * Returns a formatted command which can be used in the `command()` function 223 | * of yargs. 224 | */ 225 | private toYargsCommand() { 226 | if (!this.command) { 227 | throw new Error("Command name must be set"); 228 | } 229 | 230 | const args = this.getArguments() 231 | .map((arg) => arg.toCommand()) 232 | .join(" "); 233 | 234 | if (args !== "") { 235 | return Array.isArray(this.command) 236 | ? [`${this.command[0]} ${args}`, ...this.command.slice(1)] 237 | : `${this.command} ${args}`; 238 | } 239 | 240 | return this.command; 241 | } 242 | 243 | /** 244 | * Returns the builder function to be used with `yargs.command()`. Takes 245 | * command runner. 246 | */ 247 | private getBuilder(commandRunner: CommandRunner) { 248 | return (yargs: Argv) => { 249 | // Call toYargs on each argument and option to add it to the command. 250 | yargs = [...this.getArguments(), ...this.getOptions()].reduce( 251 | (yargs, arg) => arg.toYargs(yargs), 252 | yargs, 253 | ); 254 | // Call toYargs on each subcommand to add it to the command. 255 | yargs = this.getCommands().reduce( 256 | (yargs, cmd) => cmd.toYargs(yargs, commandRunner), 257 | yargs, 258 | ); 259 | return yargs as Argv; 260 | }; 261 | } 262 | 263 | /** 264 | * Wraps the actual command handler to insert prompt and handler logic. 265 | */ 266 | private getHandler(commandRunner: CommandRunner) { 267 | return async (argv: YargsArguments & { __promise?: Promise }) => { 268 | const prompterInstance = prompter( 269 | [...this.getArguments(), ...this.getOptions()], 270 | argv, 271 | ); 272 | 273 | let promise = prompterInstance.prompt(); 274 | 275 | promise = promise.then(({ _, $0, __promise, ...args }) => { 276 | // @todo coerce all types and remove coerce option from baseArg 277 | if (this.handler) { 278 | return this.handler(args as unknown as T, commandRunner); 279 | } 280 | 281 | // Display help if this command contains sub-commands 282 | if (this.getCommands().length) { 283 | return commandRunner(`${this.getFqn()} --help`); 284 | } 285 | 286 | throw new Error("No handler defined for this command."); 287 | }); 288 | 289 | // Save promise chain on argv instance, so we can access it in parse 290 | // callback. 291 | // @todo Upgrade to native async handlers in yarn 17 292 | argv.__promise = promise; 293 | 294 | return promise; 295 | }; 296 | } 297 | } 298 | -------------------------------------------------------------------------------- /src/program.ts: -------------------------------------------------------------------------------- 1 | import { EventEmitter } from "events"; 2 | import os from "os"; 3 | import path from "path"; 4 | import TypedEventEmitter from "typed-emitter"; 5 | import { Argv, ParserConfigurationOptions } from "yargs"; 6 | import createYargs from "yargs/yargs"; 7 | import { command, Command } from "./command.js"; 8 | import { history, History } from "./history.js"; 9 | import { Repl, repl } from "./repl.js"; 10 | import { isPromise } from "./utils.js"; 11 | 12 | const DEFAULT_PROMPT = "> "; 13 | const DEFAULT_HISTORY_FILE = ".bandersnatch_history"; 14 | 15 | type Events = { 16 | run: (command: string | readonly string[]) => void; 17 | }; 18 | 19 | type ProgramOptions = { 20 | /** 21 | * Program description. Can also be set by calling 22 | * `program().description(...)`. 23 | * 24 | * Defaults to `undefined`. 25 | */ 26 | description?: string; 27 | 28 | /** 29 | * Sets a custom REPL prompt. Can also be set by calling 30 | * `program().prompt(...)`. 31 | * 32 | * Defaults to `> `. 33 | */ 34 | prompt?: string; 35 | 36 | /** 37 | * Whether or not to add a global help command that displays an overview of 38 | * commands. 39 | * 40 | * Defaults to `true`. 41 | */ 42 | help?: boolean; 43 | 44 | /** 45 | * Whether or not to add a global version command that displays the version as 46 | * specified in the package.json file. 47 | * 48 | * Defaults to `true`. 49 | */ 50 | version?: boolean; 51 | 52 | /** 53 | * Use this history file. Set to NULL to disable history file. 54 | * 55 | * Defaults to `{homedir}/.bandersnatch_history`. 56 | */ 57 | historyFile?: string | null; 58 | 59 | /** 60 | * Specifies whether to add a default behaviour for an `exit` command. 61 | * 62 | * Takes a boolean or a function argument: 63 | * - `false` installs no handler 64 | * - `true` will install the default handler 65 | * - a given function will be installed as the handler 66 | * 67 | * Defaults to `() => process.exit()`. 68 | */ 69 | exit?: boolean | (() => void); 70 | 71 | /** 72 | * Pass Yargs parser configuration, for available options, see 73 | * https://github.com/yargs/yargs/blob/main/docs/advanced.md#customizing-yargs-parser. 74 | * 75 | * Defaults to `undefined`. 76 | */ 77 | parserConfiguration?: Partial; 78 | }; 79 | 80 | /** 81 | * Creates a new bandersnatch program. 82 | */ 83 | export function program(options: ProgramOptions = {}) { 84 | return new Program(options); 85 | } 86 | 87 | function extractCommandFromProcess() { 88 | return process.argv.slice(2); 89 | } 90 | 91 | export class Program extends (EventEmitter as new () => TypedEventEmitter) { 92 | private commands: Command[] = []; 93 | private history?: History; 94 | private replInstance?: Repl; 95 | 96 | constructor(public options: ProgramOptions = {}) { 97 | super(); 98 | 99 | // Set default prompt 100 | if (typeof this.options.prompt === "undefined") { 101 | this.options.prompt = DEFAULT_PROMPT; 102 | } 103 | 104 | // Set default historyFile 105 | if (typeof this.options.historyFile === "undefined") { 106 | this.options.historyFile = path.join(os.homedir(), DEFAULT_HISTORY_FILE); 107 | } 108 | 109 | // Set default exit handler 110 | if ( 111 | this.options.exit === true || 112 | typeof this.options.exit === "undefined" 113 | ) { 114 | this.options.exit = () => process.exit(); 115 | } 116 | 117 | if (this.options.historyFile !== null) { 118 | this.history = history(this); 119 | } 120 | } 121 | 122 | /** 123 | * Set the program description. 124 | */ 125 | public description(description: string) { 126 | this.options.description = description; 127 | return this; 128 | } 129 | 130 | /** 131 | * Sets a custom REPL prompt. 132 | */ 133 | public prompt(prompt: string) { 134 | this.options.prompt = prompt; 135 | return this; 136 | } 137 | 138 | /** 139 | * Create a new yargs instance. This method may change at any time, not 140 | * intended for public use. 141 | * 142 | * @private 143 | */ 144 | public createYargsInstance( 145 | overrideParserConfiguration?: Partial, 146 | ) { 147 | let yargs = createYargs(); 148 | 149 | this.options.description && yargs.usage(this.options.description); 150 | 151 | // Help accepts boolean 152 | yargs.help(this.options.help !== false); 153 | 154 | // Version must be false or undefined 155 | this.options.version !== false ? yargs.version() : yargs.version(false); 156 | 157 | // Pass yargs parser options if defined 158 | if (typeof this.options.parserConfiguration !== "undefined") { 159 | yargs = yargs.parserConfiguration({ 160 | ...this.options.parserConfiguration, 161 | ...overrideParserConfiguration, 162 | }); 163 | } 164 | 165 | // Non-configurable options 166 | yargs.recommendCommands(); 167 | yargs.strict(); 168 | yargs.demandCommand(); 169 | 170 | // Hidden completion command 171 | yargs.completion("completion", false); 172 | 173 | // Custom fail function. 174 | yargs.fail(this.failHandler.bind(this)); 175 | 176 | // In case we're in a REPL session, do not exit on errors. 177 | yargs.exitProcess(!this.isRepl()); 178 | 179 | // Add commands 180 | this.commands.forEach((command) => { 181 | command.toYargs(yargs, (command: string) => { 182 | return this.run(command); 183 | }); 184 | }); 185 | 186 | return yargs; 187 | } 188 | 189 | /** 190 | * Adds a new command to the program. 191 | */ 192 | public add(command: Command) { 193 | this.commands.push(command); 194 | return this; 195 | } 196 | 197 | /** 198 | * Adds a new command to the program and marks it as the default command. 199 | */ 200 | public default(command: Command) { 201 | this.commands.push(command.default()); 202 | return this; 203 | } 204 | 205 | /** 206 | * Evaluate command (or process.argv) and return promise. 207 | */ 208 | public run(command?: string | readonly string[]) { 209 | const cmd = command || extractCommandFromProcess(); 210 | 211 | this.emit("run", cmd); 212 | 213 | // Return promise resolving to the return value of the command 214 | // handler. 215 | return new Promise((resolve, reject) => { 216 | // @ts-ignore Not sure why this is needed? 217 | this.createYargsInstance() 218 | .parse(cmd, {}, (err, argv, output) => { 219 | // We don't use yargs 17 promise style argv 220 | if (isPromise(argv)) { 221 | throw new Error("argv is of unexpected type"); 222 | } 223 | 224 | /** 225 | * From the yargs docs: 226 | * > any text that would have been output by yargs to the terminal, 227 | * > had a callback not been provided. 228 | * http://yargs.js.org/docs/#api-parseargs-context-parsecallback 229 | * 230 | * Seems that this is primarily used for built-in commands like 231 | * --version and --help. 232 | */ 233 | if (output) { 234 | console.log(output); 235 | } 236 | 237 | /** 238 | * From the yargs docs: 239 | * > Populated if any validation errors raised while parsing. 240 | * http://yargs.js.org/docs/#api-parseargs-context-parsecallback 241 | * This seems to be incorrect though, and err is populated when any 242 | * error is thrown inside the command handler. 243 | */ 244 | if (err) { 245 | // Ignore err value, which encourages users to deliberately handle 246 | // error conditions in their programs. 247 | } 248 | 249 | if (isPromise(argv.__promise)) { 250 | // Delegate resolve/reject to promise returned from handler 251 | argv.__promise.then(resolve).catch(reject); 252 | } else { 253 | // Resolve with undefined if promise is not available, which is the 254 | // case with e.g. --version and --help. It should be noted that 255 | // this might need to be filtered when e.g. printing resolved values 256 | // from command handlers in a .then() function. 257 | resolve(undefined); 258 | } 259 | }) 260 | .catch(() => {}); 261 | }); 262 | } 263 | 264 | /** 265 | * Run event loop which reads command from stdin. 266 | */ 267 | public repl() { 268 | this.replInstance = repl(this); 269 | 270 | // Add exit command 271 | if (typeof this.options.exit === "function") { 272 | this.add( 273 | command("exit") 274 | .description("Exit the application") 275 | .action(this.options.exit), 276 | ); 277 | } 278 | 279 | if (this.history) { 280 | this.replInstance.attachHistory(this.history); 281 | } 282 | this.replInstance.start(); 283 | 284 | return this.replInstance; 285 | } 286 | 287 | /** 288 | * When argv is set, run the program, otherwise start repl loop. 289 | */ 290 | public runOrRepl() { 291 | return extractCommandFromProcess().length ? this.run() : this.repl(); 292 | } 293 | 294 | /** 295 | * Returns `true` if program is running a repl loop, `false` otherwise. 296 | */ 297 | public isRepl() { 298 | return !!this.replInstance; 299 | } 300 | 301 | /** 302 | * Method to execute when a failure occurs, rather than printing the failure 303 | * message. 304 | * 305 | * Called with the failure message that would have been printed, the Error 306 | * instance originally thrown and yargs state when the failure occured. 307 | */ 308 | private failHandler(msg: string, err: Error, yargs: Argv) { 309 | if (msg) { 310 | // Simply throw validation messages to reject runner promise 311 | throw new Error(msg); 312 | } 313 | } 314 | } 315 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bandersnatch [![npm](https://img.shields.io/npm/v/bandersnatch)](https://www.npmjs.com/package/bandersnatch) 2 | 3 | ```ts 4 | program() 5 | .default( 6 | command() 7 | .description("What is bandersnatch?") 8 | .action(() => console.log(description)), 9 | ) 10 | .run(); 11 | ``` 12 | 13 | ``` 14 | $ ./bandersnatch 15 | Simple and intuitive yet powerful and versatile framework for Node.js CLI programs 16 | ``` 17 | 18 | ## Features 19 | 20 | - 🌊 [Fluid](https://www.martinfowler.com/bliki/FluentInterface.html) syntax, 21 | intuitive to use 22 | - 🔜 Autocompletion of commands, arguments, options and choices 23 | - ➰ Built-in [REPL](https://en.wikipedia.org/wiki/Read–eval–print_loop) for 24 | interactive programs with 🔙 Command history 25 | - 💬 Can prompt for missing arguments 26 | - 🤯 Built for TypeScript, command arguments are fully typed 27 | - 🪆 Supports singular (e.g. `foo`) and nested commands (e.g. `foo bar`) 28 | - 🏃 Argument types are guaranteed at runtime (coming soon) 29 | 30 | ## Table of contents 31 | 32 | 33 | 34 | 35 | - [Getting started](#getting-started) 36 | - [Installation](#installation) 37 | - [Simple example](#simple-example) 38 | - [Error handling](#error-handling) 39 | - [REPL](#repl) 40 | - [Prompt](#prompt) 41 | - [TypeScript](#typescript) 42 | - [API](#api) 43 | - [`program(options)`](#programoptions) 44 | - [`program.description(description)`](#programdescriptiondescription) 45 | - [`program.prompt(prompt)`](#programpromptprompt) 46 | - [`program.add(command)`](#programaddcommand) 47 | - [`program.default(command)`](#programdefaultcommand) 48 | - [`program.run(command)`](#programruncommand) 49 | - [`program.repl()`](#programrepl) 50 | - [`program.runOrRepl()`](#programrunorrepl) 51 | - [`program.isRepl()`](#programisrepl) 52 | - [`program.on(event, listener)`](#programonevent-listener) 53 | - [`command(name, options)`](#commandname-options) 54 | - [`command.description(description)`](#commanddescriptiondescription) 55 | - [`command.hidden()`](#commandhidden) 56 | - [`command.argument(name, options)`](#commandargumentname-options) 57 | - [`command.option(name, options)`](#commandoptionname-options) 58 | - [`command.add(command)`](#commandaddcommand) 59 | - [`command.default()`](#commanddefault) 60 | - [`command.action(function)`](#commandactionfunction) 61 | - [Design principles](#design-principles) 62 | - [Errors](#errors) 63 | - [Output](#output) 64 | - [Bundle](#bundle) 65 | - [Todo](#todo) 66 | - [Contributing](#contributing) 67 | - [Local install](#local-install) 68 | - [Devcontainer](#devcontainer) 69 | - [Credits](#credits) 70 | 71 | 72 | 73 | ## Getting started 74 | 75 | ### Installation 76 | 77 | ```bash 78 | # Add dependency 79 | yarn|npm add bandersnatch 80 | ``` 81 | 82 | > [!NOTE] 83 | > We recommend using an _Active LTS_ or _Maintenance LTS_ Node.js 84 | > [version](https://nodejs.org/en/about/releases/). _Current_ versions are 85 | > tested, but not guaranteed to work. 86 | 87 | ### Simple example 88 | 89 | Let's create a simple program `foo.js`: 90 | 91 | ```js 92 | import { program, command } from "bandersnatch"; 93 | 94 | const cmd = command() 95 | .default() 96 | .description('Outputs "bar".') 97 | .action(() => console.log("bar")); 98 | 99 | const app = program().description("foo").add(cmd); 100 | 101 | app.run(); 102 | ``` 103 | 104 | This creates a new program, adds a default command which logs "bar" to the 105 | stdout, and runs the program. 106 | 107 | Now try your program by running it: 108 | 109 | ``` 110 | $ node foo.js 111 | bar 112 | ``` 113 | 114 | Try running `node foo.js --help` to see the auto-generated help output: 115 | 116 | ``` 117 | $ node foo.js help 118 | foo.js 119 | 120 | Outputs "bar". 121 | 122 | Commands: 123 | foo.js Outputs "bar". [default] 124 | 125 | Options: 126 | --help Show help [boolean] 127 | --version Show version number [boolean] 128 | ``` 129 | 130 | ### Error handling 131 | 132 | We first create a new program called `cat.js` which is a naive version of the 133 | `cat` program we all know: 134 | 135 | ```js 136 | import { readFileSync } from "fs"; 137 | import { program, command } from "bandersnatch"; 138 | 139 | const cat = command("cat") 140 | .description("Concatenate files") 141 | .argument("files", { variadic: true }) 142 | .action(({ files }) => 143 | console.log( 144 | files.reduce((str, file) => str + readFileSync(file, "utf8"), ""), 145 | ), 146 | ); 147 | 148 | program().default(cat).run(); 149 | ``` 150 | 151 | Now try your program by running it: 152 | 153 | ``` 154 | $ node cat.js somefile 155 | contents of somefile 156 | ``` 157 | 158 | However, when `somefile` doesn't exist, we get are faced with an ugly unhandled 159 | promise rejection warning/error (depending on the Node.js version you're using). 160 | 161 | Let's fix that: 162 | 163 | ```diff 164 | -program().default(cat).run() 165 | +program() 166 | + .default(cat) 167 | + .run() 168 | + .catch((err) => { 169 | + console.error(`There was a problem running this command:\n${String(err)}`) 170 | + process.exit(1) 171 | + }) 172 | ``` 173 | 174 | Which will yield: 175 | 176 | ``` 177 | $ node cat.js somefile 178 | There was a problem running this command: 179 | Error: ENOENT: no such file or directory, open 'somefile' 180 | ``` 181 | 182 | ### REPL 183 | 184 | A program can also show an interactive 185 | [REPL](https://en.wikipedia.org/wiki/Read–eval–print_loop) to make interacting 186 | with more complex programs easier and to enable autocompleting of commands and 187 | arguments. 188 | 189 | Let's create a new program `dice.js` with a command to roll a dice: 190 | 191 | ```js 192 | import { program, command } from "bandersnatch"; 193 | 194 | async function rng(bounds) { 195 | const [min, max] = bounds; 196 | return Math.floor(Math.random() * (max - min + 1)) + min; 197 | } 198 | 199 | const dice = program().add( 200 | command("roll") 201 | .option("min", { default: 1 }) 202 | .option("max", { default: 6 }) 203 | .action(async (args) => { 204 | console.log(await rng([args.min, args.max])); 205 | }), 206 | ); 207 | 208 | dice.repl(); 209 | ``` 210 | 211 | This code defines a program `dice` and a command `roll` with two options, both 212 | of which will inherit a default value. When the command is executed, it calls an 213 | async random number generator (async only for illustrative purposes) and writes 214 | its results to stdout. 215 | 216 | The last line in our code runs the program as a interactive REPL, which means it 217 | won't accept any arguments on the command line, but render a prompt instead. 218 | This prompt will read any user input, parse it, and execute matching commands. 219 | 220 | Try rolling the dice: 221 | 222 | ``` 223 | $ node dice.js 224 | > roll 225 | 5 226 | ``` 227 | 228 | The REPL can autocomplete commands, arguments, options and choices. Try typing 229 | only the letter `r` and then hit _TAB_. This works for options as well: 230 | 231 | ``` 232 | $ node dice.js 233 | > r 234 | [TAB] 235 | > roll - 236 | [TAB] 237 | > roll --m 238 | [TAB] [TAB] 239 | --min --max 240 | ``` 241 | 242 | ### Prompt 243 | 244 | Bandersnatch can also ask a user for input if arguments were not provided on the 245 | command line: 246 | 247 | Let's say we want to write a program `pizza.js` which takes pizza orders: 248 | 249 | ```js 250 | import { program, command } from "bandersnatch"; 251 | 252 | const cmd = command() 253 | .argument("address", { 254 | prompt: "Your address", 255 | }) 256 | .option("name", { 257 | description: "Your name", 258 | default: "anonymous", 259 | prompt: true, 260 | }) 261 | .option("size", { 262 | description: "Choose pizza size", 263 | choices: ["small", "medium", "large"], 264 | default: "medium", 265 | prompt: true, 266 | }) 267 | .option("toppings", { 268 | description: "Pick some toppings", 269 | choices: ["mozzarella", "pepperoni", "veggies"], 270 | default: ["mozzarella"], 271 | prompt: true, 272 | }) 273 | .option("confirmed", { 274 | description: "Order pizza?", 275 | default: true, 276 | prompt: true, 277 | }) 278 | .action((args) => { 279 | console.log(args); 280 | }); 281 | 282 | program().description("Order a pizza").default(cmd).run(); 283 | ``` 284 | 285 | And run it: 286 | 287 | ``` 288 | $ node pizza.js 289 | ? Your address The Netherlands 290 | ? Your name Joram 291 | ? Choose pizza size small 292 | ? Pick some toppings veggies 293 | ? Order pizza? Yes 294 | { 295 | name: 'Joram', 296 | size: 'small', 297 | toppings: [ 'veggies' ], 298 | confirmed: true, 299 | address: 'The Netherlands' 300 | } 301 | ``` 302 | 303 | You can choose to specify parameters on the command line, in which case you 304 | won't get a prompt for these options: 305 | 306 | ``` 307 | $ node pizza.js "The Netherlands" --name Joram --confirmed 308 | ? Choose pizza size small 309 | ? Pick some toppings veggies 310 | ? Order pizza? Yes 311 | { 312 | name: 'Joram', 313 | size: 'small', 314 | toppings: [ 'veggies' ], 315 | confirmed: true, 316 | address: 'The Netherlands' 317 | } 318 | ``` 319 | 320 | > [!WARNING] 321 | > Please note that even though `--confirmed` was specified on the command line, 322 | > it was still being prompted. This is a known issue. In this case, the default 323 | > value was the same as the input, in which case bandersnatch doesn't know 324 | > whether a value was explicitly passed in or inherited from the default value. 325 | 326 | ### TypeScript 327 | 328 | Bandersnatch works perfectly well with non-TypeScript codebases. However, when 329 | you do use TypeScript the command arguments are fully typed. 330 | 331 | Let's rename the example program to `pizza.ts` and add some minor type hints to 332 | illustrate this: 333 | 334 | ```diff 335 | .option('size', { 336 | description: 'Choose pizza size', 337 | - choices: ['small', 'medium', 'large'], 338 | + choices: ['small', 'medium', 'large'] as const, 339 | default: 'medium', 340 | prompt: true, 341 | }) 342 | .option('toppings', { 343 | description: 'Pick some toppings', 344 | - choices: ['mozzarella', 'pepperoni', 'veggies'], 345 | + choices: ['mozzarella', 'pepperoni', 'veggies'] as const, 346 | default: ['mozzarella'], 347 | prompt: true, 348 | }) 349 | ``` 350 | 351 | The first argument passed to the action handler function is now typed like this: 352 | 353 | ```ts 354 | type Args = { 355 | address: string; 356 | name: string; 357 | size: "small" | "medium" | "large"; 358 | toppings: ("mozzarella" | "pepperoni" | "veggies")[]; 359 | confirmed: boolean; 360 | }; 361 | ``` 362 | 363 | > [!TIP] 364 | > More examples in the 365 | > [examples](https://github.com/hongaar/bandersnatch/tree/main/examples) 366 | > directory. 367 | 368 | ## API 369 | 370 | All methods are chainable unless the docs mention otherwise. 371 | 372 | ### `program(options)` 373 | 374 | Creates a new program. Options (object, optional) can contain these keys: 375 | 376 | - `description` (string, optional) is used in help output. 377 | - `prompt` (string, default: `> `) use this prompt prefix when in REPL mode. 378 | - `help` (boolean, default: true) adds `help` and `--help` to the program which 379 | displays program usage information. 380 | - `version` (boolean, default: true) adds `version` and `--version` to the 381 | program which displays program version from package.json. 382 | - `historyFile` (string | null, default: {homedir}/.bandersnatch_history) is a 383 | path to the app history file. Set to NULL to disable. 384 | - `exit` (boolean | () => void, default: () => process.exit()) Specifies whether 385 | to add a default behaviour for an `exit` command. `false` disables the default 386 | implementation, a custom function will be installed as the actual handler. 387 | - `parserConfiguration` (object, optional) can be used to modify the parser 388 | configuration. For available options, see 389 | - https://github.com/yargs/yargs/blob/main/docs/api.md#parserConfiguration. 390 | 391 | #### `program.description(description)` 392 | 393 | Sets the program description (string, required) used in help output. 394 | 395 | #### `program.prompt(prompt)` 396 | 397 | Use this prompt prefix (string, required) when in REPL mode. 398 | 399 | #### `program.add(command)` 400 | 401 | Adds a command to the program. 402 | 403 | ```js 404 | program().add(command(...)) 405 | ``` 406 | 407 | #### `program.default(command)` 408 | 409 | Adds a default command to the program. Shorthand for: 410 | 411 | ```js 412 | program().add(command(...).default()) 413 | ``` 414 | 415 | #### `program.run(command)` 416 | 417 | Uses process.argv or passed in command (string, optional) to match and execute 418 | command. Returns promise. 419 | 420 | ```js 421 | program() 422 | .add(command(...)) 423 | .run() 424 | ``` 425 | 426 | #### `program.repl()` 427 | 428 | Start a read-eval-print loop. Returns promise-like REPL instance. 429 | 430 | ```js 431 | program() 432 | .add(command(...)) 433 | .repl() 434 | ``` 435 | 436 | #### `program.runOrRepl()` 437 | 438 | Invokes `run()` if process.argv is set, `repl()` otherwise. Returns promise or 439 | promise-like REPL instance. 440 | 441 | ```js 442 | program() 443 | .add(command(...)) 444 | .runOrRepl() 445 | ``` 446 | 447 | #### `program.isRepl()` 448 | 449 | Returns `true` if program is running a REPL loop, `false` otherwise. 450 | 451 | #### `program.on(event, listener)` 452 | 453 | Attaches a listener function for the event. Currently, these events are 454 | supported: 455 | 456 | ```js 457 | // Fired before a command action is invoked 458 | program().on("run", (cmd) => logger.debug(`Running ${cmd}`)); 459 | ``` 460 | 461 | ### `command(name, options)` 462 | 463 | Creates a new command. 464 | 465 | - Name (string, optional) is used to invoke a command. When not used as the 466 | default command, a name is required. 467 | - Options (object, optional) can contain these keys: 468 | - `description` (string) is used in help output. 469 | - `hidden` (boolean) hide command from help output and autocomplete. 470 | 471 | #### `command.description(description)` 472 | 473 | Sets the command description (string, required) used in help output. 474 | 475 | #### `command.hidden()` 476 | 477 | Hide command from help output and autocomplete. 478 | 479 | #### `command.argument(name, options)` 480 | 481 | Adds a positional argument to the command. 482 | 483 | - Name (string, required) is used to identify the argument. 484 | - Options can be provided to change the behavior of the argument. Object with 485 | any of these keys: 486 | - `description` (string) is used in help output. 487 | - `optional` (boolean) makes this argument optional. 488 | - `variadic` (boolean) eagerly take all remaining arguments and parse as an 489 | array. Only valid for the last argument. 490 | - `type` (string) one of `"boolean"|"number"|"string"` which determines the 491 | runtime type of the argument. 492 | - `default` (any) default value for the argument. 493 | - `choices` (array) any input value should be included in the array, or it 494 | will be rejected. 495 | - `prompt` (boolean|string) prompts for missing arguments. If it is true, it 496 | will use the arguments description or name as the question text. If it is a 497 | string, it will be used as the question text. 498 | - `alias` (string|array) alias or aliases for the argument. 499 | - `coerce` (function) transform function for this argument value (untyped). 500 | - `requires` (string|array) make another option or argument required if the 501 | argument is present 502 | - `excludes` (string|array) exclude another options or argument if the 503 | argument is present 504 | 505 | #### `command.option(name, options)` 506 | 507 | Adds an option to the command. 508 | 509 | - Name (string, required) is used to identify the option. 510 | - Options (object, optional) can be provided to change the behavior of the 511 | option. Object with any of these keys: 512 | - `description` (string) is used in help output. 513 | - `type` (string) one of `"array"|"boolean"|"count"|"number"|"string"` which 514 | determines the runtime type of the argument. Use count for the number of 515 | times an option was provided (e.g. verbosity levels). 516 | - `default` (any) default value for the argument. 517 | - `choices` (array) any input value should be included in the array, or it 518 | will be rejected. 519 | - `prompt` (boolean|string) prompts for missing arguments. If it is true, it 520 | will use the arguments description or name as the question text. If it is a 521 | string, it will be used as the question text. 522 | - `alias` (string|array) alias or aliases for the option. 523 | - `coerce` (function) transform function for this option value (untyped). 524 | - `required` (boolean) makes the option required. 525 | - `requires` (string|array) make another option or argument required if the 526 | option is present 527 | - `excludes` (string|array) exclude another options or argument if the option 528 | is present 529 | 530 | #### `command.add(command)` 531 | 532 | Adds a sub-command to the command. 533 | 534 | #### `command.default()` 535 | 536 | Mark command as default. Default commands are executed immediately and don't 537 | require a name. 538 | 539 | #### `command.action(function)` 540 | 541 | Function which executes when the command is invoked. Is called with these 542 | arguments: 543 | 544 | 1. Args (object) is an object containing key/value pairs of parsed arguments and 545 | options. 546 | 2. Command runner (function) can be invoked with one (string) parameter to 547 | execute another command. 548 | 549 | ## Design principles 550 | 551 | In general, bandersnatch is designed to create 552 | [twelve-factor apps](https://12factor.net/). 553 | 554 | ### Errors 555 | 556 | The bandersnatch API allows to catch errors in a promise-like way. The `run` and 557 | `repl` program methods return either a promise or promise-like object which can 558 | be used to handle program errors: 559 | 560 | ```js 561 | program() 562 | .default( 563 | command() 564 | .description("This command will always fail") 565 | .action(function () { 566 | throw new Error("Whoops"); 567 | }), 568 | ) 569 | .runOrRepl() 570 | .catch((error) => { 571 | console.error("[failed]", String(error)); 572 | 573 | if (!app.isRepl()) { 574 | process.exit(1); 575 | } 576 | }); 577 | ``` 578 | 579 | ### Output 580 | 581 | Programs are encouraged to use the following conventions with regards to output, 582 | based on the 583 | [POSIX standard](https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdin.html). 584 | 585 | - When a program is designed to be used in a scripting environment and its 586 | output should be available as stdin for other programs, use stdout for 587 | printing output and stderr for diagnostic output (e.g. progress and/or error 588 | messages). 589 | - When a program is designed to be used as a service (twelve-factor app), use 590 | stdout/stderr as a logging mechanism for informative messages/error and 591 | diagnostic messages. 592 | 593 | Bandersnatch has no built-in method for writing to stdout/stderr. Node.js 594 | provides [everything you need](https://nodejs.org/api/console.html). 595 | 596 | ## Bundle 597 | 598 | There are many options to bundle your application for distribution. We'll 599 | discuss a common pattern. 600 | 601 | > [!TIP] 602 | > An example can be found in the 603 | > [examples/bundle](https://github.com/hongaar/bandersnatch/tree/main/examples/bundle) 604 | > directory. 605 | 606 | Init a `package.json` if needed: 607 | 608 | ``` 609 | mkdir echo && cd echo 610 | yarn init 611 | ``` 612 | 613 | Install dependencies: 614 | 615 | ``` 616 | yarn add bandersnatch 617 | yarn add typescript @types/node pkg --dev 618 | ``` 619 | 620 | And create an example app in `src/cli.ts`: 621 | 622 | ```ts 623 | import { program, command } from "bandersnatch"; 624 | 625 | export default program().default( 626 | command("echo") 627 | .description("Echo something in the terminal") 628 | .argument("words", { description: "Say some kind words", variadic: true }) 629 | .action(console.log), 630 | ); 631 | ``` 632 | 633 | Building your app with TypeScript is very powerful, but runtime compilation is 634 | slow so we compile the code ahead of time. 635 | 636 | Add a `tsconfig.json`, similar to: 637 | 638 | ```json 639 | { 640 | "include": ["./src"], 641 | "compilerOptions": { 642 | "target": "es2017", 643 | "module": "commonjs", 644 | "lib": ["es2017"], 645 | "declaration": true, 646 | "outDir": "dist", 647 | "rootDir": "src", 648 | "strict": true, 649 | "allowSyntheticDefaultImports": true, 650 | "esModuleInterop": true, 651 | "moduleResolution": "node" 652 | } 653 | } 654 | ``` 655 | 656 | Add these scripts to your `package.json`: 657 | 658 | ```diff 659 | { 660 | "name": "echo", 661 | "version": "1.0.0", 662 | "main": "index.js", 663 | "license": "MIT", 664 | + "scripts": { 665 | + "prepublishOnly": "yarn build", 666 | + "build": "tsc", 667 | + }, 668 | "dependencies": { 669 | "bandersnatch": "^1.0.0" 670 | }, 671 | "devDependencies": { 672 | "pkg": "^5.3.1", 673 | "typescript": "^4.4.2" 674 | } 675 | } 676 | ``` 677 | 678 | And compile now by running `yarn build`. 679 | 680 | Next, we need to create a simple entry point `echo.js`, which can be run with 681 | node: 682 | 683 | ```bash 684 | #!/usr/bin/env node 685 | 686 | require('./dist/cli').default.run() 687 | ``` 688 | 689 | To run your app, users may want to run `yarn global add echo`. For this to work, 690 | we need to make a small adjustment to `package.json`: 691 | 692 | ```diff 693 | { 694 | "name": "echo", 695 | "version": "1.0.0", 696 | - "main": "index.js", 697 | + "bin": "echo.js", 698 | + "files": [ 699 | + "dist" 700 | + ], 701 | "license": "MIT", 702 | "scripts": { 703 | "prepublishOnly": "yarn build", 704 | "build": "tsc", 705 | }, 706 | "dependencies": { 707 | "bandersnatch": "^1.0.0" 708 | }, 709 | "devDependencies": { 710 | "pkg": "^5.3.1", 711 | "typescript": "^4.4.2" 712 | } 713 | } 714 | ``` 715 | 716 | You can now `npm publish`. 717 | 718 | To create a binary (your app with Node.js bundled), add this script to 719 | `package.json`: 720 | 721 | ```diff 722 | { 723 | "name": "echo", 724 | "version": "1.0.0", 725 | "bin": "echo.js", 726 | "files": [ 727 | "dist" 728 | ], 729 | "license": "MIT", 730 | "scripts": { 731 | "prepublishOnly": "yarn build", 732 | "build": "tsc", 733 | + "bundle": "yarn build && pkg -t host ." 734 | }, 735 | "dependencies": { 736 | "bandersnatch": "^1.0.0" 737 | }, 738 | "devDependencies": { 739 | "pkg": "^5.3.1", 740 | "typescript": "^4.4.2" 741 | } 742 | } 743 | ``` 744 | 745 | > [!TIP] 746 | > Omit `-t host` to create binaries for all platforms. 747 | 748 | Run `yarn bundle` and then `./echo --help`. 💪 749 | 750 | Optionally deploy to GitHub, S3, etc. using your preferred CD method if needed. 751 | 752 | ## Todo 753 | 754 | See [TODO.md](TODO.md) 755 | 756 | ## Contributing 757 | 758 | Contributions are very welcome. Please use 759 | [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/). 760 | 761 | ### Local install 762 | 763 | ```bash 764 | # Clone and install 765 | git clone git@github.com:hongaar/bandersnatch.git 766 | cd bandersnatch 767 | yarn install 768 | yarn husky install 769 | 770 | # Run an example 771 | yarn start examples/foo.ts 772 | ``` 773 | 774 | ### Devcontainer 775 | 776 | A devcontainer configuration is included in this repo to 777 | [get started quickly](https://code.visualstudio.com/docs/remote/containers#_quick-start-open-an-existing-folder-in-a-container). 778 | 779 | ## Credits 780 | 781 | ©️ Copyright 2022 [Joram van den Boezem](https://joram.dev) 782 | ♻️ Licensed under the [MIT license](LICENSE) 783 | 💡 Inspired by [vorpal](https://vorpal.js.org/) 784 | ⚡ Powered by [yargs](http://yargs.js.org) and 785 | [enquirer](https://github.com/enquirer/enquirer) 786 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [2.0.1](https://github.com/hongaar/bandersnatch/compare/v2.0.0...v2.0.1) (2024-12-09) 2 | 3 | 4 | ### Bug Fixes 5 | 6 | * **deps:** bump the npm_and_yarn group with 2 updates ([#633](https://github.com/hongaar/bandersnatch/issues/633)) ([7d06780](https://github.com/hongaar/bandersnatch/commit/7d06780ddbab99007a26e621ec34b56f5191341f)) 7 | 8 | # [2.0.0](https://github.com/hongaar/bandersnatch/compare/v1.12.15...v2.0.0) (2024-05-27) 9 | 10 | - feat!: update node.js versions (#608) 11 | ([d94e449](https://github.com/hongaar/bandersnatch/commit/d94e449006296ebd7eade66a99edf20882bbb8c1)), 12 | closes [#608](https://github.com/hongaar/bandersnatch/issues/608) 13 | 14 | ### BREAKING CHANGES 15 | 16 | - This updates the minimum supported node.js version to 18 17 | 18 | ## [1.12.15](https://github.com/hongaar/bandersnatch/compare/v1.12.14...v1.12.15) (2024-04-10) 19 | 20 | ### Bug Fixes 21 | 22 | - **deps:** bump tar from 6.1.11 to 6.2.1 23 | ([#596](https://github.com/hongaar/bandersnatch/issues/596)) 24 | ([bdb1c06](https://github.com/hongaar/bandersnatch/commit/bdb1c06ac2e0d0d2c9140b9ee70828c521ded5df)) 25 | 26 | ## [1.12.14](https://github.com/hongaar/bandersnatch/compare/v1.12.13...v1.12.14) (2024-02-21) 27 | 28 | ### Bug Fixes 29 | 30 | - **deps:** bump ip from 1.1.8 to 1.1.9 31 | ([#579](https://github.com/hongaar/bandersnatch/issues/579)) 32 | ([c5c103e](https://github.com/hongaar/bandersnatch/commit/c5c103e3e3f693e444d5f30727dc21769007ab60)) 33 | 34 | ## [1.12.13](https://github.com/hongaar/bandersnatch/compare/v1.12.12...v1.12.13) (2023-11-27) 35 | 36 | ### Bug Fixes 37 | 38 | - **deps:** bump @types/yargs from 17.0.31 to 17.0.32 39 | ([#541](https://github.com/hongaar/bandersnatch/issues/541)) 40 | ([4f33cfb](https://github.com/hongaar/bandersnatch/commit/4f33cfbebfff9d69d9146c514b6a1ef5538a13af)) 41 | 42 | ## [1.12.12](https://github.com/hongaar/bandersnatch/compare/v1.12.11...v1.12.12) (2023-11-13) 43 | 44 | ### Bug Fixes 45 | 46 | - **deps:** bump @types/yargs from 17.0.29 to 17.0.31 47 | ([#536](https://github.com/hongaar/bandersnatch/issues/536)) 48 | ([6fd5bd2](https://github.com/hongaar/bandersnatch/commit/6fd5bd24ffe82c0ffe456934c72e036112a7923e)) 49 | 50 | ## [1.12.11](https://github.com/hongaar/bandersnatch/compare/v1.12.10...v1.12.11) (2023-10-23) 51 | 52 | ### Bug Fixes 53 | 54 | - **deps:** bump @types/yargs from 17.0.28 to 17.0.29 55 | ([#522](https://github.com/hongaar/bandersnatch/issues/522)) 56 | ([29937e9](https://github.com/hongaar/bandersnatch/commit/29937e9819aeb67193e545b1ec398c3764bfdb12)) 57 | 58 | ## [1.12.10](https://github.com/hongaar/bandersnatch/compare/v1.12.9...v1.12.10) (2023-10-17) 59 | 60 | ### Bug Fixes 61 | 62 | - **deps:** bump @babel/traverse from 7.17.10 to 7.23.2 63 | ([#521](https://github.com/hongaar/bandersnatch/issues/521)) 64 | ([84cd98c](https://github.com/hongaar/bandersnatch/commit/84cd98c25697b52437ef244434dc1496a40a77dc)) 65 | 66 | ## [1.12.9](https://github.com/hongaar/bandersnatch/compare/v1.12.8...v1.12.9) (2023-10-09) 67 | 68 | ### Bug Fixes 69 | 70 | - **deps:** bump @types/yargs from 17.0.26 to 17.0.28 71 | ([#517](https://github.com/hongaar/bandersnatch/issues/517)) 72 | ([66abe50](https://github.com/hongaar/bandersnatch/commit/66abe501c8b6711ddd9137a7cc0a6c7fbb06bc17)) 73 | 74 | ## [1.12.8](https://github.com/hongaar/bandersnatch/compare/v1.12.7...v1.12.8) (2023-10-02) 75 | 76 | ### Bug Fixes 77 | 78 | - **deps:** bump @types/yargs from 17.0.25 to 17.0.26 79 | ([#515](https://github.com/hongaar/bandersnatch/issues/515)) 80 | ([6ce1a3f](https://github.com/hongaar/bandersnatch/commit/6ce1a3fbc54ba07b6327da623ce5a828c53098f7)) 81 | 82 | ## [1.12.7](https://github.com/hongaar/bandersnatch/compare/v1.12.6...v1.12.7) (2023-09-25) 83 | 84 | ### Bug Fixes 85 | 86 | - **deps:** bump @types/yargs from 17.0.24 to 17.0.25 87 | ([#514](https://github.com/hongaar/bandersnatch/issues/514)) 88 | ([9c76f43](https://github.com/hongaar/bandersnatch/commit/9c76f43050ce5648784541933e70083345c6b550)) 89 | 90 | ## [1.12.6](https://github.com/hongaar/bandersnatch/compare/v1.12.5...v1.12.6) (2023-07-31) 91 | 92 | ### Bug Fixes 93 | 94 | - **deps:** bump enquirer from 2.3.6 to 2.4.1 95 | ([#488](https://github.com/hongaar/bandersnatch/issues/488)) 96 | ([417829e](https://github.com/hongaar/bandersnatch/commit/417829ed38b17b11c7e3b075440c8c4898968261)) 97 | 98 | ## [1.12.5](https://github.com/hongaar/bandersnatch/compare/v1.12.4...v1.12.5) (2023-07-11) 99 | 100 | ### Bug Fixes 101 | 102 | - **deps:** bump semver from 5.7.1 to 5.7.2 103 | ([#482](https://github.com/hongaar/bandersnatch/issues/482)) 104 | ([1ee1766](https://github.com/hongaar/bandersnatch/commit/1ee17661df069db6997904e007ee4a602832d21c)) 105 | 106 | ## [1.12.4](https://github.com/hongaar/bandersnatch/compare/v1.12.3...v1.12.4) (2023-05-08) 107 | 108 | ### Bug Fixes 109 | 110 | - **deps:** bump string-argv from 0.3.1 to 0.3.2 111 | ([#456](https://github.com/hongaar/bandersnatch/issues/456)) 112 | ([03d9d0a](https://github.com/hongaar/bandersnatch/commit/03d9d0ad7a65c7ef184b95cd4e3911411fb3e0ad)) 113 | 114 | ## [1.12.3](https://github.com/hongaar/bandersnatch/compare/v1.12.2...v1.12.3) (2023-05-02) 115 | 116 | ### Bug Fixes 117 | 118 | - **deps:** bump yargs from 17.7.1 to 17.7.2 119 | ([#451](https://github.com/hongaar/bandersnatch/issues/451)) 120 | ([e5286df](https://github.com/hongaar/bandersnatch/commit/e5286df1b340190059118844f114c693607932c2)) 121 | 122 | ## [1.12.2](https://github.com/hongaar/bandersnatch/compare/v1.12.1...v1.12.2) (2023-04-30) 123 | 124 | ### Bug Fixes 125 | 126 | - **deps:** bump yaml from 2.2.1 to 2.2.2 127 | ([#448](https://github.com/hongaar/bandersnatch/issues/448)) 128 | ([6628bf9](https://github.com/hongaar/bandersnatch/commit/6628bf9c8088d052ea721c38adda150af5072170)) 129 | 130 | ## [1.12.1](https://github.com/hongaar/bandersnatch/compare/v1.12.0...v1.12.1) (2023-04-04) 131 | 132 | ### Bug Fixes 133 | 134 | - release artefacts ([#437](https://github.com/hongaar/bandersnatch/issues/437)) 135 | ([22e927a](https://github.com/hongaar/bandersnatch/commit/22e927ab985b51969f3d95404922da93e354c912)) 136 | 137 | # [1.12.0](https://github.com/hongaar/bandersnatch/compare/v1.11.2...v1.12.0) (2023-04-03) 138 | 139 | ### Bug Fixes 140 | 141 | - **deps:** bump yargs and @types/yargs 142 | ([#427](https://github.com/hongaar/bandersnatch/issues/427)) 143 | ([cf636e1](https://github.com/hongaar/bandersnatch/commit/cf636e19958681f7a23df4e08765e3a5f54c5d7a)) 144 | 145 | ### Features 146 | 147 | - add requires and excludes 148 | ([#434](https://github.com/hongaar/bandersnatch/issues/434)) 149 | ([24982cb](https://github.com/hongaar/bandersnatch/commit/24982cb92f0f55336950a6a0dd9cb4ea21f92f27)) 150 | 151 | ## [1.11.2](https://github.com/hongaar/bandersnatch/compare/v1.11.1...v1.11.2) (2023-04-03) 152 | 153 | ### Bug Fixes 154 | 155 | - **chore:** moker ([#423](https://github.com/hongaar/bandersnatch/issues/423)) 156 | ([a42dcc0](https://github.com/hongaar/bandersnatch/commit/a42dcc0e395d0d0f4790183b17cbf6769c3ed20d)) 157 | 158 | ### Reverts 159 | 160 | - bump mock-argv from 2.0.8 to 3.0.0 161 | ([#432](https://github.com/hongaar/bandersnatch/issues/432)) 162 | ([c41ca63](https://github.com/hongaar/bandersnatch/commit/c41ca63b2622c1c94ba7990d45a96f8fa7d50b53)) 163 | 164 | ## [1.11.1](https://github.com/hongaar/bandersnatch/compare/v1.11.0...v1.11.1) (2022-11-17) 165 | 166 | ### Bug Fixes 167 | 168 | - variadic enum type 169 | ([#414](https://github.com/hongaar/bandersnatch/issues/414)) 170 | ([f34e68f](https://github.com/hongaar/bandersnatch/commit/f34e68fe2202595abea1b18f2c989526b80872ac)) 171 | 172 | # [1.11.0](https://github.com/hongaar/bandersnatch/compare/v1.10.3...v1.11.0) (2022-06-20) 173 | 174 | ### Features 175 | 176 | - **prompter:** add limit to array prompts 177 | ([#405](https://github.com/hongaar/bandersnatch/issues/405)) 178 | ([3f951b6](https://github.com/hongaar/bandersnatch/commit/3f951b62684fd7fd0fc2ab5013a7016ea47fadac)) 179 | 180 | ## [1.10.3](https://github.com/hongaar/bandersnatch/compare/v1.10.2...v1.10.3) (2022-05-17) 181 | 182 | ### Bug Fixes 183 | 184 | - use esm build when using import 185 | ([#392](https://github.com/hongaar/bandersnatch/issues/392)) 186 | ([03e5cdb](https://github.com/hongaar/bandersnatch/commit/03e5cdb6b06eaf08db4f7f96852e70b7700d2077)) 187 | 188 | ## [1.10.2](https://github.com/hongaar/bandersnatch/compare/v1.10.1...v1.10.2) (2022-04-02) 189 | 190 | ### Bug Fixes 191 | 192 | - upgrade deps ([#393](https://github.com/hongaar/bandersnatch/issues/393)) 193 | ([eecfd4a](https://github.com/hongaar/bandersnatch/commit/eecfd4a2541f247f244c685d535721f1ba439d79)) 194 | 195 | ## [1.10.1](https://github.com/hongaar/bandersnatch/compare/v1.10.0...v1.10.1) (2022-03-23) 196 | 197 | ### Bug Fixes 198 | 199 | - package.json main entry 200 | ([10f1828](https://github.com/hongaar/bandersnatch/commit/10f18280b46ef43d06fd3c9799e46c7fb272846b)) 201 | 202 | # [1.10.0](https://github.com/hongaar/bandersnatch/compare/v1.9.2...v1.10.0) (2022-03-23) 203 | 204 | ### Features 205 | 206 | - esm support ([#391](https://github.com/hongaar/bandersnatch/issues/391)) 207 | ([243b498](https://github.com/hongaar/bandersnatch/commit/243b4988f9527000d3f9ff1d7ca57a5f94dba7bb)) 208 | 209 | ## [1.9.2](https://github.com/hongaar/bandersnatch/compare/v1.9.1...v1.9.2) (2022-03-22) 210 | 211 | ### Bug Fixes 212 | 213 | - **deps:** update dependency typed-emitter to v2 214 | ([#368](https://github.com/hongaar/bandersnatch/issues/368)) 215 | ([8435770](https://github.com/hongaar/bandersnatch/commit/8435770e8500937b41a05b4c82de6c393a69b18c)) 216 | 217 | ## [1.9.1](https://github.com/hongaar/bandersnatch/compare/v1.9.0...v1.9.1) (2022-03-22) 218 | 219 | ### Bug Fixes 220 | 221 | - args typed with undefined 222 | ([#389](https://github.com/hongaar/bandersnatch/issues/389)) 223 | ([419f048](https://github.com/hongaar/bandersnatch/commit/419f0486e55b79a671185eda0ce3558c4cf3665f)) 224 | 225 | # [1.9.0](https://github.com/hongaar/bandersnatch/compare/v1.8.4...v1.9.0) (2021-10-25) 226 | 227 | ### Features 228 | 229 | - add option to pass yargs parserConfiguration 230 | ([#334](https://github.com/hongaar/bandersnatch/issues/334)) 231 | ([9a19c98](https://github.com/hongaar/bandersnatch/commit/9a19c983058b0d3598d8a07015fa69a788906d84)) 232 | 233 | ## [1.8.4](https://github.com/hongaar/bandersnatch/compare/v1.8.3...v1.8.4) (2021-10-14) 234 | 235 | ### Bug Fixes 236 | 237 | - **deps:** update dependency typed-emitter to v1.4.0 238 | ([#323](https://github.com/hongaar/bandersnatch/issues/323)) 239 | ([38570cd](https://github.com/hongaar/bandersnatch/commit/38570cdc754ac35f093b4c7415e3a0989a94c244)) 240 | 241 | ## [1.8.3](https://github.com/hongaar/bandersnatch/compare/v1.8.2...v1.8.3) (2021-09-26) 242 | 243 | ### Bug Fixes 244 | 245 | - **deps:** update dependency yargs to v17.2.1 246 | ([#313](https://github.com/hongaar/bandersnatch/issues/313)) 247 | ([65d2fd5](https://github.com/hongaar/bandersnatch/commit/65d2fd57f00dec73308175578a99b46521df7e70)) 248 | 249 | ## [1.8.2](https://github.com/hongaar/bandersnatch/compare/v1.8.1...v1.8.2) (2021-09-23) 250 | 251 | ### Bug Fixes 252 | 253 | - **deps:** update dependency yargs to v17.2.0 254 | ([#311](https://github.com/hongaar/bandersnatch/issues/311)) 255 | ([103eec3](https://github.com/hongaar/bandersnatch/commit/103eec38f3ddd5fab603b8c04aa4943b830f77f4)) 256 | 257 | ## [1.8.1](https://github.com/hongaar/bandersnatch/compare/v1.8.0...v1.8.1) (2021-09-21) 258 | 259 | ### Bug Fixes 260 | 261 | - **deps:** update dependency @types/yargs to v17.0.3 262 | ([#309](https://github.com/hongaar/bandersnatch/issues/309)) 263 | ([14ddd2f](https://github.com/hongaar/bandersnatch/commit/14ddd2fbfd32db7c7355078108731048f0c54039)) 264 | 265 | # [1.8.0](https://github.com/hongaar/bandersnatch/compare/v1.7.2...v1.8.0) (2021-09-08) 266 | 267 | ### Features 268 | 269 | - do not print errors returned from yargs 270 | ([#300](https://github.com/hongaar/bandersnatch/issues/300)) 271 | ([90712a9](https://github.com/hongaar/bandersnatch/commit/90712a93a45ff89e12f123ec851b08704f1e9b83)) 272 | 273 | ## [1.7.2](https://github.com/hongaar/bandersnatch/compare/v1.7.1...v1.7.2) (2021-08-13) 274 | 275 | ### Bug Fixes 276 | 277 | - **deps:** update dependency yargs to v17.1.1 278 | ([#288](https://github.com/hongaar/bandersnatch/issues/288)) 279 | ([f6d072f](https://github.com/hongaar/bandersnatch/commit/f6d072f24ca5ec7a07db304454fb157e41a58029)) 280 | 281 | ## [1.7.1](https://github.com/hongaar/bandersnatch/compare/v1.7.0...v1.7.1) (2021-08-05) 282 | 283 | ### Bug Fixes 284 | 285 | - **deps:** update dependency yargs to v17.1.0 286 | ([#282](https://github.com/hongaar/bandersnatch/issues/282)) 287 | ([0f97980](https://github.com/hongaar/bandersnatch/commit/0f9798063754a15a88f163d281e6f8e9b548bc58)) 288 | 289 | # [1.7.0](https://github.com/hongaar/bandersnatch/compare/v1.6.4...v1.7.0) (2021-07-29) 290 | 291 | ### Features 292 | 293 | - allow custom exit command implementation 294 | ([#275](https://github.com/hongaar/bandersnatch/issues/275)) 295 | ([9527735](https://github.com/hongaar/bandersnatch/commit/9527735bb440ab7701c4f27e2acb676e81bae2f6)) 296 | 297 | ## [1.6.4](https://github.com/hongaar/bandersnatch/compare/v1.6.3...v1.6.4) (2021-07-05) 298 | 299 | ### Bug Fixes 300 | 301 | - **deps:** update dependency @types/yargs to v17.0.2 302 | ([#271](https://github.com/hongaar/bandersnatch/issues/271)) 303 | ([b11ad1a](https://github.com/hongaar/bandersnatch/commit/b11ad1aeb16f0c44a605af49abbf2cd78115147c)) 304 | 305 | ## [1.6.3](https://github.com/hongaar/bandersnatch/compare/v1.6.2...v1.6.3) (2021-07-02) 306 | 307 | ### Bug Fixes 308 | 309 | - **deps:** update dependency @types/yargs to v17.0.1 310 | ([#270](https://github.com/hongaar/bandersnatch/issues/270)) 311 | ([f7ced20](https://github.com/hongaar/bandersnatch/commit/f7ced205c655fc3902e01540b31c79d8b2cd7513)) 312 | 313 | ## [1.6.2](https://github.com/hongaar/bandersnatch/compare/v1.6.1...v1.6.2) (2021-05-21) 314 | 315 | ### Bug Fixes 316 | 317 | - **deps:** update dependency @types/yargs to v16.0.3 318 | ([#252](https://github.com/hongaar/bandersnatch/issues/252)) 319 | ([f96d761](https://github.com/hongaar/bandersnatch/commit/f96d761fb6fb1cbae78da6eca3049be6d76304c5)) 320 | 321 | ## [1.6.1](https://github.com/hongaar/bandersnatch/compare/v1.6.0...v1.6.1) (2021-05-18) 322 | 323 | ### Bug Fixes 324 | 325 | - **deps:** update dependency @types/yargs to v16.0.2 326 | ([#250](https://github.com/hongaar/bandersnatch/issues/250)) 327 | ([ec587c9](https://github.com/hongaar/bandersnatch/commit/ec587c97a8a96d97ae9481d31122bb6c942cfb3e)) 328 | 329 | # [1.6.0](https://github.com/hongaar/bandersnatch/compare/v1.5.4...v1.6.0) (2021-05-13) 330 | 331 | ### Features 332 | 333 | - truncate history file 334 | ([#249](https://github.com/hongaar/bandersnatch/issues/249)) 335 | ([efee1a8](https://github.com/hongaar/bandersnatch/commit/efee1a8204fbaf48a6dd4a0dcf9346a035721415)) 336 | 337 | ## [1.5.4](https://github.com/hongaar/bandersnatch/compare/v1.5.3...v1.5.4) (2021-05-12) 338 | 339 | ### Bug Fixes 340 | 341 | - **deps:** update dependency yargs to v17 342 | ([#239](https://github.com/hongaar/bandersnatch/issues/239)) 343 | ([7ba1c64](https://github.com/hongaar/bandersnatch/commit/7ba1c64c5817b9ff437258eb13c571f11e7d952d)) 344 | 345 | ## [1.5.3](https://github.com/hongaar/bandersnatch/compare/v1.5.2...v1.5.3) (2021-05-10) 346 | 347 | ### Bug Fixes 348 | 349 | - **deps:** bump hosted-git-info from 2.8.8 to 2.8.9 350 | ([#246](https://github.com/hongaar/bandersnatch/issues/246)) 351 | ([9167797](https://github.com/hongaar/bandersnatch/commit/9167797d289c5623d00566599d90620500eaabb2)) 352 | - **deps:** bump lodash from 4.17.19 to 4.17.21 353 | ([#244](https://github.com/hongaar/bandersnatch/issues/244)) 354 | ([a0b4b61](https://github.com/hongaar/bandersnatch/commit/a0b4b619edd6d9ad4943799c9a41886c09c30c92)) 355 | 356 | ## [1.5.2](https://github.com/hongaar/bandersnatch/compare/v1.5.1...v1.5.2) (2021-03-26) 357 | 358 | ### Bug Fixes 359 | 360 | - **deps:** update dependency @types/yargs to v16.0.1 361 | ([#221](https://github.com/hongaar/bandersnatch/issues/221)) 362 | ([5462db8](https://github.com/hongaar/bandersnatch/commit/5462db8125e2813f8b40d099db006e9cbad31ecd)) 363 | 364 | ## [1.5.1](https://github.com/hongaar/bandersnatch/compare/v1.5.0...v1.5.1) (2021-01-30) 365 | 366 | ### Bug Fixes 367 | 368 | - bump @types/node 369 | ([8672bf5](https://github.com/hongaar/bandersnatch/commit/8672bf5e17a2efe88bfcbb913088bb642db6c40a)) 370 | 371 | # [1.5.0](https://github.com/hongaar/bandersnatch/compare/v1.4.0...v1.5.0) (2021-01-30) 372 | 373 | ### Features 374 | 375 | - history file ([#191](https://github.com/hongaar/bandersnatch/issues/191)) 376 | ([14b2b0d](https://github.com/hongaar/bandersnatch/commit/14b2b0d02d9cfa8e60b66489172d0aae10545b5d)) 377 | 378 | # [1.4.0](https://github.com/hongaar/bandersnatch/compare/v1.3.9...v1.4.0) (2021-01-30) 379 | 380 | ### Features 381 | 382 | - bump dependencies 383 | ([10dac0f](https://github.com/hongaar/bandersnatch/commit/10dac0f879d8b760d2c74ac94d560250d2d937d8)) 384 | 385 | ## [1.3.9](https://github.com/hongaar/bandersnatch/compare/v1.3.8...v1.3.9) (2021-01-30) 386 | 387 | ### Bug Fixes 388 | 389 | - stop and restart repl to allow enquirer prompt 390 | ([#188](https://github.com/hongaar/bandersnatch/issues/188)) 391 | ([059461a](https://github.com/hongaar/bandersnatch/commit/059461af748f4a3ca6948549ccf0c5d5b4190a37)) 392 | 393 | ## [1.3.8](https://github.com/hongaar/bandersnatch/compare/v1.3.7...v1.3.8) (2020-10-16) 394 | 395 | ### Bug Fixes 396 | 397 | - **deps:** update dependency @types/yargs to v15.0.9 398 | ([#131](https://github.com/hongaar/bandersnatch/issues/131)) 399 | ([b4d4c8f](https://github.com/hongaar/bandersnatch/commit/b4d4c8fb34d7cc9255dde5bf20487e2388b65a9b)) 400 | 401 | ## [1.3.7](https://github.com/hongaar/bandersnatch/compare/v1.3.6...v1.3.7) (2020-10-16) 402 | 403 | ### Bug Fixes 404 | 405 | - **deps:** update dependency yargs to v16.1.0 406 | ([#130](https://github.com/hongaar/bandersnatch/issues/130)) 407 | ([af53afb](https://github.com/hongaar/bandersnatch/commit/af53afbd2e51dd0e6e97b0c84c7bebbb41620986)) 408 | 409 | ## [1.3.6](https://github.com/hongaar/bandersnatch/compare/v1.3.5...v1.3.6) (2020-10-08) 410 | 411 | ### Bug Fixes 412 | 413 | - **deps:** update dependency @types/yargs to v15.0.8 414 | ([#126](https://github.com/hongaar/bandersnatch/issues/126)) 415 | ([9c3c3e4](https://github.com/hongaar/bandersnatch/commit/9c3c3e41318fe31391045b77435d373b803b5c6e)) 416 | 417 | ## [1.3.5](https://github.com/hongaar/bandersnatch/compare/v1.3.4...v1.3.5) (2020-10-05) 418 | 419 | ### Bug Fixes 420 | 421 | - **deps:** update dependency yargs to v16 422 | ([#108](https://github.com/hongaar/bandersnatch/issues/108)) 423 | ([d82546c](https://github.com/hongaar/bandersnatch/commit/d82546c75f68fe78f946548b374736513749419c)) 424 | 425 | ## [1.3.4](https://github.com/hongaar/bandersnatch/compare/v1.3.3...v1.3.4) (2020-09-23) 426 | 427 | ### Bug Fixes 428 | 429 | - **deps:** update dependency typed-emitter to v1.3.1 430 | ([#119](https://github.com/hongaar/bandersnatch/issues/119)) 431 | ([c8c2451](https://github.com/hongaar/bandersnatch/commit/c8c24512f450856649abddca8a7e67b4967b6763)) 432 | 433 | ## [1.3.3](https://github.com/hongaar/bandersnatch/compare/v1.3.2...v1.3.3) (2020-09-23) 434 | 435 | ### Bug Fixes 436 | 437 | - **deps:** update dependency @types/yargs to v15.0.7 438 | ([#118](https://github.com/hongaar/bandersnatch/issues/118)) 439 | ([08f289c](https://github.com/hongaar/bandersnatch/commit/08f289c544e872b0d2fb7088adb02add2017a0ef)) 440 | 441 | ## [1.3.2](https://github.com/hongaar/bandersnatch/compare/v1.3.1...v1.3.2) (2020-09-23) 442 | 443 | ### Bug Fixes 444 | 445 | - **deps:** update dependency @types/yargs to v15.0.6 446 | ([#117](https://github.com/hongaar/bandersnatch/issues/117)) 447 | ([57a29ee](https://github.com/hongaar/bandersnatch/commit/57a29ee3d9bc8d41b955ef9950d07873696a1370)) 448 | 449 | ## [1.3.1](https://github.com/hongaar/bandersnatch/compare/v1.3.0...v1.3.1) (2020-08-16) 450 | 451 | ### Bug Fixes 452 | 453 | - **deps:** update dependency typed-emitter to v1.3.0 454 | ([#90](https://github.com/hongaar/bandersnatch/issues/90)) 455 | ([94d9002](https://github.com/hongaar/bandersnatch/commit/94d90021d3e03fdcb7fdc21ceacb4df3f1d316b6)) 456 | 457 | # [1.3.0](https://github.com/hongaar/bandersnatch/compare/v1.2.6...v1.3.0) (2020-07-28) 458 | 459 | ### Features 460 | 461 | - enquirer ([#81](https://github.com/hongaar/bandersnatch/issues/81)) 462 | ([7891e70](https://github.com/hongaar/bandersnatch/commit/7891e70f11cdbfbae40a3932c51e4104b810c930)) 463 | 464 | ## [1.2.6](https://github.com/hongaar/bandersnatch/compare/v1.2.5...v1.2.6) (2020-07-23) 465 | 466 | ### Bug Fixes 467 | 468 | - **deps:** update dependency inquirer to v7.3.3 469 | ([#75](https://github.com/hongaar/bandersnatch/issues/75)) 470 | ([a83a1bf](https://github.com/hongaar/bandersnatch/commit/a83a1bf9ebc74226d3f87f9f450397f90f3524ac)) 471 | 472 | ## [1.2.5](https://github.com/hongaar/bandersnatch/compare/v1.2.4...v1.2.5) (2020-07-21) 473 | 474 | ### Bug Fixes 475 | 476 | - **deps:** update dependency @types/inquirer to v7 477 | ([#74](https://github.com/hongaar/bandersnatch/issues/74)) 478 | ([f5a53d1](https://github.com/hongaar/bandersnatch/commit/f5a53d1a4b6b164fee0cf442d3803953394ded25)) 479 | 480 | ## [1.2.4](https://github.com/hongaar/bandersnatch/compare/v1.2.3...v1.2.4) (2020-07-13) 481 | 482 | ### Bug Fixes 483 | 484 | - **deps:** update dependency inquirer to v7.3.2 485 | ([#68](https://github.com/hongaar/bandersnatch/issues/68)) 486 | ([802f3e4](https://github.com/hongaar/bandersnatch/commit/802f3e4edd453298a408b37ab40dd3a9a8929918)) 487 | 488 | ## [1.2.3](https://github.com/hongaar/bandersnatch/compare/v1.2.2...v1.2.3) (2020-07-11) 489 | 490 | ### Bug Fixes 491 | 492 | - **deps:** update dependency yargs to v15.4.1 493 | ([#65](https://github.com/hongaar/bandersnatch/issues/65)) 494 | ([232f249](https://github.com/hongaar/bandersnatch/commit/232f24914301d0254dc3f49446b1bcce5484cb6c)) 495 | 496 | ## [1.2.2](https://github.com/hongaar/bandersnatch/compare/v1.2.1...v1.2.2) (2020-07-10) 497 | 498 | ### Bug Fixes 499 | 500 | - **deps:** update dependency inquirer to v7.3.1 501 | ([#64](https://github.com/hongaar/bandersnatch/issues/64)) 502 | ([058af9b](https://github.com/hongaar/bandersnatch/commit/058af9ba0724706319476309c3edc7ea344a01a3)) 503 | 504 | ## [1.2.1](https://github.com/hongaar/bandersnatch/compare/v1.2.0...v1.2.1) (2020-07-10) 505 | 506 | ### Bug Fixes 507 | 508 | - replace constructor.name comparison with instanceof statement 509 | ([fedb2f8](https://github.com/hongaar/bandersnatch/commit/fedb2f88a93597501bf23a00424e9c81ee154b36)) 510 | 511 | # [1.2.0](https://github.com/hongaar/bandersnatch/compare/v1.1.0...v1.2.0) (2020-07-10) 512 | 513 | ### Features 514 | 515 | - add hidden option for commands 516 | ([3b16235](https://github.com/hongaar/bandersnatch/commit/3b16235279638f4c0151ff6d0f919a25a8969722)) 517 | 518 | # [1.1.0](https://github.com/hongaar/bandersnatch/compare/v1.0.1...v1.1.0) (2020-07-07) 519 | 520 | ### Features 521 | 522 | - add commandHandler to action callback and add ts section to readme 523 | ([2c34c21](https://github.com/hongaar/bandersnatch/commit/2c34c21626e5146b78f12a62362623663d09fb95)) 524 | 525 | ## [1.0.1](https://github.com/hongaar/bandersnatch/compare/v1.0.0...v1.0.1) (2020-07-07) 526 | 527 | ### Bug Fixes 528 | 529 | - remove console.log 530 | ([341432c](https://github.com/hongaar/bandersnatch/commit/341432c2f13711808ef48da0f1afb0a260c4c7df)) 531 | 532 | # 1.0.0 (2020-07-07) 533 | 534 | ### Bug Fixes 535 | 536 | - **deps:** update dependency @types/yargs to v15.0.5 537 | ([#34](https://github.com/hongaar/bandersnatch/issues/34)) 538 | ([3a4e61b](https://github.com/hongaar/bandersnatch/commit/3a4e61b225802a5e015b334356914f3d560a4eaf)) 539 | - **deps:** update dependency inquirer to v7.0.6 540 | ([#3](https://github.com/hongaar/bandersnatch/issues/3)) 541 | ([c8efb98](https://github.com/hongaar/bandersnatch/commit/c8efb98f8ba560ec499623de9fc044ba8db9ae8a)) 542 | - **deps:** update dependency inquirer to v7.1.0 543 | ([#6](https://github.com/hongaar/bandersnatch/issues/6)) 544 | ([8336ea4](https://github.com/hongaar/bandersnatch/commit/8336ea4a56aa66b22815985fc0f4026c68389ae0)) 545 | - **deps:** update dependency inquirer to v7.2.0 546 | ([#45](https://github.com/hongaar/bandersnatch/issues/45)) 547 | ([99b1b0a](https://github.com/hongaar/bandersnatch/commit/99b1b0ae77af2e68fba180d350c4834b8e61a8ff)) 548 | - **deps:** update dependency inquirer to v7.3.0 549 | ([#52](https://github.com/hongaar/bandersnatch/issues/52)) 550 | ([5ae6e06](https://github.com/hongaar/bandersnatch/commit/5ae6e066c2d1e764da5ccec7f6d0c21c67493e0f)) 551 | - **deps:** update dependency yargs to v15.3.0 552 | ([#5](https://github.com/hongaar/bandersnatch/issues/5)) 553 | ([cb03568](https://github.com/hongaar/bandersnatch/commit/cb03568e24e0ae9e078064b13dcff93c3f0441c8)) 554 | - **deps:** update dependency yargs to v15.3.1 555 | ([#8](https://github.com/hongaar/bandersnatch/issues/8)) 556 | ([afb63c8](https://github.com/hongaar/bandersnatch/commit/afb63c847c72ab79838cc20f4c13b077afdb8201)) 557 | - **deps:** update dependency yargs to v15.4.0 558 | ([#53](https://github.com/hongaar/bandersnatch/issues/53)) 559 | ([50caa78](https://github.com/hongaar/bandersnatch/commit/50caa783a098f92e1ab3c57a643e519da513f004)) 560 | 561 | ### Features 562 | 563 | - arg types are working 564 | ([8a2cdf9](https://github.com/hongaar/bandersnatch/commit/8a2cdf96110b11172850f000c39c5790ecc6e791)) 565 | - arguments 566 | ([c186a86](https://github.com/hongaar/bandersnatch/commit/c186a86ff672dc46c96dfbaccf4017fe7fda9937)) 567 | - better error handling 568 | ([c5c7601](https://github.com/hongaar/bandersnatch/commit/c5c760105b34f2b15c20ddd7d3771dc9eff69eee)) 569 | - prefer choices 570 | ([e7bdc11](https://github.com/hongaar/bandersnatch/commit/e7bdc117ee851868345ff771b9879db8107a969b)) 571 | - prompt example 572 | ([8ff414b](https://github.com/hongaar/bandersnatch/commit/8ff414bb3a801ddd19adbf5327a8f5ee8f4896d1)) 573 | - prompter (wip) 574 | ([5bc9595](https://github.com/hongaar/bandersnatch/commit/5bc95954082c2d41a15cd914f9fc27e0b1b012ff)) 575 | - repl 576 | ([6ee5b10](https://github.com/hongaar/bandersnatch/commit/6ee5b10378847c05f7f111bcee6c3c79889c9058)) 577 | - show help when no handler is defined 578 | ([5c9b5e7](https://github.com/hongaar/bandersnatch/commit/5c9b5e7ed3d9d8b7cdc1677d0ecb7b5615be7e6d)) 579 | 580 | ### Reverts 581 | 582 | - pin dependencies 583 | ([3043bf6](https://github.com/hongaar/bandersnatch/commit/3043bf63a2a07d43a19c3a6e7ebae54e325387a3)) 584 | -------------------------------------------------------------------------------- /.yarn/plugins/@yarnpkg/plugin-typescript.cjs: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | //prettier-ignore 3 | module.exports = { 4 | name: "@yarnpkg/plugin-typescript", 5 | factory: function (require) { 6 | var plugin=(()=>{var Ft=Object.create,H=Object.defineProperty,Bt=Object.defineProperties,Kt=Object.getOwnPropertyDescriptor,zt=Object.getOwnPropertyDescriptors,Gt=Object.getOwnPropertyNames,Q=Object.getOwnPropertySymbols,$t=Object.getPrototypeOf,ne=Object.prototype.hasOwnProperty,De=Object.prototype.propertyIsEnumerable;var Re=(e,t,r)=>t in e?H(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,u=(e,t)=>{for(var r in t||(t={}))ne.call(t,r)&&Re(e,r,t[r]);if(Q)for(var r of Q(t))De.call(t,r)&&Re(e,r,t[r]);return e},g=(e,t)=>Bt(e,zt(t)),Lt=e=>H(e,"__esModule",{value:!0});var R=(e,t)=>{var r={};for(var s in e)ne.call(e,s)&&t.indexOf(s)<0&&(r[s]=e[s]);if(e!=null&&Q)for(var s of Q(e))t.indexOf(s)<0&&De.call(e,s)&&(r[s]=e[s]);return r};var I=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),Vt=(e,t)=>{for(var r in t)H(e,r,{get:t[r],enumerable:!0})},Qt=(e,t,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of Gt(t))!ne.call(e,s)&&s!=="default"&&H(e,s,{get:()=>t[s],enumerable:!(r=Kt(t,s))||r.enumerable});return e},C=e=>Qt(Lt(H(e!=null?Ft($t(e)):{},"default",e&&e.__esModule&&"default"in e?{get:()=>e.default,enumerable:!0}:{value:e,enumerable:!0})),e);var xe=I(J=>{"use strict";Object.defineProperty(J,"__esModule",{value:!0});function _(e){let t=[...e.caches],r=t.shift();return r===void 0?ve():{get(s,n,a={miss:()=>Promise.resolve()}){return r.get(s,n,a).catch(()=>_({caches:t}).get(s,n,a))},set(s,n){return r.set(s,n).catch(()=>_({caches:t}).set(s,n))},delete(s){return r.delete(s).catch(()=>_({caches:t}).delete(s))},clear(){return r.clear().catch(()=>_({caches:t}).clear())}}}function ve(){return{get(e,t,r={miss:()=>Promise.resolve()}){return t().then(n=>Promise.all([n,r.miss(n)])).then(([n])=>n)},set(e,t){return Promise.resolve(t)},delete(e){return Promise.resolve()},clear(){return Promise.resolve()}}}J.createFallbackableCache=_;J.createNullCache=ve});var Ee=I(($s,qe)=>{qe.exports=xe()});var Te=I(ae=>{"use strict";Object.defineProperty(ae,"__esModule",{value:!0});function Jt(e={serializable:!0}){let t={};return{get(r,s,n={miss:()=>Promise.resolve()}){let a=JSON.stringify(r);if(a in t)return Promise.resolve(e.serializable?JSON.parse(t[a]):t[a]);let o=s(),d=n&&n.miss||(()=>Promise.resolve());return o.then(y=>d(y)).then(()=>o)},set(r,s){return t[JSON.stringify(r)]=e.serializable?JSON.stringify(s):s,Promise.resolve(s)},delete(r){return delete t[JSON.stringify(r)],Promise.resolve()},clear(){return t={},Promise.resolve()}}}ae.createInMemoryCache=Jt});var we=I((Vs,Me)=>{Me.exports=Te()});var Ce=I(M=>{"use strict";Object.defineProperty(M,"__esModule",{value:!0});function Xt(e,t,r){let s={"x-algolia-api-key":r,"x-algolia-application-id":t};return{headers(){return e===oe.WithinHeaders?s:{}},queryParameters(){return e===oe.WithinQueryParameters?s:{}}}}function Yt(e){let t=0,r=()=>(t++,new Promise(s=>{setTimeout(()=>{s(e(r))},Math.min(100*t,1e3))}));return e(r)}function ke(e,t=(r,s)=>Promise.resolve()){return Object.assign(e,{wait(r){return ke(e.then(s=>Promise.all([t(s,r),s])).then(s=>s[1]))}})}function Zt(e){let t=e.length-1;for(t;t>0;t--){let r=Math.floor(Math.random()*(t+1)),s=e[t];e[t]=e[r],e[r]=s}return e}function er(e,t){return Object.keys(t!==void 0?t:{}).forEach(r=>{e[r]=t[r](e)}),e}function tr(e,...t){let r=0;return e.replace(/%s/g,()=>encodeURIComponent(t[r++]))}var rr="4.2.0",sr=e=>()=>e.transporter.requester.destroy(),oe={WithinQueryParameters:0,WithinHeaders:1};M.AuthMode=oe;M.addMethods=er;M.createAuth=Xt;M.createRetryablePromise=Yt;M.createWaitablePromise=ke;M.destroy=sr;M.encode=tr;M.shuffle=Zt;M.version=rr});var F=I((Js,Ue)=>{Ue.exports=Ce()});var Ne=I(ie=>{"use strict";Object.defineProperty(ie,"__esModule",{value:!0});var nr={Delete:"DELETE",Get:"GET",Post:"POST",Put:"PUT"};ie.MethodEnum=nr});var B=I((Ys,We)=>{We.exports=Ne()});var Ze=I(A=>{"use strict";Object.defineProperty(A,"__esModule",{value:!0});var He=B();function ce(e,t){let r=e||{},s=r.data||{};return Object.keys(r).forEach(n=>{["timeout","headers","queryParameters","data","cacheable"].indexOf(n)===-1&&(s[n]=r[n])}),{data:Object.entries(s).length>0?s:void 0,timeout:r.timeout||t,headers:r.headers||{},queryParameters:r.queryParameters||{},cacheable:r.cacheable}}var X={Read:1,Write:2,Any:3},U={Up:1,Down:2,Timeouted:3},_e=2*60*1e3;function ue(e,t=U.Up){return g(u({},e),{status:t,lastUpdate:Date.now()})}function Fe(e){return e.status===U.Up||Date.now()-e.lastUpdate>_e}function Be(e){return e.status===U.Timeouted&&Date.now()-e.lastUpdate<=_e}function le(e){return{protocol:e.protocol||"https",url:e.url,accept:e.accept||X.Any}}function ar(e,t){return Promise.all(t.map(r=>e.get(r,()=>Promise.resolve(ue(r))))).then(r=>{let s=r.filter(d=>Fe(d)),n=r.filter(d=>Be(d)),a=[...s,...n],o=a.length>0?a.map(d=>le(d)):t;return{getTimeout(d,y){return(n.length===0&&d===0?1:n.length+3+d)*y},statelessHosts:o}})}var or=({isTimedOut:e,status:t})=>!e&&~~t==0,ir=e=>{let t=e.status;return e.isTimedOut||or(e)||~~(t/100)!=2&&~~(t/100)!=4},cr=({status:e})=>~~(e/100)==2,ur=(e,t)=>ir(e)?t.onRetry(e):cr(e)?t.onSucess(e):t.onFail(e);function Qe(e,t,r,s){let n=[],a=$e(r,s),o=Le(e,s),d=r.method,y=r.method!==He.MethodEnum.Get?{}:u(u({},r.data),s.data),b=u(u(u({"x-algolia-agent":e.userAgent.value},e.queryParameters),y),s.queryParameters),f=0,p=(h,S)=>{let O=h.pop();if(O===void 0)throw Ve(de(n));let P={data:a,headers:o,method:d,url:Ge(O,r.path,b),connectTimeout:S(f,e.timeouts.connect),responseTimeout:S(f,s.timeout)},x=j=>{let T={request:P,response:j,host:O,triesLeft:h.length};return n.push(T),T},v={onSucess:j=>Ke(j),onRetry(j){let T=x(j);return j.isTimedOut&&f++,Promise.all([e.logger.info("Retryable failure",pe(T)),e.hostsCache.set(O,ue(O,j.isTimedOut?U.Timeouted:U.Down))]).then(()=>p(h,S))},onFail(j){throw x(j),ze(j,de(n))}};return e.requester.send(P).then(j=>ur(j,v))};return ar(e.hostsCache,t).then(h=>p([...h.statelessHosts].reverse(),h.getTimeout))}function lr(e){let{hostsCache:t,logger:r,requester:s,requestsCache:n,responsesCache:a,timeouts:o,userAgent:d,hosts:y,queryParameters:b,headers:f}=e,p={hostsCache:t,logger:r,requester:s,requestsCache:n,responsesCache:a,timeouts:o,userAgent:d,headers:f,queryParameters:b,hosts:y.map(h=>le(h)),read(h,S){let O=ce(S,p.timeouts.read),P=()=>Qe(p,p.hosts.filter(j=>(j.accept&X.Read)!=0),h,O);if((O.cacheable!==void 0?O.cacheable:h.cacheable)!==!0)return P();let v={request:h,mappedRequestOptions:O,transporter:{queryParameters:p.queryParameters,headers:p.headers}};return p.responsesCache.get(v,()=>p.requestsCache.get(v,()=>p.requestsCache.set(v,P()).then(j=>Promise.all([p.requestsCache.delete(v),j]),j=>Promise.all([p.requestsCache.delete(v),Promise.reject(j)])).then(([j,T])=>T)),{miss:j=>p.responsesCache.set(v,j)})},write(h,S){return Qe(p,p.hosts.filter(O=>(O.accept&X.Write)!=0),h,ce(S,p.timeouts.write))}};return p}function dr(e){let t={value:`Algolia for JavaScript (${e})`,add(r){let s=`; ${r.segment}${r.version!==void 0?` (${r.version})`:""}`;return t.value.indexOf(s)===-1&&(t.value=`${t.value}${s}`),t}};return t}function Ke(e){try{return JSON.parse(e.content)}catch(t){throw Je(t.message,e)}}function ze({content:e,status:t},r){let s=e;try{s=JSON.parse(e).message}catch(n){}return Xe(s,t,r)}function pr(e,...t){let r=0;return e.replace(/%s/g,()=>encodeURIComponent(t[r++]))}function Ge(e,t,r){let s=Ye(r),n=`${e.protocol}://${e.url}/${t.charAt(0)==="/"?t.substr(1):t}`;return s.length&&(n+=`?${s}`),n}function Ye(e){let t=r=>Object.prototype.toString.call(r)==="[object Object]"||Object.prototype.toString.call(r)==="[object Array]";return Object.keys(e).map(r=>pr("%s=%s",r,t(e[r])?JSON.stringify(e[r]):e[r])).join("&")}function $e(e,t){if(e.method===He.MethodEnum.Get||e.data===void 0&&t.data===void 0)return;let r=Array.isArray(e.data)?e.data:u(u({},e.data),t.data);return JSON.stringify(r)}function Le(e,t){let r=u(u({},e.headers),t.headers),s={};return Object.keys(r).forEach(n=>{let a=r[n];s[n.toLowerCase()]=a}),s}function de(e){return e.map(t=>pe(t))}function pe(e){let t=e.request.headers["x-algolia-api-key"]?{"x-algolia-api-key":"*****"}:{};return g(u({},e),{request:g(u({},e.request),{headers:u(u({},e.request.headers),t)})})}function Xe(e,t,r){return{name:"ApiError",message:e,status:t,transporterStackTrace:r}}function Je(e,t){return{name:"DeserializationError",message:e,response:t}}function Ve(e){return{name:"RetryError",message:"Unreachable hosts - your application id may be incorrect. If the error persists, contact support@algolia.com.",transporterStackTrace:e}}A.CallEnum=X;A.HostStatusEnum=U;A.createApiError=Xe;A.createDeserializationError=Je;A.createMappedRequestOptions=ce;A.createRetryError=Ve;A.createStatefulHost=ue;A.createStatelessHost=le;A.createTransporter=lr;A.createUserAgent=dr;A.deserializeFailure=ze;A.deserializeSuccess=Ke;A.isStatefulHostTimeouted=Be;A.isStatefulHostUp=Fe;A.serializeData=$e;A.serializeHeaders=Le;A.serializeQueryParameters=Ye;A.serializeUrl=Ge;A.stackFrameWithoutCredentials=pe;A.stackTraceWithoutCredentials=de});var K=I((en,et)=>{et.exports=Ze()});var tt=I(w=>{"use strict";Object.defineProperty(w,"__esModule",{value:!0});var N=F(),mr=K(),z=B(),hr=e=>{let t=e.region||"us",r=N.createAuth(N.AuthMode.WithinHeaders,e.appId,e.apiKey),s=mr.createTransporter(g(u({hosts:[{url:`analytics.${t}.algolia.com`}]},e),{headers:u(g(u({},r.headers()),{"content-type":"application/json"}),e.headers),queryParameters:u(u({},r.queryParameters()),e.queryParameters)})),n=e.appId;return N.addMethods({appId:n,transporter:s},e.methods)},yr=e=>(t,r)=>e.transporter.write({method:z.MethodEnum.Post,path:"2/abtests",data:t},r),gr=e=>(t,r)=>e.transporter.write({method:z.MethodEnum.Delete,path:N.encode("2/abtests/%s",t)},r),fr=e=>(t,r)=>e.transporter.read({method:z.MethodEnum.Get,path:N.encode("2/abtests/%s",t)},r),br=e=>t=>e.transporter.read({method:z.MethodEnum.Get,path:"2/abtests"},t),Pr=e=>(t,r)=>e.transporter.write({method:z.MethodEnum.Post,path:N.encode("2/abtests/%s/stop",t)},r);w.addABTest=yr;w.createAnalyticsClient=hr;w.deleteABTest=gr;w.getABTest=fr;w.getABTests=br;w.stopABTest=Pr});var st=I((rn,rt)=>{rt.exports=tt()});var at=I(G=>{"use strict";Object.defineProperty(G,"__esModule",{value:!0});var me=F(),jr=K(),nt=B(),Or=e=>{let t=e.region||"us",r=me.createAuth(me.AuthMode.WithinHeaders,e.appId,e.apiKey),s=jr.createTransporter(g(u({hosts:[{url:`recommendation.${t}.algolia.com`}]},e),{headers:u(g(u({},r.headers()),{"content-type":"application/json"}),e.headers),queryParameters:u(u({},r.queryParameters()),e.queryParameters)}));return me.addMethods({appId:e.appId,transporter:s},e.methods)},Ir=e=>t=>e.transporter.read({method:nt.MethodEnum.Get,path:"1/strategies/personalization"},t),Ar=e=>(t,r)=>e.transporter.write({method:nt.MethodEnum.Post,path:"1/strategies/personalization",data:t},r);G.createRecommendationClient=Or;G.getPersonalizationStrategy=Ir;G.setPersonalizationStrategy=Ar});var it=I((nn,ot)=>{ot.exports=at()});var jt=I(i=>{"use strict";Object.defineProperty(i,"__esModule",{value:!0});var l=F(),q=K(),m=B(),Sr=require("crypto");function Y(e){let t=r=>e.request(r).then(s=>{if(e.batch!==void 0&&e.batch(s.hits),!e.shouldStop(s))return s.cursor?t({cursor:s.cursor}):t({page:(r.page||0)+1})});return t({})}var Dr=e=>{let t=e.appId,r=l.createAuth(e.authMode!==void 0?e.authMode:l.AuthMode.WithinHeaders,t,e.apiKey),s=q.createTransporter(g(u({hosts:[{url:`${t}-dsn.algolia.net`,accept:q.CallEnum.Read},{url:`${t}.algolia.net`,accept:q.CallEnum.Write}].concat(l.shuffle([{url:`${t}-1.algolianet.com`},{url:`${t}-2.algolianet.com`},{url:`${t}-3.algolianet.com`}]))},e),{headers:u(g(u({},r.headers()),{"content-type":"application/x-www-form-urlencoded"}),e.headers),queryParameters:u(u({},r.queryParameters()),e.queryParameters)})),n={transporter:s,appId:t,addAlgoliaAgent(a,o){s.userAgent.add({segment:a,version:o})},clearCache(){return Promise.all([s.requestsCache.clear(),s.responsesCache.clear()]).then(()=>{})}};return l.addMethods(n,e.methods)};function ct(){return{name:"MissingObjectIDError",message:"All objects must have an unique objectID (like a primary key) to be valid. Algolia is also able to generate objectIDs automatically but *it's not recommended*. To do it, use the `{'autoGenerateObjectIDIfNotExist': true}` option."}}function ut(){return{name:"ObjectNotFoundError",message:"Object not found."}}function lt(){return{name:"ValidUntilNotFoundError",message:"ValidUntil not found in given secured api key."}}var Rr=e=>(t,r)=>{let d=r||{},{queryParameters:s}=d,n=R(d,["queryParameters"]),a=u({acl:t},s!==void 0?{queryParameters:s}:{}),o=(y,b)=>l.createRetryablePromise(f=>$(e)(y.key,b).catch(p=>{if(p.status!==404)throw p;return f()}));return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:"1/keys",data:a},n),o)},vr=e=>(t,r,s)=>{let n=q.createMappedRequestOptions(s);return n.queryParameters["X-Algolia-User-ID"]=t,e.transporter.write({method:m.MethodEnum.Post,path:"1/clusters/mapping",data:{cluster:r}},n)},xr=e=>(t,r,s)=>e.transporter.write({method:m.MethodEnum.Post,path:"1/clusters/mapping/batch",data:{users:t,cluster:r}},s),Z=e=>(t,r,s)=>{let n=(a,o)=>L(e)(t,{methods:{waitTask:D}}).waitTask(a.taskID,o);return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/operation",t),data:{operation:"copy",destination:r}},s),n)},qr=e=>(t,r,s)=>Z(e)(t,r,g(u({},s),{scope:[ee.Rules]})),Er=e=>(t,r,s)=>Z(e)(t,r,g(u({},s),{scope:[ee.Settings]})),Tr=e=>(t,r,s)=>Z(e)(t,r,g(u({},s),{scope:[ee.Synonyms]})),Mr=e=>(t,r)=>{let s=(n,a)=>l.createRetryablePromise(o=>$(e)(t,a).then(o).catch(d=>{if(d.status!==404)throw d}));return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Delete,path:l.encode("1/keys/%s",t)},r),s)},wr=()=>(e,t)=>{let r=q.serializeQueryParameters(t),s=Sr.createHmac("sha256",e).update(r).digest("hex");return Buffer.from(s+r).toString("base64")},$=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/keys/%s",t)},r),kr=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:"1/logs"},t),Cr=()=>e=>{let t=Buffer.from(e,"base64").toString("ascii"),r=/validUntil=(\d+)/,s=t.match(r);if(s===null)throw lt();return parseInt(s[1],10)-Math.round(new Date().getTime()/1e3)},Ur=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:"1/clusters/mapping/top"},t),Nr=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/clusters/mapping/%s",t)},r),Wr=e=>t=>{let n=t||{},{retrieveMappings:r}=n,s=R(n,["retrieveMappings"]);return r===!0&&(s.getClusters=!0),e.transporter.read({method:m.MethodEnum.Get,path:"1/clusters/mapping/pending"},s)},L=e=>(t,r={})=>{let s={transporter:e.transporter,appId:e.appId,indexName:t};return l.addMethods(s,r.methods)},Hr=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:"1/keys"},t),_r=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:"1/clusters"},t),Fr=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:"1/indexes"},t),Br=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:"1/clusters/mapping"},t),Kr=e=>(t,r,s)=>{let n=(a,o)=>L(e)(t,{methods:{waitTask:D}}).waitTask(a.taskID,o);return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/operation",t),data:{operation:"move",destination:r}},s),n)},zr=e=>(t,r)=>{let s=(n,a)=>Promise.all(Object.keys(n.taskID).map(o=>L(e)(o,{methods:{waitTask:D}}).waitTask(n.taskID[o],a)));return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:"1/indexes/*/batch",data:{requests:t}},r),s)},Gr=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Post,path:"1/indexes/*/objects",data:{requests:t}},r),$r=e=>(t,r)=>{let s=t.map(n=>g(u({},n),{params:q.serializeQueryParameters(n.params||{})}));return e.transporter.read({method:m.MethodEnum.Post,path:"1/indexes/*/queries",data:{requests:s},cacheable:!0},r)},Lr=e=>(t,r)=>Promise.all(t.map(s=>{let d=s.params,{facetName:n,facetQuery:a}=d,o=R(d,["facetName","facetQuery"]);return L(e)(s.indexName,{methods:{searchForFacetValues:dt}}).searchForFacetValues(n,a,u(u({},r),o))})),Vr=e=>(t,r)=>{let s=q.createMappedRequestOptions(r);return s.queryParameters["X-Algolia-User-ID"]=t,e.transporter.write({method:m.MethodEnum.Delete,path:"1/clusters/mapping"},s)},Qr=e=>(t,r)=>{let s=(n,a)=>l.createRetryablePromise(o=>$(e)(t,a).catch(d=>{if(d.status!==404)throw d;return o()}));return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/keys/%s/restore",t)},r),s)},Jr=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Post,path:"1/clusters/mapping/search",data:{query:t}},r),Xr=e=>(t,r)=>{let s=Object.assign({},r),f=r||{},{queryParameters:n}=f,a=R(f,["queryParameters"]),o=n?{queryParameters:n}:{},d=["acl","indexes","referers","restrictSources","queryParameters","description","maxQueriesPerIPPerHour","maxHitsPerQuery"],y=p=>Object.keys(s).filter(h=>d.indexOf(h)!==-1).every(h=>p[h]===s[h]),b=(p,h)=>l.createRetryablePromise(S=>$(e)(t,h).then(O=>y(O)?Promise.resolve():S()));return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Put,path:l.encode("1/keys/%s",t),data:o},a),b)},pt=e=>(t,r)=>{let s=(n,a)=>D(e)(n.taskID,a);return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/batch",e.indexName),data:{requests:t}},r),s)},Yr=e=>t=>Y(g(u({},t),{shouldStop:r=>r.cursor===void 0,request:r=>e.transporter.read({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/browse",e.indexName),data:r},t)})),Zr=e=>t=>{let r=u({hitsPerPage:1e3},t);return Y(g(u({},r),{shouldStop:s=>s.hits.lengthg(u({},n),{hits:n.hits.map(a=>(delete a._highlightResult,a))}))}}))},es=e=>t=>{let r=u({hitsPerPage:1e3},t);return Y(g(u({},r),{shouldStop:s=>s.hits.lengthg(u({},n),{hits:n.hits.map(a=>(delete a._highlightResult,a))}))}}))},te=e=>(t,r,s)=>{let y=s||{},{batchSize:n}=y,a=R(y,["batchSize"]),o={taskIDs:[],objectIDs:[]},d=(b=0)=>{let f=[],p;for(p=b;p({action:r,body:h})),a).then(h=>(o.objectIDs=o.objectIDs.concat(h.objectIDs),o.taskIDs.push(h.taskID),p++,d(p)))};return l.createWaitablePromise(d(),(b,f)=>Promise.all(b.taskIDs.map(p=>D(e)(p,f))))},ts=e=>t=>l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/clear",e.indexName)},t),(r,s)=>D(e)(r.taskID,s)),rs=e=>t=>{let a=t||{},{forwardToReplicas:r}=a,s=R(a,["forwardToReplicas"]),n=q.createMappedRequestOptions(s);return r&&(n.queryParameters.forwardToReplicas=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/rules/clear",e.indexName)},n),(o,d)=>D(e)(o.taskID,d))},ss=e=>t=>{let a=t||{},{forwardToReplicas:r}=a,s=R(a,["forwardToReplicas"]),n=q.createMappedRequestOptions(s);return r&&(n.queryParameters.forwardToReplicas=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/synonyms/clear",e.indexName)},n),(o,d)=>D(e)(o.taskID,d))},ns=e=>(t,r)=>l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/deleteByQuery",e.indexName),data:t},r),(s,n)=>D(e)(s.taskID,n)),as=e=>t=>l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Delete,path:l.encode("1/indexes/%s",e.indexName)},t),(r,s)=>D(e)(r.taskID,s)),os=e=>(t,r)=>l.createWaitablePromise(yt(e)([t],r).then(s=>({taskID:s.taskIDs[0]})),(s,n)=>D(e)(s.taskID,n)),yt=e=>(t,r)=>{let s=t.map(n=>({objectID:n}));return te(e)(s,k.DeleteObject,r)},is=e=>(t,r)=>{let o=r||{},{forwardToReplicas:s}=o,n=R(o,["forwardToReplicas"]),a=q.createMappedRequestOptions(n);return s&&(a.queryParameters.forwardToReplicas=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Delete,path:l.encode("1/indexes/%s/rules/%s",e.indexName,t)},a),(d,y)=>D(e)(d.taskID,y))},cs=e=>(t,r)=>{let o=r||{},{forwardToReplicas:s}=o,n=R(o,["forwardToReplicas"]),a=q.createMappedRequestOptions(n);return s&&(a.queryParameters.forwardToReplicas=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Delete,path:l.encode("1/indexes/%s/synonyms/%s",e.indexName,t)},a),(d,y)=>D(e)(d.taskID,y))},us=e=>t=>gt(e)(t).then(()=>!0).catch(r=>{if(r.status!==404)throw r;return!1}),ls=e=>(t,r)=>{let y=r||{},{query:s,paginate:n}=y,a=R(y,["query","paginate"]),o=0,d=()=>ft(e)(s||"",g(u({},a),{page:o})).then(b=>{for(let[f,p]of Object.entries(b.hits))if(t(p))return{object:p,position:parseInt(f,10),page:o};if(o++,n===!1||o>=b.nbPages)throw ut();return d()});return d()},ds=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/indexes/%s/%s",e.indexName,t)},r),ps=()=>(e,t)=>{for(let[r,s]of Object.entries(e.hits))if(s.objectID===t)return parseInt(r,10);return-1},ms=e=>(t,r)=>{let o=r||{},{attributesToRetrieve:s}=o,n=R(o,["attributesToRetrieve"]),a=t.map(d=>u({indexName:e.indexName,objectID:d},s?{attributesToRetrieve:s}:{}));return e.transporter.read({method:m.MethodEnum.Post,path:"1/indexes/*/objects",data:{requests:a}},n)},hs=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/indexes/%s/rules/%s",e.indexName,t)},r),gt=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/indexes/%s/settings",e.indexName),data:{getVersion:2}},t),ys=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/indexes/%s/synonyms/%s",e.indexName,t)},r),bt=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/indexes/%s/task/%s",e.indexName,t.toString())},r),gs=e=>(t,r)=>l.createWaitablePromise(Pt(e)([t],r).then(s=>({objectID:s.objectIDs[0],taskID:s.taskIDs[0]})),(s,n)=>D(e)(s.taskID,n)),Pt=e=>(t,r)=>{let o=r||{},{createIfNotExists:s}=o,n=R(o,["createIfNotExists"]),a=s?k.PartialUpdateObject:k.PartialUpdateObjectNoCreate;return te(e)(t,a,n)},fs=e=>(t,r)=>{let O=r||{},{safe:s,autoGenerateObjectIDIfNotExist:n,batchSize:a}=O,o=R(O,["safe","autoGenerateObjectIDIfNotExist","batchSize"]),d=(P,x,v,j)=>l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/operation",P),data:{operation:v,destination:x}},j),(T,V)=>D(e)(T.taskID,V)),y=Math.random().toString(36).substring(7),b=`${e.indexName}_tmp_${y}`,f=he({appId:e.appId,transporter:e.transporter,indexName:b}),p=[],h=d(e.indexName,b,"copy",g(u({},o),{scope:["settings","synonyms","rules"]}));p.push(h);let S=(s?h.wait(o):h).then(()=>{let P=f(t,g(u({},o),{autoGenerateObjectIDIfNotExist:n,batchSize:a}));return p.push(P),s?P.wait(o):P}).then(()=>{let P=d(b,e.indexName,"move",o);return p.push(P),s?P.wait(o):P}).then(()=>Promise.all(p)).then(([P,x,v])=>({objectIDs:x.objectIDs,taskIDs:[P.taskID,...x.taskIDs,v.taskID]}));return l.createWaitablePromise(S,(P,x)=>Promise.all(p.map(v=>v.wait(x))))},bs=e=>(t,r)=>ye(e)(t,g(u({},r),{clearExistingRules:!0})),Ps=e=>(t,r)=>ge(e)(t,g(u({},r),{replaceExistingSynonyms:!0})),js=e=>(t,r)=>l.createWaitablePromise(he(e)([t],r).then(s=>({objectID:s.objectIDs[0],taskID:s.taskIDs[0]})),(s,n)=>D(e)(s.taskID,n)),he=e=>(t,r)=>{let o=r||{},{autoGenerateObjectIDIfNotExist:s}=o,n=R(o,["autoGenerateObjectIDIfNotExist"]),a=s?k.AddObject:k.UpdateObject;if(a===k.UpdateObject){for(let d of t)if(d.objectID===void 0)return l.createWaitablePromise(Promise.reject(ct()))}return te(e)(t,a,n)},Os=e=>(t,r)=>ye(e)([t],r),ye=e=>(t,r)=>{let d=r||{},{forwardToReplicas:s,clearExistingRules:n}=d,a=R(d,["forwardToReplicas","clearExistingRules"]),o=q.createMappedRequestOptions(a);return s&&(o.queryParameters.forwardToReplicas=1),n&&(o.queryParameters.clearExistingRules=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/rules/batch",e.indexName),data:t},o),(y,b)=>D(e)(y.taskID,b))},Is=e=>(t,r)=>ge(e)([t],r),ge=e=>(t,r)=>{let d=r||{},{forwardToReplicas:s,replaceExistingSynonyms:n}=d,a=R(d,["forwardToReplicas","replaceExistingSynonyms"]),o=q.createMappedRequestOptions(a);return s&&(o.queryParameters.forwardToReplicas=1),n&&(o.queryParameters.replaceExistingSynonyms=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/synonyms/batch",e.indexName),data:t},o),(y,b)=>D(e)(y.taskID,b))},ft=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/query",e.indexName),data:{query:t},cacheable:!0},r),dt=e=>(t,r,s)=>e.transporter.read({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/facets/%s/query",e.indexName,t),data:{facetQuery:r},cacheable:!0},s),mt=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/rules/search",e.indexName),data:{query:t}},r),ht=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/synonyms/search",e.indexName),data:{query:t}},r),As=e=>(t,r)=>{let o=r||{},{forwardToReplicas:s}=o,n=R(o,["forwardToReplicas"]),a=q.createMappedRequestOptions(n);return s&&(a.queryParameters.forwardToReplicas=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Put,path:l.encode("1/indexes/%s/settings",e.indexName),data:t},a),(d,y)=>D(e)(d.taskID,y))},D=e=>(t,r)=>l.createRetryablePromise(s=>bt(e)(t,r).then(n=>n.status!=="published"?s():void 0)),Ss={AddObject:"addObject",Analytics:"analytics",Browser:"browse",DeleteIndex:"deleteIndex",DeleteObject:"deleteObject",EditSettings:"editSettings",ListIndexes:"listIndexes",Logs:"logs",Recommendation:"recommendation",Search:"search",SeeUnretrievableAttributes:"seeUnretrievableAttributes",Settings:"settings",Usage:"usage"},k={AddObject:"addObject",UpdateObject:"updateObject",PartialUpdateObject:"partialUpdateObject",PartialUpdateObjectNoCreate:"partialUpdateObjectNoCreate",DeleteObject:"deleteObject"},ee={Settings:"settings",Synonyms:"synonyms",Rules:"rules"},Ds={None:"none",StopIfEnoughMatches:"stopIfEnoughMatches"},Rs={Synonym:"synonym",OneWaySynonym:"oneWaySynonym",AltCorrection1:"altCorrection1",AltCorrection2:"altCorrection2",Placeholder:"placeholder"};i.ApiKeyACLEnum=Ss;i.BatchActionEnum=k;i.ScopeEnum=ee;i.StrategyEnum=Ds;i.SynonymEnum=Rs;i.addApiKey=Rr;i.assignUserID=vr;i.assignUserIDs=xr;i.batch=pt;i.browseObjects=Yr;i.browseRules=Zr;i.browseSynonyms=es;i.chunkedBatch=te;i.clearObjects=ts;i.clearRules=rs;i.clearSynonyms=ss;i.copyIndex=Z;i.copyRules=qr;i.copySettings=Er;i.copySynonyms=Tr;i.createBrowsablePromise=Y;i.createMissingObjectIDError=ct;i.createObjectNotFoundError=ut;i.createSearchClient=Dr;i.createValidUntilNotFoundError=lt;i.deleteApiKey=Mr;i.deleteBy=ns;i.deleteIndex=as;i.deleteObject=os;i.deleteObjects=yt;i.deleteRule=is;i.deleteSynonym=cs;i.exists=us;i.findObject=ls;i.generateSecuredApiKey=wr;i.getApiKey=$;i.getLogs=kr;i.getObject=ds;i.getObjectPosition=ps;i.getObjects=ms;i.getRule=hs;i.getSecuredApiKeyRemainingValidity=Cr;i.getSettings=gt;i.getSynonym=ys;i.getTask=bt;i.getTopUserIDs=Ur;i.getUserID=Nr;i.hasPendingMappings=Wr;i.initIndex=L;i.listApiKeys=Hr;i.listClusters=_r;i.listIndices=Fr;i.listUserIDs=Br;i.moveIndex=Kr;i.multipleBatch=zr;i.multipleGetObjects=Gr;i.multipleQueries=$r;i.multipleSearchForFacetValues=Lr;i.partialUpdateObject=gs;i.partialUpdateObjects=Pt;i.removeUserID=Vr;i.replaceAllObjects=fs;i.replaceAllRules=bs;i.replaceAllSynonyms=Ps;i.restoreApiKey=Qr;i.saveObject=js;i.saveObjects=he;i.saveRule=Os;i.saveRules=ye;i.saveSynonym=Is;i.saveSynonyms=ge;i.search=ft;i.searchForFacetValues=dt;i.searchRules=mt;i.searchSynonyms=ht;i.searchUserIDs=Jr;i.setSettings=As;i.updateApiKey=Xr;i.waitTask=D});var It=I((on,Ot)=>{Ot.exports=jt()});var At=I(re=>{"use strict";Object.defineProperty(re,"__esModule",{value:!0});function vs(){return{debug(e,t){return Promise.resolve()},info(e,t){return Promise.resolve()},error(e,t){return Promise.resolve()}}}var xs={Debug:1,Info:2,Error:3};re.LogLevelEnum=xs;re.createNullLogger=vs});var Dt=I((un,St)=>{St.exports=At()});var xt=I(fe=>{"use strict";Object.defineProperty(fe,"__esModule",{value:!0});var Rt=require("http"),vt=require("https"),qs=require("url");function Es(){let e={keepAlive:!0},t=new Rt.Agent(e),r=new vt.Agent(e);return{send(s){return new Promise(n=>{let a=qs.parse(s.url),o=a.query===null?a.pathname:`${a.pathname}?${a.query}`,d=u({agent:a.protocol==="https:"?r:t,hostname:a.hostname,path:o,method:s.method,headers:s.headers},a.port!==void 0?{port:a.port||""}:{}),y=(a.protocol==="https:"?vt:Rt).request(d,h=>{let S="";h.on("data",O=>S+=O),h.on("end",()=>{clearTimeout(f),clearTimeout(p),n({status:h.statusCode||0,content:S,isTimedOut:!1})})}),b=(h,S)=>setTimeout(()=>{y.abort(),n({status:0,content:S,isTimedOut:!0})},h*1e3),f=b(s.connectTimeout,"Connection timeout"),p;y.on("error",h=>{clearTimeout(f),clearTimeout(p),n({status:0,content:h.message,isTimedOut:!1})}),y.once("response",()=>{clearTimeout(f),p=b(s.responseTimeout,"Socket timeout")}),s.data!==void 0&&y.write(s.data),y.end()})},destroy(){return t.destroy(),r.destroy(),Promise.resolve()}}}fe.createNodeHttpRequester=Es});var Et=I((dn,qt)=>{qt.exports=xt()});var kt=I((pn,Tt)=>{"use strict";var Mt=Ee(),Ts=we(),W=st(),be=F(),Pe=it(),c=It(),Ms=Dt(),ws=Et(),ks=K();function wt(e,t,r){let s={appId:e,apiKey:t,timeouts:{connect:2,read:5,write:30},requester:ws.createNodeHttpRequester(),logger:Ms.createNullLogger(),responsesCache:Mt.createNullCache(),requestsCache:Mt.createNullCache(),hostsCache:Ts.createInMemoryCache(),userAgent:ks.createUserAgent(be.version).add({segment:"Node.js",version:process.versions.node})};return c.createSearchClient(g(u(u({},s),r),{methods:{search:c.multipleQueries,searchForFacetValues:c.multipleSearchForFacetValues,multipleBatch:c.multipleBatch,multipleGetObjects:c.multipleGetObjects,multipleQueries:c.multipleQueries,copyIndex:c.copyIndex,copySettings:c.copySettings,copyRules:c.copyRules,copySynonyms:c.copySynonyms,moveIndex:c.moveIndex,listIndices:c.listIndices,getLogs:c.getLogs,listClusters:c.listClusters,multipleSearchForFacetValues:c.multipleSearchForFacetValues,getApiKey:c.getApiKey,addApiKey:c.addApiKey,listApiKeys:c.listApiKeys,updateApiKey:c.updateApiKey,deleteApiKey:c.deleteApiKey,restoreApiKey:c.restoreApiKey,assignUserID:c.assignUserID,assignUserIDs:c.assignUserIDs,getUserID:c.getUserID,searchUserIDs:c.searchUserIDs,listUserIDs:c.listUserIDs,getTopUserIDs:c.getTopUserIDs,removeUserID:c.removeUserID,hasPendingMappings:c.hasPendingMappings,generateSecuredApiKey:c.generateSecuredApiKey,getSecuredApiKeyRemainingValidity:c.getSecuredApiKeyRemainingValidity,destroy:be.destroy,initIndex:n=>a=>c.initIndex(n)(a,{methods:{batch:c.batch,delete:c.deleteIndex,getObject:c.getObject,getObjects:c.getObjects,saveObject:c.saveObject,saveObjects:c.saveObjects,search:c.search,searchForFacetValues:c.searchForFacetValues,waitTask:c.waitTask,setSettings:c.setSettings,getSettings:c.getSettings,partialUpdateObject:c.partialUpdateObject,partialUpdateObjects:c.partialUpdateObjects,deleteObject:c.deleteObject,deleteObjects:c.deleteObjects,deleteBy:c.deleteBy,clearObjects:c.clearObjects,browseObjects:c.browseObjects,getObjectPosition:c.getObjectPosition,findObject:c.findObject,exists:c.exists,saveSynonym:c.saveSynonym,saveSynonyms:c.saveSynonyms,getSynonym:c.getSynonym,searchSynonyms:c.searchSynonyms,browseSynonyms:c.browseSynonyms,deleteSynonym:c.deleteSynonym,clearSynonyms:c.clearSynonyms,replaceAllObjects:c.replaceAllObjects,replaceAllSynonyms:c.replaceAllSynonyms,searchRules:c.searchRules,getRule:c.getRule,deleteRule:c.deleteRule,saveRule:c.saveRule,saveRules:c.saveRules,replaceAllRules:c.replaceAllRules,browseRules:c.browseRules,clearRules:c.clearRules}}),initAnalytics:()=>n=>W.createAnalyticsClient(g(u(u({},s),n),{methods:{addABTest:W.addABTest,getABTest:W.getABTest,getABTests:W.getABTests,stopABTest:W.stopABTest,deleteABTest:W.deleteABTest}})),initRecommendation:()=>n=>Pe.createRecommendationClient(g(u(u({},s),n),{methods:{getPersonalizationStrategy:Pe.getPersonalizationStrategy,setPersonalizationStrategy:Pe.setPersonalizationStrategy}}))}}))}wt.version=be.version;Tt.exports=wt});var Ut=I((mn,je)=>{var Ct=kt();je.exports=Ct;je.exports.default=Ct});var Ws={};Vt(Ws,{default:()=>Ks});var Oe=C(require("@yarnpkg/core")),E=C(require("@yarnpkg/core")),Ie=C(require("@yarnpkg/plugin-essentials")),Ht=C(require("semver"));var se=C(require("@yarnpkg/core")),Nt=C(Ut()),Cs="e8e1bd300d860104bb8c58453ffa1eb4",Us="OFCNCOG2CU",Wt=async(e,t)=>{var a;let r=se.structUtils.stringifyIdent(e),n=Ns(t).initIndex("npm-search");try{return((a=(await n.getObject(r,{attributesToRetrieve:["types"]})).types)==null?void 0:a.ts)==="definitely-typed"}catch(o){return!1}},Ns=e=>(0,Nt.default)(Us,Cs,{requester:{async send(r){try{let s=await se.httpUtils.request(r.url,r.data||null,{configuration:e,headers:r.headers});return{content:s.body,isTimedOut:!1,status:s.statusCode}}catch(s){return{content:s.response.body,isTimedOut:!1,status:s.response.statusCode}}}}});var _t=e=>e.scope?`${e.scope}__${e.name}`:`${e.name}`,Hs=async(e,t,r,s)=>{if(r.scope==="types")return;let{project:n}=e,{configuration:a}=n,o=a.makeResolver(),d={project:n,resolver:o,report:new E.ThrowReport};if(!await Wt(r,a))return;let b=_t(r),f=E.structUtils.parseRange(r.range).selector;if(!E.semverUtils.validRange(f)){let P=await o.getCandidates(r,new Map,d);f=E.structUtils.parseRange(P[0].reference).selector}let p=Ht.default.coerce(f);if(p===null)return;let h=`${Ie.suggestUtils.Modifier.CARET}${p.major}`,S=E.structUtils.makeDescriptor(E.structUtils.makeIdent("types",b),h),O=E.miscUtils.mapAndFind(n.workspaces,P=>{var T,V;let x=(T=P.manifest.dependencies.get(r.identHash))==null?void 0:T.descriptorHash,v=(V=P.manifest.devDependencies.get(r.identHash))==null?void 0:V.descriptorHash;if(x!==r.descriptorHash&&v!==r.descriptorHash)return E.miscUtils.mapAndFind.skip;let j=[];for(let Ae of Oe.Manifest.allDependencies){let Se=P.manifest[Ae].get(S.identHash);typeof Se!="undefined"&&j.push([Ae,Se])}return j.length===0?E.miscUtils.mapAndFind.skip:j});if(typeof O!="undefined")for(let[P,x]of O)e.manifest[P].set(x.identHash,x);else{try{if((await o.getCandidates(S,new Map,d)).length===0)return}catch{return}e.manifest[Ie.suggestUtils.Target.DEVELOPMENT].set(S.identHash,S)}},_s=async(e,t,r)=>{if(r.scope==="types")return;let s=_t(r),n=E.structUtils.makeIdent("types",s);for(let a of Oe.Manifest.allDependencies)typeof e.manifest[a].get(n.identHash)!="undefined"&&e.manifest[a].delete(n.identHash)},Fs=(e,t)=>{t.publishConfig&&t.publishConfig.typings&&(t.typings=t.publishConfig.typings),t.publishConfig&&t.publishConfig.types&&(t.types=t.publishConfig.types)},Bs={hooks:{afterWorkspaceDependencyAddition:Hs,afterWorkspaceDependencyRemoval:_s,beforeWorkspacePacking:Fs}},Ks=Bs;return Ws;})(); 7 | return plugin; 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /examples/bundle/yarn.lock: -------------------------------------------------------------------------------- 1 | # This file is generated by running "yarn install" inside your project. 2 | # Manual changes might be lost - proceed with caution! 3 | 4 | __metadata: 5 | version: 4 6 | cacheKey: 8 7 | 8 | "@babel/generator@npm:7.18.2": 9 | version: 7.18.2 10 | resolution: "@babel/generator@npm:7.18.2" 11 | dependencies: 12 | "@babel/types": ^7.18.2 13 | "@jridgewell/gen-mapping": ^0.3.0 14 | jsesc: ^2.5.1 15 | checksum: d0661e95532ddd97566d41fec26355a7b28d1cbc4df95fe80cc084c413342935911b48db20910708db39714844ddd614f61c2ec4cca3fb10181418bdcaa2e7a3 16 | languageName: node 17 | linkType: hard 18 | 19 | "@babel/helper-string-parser@npm:^7.18.10, @babel/helper-string-parser@npm:^7.19.4": 20 | version: 7.19.4 21 | resolution: "@babel/helper-string-parser@npm:7.19.4" 22 | checksum: b2f8a3920b30dfac81ec282ac4ad9598ea170648f8254b10f475abe6d944808fb006aab325d3eb5a8ad3bea8dfa888cfa6ef471050dae5748497c110ec060943 23 | languageName: node 24 | linkType: hard 25 | 26 | "@babel/helper-validator-identifier@npm:^7.14.9": 27 | version: 7.14.9 28 | resolution: "@babel/helper-validator-identifier@npm:7.14.9" 29 | checksum: 58552531a7674363e74672434c312ddaf1545b8a43308e1a7f38db58bf79c796c095a6dab6a6105eb0d783b97441f6cbb525bb887f29a35f232fcdbd8cb240dc 30 | languageName: node 31 | linkType: hard 32 | 33 | "@babel/helper-validator-identifier@npm:^7.18.6, @babel/helper-validator-identifier@npm:^7.19.1": 34 | version: 7.19.1 35 | resolution: "@babel/helper-validator-identifier@npm:7.19.1" 36 | checksum: 0eca5e86a729162af569b46c6c41a63e18b43dbe09fda1d2a3c8924f7d617116af39cac5e4cd5d431bb760b4dca3c0970e0c444789b1db42bcf1fa41fbad0a3a 37 | languageName: node 38 | linkType: hard 39 | 40 | "@babel/parser@npm:7.18.4": 41 | version: 7.18.4 42 | resolution: "@babel/parser@npm:7.18.4" 43 | bin: 44 | parser: ./bin/babel-parser.js 45 | checksum: e05b2dc720c4b200e088258f3c2a2de5041c140444edc38181d1217b10074e881a7133162c5b62356061f26279f08df5a06ec14c5842996ee8601ad03c57a44f 46 | languageName: node 47 | linkType: hard 48 | 49 | "@babel/types@npm:7.19.0": 50 | version: 7.19.0 51 | resolution: "@babel/types@npm:7.19.0" 52 | dependencies: 53 | "@babel/helper-string-parser": ^7.18.10 54 | "@babel/helper-validator-identifier": ^7.18.6 55 | to-fast-properties: ^2.0.0 56 | checksum: 9b346715a68aeede70ba9c685a144b0b26c53bcd595d448e24c8fa8df4d5956a5712e56ebadb7c85dcc32f218ee42788e37b93d50d3295c992072224cb3ef3fe 57 | languageName: node 58 | linkType: hard 59 | 60 | "@babel/types@npm:^7.18.2": 61 | version: 7.21.4 62 | resolution: "@babel/types@npm:7.21.4" 63 | dependencies: 64 | "@babel/helper-string-parser": ^7.19.4 65 | "@babel/helper-validator-identifier": ^7.19.1 66 | to-fast-properties: ^2.0.0 67 | checksum: 587bc55a91ce003b0f8aa10d70070f8006560d7dc0360dc0406d306a2cb2a10154e2f9080b9c37abec76907a90b330a536406cb75e6bdc905484f37b75c73219 68 | languageName: node 69 | linkType: hard 70 | 71 | "@babel/types@npm:^7.8.3": 72 | version: 7.15.4 73 | resolution: "@babel/types@npm:7.15.4" 74 | dependencies: 75 | "@babel/helper-validator-identifier": ^7.14.9 76 | to-fast-properties: ^2.0.0 77 | checksum: dac7d733edf2102e97f197929693fae6025161f3edda5a0f621f69e9d0741b8596c6f2152492bef869b55d0205e214867e8730f389283e85432b8f093e295c4b 78 | languageName: node 79 | linkType: hard 80 | 81 | "@jridgewell/gen-mapping@npm:^0.3.0": 82 | version: 0.3.2 83 | resolution: "@jridgewell/gen-mapping@npm:0.3.2" 84 | dependencies: 85 | "@jridgewell/set-array": ^1.0.1 86 | "@jridgewell/sourcemap-codec": ^1.4.10 87 | "@jridgewell/trace-mapping": ^0.3.9 88 | checksum: 1832707a1c476afebe4d0fbbd4b9434fdb51a4c3e009ab1e9938648e21b7a97049fa6009393bdf05cab7504108413441df26d8a3c12193996e65493a4efb6882 89 | languageName: node 90 | linkType: hard 91 | 92 | "@jridgewell/resolve-uri@npm:3.1.0": 93 | version: 3.1.0 94 | resolution: "@jridgewell/resolve-uri@npm:3.1.0" 95 | checksum: b5ceaaf9a110fcb2780d1d8f8d4a0bfd216702f31c988d8042e5f8fbe353c55d9b0f55a1733afdc64806f8e79c485d2464680ac48a0d9fcadb9548ee6b81d267 96 | languageName: node 97 | linkType: hard 98 | 99 | "@jridgewell/set-array@npm:^1.0.1": 100 | version: 1.1.2 101 | resolution: "@jridgewell/set-array@npm:1.1.2" 102 | checksum: 69a84d5980385f396ff60a175f7177af0b8da4ddb81824cb7016a9ef914eee9806c72b6b65942003c63f7983d4f39a5c6c27185bbca88eb4690b62075602e28e 103 | languageName: node 104 | linkType: hard 105 | 106 | "@jridgewell/sourcemap-codec@npm:1.4.14, @jridgewell/sourcemap-codec@npm:^1.4.10": 107 | version: 1.4.14 108 | resolution: "@jridgewell/sourcemap-codec@npm:1.4.14" 109 | checksum: 61100637b6d173d3ba786a5dff019e1a74b1f394f323c1fee337ff390239f053b87266c7a948777f4b1ee68c01a8ad0ab61e5ff4abb5a012a0b091bec391ab97 110 | languageName: node 111 | linkType: hard 112 | 113 | "@jridgewell/trace-mapping@npm:^0.3.9": 114 | version: 0.3.17 115 | resolution: "@jridgewell/trace-mapping@npm:0.3.17" 116 | dependencies: 117 | "@jridgewell/resolve-uri": 3.1.0 118 | "@jridgewell/sourcemap-codec": 1.4.14 119 | checksum: 9d703b859cff5cd83b7308fd457a431387db5db96bd781a63bf48e183418dd9d3d44e76b9e4ae13237f6abeeb25d739ec9215c1d5bfdd08f66f750a50074a339 120 | languageName: node 121 | linkType: hard 122 | 123 | "@nodelib/fs.scandir@npm:2.1.3": 124 | version: 2.1.3 125 | resolution: "@nodelib/fs.scandir@npm:2.1.3" 126 | dependencies: 127 | "@nodelib/fs.stat": 2.0.3 128 | run-parallel: ^1.1.9 129 | checksum: 0054efbba1385629886fe017d99f7045cb8300d6de1923f7a37e05e480c853abbedaff90f6a6b88fd0d406e1cd1e97fb60bd4e059b44468b174f46bef2e21dd1 130 | languageName: node 131 | linkType: hard 132 | 133 | "@nodelib/fs.stat@npm:2.0.3, @nodelib/fs.stat@npm:^2.0.2": 134 | version: 2.0.3 135 | resolution: "@nodelib/fs.stat@npm:2.0.3" 136 | checksum: d3612efceea83fb0bec4e64967888ff0c3e5fbbae96121bc526bbbe5529f32fc6f8a785b550f397d20f09c84dc1e5a6c8e9fd7f9b8b62387a8f80f680be8430e 137 | languageName: node 138 | linkType: hard 139 | 140 | "@nodelib/fs.walk@npm:^1.2.3": 141 | version: 1.2.4 142 | resolution: "@nodelib/fs.walk@npm:1.2.4" 143 | dependencies: 144 | "@nodelib/fs.scandir": 2.1.3 145 | fastq: ^1.6.0 146 | checksum: a971d1dcc1cf593e25651738e915be201053b63775c39c1ee221d2adee6316503ad6043136ceda0e099724875f2d72ea04b3b57c0e3a20b7f280bd3e951ae2e4 147 | languageName: node 148 | linkType: hard 149 | 150 | "@types/color-name@npm:^1.1.1": 151 | version: 1.1.1 152 | resolution: "@types/color-name@npm:1.1.1" 153 | checksum: b71fcad728cc68abcba1d405742134410c8f8eb3c2ef18113b047afca158ad23a4f2c229bcf71a38f4a818dead375c45b20db121d0e69259c2d81e97a740daa6 154 | languageName: node 155 | linkType: hard 156 | 157 | "@types/yargs-parser@npm:*": 158 | version: 21.0.0 159 | resolution: "@types/yargs-parser@npm:21.0.0" 160 | checksum: b2f4c8d12ac18a567440379909127cf2cec393daffb73f246d0a25df36ea983b93b7e9e824251f959e9f928cbc7c1aab6728d0a0ff15d6145f66cec2be67d9a2 161 | languageName: node 162 | linkType: hard 163 | 164 | "@types/yargs@npm:17.0.24": 165 | version: 17.0.24 166 | resolution: "@types/yargs@npm:17.0.24" 167 | dependencies: 168 | "@types/yargs-parser": "*" 169 | checksum: 5f3ac4dc4f6e211c1627340160fbe2fd247ceba002190da6cf9155af1798450501d628c9165a183f30a224fc68fa5e700490d740ff4c73e2cdef95bc4e8ba7bf 170 | languageName: node 171 | linkType: hard 172 | 173 | "agent-base@npm:6": 174 | version: 6.0.2 175 | resolution: "agent-base@npm:6.0.2" 176 | dependencies: 177 | debug: 4 178 | checksum: f52b6872cc96fd5f622071b71ef200e01c7c4c454ee68bc9accca90c98cfb39f2810e3e9aa330435835eedc8c23f4f8a15267f67c6e245d2b33757575bdac49d 179 | languageName: node 180 | linkType: hard 181 | 182 | "ansi-colors@npm:^4.1.1": 183 | version: 4.1.1 184 | resolution: "ansi-colors@npm:4.1.1" 185 | checksum: 138d04a51076cb085da0a7e2d000c5c0bb09f6e772ed5c65c53cb118d37f6c5f1637506d7155fb5f330f0abcf6f12fa2e489ac3f8cdab9da393bf1bb4f9a32b0 186 | languageName: node 187 | linkType: hard 188 | 189 | "ansi-regex@npm:^5.0.0": 190 | version: 5.0.0 191 | resolution: "ansi-regex@npm:5.0.0" 192 | checksum: b1bb4e992a5d96327bb4f72eaba9f8047f1d808d273ad19d399e266bfcc7fb19a4d1a127a32f7bc61fe46f1a94a4d04ec4c424e3fbe184929aa866323d8ed4ce 193 | languageName: node 194 | linkType: hard 195 | 196 | "ansi-regex@npm:^5.0.1": 197 | version: 5.0.1 198 | resolution: "ansi-regex@npm:5.0.1" 199 | checksum: 2aa4bb54caf2d622f1afdad09441695af2a83aa3fe8b8afa581d205e57ed4261c183c4d3877cee25794443fde5876417d859c108078ab788d6af7e4fe52eb66b 200 | languageName: node 201 | linkType: hard 202 | 203 | "ansi-styles@npm:^4.0.0, ansi-styles@npm:^4.1.0": 204 | version: 4.2.0 205 | resolution: "ansi-styles@npm:4.2.0" 206 | dependencies: 207 | "@types/color-name": ^1.1.1 208 | color-convert: ^2.0.1 209 | checksum: 97f0f21a77f1e120cc51e439d5c05847269ee7667267b83cffdacb5987f82560a7e0dadae4f31e02795ff601ccba1320b40e9760eda1ec67129343a407027a1a 210 | languageName: node 211 | linkType: hard 212 | 213 | "array-union@npm:^2.1.0": 214 | version: 2.1.0 215 | resolution: "array-union@npm:2.1.0" 216 | checksum: 5bee12395cba82da674931df6d0fea23c4aa4660cb3b338ced9f828782a65caa232573e6bf3968f23e0c5eb301764a382cef2f128b170a9dc59de0e36c39f98d 217 | languageName: node 218 | linkType: hard 219 | 220 | "at-least-node@npm:^1.0.0": 221 | version: 1.0.0 222 | resolution: "at-least-node@npm:1.0.0" 223 | checksum: 463e2f8e43384f1afb54bc68485c436d7622acec08b6fad269b421cb1d29cebb5af751426793d0961ed243146fe4dc983402f6d5a51b720b277818dbf6f2e49e 224 | languageName: node 225 | linkType: hard 226 | 227 | "bandersnatch@npm:^1.9.2": 228 | version: 1.12.5 229 | resolution: "bandersnatch@npm:1.12.5" 230 | dependencies: 231 | "@types/yargs": 17.0.24 232 | enquirer: ^2.3.6 233 | string-argv: ^0.3.1 234 | typed-emitter: ^2.1.0 235 | yargs: ^17.5.1 236 | checksum: fa6892607d15bb08a26c24e1f53395888a56f75baad5128addd49e4f23c1cc4e2ec6db35c7be7d06312b857b0145d972d80cd05c17b1d53f382330c0f956877b 237 | languageName: node 238 | linkType: hard 239 | 240 | "base64-js@npm:^1.3.1": 241 | version: 1.5.1 242 | resolution: "base64-js@npm:1.5.1" 243 | checksum: 669632eb3745404c2f822a18fc3a0122d2f9a7a13f7fb8b5823ee19d1d2ff9ee5b52c53367176ea4ad093c332fd5ab4bd0ebae5a8e27917a4105a4cfc86b1005 244 | languageName: node 245 | linkType: hard 246 | 247 | "bl@npm:^4.0.3": 248 | version: 4.1.0 249 | resolution: "bl@npm:4.1.0" 250 | dependencies: 251 | buffer: ^5.5.0 252 | inherits: ^2.0.4 253 | readable-stream: ^3.4.0 254 | checksum: 9e8521fa7e83aa9427c6f8ccdcba6e8167ef30cc9a22df26effcc5ab682ef91d2cbc23a239f945d099289e4bbcfae7a192e9c28c84c6202e710a0dfec3722662 255 | languageName: node 256 | linkType: hard 257 | 258 | "braces@npm:^3.0.1": 259 | version: 3.0.2 260 | resolution: "braces@npm:3.0.2" 261 | dependencies: 262 | fill-range: ^7.0.1 263 | checksum: e2a8e769a863f3d4ee887b5fe21f63193a891c68b612ddb4b68d82d1b5f3ff9073af066c343e9867a393fe4c2555dcb33e89b937195feb9c1613d259edfcd459 264 | languageName: node 265 | linkType: hard 266 | 267 | "buffer@npm:^5.5.0": 268 | version: 5.7.1 269 | resolution: "buffer@npm:5.7.1" 270 | dependencies: 271 | base64-js: ^1.3.1 272 | ieee754: ^1.1.13 273 | checksum: e2cf8429e1c4c7b8cbd30834ac09bd61da46ce35f5c22a78e6c2f04497d6d25541b16881e30a019c6fd3154150650ccee27a308eff3e26229d788bbdeb08ab84 274 | languageName: node 275 | linkType: hard 276 | 277 | "chalk@npm:^4.1.2": 278 | version: 4.1.2 279 | resolution: "chalk@npm:4.1.2" 280 | dependencies: 281 | ansi-styles: ^4.1.0 282 | supports-color: ^7.1.0 283 | checksum: fe75c9d5c76a7a98d45495b91b2172fa3b7a09e0cc9370e5c8feb1c567b85c4288e2b3fded7cfdd7359ac28d6b3844feb8b82b8686842e93d23c827c417e83fc 284 | languageName: node 285 | linkType: hard 286 | 287 | "chownr@npm:^1.1.1": 288 | version: 1.1.4 289 | resolution: "chownr@npm:1.1.4" 290 | checksum: 115648f8eb38bac5e41c3857f3e663f9c39ed6480d1349977c4d96c95a47266fcacc5a5aabf3cb6c481e22d72f41992827db47301851766c4fd77ac21a4f081d 291 | languageName: node 292 | linkType: hard 293 | 294 | "cliui@npm:^7.0.2": 295 | version: 7.0.4 296 | resolution: "cliui@npm:7.0.4" 297 | dependencies: 298 | string-width: ^4.2.0 299 | strip-ansi: ^6.0.0 300 | wrap-ansi: ^7.0.0 301 | checksum: ce2e8f578a4813806788ac399b9e866297740eecd4ad1823c27fd344d78b22c5f8597d548adbcc46f0573e43e21e751f39446c5a5e804a12aace402b7a315d7f 302 | languageName: node 303 | linkType: hard 304 | 305 | "cliui@npm:^8.0.1": 306 | version: 8.0.1 307 | resolution: "cliui@npm:8.0.1" 308 | dependencies: 309 | string-width: ^4.2.0 310 | strip-ansi: ^6.0.1 311 | wrap-ansi: ^7.0.0 312 | checksum: 79648b3b0045f2e285b76fb2e24e207c6db44323581e421c3acbd0e86454cba1b37aea976ab50195a49e7384b871e6dfb2247ad7dec53c02454ac6497394cb56 313 | languageName: node 314 | linkType: hard 315 | 316 | "color-convert@npm:^2.0.1": 317 | version: 2.0.1 318 | resolution: "color-convert@npm:2.0.1" 319 | dependencies: 320 | color-name: ~1.1.4 321 | checksum: 79e6bdb9fd479a205c71d89574fccfb22bd9053bd98c6c4d870d65c132e5e904e6034978e55b43d69fcaa7433af2016ee203ce76eeba9cfa554b373e7f7db336 322 | languageName: node 323 | linkType: hard 324 | 325 | "color-name@npm:~1.1.4": 326 | version: 1.1.4 327 | resolution: "color-name@npm:1.1.4" 328 | checksum: b0445859521eb4021cd0fb0cc1a75cecf67fceecae89b63f62b201cca8d345baf8b952c966862a9d9a2632987d4f6581f0ec8d957dfacece86f0a7919316f610 329 | languageName: node 330 | linkType: hard 331 | 332 | "core-util-is@npm:~1.0.0": 333 | version: 1.0.2 334 | resolution: "core-util-is@npm:1.0.2" 335 | checksum: 7a4c925b497a2c91421e25bf76d6d8190f0b2359a9200dbeed136e63b2931d6294d3b1893eda378883ed363cd950f44a12a401384c609839ea616befb7927dab 336 | languageName: node 337 | linkType: hard 338 | 339 | "debug@npm:4": 340 | version: 4.3.2 341 | resolution: "debug@npm:4.3.2" 342 | dependencies: 343 | ms: 2.1.2 344 | peerDependenciesMeta: 345 | supports-color: 346 | optional: true 347 | checksum: 820ea160e267e23c953c9ed87e7ad93494d8cda2f7349af5e7e3bb236d23707ee3022f477d5a7d2ee86ef2bf7d60aa9ab22d1f58080d7deb9dccd073585e1e43 348 | languageName: node 349 | linkType: hard 350 | 351 | "decompress-response@npm:^6.0.0": 352 | version: 6.0.0 353 | resolution: "decompress-response@npm:6.0.0" 354 | dependencies: 355 | mimic-response: ^3.1.0 356 | checksum: d377cf47e02d805e283866c3f50d3d21578b779731e8c5072d6ce8c13cc31493db1c2f6784da9d1d5250822120cefa44f1deab112d5981015f2e17444b763812 357 | languageName: node 358 | linkType: hard 359 | 360 | "deep-extend@npm:^0.6.0": 361 | version: 0.6.0 362 | resolution: "deep-extend@npm:0.6.0" 363 | checksum: 7be7e5a8d468d6b10e6a67c3de828f55001b6eb515d014f7aeb9066ce36bd5717161eb47d6a0f7bed8a9083935b465bc163ee2581c8b128d29bf61092fdf57a7 364 | languageName: node 365 | linkType: hard 366 | 367 | "detect-libc@npm:^2.0.0": 368 | version: 2.0.1 369 | resolution: "detect-libc@npm:2.0.1" 370 | checksum: ccb05fcabbb555beb544d48080179c18523a343face9ee4e1a86605a8715b4169f94d663c21a03c310ac824592f2ba9a5270218819bb411ad7be578a527593d7 371 | languageName: node 372 | linkType: hard 373 | 374 | "dir-glob@npm:^3.0.1": 375 | version: 3.0.1 376 | resolution: "dir-glob@npm:3.0.1" 377 | dependencies: 378 | path-type: ^4.0.0 379 | checksum: fa05e18324510d7283f55862f3161c6759a3f2f8dbce491a2fc14c8324c498286c54282c1f0e933cb930da8419b30679389499b919122952a4f8592362ef4615 380 | languageName: node 381 | linkType: hard 382 | 383 | "echo@workspace:.": 384 | version: 0.0.0-use.local 385 | resolution: "echo@workspace:." 386 | dependencies: 387 | bandersnatch: ^1.9.2 388 | pkg: ^5.5.2 389 | typescript: ^5.0.3 390 | bin: 391 | echo: echo.js 392 | languageName: unknown 393 | linkType: soft 394 | 395 | "emoji-regex@npm:^8.0.0": 396 | version: 8.0.0 397 | resolution: "emoji-regex@npm:8.0.0" 398 | checksum: d4c5c39d5a9868b5fa152f00cada8a936868fd3367f33f71be515ecee4c803132d11b31a6222b2571b1e5f7e13890156a94880345594d0ce7e3c9895f560f192 399 | languageName: node 400 | linkType: hard 401 | 402 | "end-of-stream@npm:^1.1.0, end-of-stream@npm:^1.4.1": 403 | version: 1.4.4 404 | resolution: "end-of-stream@npm:1.4.4" 405 | dependencies: 406 | once: ^1.4.0 407 | checksum: 530a5a5a1e517e962854a31693dbb5c0b2fc40b46dad2a56a2deec656ca040631124f4795823acc68238147805f8b021abbe221f4afed5ef3c8e8efc2024908b 408 | languageName: node 409 | linkType: hard 410 | 411 | "enquirer@npm:^2.3.6": 412 | version: 2.3.6 413 | resolution: "enquirer@npm:2.3.6" 414 | dependencies: 415 | ansi-colors: ^4.1.1 416 | checksum: 1c0911e14a6f8d26721c91e01db06092a5f7675159f0261d69c403396a385afd13dd76825e7678f66daffa930cfaa8d45f506fb35f818a2788463d022af1b884 417 | languageName: node 418 | linkType: hard 419 | 420 | "escalade@npm:^3.1.1": 421 | version: 3.1.1 422 | resolution: "escalade@npm:3.1.1" 423 | checksum: a3e2a99f07acb74b3ad4989c48ca0c3140f69f923e56d0cba0526240ee470b91010f9d39001f2a4a313841d237ede70a729e92125191ba5d21e74b106800b133 424 | languageName: node 425 | linkType: hard 426 | 427 | "expand-template@npm:^2.0.3": 428 | version: 2.0.3 429 | resolution: "expand-template@npm:2.0.3" 430 | checksum: 588c19847216421ed92befb521767b7018dc88f88b0576df98cb242f20961425e96a92cbece525ef28cc5becceae5d544ae0f5b9b5e2aa05acb13716ca5b3099 431 | languageName: node 432 | linkType: hard 433 | 434 | "fast-glob@npm:^3.2.9": 435 | version: 3.2.11 436 | resolution: "fast-glob@npm:3.2.11" 437 | dependencies: 438 | "@nodelib/fs.stat": ^2.0.2 439 | "@nodelib/fs.walk": ^1.2.3 440 | glob-parent: ^5.1.2 441 | merge2: ^1.3.0 442 | micromatch: ^4.0.4 443 | checksum: f473105324a7780a20c06de842e15ddbb41d3cb7e71d1e4fe6e8373204f22245d54f5ab9e2061e6a1c613047345954d29b022e0e76f5c28b1df9858179a0e6d7 444 | languageName: node 445 | linkType: hard 446 | 447 | "fastq@npm:^1.6.0": 448 | version: 1.6.0 449 | resolution: "fastq@npm:1.6.0" 450 | dependencies: 451 | reusify: ^1.0.0 452 | checksum: e643b1c3046cea208e0aeb5ab9601b0d53f55d5a00efad2e8e4149f6be08d6a351c2a9521bc089a80df91c5616d1716c105d601c431afd83814a09edf5e0e29e 453 | languageName: node 454 | linkType: hard 455 | 456 | "fill-range@npm:^7.0.1": 457 | version: 7.0.1 458 | resolution: "fill-range@npm:7.0.1" 459 | dependencies: 460 | to-regex-range: ^5.0.1 461 | checksum: cc283f4e65b504259e64fd969bcf4def4eb08d85565e906b7d36516e87819db52029a76b6363d0f02d0d532f0033c9603b9e2d943d56ee3b0d4f7ad3328ff917 462 | languageName: node 463 | linkType: hard 464 | 465 | "from2@npm:^2.3.0": 466 | version: 2.3.0 467 | resolution: "from2@npm:2.3.0" 468 | dependencies: 469 | inherits: ^2.0.1 470 | readable-stream: ^2.0.0 471 | checksum: 6080eba0793dce32f475141fb3d54cc15f84ee52e420ee22ac3ab0ad639dc95a1875bc6eb9c0e1140e94972a36a89dc5542491b85f1ab8df0c126241e0f1a61b 472 | languageName: node 473 | linkType: hard 474 | 475 | "fs-constants@npm:^1.0.0": 476 | version: 1.0.0 477 | resolution: "fs-constants@npm:1.0.0" 478 | checksum: 18f5b718371816155849475ac36c7d0b24d39a11d91348cfcb308b4494824413e03572c403c86d3a260e049465518c4f0d5bd00f0371cdfcad6d4f30a85b350d 479 | languageName: node 480 | linkType: hard 481 | 482 | "fs-extra@npm:^9.1.0": 483 | version: 9.1.0 484 | resolution: "fs-extra@npm:9.1.0" 485 | dependencies: 486 | at-least-node: ^1.0.0 487 | graceful-fs: ^4.2.0 488 | jsonfile: ^6.0.1 489 | universalify: ^2.0.0 490 | checksum: ba71ba32e0faa74ab931b7a0031d1523c66a73e225de7426e275e238e312d07313d2da2d33e34a52aa406c8763ade5712eb3ec9ba4d9edce652bcacdc29e6b20 491 | languageName: node 492 | linkType: hard 493 | 494 | "function-bind@npm:^1.1.1": 495 | version: 1.1.1 496 | resolution: "function-bind@npm:1.1.1" 497 | checksum: b32fbaebb3f8ec4969f033073b43f5c8befbb58f1a79e12f1d7490358150359ebd92f49e72ff0144f65f2c48ea2a605bff2d07965f548f6474fd8efd95bf361a 498 | languageName: node 499 | linkType: hard 500 | 501 | "get-caller-file@npm:^2.0.5": 502 | version: 2.0.5 503 | resolution: "get-caller-file@npm:2.0.5" 504 | checksum: b9769a836d2a98c3ee734a88ba712e62703f1df31b94b784762c433c27a386dd6029ff55c2a920c392e33657d80191edbf18c61487e198844844516f843496b9 505 | languageName: node 506 | linkType: hard 507 | 508 | "github-from-package@npm:0.0.0": 509 | version: 0.0.0 510 | resolution: "github-from-package@npm:0.0.0" 511 | checksum: 14e448192a35c1e42efee94c9d01a10f42fe790375891a24b25261246ce9336ab9df5d274585aedd4568f7922246c2a78b8a8cd2571bfe99c693a9718e7dd0e3 512 | languageName: node 513 | linkType: hard 514 | 515 | "glob-parent@npm:^5.1.2": 516 | version: 5.1.2 517 | resolution: "glob-parent@npm:5.1.2" 518 | dependencies: 519 | is-glob: ^4.0.1 520 | checksum: f4f2bfe2425296e8a47e36864e4f42be38a996db40420fe434565e4480e3322f18eb37589617a98640c5dc8fdec1a387007ee18dbb1f3f5553409c34d17f425e 521 | languageName: node 522 | linkType: hard 523 | 524 | "globby@npm:^11.1.0": 525 | version: 11.1.0 526 | resolution: "globby@npm:11.1.0" 527 | dependencies: 528 | array-union: ^2.1.0 529 | dir-glob: ^3.0.1 530 | fast-glob: ^3.2.9 531 | ignore: ^5.2.0 532 | merge2: ^1.4.1 533 | slash: ^3.0.0 534 | checksum: b4be8885e0cfa018fc783792942d53926c35c50b3aefd3fdcfb9d22c627639dc26bd2327a40a0b74b074100ce95bb7187bfeae2f236856aa3de183af7a02aea6 535 | languageName: node 536 | linkType: hard 537 | 538 | "graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0": 539 | version: 4.2.3 540 | resolution: "graceful-fs@npm:4.2.3" 541 | checksum: ec1f6a7027dfd4f6b69a15b2c78493d7211e88a8c0fdb6d93aa504f8f6b5353abac6ba0a202aedb9d970be22c2c257a1481426913ae0166bdc8bb8f3bed378dc 542 | languageName: node 543 | linkType: hard 544 | 545 | "has-flag@npm:^4.0.0": 546 | version: 4.0.0 547 | resolution: "has-flag@npm:4.0.0" 548 | checksum: 261a1357037ead75e338156b1f9452c016a37dcd3283a972a30d9e4a87441ba372c8b81f818cd0fbcd9c0354b4ae7e18b9e1afa1971164aef6d18c2b6095a8ad 549 | languageName: node 550 | linkType: hard 551 | 552 | "has@npm:^1.0.3": 553 | version: 1.0.3 554 | resolution: "has@npm:1.0.3" 555 | dependencies: 556 | function-bind: ^1.1.1 557 | checksum: b9ad53d53be4af90ce5d1c38331e712522417d017d5ef1ebd0507e07c2fbad8686fffb8e12ddecd4c39ca9b9b47431afbb975b8abf7f3c3b82c98e9aad052792 558 | languageName: node 559 | linkType: hard 560 | 561 | "https-proxy-agent@npm:^5.0.0": 562 | version: 5.0.0 563 | resolution: "https-proxy-agent@npm:5.0.0" 564 | dependencies: 565 | agent-base: 6 566 | debug: 4 567 | checksum: 165bfb090bd26d47693597661298006841ab733d0c7383a8cb2f17373387a94c903a3ac687090aa739de05e379ab6f868bae84ab4eac288ad85c328cd1ec9e53 568 | languageName: node 569 | linkType: hard 570 | 571 | "ieee754@npm:^1.1.13": 572 | version: 1.2.1 573 | resolution: "ieee754@npm:1.2.1" 574 | checksum: 5144c0c9815e54ada181d80a0b810221a253562422e7c6c3a60b1901154184f49326ec239d618c416c1c5945a2e197107aee8d986a3dd836b53dffefd99b5e7e 575 | languageName: node 576 | linkType: hard 577 | 578 | "ignore@npm:^5.2.0": 579 | version: 5.2.0 580 | resolution: "ignore@npm:5.2.0" 581 | checksum: 6b1f926792d614f64c6c83da3a1f9c83f6196c2839aa41e1e32dd7b8d174cef2e329d75caabb62cb61ce9dc432f75e67d07d122a037312db7caa73166a1bdb77 582 | languageName: node 583 | linkType: hard 584 | 585 | "inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3": 586 | version: 2.0.4 587 | resolution: "inherits@npm:2.0.4" 588 | checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 589 | languageName: node 590 | linkType: hard 591 | 592 | "ini@npm:~1.3.0": 593 | version: 1.3.8 594 | resolution: "ini@npm:1.3.8" 595 | checksum: dfd98b0ca3a4fc1e323e38a6c8eb8936e31a97a918d3b377649ea15bdb15d481207a0dda1021efbd86b464cae29a0d33c1d7dcaf6c5672bee17fa849bc50a1b3 596 | languageName: node 597 | linkType: hard 598 | 599 | "into-stream@npm:^6.0.0": 600 | version: 6.0.0 601 | resolution: "into-stream@npm:6.0.0" 602 | dependencies: 603 | from2: ^2.3.0 604 | p-is-promise: ^3.0.0 605 | checksum: 8df24c9eadd7cdd1cbc160bc20914b961dfd0ca29767785b69e698f799e85466b6f7c637d237dca1472d09d333399f70cc05a2fb8d08cb449dc9a80d92193980 606 | languageName: node 607 | linkType: hard 608 | 609 | "is-core-module@npm:2.9.0": 610 | version: 2.9.0 611 | resolution: "is-core-module@npm:2.9.0" 612 | dependencies: 613 | has: ^1.0.3 614 | checksum: b27034318b4b462f1c8f1dfb1b32baecd651d891a4e2d1922135daeff4141dfced2b82b07aef83ef54275c4a3526aa38da859223664d0868ca24182badb784ce 615 | languageName: node 616 | linkType: hard 617 | 618 | "is-core-module@npm:^2.9.0": 619 | version: 2.11.0 620 | resolution: "is-core-module@npm:2.11.0" 621 | dependencies: 622 | has: ^1.0.3 623 | checksum: f96fd490c6b48eb4f6d10ba815c6ef13f410b0ba6f7eb8577af51697de523e5f2cd9de1c441b51d27251bf0e4aebc936545e33a5d26d5d51f28d25698d4a8bab 624 | languageName: node 625 | linkType: hard 626 | 627 | "is-extglob@npm:^2.1.1": 628 | version: 2.1.1 629 | resolution: "is-extglob@npm:2.1.1" 630 | checksum: df033653d06d0eb567461e58a7a8c9f940bd8c22274b94bf7671ab36df5719791aae15eef6d83bbb5e23283967f2f984b8914559d4449efda578c775c4be6f85 631 | languageName: node 632 | linkType: hard 633 | 634 | "is-fullwidth-code-point@npm:^3.0.0": 635 | version: 3.0.0 636 | resolution: "is-fullwidth-code-point@npm:3.0.0" 637 | checksum: 44a30c29457c7fb8f00297bce733f0a64cd22eca270f83e58c105e0d015e45c019491a4ab2faef91ab51d4738c670daff901c799f6a700e27f7314029e99e348 638 | languageName: node 639 | linkType: hard 640 | 641 | "is-glob@npm:^4.0.1": 642 | version: 4.0.1 643 | resolution: "is-glob@npm:4.0.1" 644 | dependencies: 645 | is-extglob: ^2.1.1 646 | checksum: 84627cad11b4e745f5db5a163f32c47b711585a5ff6e14f8f8d026db87f4cdd3e2c95f6fa1f94ad22e469f36d819ae2814f03f9c668b164422ac3354a94672d3 647 | languageName: node 648 | linkType: hard 649 | 650 | "is-number@npm:^7.0.0": 651 | version: 7.0.0 652 | resolution: "is-number@npm:7.0.0" 653 | checksum: 456ac6f8e0f3111ed34668a624e45315201dff921e5ac181f8ec24923b99e9f32ca1a194912dc79d539c97d33dba17dc635202ff0b2cf98326f608323276d27a 654 | languageName: node 655 | linkType: hard 656 | 657 | "isarray@npm:~1.0.0": 658 | version: 1.0.0 659 | resolution: "isarray@npm:1.0.0" 660 | checksum: f032df8e02dce8ec565cf2eb605ea939bdccea528dbcf565cdf92bfa2da9110461159d86a537388ef1acef8815a330642d7885b29010e8f7eac967c9993b65ab 661 | languageName: node 662 | linkType: hard 663 | 664 | "jsesc@npm:^2.5.1": 665 | version: 2.5.2 666 | resolution: "jsesc@npm:2.5.2" 667 | bin: 668 | jsesc: bin/jsesc 669 | checksum: 4dc190771129e12023f729ce20e1e0bfceac84d73a85bc3119f7f938843fe25a4aeccb54b6494dce26fcf263d815f5f31acdefac7cc9329efb8422a4f4d9fa9d 670 | languageName: node 671 | linkType: hard 672 | 673 | "jsonfile@npm:^6.0.1": 674 | version: 6.1.0 675 | resolution: "jsonfile@npm:6.1.0" 676 | dependencies: 677 | graceful-fs: ^4.1.6 678 | universalify: ^2.0.0 679 | dependenciesMeta: 680 | graceful-fs: 681 | optional: true 682 | checksum: 7af3b8e1ac8fe7f1eccc6263c6ca14e1966fcbc74b618d3c78a0a2075579487547b94f72b7a1114e844a1e15bb00d440e5d1720bfc4612d790a6f285d5ea8354 683 | languageName: node 684 | linkType: hard 685 | 686 | "lru-cache@npm:^6.0.0": 687 | version: 6.0.0 688 | resolution: "lru-cache@npm:6.0.0" 689 | dependencies: 690 | yallist: ^4.0.0 691 | checksum: f97f499f898f23e4585742138a22f22526254fdba6d75d41a1c2526b3b6cc5747ef59c5612ba7375f42aca4f8461950e925ba08c991ead0651b4918b7c978297 692 | languageName: node 693 | linkType: hard 694 | 695 | "merge2@npm:^1.3.0": 696 | version: 1.3.0 697 | resolution: "merge2@npm:1.3.0" 698 | checksum: bff71d47cd8c01edf2222f205f1c312cae0082e2c05b06123b0990605447dc395208367bb1d1635caec6083d3e6bb0756df05ac24cdc15cb630d5af6daa8eb7c 699 | languageName: node 700 | linkType: hard 701 | 702 | "merge2@npm:^1.4.1": 703 | version: 1.4.1 704 | resolution: "merge2@npm:1.4.1" 705 | checksum: 7268db63ed5169466540b6fb947aec313200bcf6d40c5ab722c22e242f651994619bcd85601602972d3c85bd2cc45a358a4c61937e9f11a061919a1da569b0c2 706 | languageName: node 707 | linkType: hard 708 | 709 | "micromatch@npm:^4.0.4": 710 | version: 4.0.4 711 | resolution: "micromatch@npm:4.0.4" 712 | dependencies: 713 | braces: ^3.0.1 714 | picomatch: ^2.2.3 715 | checksum: ef3d1c88e79e0a68b0e94a03137676f3324ac18a908c245a9e5936f838079fcc108ac7170a5fadc265a9c2596963462e402841406bda1a4bb7b68805601d631c 716 | languageName: node 717 | linkType: hard 718 | 719 | "mimic-response@npm:^3.1.0": 720 | version: 3.1.0 721 | resolution: "mimic-response@npm:3.1.0" 722 | checksum: 25739fee32c17f433626bf19f016df9036b75b3d84a3046c7d156e72ec963dd29d7fc8a302f55a3d6c5a4ff24259676b15d915aad6480815a969ff2ec0836867 723 | languageName: node 724 | linkType: hard 725 | 726 | "minimist@npm:^1.2.0, minimist@npm:^1.2.3, minimist@npm:^1.2.6": 727 | version: 1.2.8 728 | resolution: "minimist@npm:1.2.8" 729 | checksum: 75a6d645fb122dad29c06a7597bddea977258957ed88d7a6df59b5cd3fe4a527e253e9bbf2e783e4b73657f9098b96a5fe96ab8a113655d4109108577ecf85b0 730 | languageName: node 731 | linkType: hard 732 | 733 | "mkdirp-classic@npm:^0.5.2, mkdirp-classic@npm:^0.5.3": 734 | version: 0.5.3 735 | resolution: "mkdirp-classic@npm:0.5.3" 736 | checksum: 3f4e088208270bbcc148d53b73e9a5bd9eef05ad2cbf3b3d0ff8795278d50dd1d11a8ef1875ff5aea3fa888931f95bfcb2ad5b7c1061cfefd6284d199e6776ac 737 | languageName: node 738 | linkType: hard 739 | 740 | "ms@npm:2.1.2": 741 | version: 2.1.2 742 | resolution: "ms@npm:2.1.2" 743 | checksum: 673cdb2c3133eb050c745908d8ce632ed2c02d85640e2edb3ace856a2266a813b30c613569bf3354fdf4ea7d1a1494add3bfa95e2713baa27d0c2c71fc44f58f 744 | languageName: node 745 | linkType: hard 746 | 747 | "multistream@npm:^4.1.0": 748 | version: 4.1.0 749 | resolution: "multistream@npm:4.1.0" 750 | dependencies: 751 | once: ^1.4.0 752 | readable-stream: ^3.6.0 753 | checksum: 305c49a1aadcb7f63f64d8ca2bb6e7852e5f7dba94c7329e9a72ce53cd0046686b71668dc1adbf123f17d2dd107765fc946e64c36a26b15c470a3146ea3bc923 754 | languageName: node 755 | linkType: hard 756 | 757 | "napi-build-utils@npm:^1.0.1": 758 | version: 1.0.2 759 | resolution: "napi-build-utils@npm:1.0.2" 760 | checksum: 06c14271ee966e108d55ae109f340976a9556c8603e888037145d6522726aebe89dd0c861b4b83947feaf6d39e79e08817559e8693deedc2c94e82c5cbd090c7 761 | languageName: node 762 | linkType: hard 763 | 764 | "node-abi@npm:^3.3.0": 765 | version: 3.33.0 766 | resolution: "node-abi@npm:3.33.0" 767 | dependencies: 768 | semver: ^7.3.5 769 | checksum: 59e5e00d9a15225087b6dd55b7d4f99686a6d64a8bdbe2c9aa98f4f74554873a7225d3dc975fa32718e7695eed8abcfeaae58b03db118a01392f6d25b0469b52 770 | languageName: node 771 | linkType: hard 772 | 773 | "node-fetch@npm:^2.6.6": 774 | version: 2.6.7 775 | resolution: "node-fetch@npm:2.6.7" 776 | dependencies: 777 | whatwg-url: ^5.0.0 778 | peerDependencies: 779 | encoding: ^0.1.0 780 | peerDependenciesMeta: 781 | encoding: 782 | optional: true 783 | checksum: 8d816ffd1ee22cab8301c7756ef04f3437f18dace86a1dae22cf81db8ef29c0bf6655f3215cb0cdb22b420b6fe141e64b26905e7f33f9377a7fa59135ea3e10b 784 | languageName: node 785 | linkType: hard 786 | 787 | "once@npm:^1.3.1, once@npm:^1.4.0": 788 | version: 1.4.0 789 | resolution: "once@npm:1.4.0" 790 | dependencies: 791 | wrappy: 1 792 | checksum: cd0a88501333edd640d95f0d2700fbde6bff20b3d4d9bdc521bdd31af0656b5706570d6c6afe532045a20bb8dc0849f8332d6f2a416e0ba6d3d3b98806c7db68 793 | languageName: node 794 | linkType: hard 795 | 796 | "p-is-promise@npm:^3.0.0": 797 | version: 3.0.0 798 | resolution: "p-is-promise@npm:3.0.0" 799 | checksum: 74e511225fde5eeda7a120d51c60c284de90d68dec7c73611e7e59e8d1c44cc7e2246686544515849149b74ed0571ad470a456ac0d00314f8d03d2cc1ad43aae 800 | languageName: node 801 | linkType: hard 802 | 803 | "path-parse@npm:^1.0.7": 804 | version: 1.0.7 805 | resolution: "path-parse@npm:1.0.7" 806 | checksum: 49abf3d81115642938a8700ec580da6e830dde670be21893c62f4e10bd7dd4c3742ddc603fe24f898cba7eb0c6bc1777f8d9ac14185d34540c6d4d80cd9cae8a 807 | languageName: node 808 | linkType: hard 809 | 810 | "path-type@npm:^4.0.0": 811 | version: 4.0.0 812 | resolution: "path-type@npm:4.0.0" 813 | checksum: 5b1e2daa247062061325b8fdbfd1fb56dde0a448fb1455453276ea18c60685bdad23a445dc148cf87bc216be1573357509b7d4060494a6fd768c7efad833ee45 814 | languageName: node 815 | linkType: hard 816 | 817 | "picomatch@npm:^2.2.3": 818 | version: 2.3.0 819 | resolution: "picomatch@npm:2.3.0" 820 | checksum: 16818720ea7c5872b6af110760dee856c8e4cd79aed1c7a006d076b1cc09eff3ae41ca5019966694c33fbd2e1cc6ea617ab10e4adac6df06556168f13be3fca2 821 | languageName: node 822 | linkType: hard 823 | 824 | "pkg-fetch@npm:3.4.2": 825 | version: 3.4.2 826 | resolution: "pkg-fetch@npm:3.4.2" 827 | dependencies: 828 | chalk: ^4.1.2 829 | fs-extra: ^9.1.0 830 | https-proxy-agent: ^5.0.0 831 | node-fetch: ^2.6.6 832 | progress: ^2.0.3 833 | semver: ^7.3.5 834 | tar-fs: ^2.1.1 835 | yargs: ^16.2.0 836 | bin: 837 | pkg-fetch: lib-es5/bin.js 838 | checksum: e0f73cedf6cb8882e4d998700031443e6542d213f9817d66deb03fb89c122ca7f7505f11401f85a760a2d3951f9b793d0f78782be220c46c56ccf70f9915812a 839 | languageName: node 840 | linkType: hard 841 | 842 | "pkg@npm:^5.5.2": 843 | version: 5.8.1 844 | resolution: "pkg@npm:5.8.1" 845 | dependencies: 846 | "@babel/generator": 7.18.2 847 | "@babel/parser": 7.18.4 848 | "@babel/types": 7.19.0 849 | chalk: ^4.1.2 850 | fs-extra: ^9.1.0 851 | globby: ^11.1.0 852 | into-stream: ^6.0.0 853 | is-core-module: 2.9.0 854 | minimist: ^1.2.6 855 | multistream: ^4.1.0 856 | pkg-fetch: 3.4.2 857 | prebuild-install: 7.1.1 858 | resolve: ^1.22.0 859 | stream-meter: ^1.0.4 860 | peerDependencies: 861 | node-notifier: ">=9.0.1" 862 | peerDependenciesMeta: 863 | node-notifier: 864 | optional: true 865 | bin: 866 | pkg: lib-es5/bin.js 867 | checksum: 5e750e716c3426706ea1fbd26832faf6a3ab8376b99f20aeb9c40fd48ad48e7b51375cd077b77669f3bfbefee69cc8111f49e0ca39e353fd0fc2dff95a57f822 868 | languageName: node 869 | linkType: hard 870 | 871 | "prebuild-install@npm:7.1.1": 872 | version: 7.1.1 873 | resolution: "prebuild-install@npm:7.1.1" 874 | dependencies: 875 | detect-libc: ^2.0.0 876 | expand-template: ^2.0.3 877 | github-from-package: 0.0.0 878 | minimist: ^1.2.3 879 | mkdirp-classic: ^0.5.3 880 | napi-build-utils: ^1.0.1 881 | node-abi: ^3.3.0 882 | pump: ^3.0.0 883 | rc: ^1.2.7 884 | simple-get: ^4.0.0 885 | tar-fs: ^2.0.0 886 | tunnel-agent: ^0.6.0 887 | bin: 888 | prebuild-install: bin.js 889 | checksum: dbf96d0146b6b5827fc8f67f72074d2e19c69628b9a7a0a17d0fad1bf37e9f06922896972e074197fc00a52eae912993e6ef5a0d471652f561df5cb516f3f467 890 | languageName: node 891 | linkType: hard 892 | 893 | "process-nextick-args@npm:~2.0.0": 894 | version: 2.0.1 895 | resolution: "process-nextick-args@npm:2.0.1" 896 | checksum: 1d38588e520dab7cea67cbbe2efdd86a10cc7a074c09657635e34f035277b59fbb57d09d8638346bf7090f8e8ebc070c96fa5fd183b777fff4f5edff5e9466cf 897 | languageName: node 898 | linkType: hard 899 | 900 | "progress@npm:^2.0.3": 901 | version: 2.0.3 902 | resolution: "progress@npm:2.0.3" 903 | checksum: f67403fe7b34912148d9252cb7481266a354bd99ce82c835f79070643bb3c6583d10dbcfda4d41e04bbc1d8437e9af0fb1e1f2135727878f5308682a579429b7 904 | languageName: node 905 | linkType: hard 906 | 907 | "pump@npm:^3.0.0": 908 | version: 3.0.0 909 | resolution: "pump@npm:3.0.0" 910 | dependencies: 911 | end-of-stream: ^1.1.0 912 | once: ^1.3.1 913 | checksum: e42e9229fba14732593a718b04cb5e1cfef8254544870997e0ecd9732b189a48e1256e4e5478148ecb47c8511dca2b09eae56b4d0aad8009e6fac8072923cfc9 914 | languageName: node 915 | linkType: hard 916 | 917 | "rc@npm:^1.2.7": 918 | version: 1.2.8 919 | resolution: "rc@npm:1.2.8" 920 | dependencies: 921 | deep-extend: ^0.6.0 922 | ini: ~1.3.0 923 | minimist: ^1.2.0 924 | strip-json-comments: ~2.0.1 925 | bin: 926 | rc: ./cli.js 927 | checksum: 2e26e052f8be2abd64e6d1dabfbd7be03f80ec18ccbc49562d31f617d0015fbdbcf0f9eed30346ea6ab789e0fdfe4337f033f8016efdbee0df5354751842080e 928 | languageName: node 929 | linkType: hard 930 | 931 | "readable-stream@npm:^2.0.0, readable-stream@npm:^2.1.4": 932 | version: 2.3.6 933 | resolution: "readable-stream@npm:2.3.6" 934 | dependencies: 935 | core-util-is: ~1.0.0 936 | inherits: ~2.0.3 937 | isarray: ~1.0.0 938 | process-nextick-args: ~2.0.0 939 | safe-buffer: ~5.1.1 940 | string_decoder: ~1.1.1 941 | util-deprecate: ~1.0.1 942 | checksum: 686bbf9e2300cd24bbd71ba8999202613ef19441da9223bfe2c7da4f0dfab233302e2604846e9b8e814664ccdf365881e593da963ac9e2120abfa21f14f257fb 943 | languageName: node 944 | linkType: hard 945 | 946 | "readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.6.0": 947 | version: 3.6.0 948 | resolution: "readable-stream@npm:3.6.0" 949 | dependencies: 950 | inherits: ^2.0.3 951 | string_decoder: ^1.1.1 952 | util-deprecate: ^1.0.1 953 | checksum: d4ea81502d3799439bb955a3a5d1d808592cf3133350ed352aeaa499647858b27b1c4013984900238b0873ec8d0d8defce72469fb7a83e61d53f5ad61cb80dc8 954 | languageName: node 955 | linkType: hard 956 | 957 | "require-directory@npm:^2.1.1": 958 | version: 2.1.1 959 | resolution: "require-directory@npm:2.1.1" 960 | checksum: fb47e70bf0001fdeabdc0429d431863e9475e7e43ea5f94ad86503d918423c1543361cc5166d713eaa7029dd7a3d34775af04764bebff99ef413111a5af18c80 961 | languageName: node 962 | linkType: hard 963 | 964 | resolve@^1.22.0: 965 | version: 1.22.1 966 | resolution: "resolve@npm:1.22.1" 967 | dependencies: 968 | is-core-module: ^2.9.0 969 | path-parse: ^1.0.7 970 | supports-preserve-symlinks-flag: ^1.0.0 971 | bin: 972 | resolve: bin/resolve 973 | checksum: 07af5fc1e81aa1d866cbc9e9460fbb67318a10fa3c4deadc35c3ad8a898ee9a71a86a65e4755ac3195e0ea0cfbe201eb323ebe655ce90526fd61917313a34e4e 974 | languageName: node 975 | linkType: hard 976 | 977 | "resolve@patch:resolve@^1.22.0#~builtin": 978 | version: 1.22.1 979 | resolution: "resolve@patch:resolve@npm%3A1.22.1#~builtin::version=1.22.1&hash=00b1ff" 980 | dependencies: 981 | is-core-module: ^2.9.0 982 | path-parse: ^1.0.7 983 | supports-preserve-symlinks-flag: ^1.0.0 984 | bin: 985 | resolve: bin/resolve 986 | checksum: d45553550a85af4c6c310a4d9790b60f1fcbdbb1b7ca93f1ad8e06424d69aa6782d59bd93a4c085777baf6159ecc1dbe432299a6027c4837de4db5851a5d3435 987 | languageName: node 988 | linkType: hard 989 | 990 | "reusify@npm:^1.0.0": 991 | version: 1.0.4 992 | resolution: "reusify@npm:1.0.4" 993 | checksum: c3076ebcc22a6bc252cb0b9c77561795256c22b757f40c0d8110b1300723f15ec0fc8685e8d4ea6d7666f36c79ccc793b1939c748bf36f18f542744a4e379fcc 994 | languageName: node 995 | linkType: hard 996 | 997 | "run-parallel@npm:^1.1.9": 998 | version: 1.1.9 999 | resolution: "run-parallel@npm:1.1.9" 1000 | checksum: 8bbeda89c2c1dbfeaa0cdb9f17e93a011ac58ef77339ef1e61a62208b67c8e7b661891df677bb7c5be84b8792e27061177368d500b3c731bb019b0c71e667591 1001 | languageName: node 1002 | linkType: hard 1003 | 1004 | "rxjs@npm:*": 1005 | version: 7.5.5 1006 | resolution: "rxjs@npm:7.5.5" 1007 | dependencies: 1008 | tslib: ^2.1.0 1009 | checksum: e034f60805210cce756dd2f49664a8108780b117cf5d0e2281506e9e6387f7b4f1532d974a8c8b09314fa7a16dd2f6cff3462072a5789672b5dcb45c4173f3c6 1010 | languageName: node 1011 | linkType: hard 1012 | 1013 | "safe-buffer@npm:^5.0.1": 1014 | version: 5.2.0 1015 | resolution: "safe-buffer@npm:5.2.0" 1016 | checksum: 91d50127aeaee9b8cb1ee12c810d719e29813d1ab1ce6d1b4704cd9ca0e0bfa47455e02cf1bb238be90f2db764447f058fbaef1a1018ae8387c692615d72f86c 1017 | languageName: node 1018 | linkType: hard 1019 | 1020 | "safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": 1021 | version: 5.1.2 1022 | resolution: "safe-buffer@npm:5.1.2" 1023 | checksum: f2f1f7943ca44a594893a852894055cf619c1fbcb611237fc39e461ae751187e7baf4dc391a72125e0ac4fb2d8c5c0b3c71529622e6a58f46b960211e704903c 1024 | languageName: node 1025 | linkType: hard 1026 | 1027 | "safe-buffer@npm:~5.2.0": 1028 | version: 5.2.1 1029 | resolution: "safe-buffer@npm:5.2.1" 1030 | checksum: b99c4b41fdd67a6aaf280fcd05e9ffb0813654894223afb78a31f14a19ad220bba8aba1cb14eddce1fcfb037155fe6de4e861784eb434f7d11ed58d1e70dd491 1031 | languageName: node 1032 | linkType: hard 1033 | 1034 | "semver@npm:^7.3.5": 1035 | version: 7.5.3 1036 | resolution: "semver@npm:7.5.3" 1037 | dependencies: 1038 | lru-cache: ^6.0.0 1039 | bin: 1040 | semver: bin/semver.js 1041 | checksum: 9d58db16525e9f749ad0a696a1f27deabaa51f66e91d2fa2b0db3de3e9644e8677de3b7d7a03f4c15bc81521e0c3916d7369e0572dbde250d9bedf5194e2a8a7 1042 | languageName: node 1043 | linkType: hard 1044 | 1045 | "simple-concat@npm:^1.0.0": 1046 | version: 1.0.1 1047 | resolution: "simple-concat@npm:1.0.1" 1048 | checksum: 4d211042cc3d73a718c21ac6c4e7d7a0363e184be6a5ad25c8a1502e49df6d0a0253979e3d50dbdd3f60ef6c6c58d756b5d66ac1e05cda9cacd2e9fc59e3876a 1049 | languageName: node 1050 | linkType: hard 1051 | 1052 | "simple-get@npm:^4.0.0": 1053 | version: 4.0.1 1054 | resolution: "simple-get@npm:4.0.1" 1055 | dependencies: 1056 | decompress-response: ^6.0.0 1057 | once: ^1.3.1 1058 | simple-concat: ^1.0.0 1059 | checksum: e4132fd27cf7af230d853fa45c1b8ce900cb430dd0a3c6d3829649fe4f2b26574c803698076c4006450efb0fad2ba8c5455fbb5755d4b0a5ec42d4f12b31d27e 1060 | languageName: node 1061 | linkType: hard 1062 | 1063 | "slash@npm:^3.0.0": 1064 | version: 3.0.0 1065 | resolution: "slash@npm:3.0.0" 1066 | checksum: 94a93fff615f25a999ad4b83c9d5e257a7280c90a32a7cb8b4a87996e4babf322e469c42b7f649fd5796edd8687652f3fb452a86dc97a816f01113183393f11c 1067 | languageName: node 1068 | linkType: hard 1069 | 1070 | "stream-meter@npm:^1.0.4": 1071 | version: 1.0.4 1072 | resolution: "stream-meter@npm:1.0.4" 1073 | dependencies: 1074 | readable-stream: ^2.1.4 1075 | checksum: a732f7ede9dadd6214083aaf4e3014d664498a56b91cdbc4e6abae59ec8ae507883f58f1f3ca7a939cdb9cc8e2320997241191e9fb8c7717f3fad9ca8cb5dc46 1076 | languageName: node 1077 | linkType: hard 1078 | 1079 | "string-argv@npm:^0.3.1": 1080 | version: 0.3.1 1081 | resolution: "string-argv@npm:0.3.1" 1082 | checksum: efbd0289b599bee808ce80820dfe49c9635610715429c6b7cc50750f0437e3c2f697c81e5c390208c13b5d5d12d904a1546172a88579f6ee5cbaaaa4dc9ec5cf 1083 | languageName: node 1084 | linkType: hard 1085 | 1086 | "string-width@npm:^4.1.0, string-width@npm:^4.2.0": 1087 | version: 4.2.0 1088 | resolution: "string-width@npm:4.2.0" 1089 | dependencies: 1090 | emoji-regex: ^8.0.0 1091 | is-fullwidth-code-point: ^3.0.0 1092 | strip-ansi: ^6.0.0 1093 | checksum: ee2c68df9a3ce4256565d2bdc8490f5706f195f88e799d3d425889264d3eff3d7984fe8b38dfc983dac948e03d8cdc737294b1c81f1528c37c9935d86b67593d 1094 | languageName: node 1095 | linkType: hard 1096 | 1097 | "string-width@npm:^4.2.3": 1098 | version: 4.2.3 1099 | resolution: "string-width@npm:4.2.3" 1100 | dependencies: 1101 | emoji-regex: ^8.0.0 1102 | is-fullwidth-code-point: ^3.0.0 1103 | strip-ansi: ^6.0.1 1104 | checksum: e52c10dc3fbfcd6c3a15f159f54a90024241d0f149cf8aed2982a2d801d2e64df0bf1dc351cf8e95c3319323f9f220c16e740b06faecd53e2462df1d2b5443fb 1105 | languageName: node 1106 | linkType: hard 1107 | 1108 | "string_decoder@npm:^1.1.1": 1109 | version: 1.3.0 1110 | resolution: "string_decoder@npm:1.3.0" 1111 | dependencies: 1112 | safe-buffer: ~5.2.0 1113 | checksum: 8417646695a66e73aefc4420eb3b84cc9ffd89572861fe004e6aeb13c7bc00e2f616247505d2dbbef24247c372f70268f594af7126f43548565c68c117bdeb56 1114 | languageName: node 1115 | linkType: hard 1116 | 1117 | "string_decoder@npm:~1.1.1": 1118 | version: 1.1.1 1119 | resolution: "string_decoder@npm:1.1.1" 1120 | dependencies: 1121 | safe-buffer: ~5.1.0 1122 | checksum: 9ab7e56f9d60a28f2be697419917c50cac19f3e8e6c28ef26ed5f4852289fe0de5d6997d29becf59028556f2c62983790c1d9ba1e2a3cc401768ca12d5183a5b 1123 | languageName: node 1124 | linkType: hard 1125 | 1126 | "strip-ansi@npm:^6.0.0": 1127 | version: 6.0.0 1128 | resolution: "strip-ansi@npm:6.0.0" 1129 | dependencies: 1130 | ansi-regex: ^5.0.0 1131 | checksum: 04c3239ede44c4d195b0e66c0ad58b932f08bec7d05290416d361ff908ad282ecdaf5d9731e322c84f151d427436bde01f05b7422c3ec26dd927586736b0e5d0 1132 | languageName: node 1133 | linkType: hard 1134 | 1135 | "strip-ansi@npm:^6.0.1": 1136 | version: 6.0.1 1137 | resolution: "strip-ansi@npm:6.0.1" 1138 | dependencies: 1139 | ansi-regex: ^5.0.1 1140 | checksum: f3cd25890aef3ba6e1a74e20896c21a46f482e93df4a06567cebf2b57edabb15133f1f94e57434e0a958d61186087b1008e89c94875d019910a213181a14fc8c 1141 | languageName: node 1142 | linkType: hard 1143 | 1144 | "strip-json-comments@npm:~2.0.1": 1145 | version: 2.0.1 1146 | resolution: "strip-json-comments@npm:2.0.1" 1147 | checksum: 1074ccb63270d32ca28edfb0a281c96b94dc679077828135141f27d52a5a398ef5e78bcf22809d23cadc2b81dfbe345eb5fd8699b385c8b1128907dec4a7d1e1 1148 | languageName: node 1149 | linkType: hard 1150 | 1151 | "supports-color@npm:^7.1.0": 1152 | version: 7.1.0 1153 | resolution: "supports-color@npm:7.1.0" 1154 | dependencies: 1155 | has-flag: ^4.0.0 1156 | checksum: 899480ac858a650abcca4a02ae655555270e6ace833b15a74e4a2d3456f54cd19b6b12ce14e9bac997c18dd69a0596ee65b95ba013f209dd0f99ebfe87783e41 1157 | languageName: node 1158 | linkType: hard 1159 | 1160 | "supports-preserve-symlinks-flag@npm:^1.0.0": 1161 | version: 1.0.0 1162 | resolution: "supports-preserve-symlinks-flag@npm:1.0.0" 1163 | checksum: 53b1e247e68e05db7b3808b99b892bd36fb096e6fba213a06da7fab22045e97597db425c724f2bbd6c99a3c295e1e73f3e4de78592289f38431049e1277ca0ae 1164 | languageName: node 1165 | linkType: hard 1166 | 1167 | "tar-fs@npm:^2.0.0, tar-fs@npm:^2.1.1": 1168 | version: 2.1.1 1169 | resolution: "tar-fs@npm:2.1.1" 1170 | dependencies: 1171 | chownr: ^1.1.1 1172 | mkdirp-classic: ^0.5.2 1173 | pump: ^3.0.0 1174 | tar-stream: ^2.1.4 1175 | checksum: f5b9a70059f5b2969e65f037b4e4da2daf0fa762d3d232ffd96e819e3f94665dbbbe62f76f084f1acb4dbdcce16c6e4dac08d12ffc6d24b8d76720f4d9cf032d 1176 | languageName: node 1177 | linkType: hard 1178 | 1179 | "tar-stream@npm:^2.1.4": 1180 | version: 2.2.0 1181 | resolution: "tar-stream@npm:2.2.0" 1182 | dependencies: 1183 | bl: ^4.0.3 1184 | end-of-stream: ^1.4.1 1185 | fs-constants: ^1.0.0 1186 | inherits: ^2.0.3 1187 | readable-stream: ^3.1.1 1188 | checksum: 699831a8b97666ef50021c767f84924cfee21c142c2eb0e79c63254e140e6408d6d55a065a2992548e72b06de39237ef2b802b99e3ece93ca3904a37622a66f3 1189 | languageName: node 1190 | linkType: hard 1191 | 1192 | "to-fast-properties@npm:^2.0.0": 1193 | version: 2.0.0 1194 | resolution: "to-fast-properties@npm:2.0.0" 1195 | checksum: be2de62fe58ead94e3e592680052683b1ec986c72d589e7b21e5697f8744cdbf48c266fa72f6c15932894c10187b5f54573a3bcf7da0bfd964d5caf23d436168 1196 | languageName: node 1197 | linkType: hard 1198 | 1199 | "to-regex-range@npm:^5.0.1": 1200 | version: 5.0.1 1201 | resolution: "to-regex-range@npm:5.0.1" 1202 | dependencies: 1203 | is-number: ^7.0.0 1204 | checksum: f76fa01b3d5be85db6a2a143e24df9f60dd047d151062d0ba3df62953f2f697b16fe5dad9b0ac6191c7efc7b1d9dcaa4b768174b7b29da89d4428e64bc0a20ed 1205 | languageName: node 1206 | linkType: hard 1207 | 1208 | "tr46@npm:~0.0.3": 1209 | version: 0.0.3 1210 | resolution: "tr46@npm:0.0.3" 1211 | checksum: 726321c5eaf41b5002e17ffbd1fb7245999a073e8979085dacd47c4b4e8068ff5777142fc6726d6ca1fd2ff16921b48788b87225cbc57c72636f6efa8efbffe3 1212 | languageName: node 1213 | linkType: hard 1214 | 1215 | "tslib@npm:^2.1.0": 1216 | version: 2.3.1 1217 | resolution: "tslib@npm:2.3.1" 1218 | checksum: de17a98d4614481f7fcb5cd53ffc1aaf8654313be0291e1bfaee4b4bb31a20494b7d218ff2e15017883e8ea9626599b3b0e0229c18383ba9dce89da2adf15cb9 1219 | languageName: node 1220 | linkType: hard 1221 | 1222 | "tunnel-agent@npm:^0.6.0": 1223 | version: 0.6.0 1224 | resolution: "tunnel-agent@npm:0.6.0" 1225 | dependencies: 1226 | safe-buffer: ^5.0.1 1227 | checksum: 05f6510358f8afc62a057b8b692f05d70c1782b70db86d6a1e0d5e28a32389e52fa6e7707b6c5ecccacc031462e4bc35af85ecfe4bbc341767917b7cf6965711 1228 | languageName: node 1229 | linkType: hard 1230 | 1231 | "typed-emitter@npm:^2.1.0": 1232 | version: 2.1.0 1233 | resolution: "typed-emitter@npm:2.1.0" 1234 | dependencies: 1235 | rxjs: "*" 1236 | dependenciesMeta: 1237 | rxjs: 1238 | optional: true 1239 | checksum: 95821a9e05784b972cc9d152891fd12a56cb4b1a7c57e768c02bea6a8984da7aff8f19404a7b69eea11fae2a3b6c0c510a4c510f575f50162c759ae9059f2520 1240 | languageName: node 1241 | linkType: hard 1242 | 1243 | typescript@^5.0.3: 1244 | version: 5.1.6 1245 | resolution: "typescript@npm:5.1.6" 1246 | bin: 1247 | tsc: bin/tsc 1248 | tsserver: bin/tsserver 1249 | checksum: b2f2c35096035fe1f5facd1e38922ccb8558996331405eb00a5111cc948b2e733163cc22fab5db46992aba7dd520fff637f2c1df4996ff0e134e77d3249a7350 1250 | languageName: node 1251 | linkType: hard 1252 | 1253 | "typescript@patch:typescript@^5.0.3#~builtin": 1254 | version: 5.1.6 1255 | resolution: "typescript@patch:typescript@npm%3A5.1.6#~builtin::version=5.1.6&hash=32657b" 1256 | bin: 1257 | tsc: bin/tsc 1258 | tsserver: bin/tsserver 1259 | checksum: 7a15027671df3545ba285077c1876d23403b1bb158ec860f7a019d4b8bdc18b89a9d19dc0845991e5431be63fe4ec4235223a662428d8adce7916d7119edd5ab 1260 | languageName: node 1261 | linkType: hard 1262 | 1263 | "universalify@npm:^2.0.0": 1264 | version: 2.0.0 1265 | resolution: "universalify@npm:2.0.0" 1266 | checksum: 2406a4edf4a8830aa6813278bab1f953a8e40f2f63a37873ffa9a3bc8f9745d06cc8e88f3572cb899b7e509013f7f6fcc3e37e8a6d914167a5381d8440518c44 1267 | languageName: node 1268 | linkType: hard 1269 | 1270 | "util-deprecate@npm:^1.0.1, util-deprecate@npm:~1.0.1": 1271 | version: 1.0.2 1272 | resolution: "util-deprecate@npm:1.0.2" 1273 | checksum: 474acf1146cb2701fe3b074892217553dfcf9a031280919ba1b8d651a068c9b15d863b7303cb15bd00a862b498e6cf4ad7b4a08fb134edd5a6f7641681cb54a2 1274 | languageName: node 1275 | linkType: hard 1276 | 1277 | "webidl-conversions@npm:^3.0.0": 1278 | version: 3.0.1 1279 | resolution: "webidl-conversions@npm:3.0.1" 1280 | checksum: c92a0a6ab95314bde9c32e1d0a6dfac83b578f8fa5f21e675bc2706ed6981bc26b7eb7e6a1fab158e5ce4adf9caa4a0aee49a52505d4d13c7be545f15021b17c 1281 | languageName: node 1282 | linkType: hard 1283 | 1284 | "whatwg-url@npm:^5.0.0": 1285 | version: 5.0.0 1286 | resolution: "whatwg-url@npm:5.0.0" 1287 | dependencies: 1288 | tr46: ~0.0.3 1289 | webidl-conversions: ^3.0.0 1290 | checksum: b8daed4ad3356cc4899048a15b2c143a9aed0dfae1f611ebd55073310c7b910f522ad75d727346ad64203d7e6c79ef25eafd465f4d12775ca44b90fa82ed9e2c 1291 | languageName: node 1292 | linkType: hard 1293 | 1294 | "wrap-ansi@npm:^7.0.0": 1295 | version: 7.0.0 1296 | resolution: "wrap-ansi@npm:7.0.0" 1297 | dependencies: 1298 | ansi-styles: ^4.0.0 1299 | string-width: ^4.1.0 1300 | strip-ansi: ^6.0.0 1301 | checksum: a790b846fd4505de962ba728a21aaeda189b8ee1c7568ca5e817d85930e06ef8d1689d49dbf0e881e8ef84436af3a88bc49115c2e2788d841ff1b8b5b51a608b 1302 | languageName: node 1303 | linkType: hard 1304 | 1305 | "wrappy@npm:1": 1306 | version: 1.0.2 1307 | resolution: "wrappy@npm:1.0.2" 1308 | checksum: 159da4805f7e84a3d003d8841557196034155008f817172d4e986bd591f74aa82aa7db55929a54222309e01079a65a92a9e6414da5a6aa4b01ee44a511ac3ee5 1309 | languageName: node 1310 | linkType: hard 1311 | 1312 | "y18n@npm:^5.0.5": 1313 | version: 5.0.8 1314 | resolution: "y18n@npm:5.0.8" 1315 | checksum: 54f0fb95621ee60898a38c572c515659e51cc9d9f787fb109cef6fde4befbe1c4602dc999d30110feee37456ad0f1660fa2edcfde6a9a740f86a290999550d30 1316 | languageName: node 1317 | linkType: hard 1318 | 1319 | "yallist@npm:^4.0.0": 1320 | version: 4.0.0 1321 | resolution: "yallist@npm:4.0.0" 1322 | checksum: 343617202af32df2a15a3be36a5a8c0c8545208f3d3dfbc6bb7c3e3b7e8c6f8e7485432e4f3b88da3031a6e20afa7c711eded32ddfb122896ac5d914e75848d5 1323 | languageName: node 1324 | linkType: hard 1325 | 1326 | "yargs-parser@npm:^20.2.2": 1327 | version: 20.2.9 1328 | resolution: "yargs-parser@npm:20.2.9" 1329 | checksum: 8bb69015f2b0ff9e17b2c8e6bfe224ab463dd00ca211eece72a4cd8a906224d2703fb8a326d36fdd0e68701e201b2a60ed7cf81ce0fd9b3799f9fe7745977ae3 1330 | languageName: node 1331 | linkType: hard 1332 | 1333 | "yargs-parser@npm:^21.1.1": 1334 | version: 21.1.1 1335 | resolution: "yargs-parser@npm:21.1.1" 1336 | checksum: ed2d96a616a9e3e1cc7d204c62ecc61f7aaab633dcbfab2c6df50f7f87b393993fe6640d017759fe112d0cb1e0119f2b4150a87305cc873fd90831c6a58ccf1c 1337 | languageName: node 1338 | linkType: hard 1339 | 1340 | "yargs@npm:^16.2.0": 1341 | version: 16.2.0 1342 | resolution: "yargs@npm:16.2.0" 1343 | dependencies: 1344 | cliui: ^7.0.2 1345 | escalade: ^3.1.1 1346 | get-caller-file: ^2.0.5 1347 | require-directory: ^2.1.1 1348 | string-width: ^4.2.0 1349 | y18n: ^5.0.5 1350 | yargs-parser: ^20.2.2 1351 | checksum: b14afbb51e3251a204d81937c86a7e9d4bdbf9a2bcee38226c900d00f522969ab675703bee2a6f99f8e20103f608382936034e64d921b74df82b63c07c5e8f59 1352 | languageName: node 1353 | linkType: hard 1354 | 1355 | "yargs@npm:^17.5.1": 1356 | version: 17.7.1 1357 | resolution: "yargs@npm:17.7.1" 1358 | dependencies: 1359 | cliui: ^8.0.1 1360 | escalade: ^3.1.1 1361 | get-caller-file: ^2.0.5 1362 | require-directory: ^2.1.1 1363 | string-width: ^4.2.3 1364 | y18n: ^5.0.5 1365 | yargs-parser: ^21.1.1 1366 | checksum: 3d8a43c336a4942bc68080768664aca85c7bd406f018bad362fd255c41c8f4e650277f42fd65d543fce99e084124ddafee7bbfc1a5c6a8fda4cec78609dcf8d4 1367 | languageName: node 1368 | linkType: hard 1369 | --------------------------------------------------------------------------------