From a55b2e2f5b5724e2f7091675708dc194fd107ae2 Mon Sep 17 00:00:00 2001 From: Kenta HATTORI Date: Sat, 12 Oct 2024 22:53:41 +0900 Subject: [PATCH 01/11] Add: mkdir and rmdir commands --- .gitignore | 3 +- README.md | 347 +-- config/default.json | 4 + package-lock.json | 3376 ++--------------------------- package.json | 7 +- src/client.ts | 85 + src/commands/hello/index.ts | 25 - src/commands/hello/world.ts | 19 - src/commands/mkdir.ts | 72 + src/commands/rmdir.ts | 74 + src/common-flags.ts | 0 src/config.ts | 15 + src/const.ts | 1 + src/flags.ts | 7 + test/commands/hello/index.test.ts | 9 - test/commands/hello/world.test.ts | 9 - test/commands/mkdir.test.ts | 14 + test/commands/rmdir.test.ts | 14 + tsconfig.tsbuildinfo | 1 - 19 files changed, 559 insertions(+), 3523 deletions(-) create mode 100644 config/default.json create mode 100644 src/client.ts delete mode 100644 src/commands/hello/index.ts delete mode 100644 src/commands/hello/world.ts create mode 100644 src/commands/mkdir.ts create mode 100644 src/commands/rmdir.ts create mode 100644 src/common-flags.ts create mode 100644 src/config.ts create mode 100644 src/const.ts create mode 100644 src/flags.ts delete mode 100644 test/commands/hello/index.test.ts delete mode 100644 test/commands/hello/world.test.ts create mode 100644 test/commands/mkdir.test.ts create mode 100644 test/commands/rmdir.test.ts delete mode 100644 tsconfig.tsbuildinfo diff --git a/.gitignore b/.gitignore index 09c33a9..e5f8e4d 100644 --- a/.gitignore +++ b/.gitignore @@ -6,9 +6,10 @@ /tmp /node_modules oclif.manifest.json - +*.tsbuildinfo yarn.lock pnpm-lock.yaml +*~ \ No newline at end of file diff --git a/README.md b/README.md index af0891d..fb0817a 100644 --- a/README.md +++ b/README.md @@ -29,61 +29,65 @@ USAGE # Commands -* [`ketool hello PERSON`](#ketool-hello-person) -* [`ketool hello world`](#ketool-hello-world) +* [`ketool mkdir DIRECTORY`](#ketool-mkdir) +* [`ketool rmdir DIRECTORY`](#ketool-rmdir) * [`ketool help [COMMAND]`](#ketool-help-command) -* [`ketool plugins`](#ketool-plugins) -* [`ketool plugins add PLUGIN`](#ketool-plugins-add-plugin) -* [`ketool plugins:inspect PLUGIN...`](#ketool-pluginsinspect-plugin) -* [`ketool plugins install PLUGIN`](#ketool-plugins-install-plugin) -* [`ketool plugins link PATH`](#ketool-plugins-link-path) -* [`ketool plugins remove [PLUGIN]`](#ketool-plugins-remove-plugin) -* [`ketool plugins reset`](#ketool-plugins-reset) -* [`ketool plugins uninstall [PLUGIN]`](#ketool-plugins-uninstall-plugin) -* [`ketool plugins unlink [PLUGIN]`](#ketool-plugins-unlink-plugin) -* [`ketool plugins update`](#ketool-plugins-update) -## `ketool hello PERSON` +## `ketool mkdir DIRECTORY` Say hello ``` +Create the directories, if they do not already exist. + USAGE - $ ketool hello PERSON -f + $ ketool mkdir DIRECTORY... [-u ] [-t ] [-c ] [-p] [-v] ARGUMENTS - PERSON Person to say hello to + DIRECTORY... path of the directory to be created FLAGS - -f, --from= (required) Who is saying hello + -c, --cwd= set current working directory to VALUE + -p, --parent no error if existing, make parent directories as needed + -t, --token= API access token of the Kompira Enterprise server + -u, --baseurl= base URL of the Kompira Enterprise server + -v, --verbose print a message for each created directory DESCRIPTION - Say hello + Create the directories, if they do not already exist. EXAMPLES - $ ketool hello friend --from oclif - hello friend from oclif! (./src/commands/hello/index.ts) + $ ketool mkdir ``` -_See code: [src/commands/hello/index.ts](https://github.com/fixpoint/ketool/blob/v0.0.0/src/commands/hello/index.ts)_ +_See code: [src/commands/mkdir.ts](https://github.com/fixpoint/ketool/blob/v0.0.0/src/commands/mkdir.ts)_ -## `ketool hello world` +## `ketool rmdir DIRECTORY` -Say hello world +Remove the directories, if they are empty. ``` USAGE - $ ketool hello world + $ ketool rmdir DIRECTORY... [-u ] [-t ] [-c ] [-p] [-v] + +ARGUMENTS + DIRECTORY... path of the directory to be removed + +FLAGS + -c, --cwd= set current working directory to VALUE + -p, --parent remove DIRECTORY and its ancestors + -t, --token= API access token of the Kompira Enterprise server + -u, --baseurl= base URL of the Kompira Enterprise server + -v, --verbose print a message for each removed directory DESCRIPTION - Say hello world + Remove the directories, if they are empty. EXAMPLES - $ ketool hello world - hello world! (./src/commands/hello/world.ts) + $ ketool rmdir ``` -_See code: [src/commands/hello/world.ts](https://github.com/fixpoint/ketool/blob/v0.0.0/src/commands/hello/world.ts)_ +_See code: [src/commands/rmdir.ts](https://github.com/fixpoint/ketool/blob/v0.0.0/src/commands/rmdir.ts)_ ## `ketool help [COMMAND]` @@ -105,293 +109,4 @@ DESCRIPTION _See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v6.2.15/src/commands/help.ts)_ -## `ketool plugins` - -List installed plugins. - -``` -USAGE - $ ketool plugins [--json] [--core] - -FLAGS - --core Show core plugins. - -GLOBAL FLAGS - --json Format output as json. - -DESCRIPTION - List installed plugins. - -EXAMPLES - $ ketool plugins -``` - -_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.15/src/commands/plugins/index.ts)_ - -## `ketool plugins add PLUGIN` - -Installs a plugin into ketool. - -``` -USAGE - $ ketool plugins add PLUGIN... [--json] [-f] [-h] [-s | -v] - -ARGUMENTS - PLUGIN... Plugin to install. - -FLAGS - -f, --force Force npm to fetch remote resources even if a local copy exists on disk. - -h, --help Show CLI help. - -s, --silent Silences npm output. - -v, --verbose Show verbose npm output. - -GLOBAL FLAGS - --json Format output as json. - -DESCRIPTION - Installs a plugin into ketool. - - Uses npm to install plugins. - - Installation of a user-installed plugin will override a core plugin. - - Use the KETOOL_NPM_LOG_LEVEL environment variable to set the npm loglevel. - Use the KETOOL_NPM_REGISTRY environment variable to set the npm registry. - -ALIASES - $ ketool plugins add - -EXAMPLES - Install a plugin from npm registry. - - $ ketool plugins add myplugin - - Install a plugin from a github url. - - $ ketool plugins add https://github.com/someuser/someplugin - - Install a plugin from a github slug. - - $ ketool plugins add someuser/someplugin -``` - -## `ketool plugins:inspect PLUGIN...` - -Displays installation properties of a plugin. - -``` -USAGE - $ ketool plugins inspect PLUGIN... - -ARGUMENTS - PLUGIN... [default: .] Plugin to inspect. - -FLAGS - -h, --help Show CLI help. - -v, --verbose - -GLOBAL FLAGS - --json Format output as json. - -DESCRIPTION - Displays installation properties of a plugin. - -EXAMPLES - $ ketool plugins inspect myplugin -``` - -_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.15/src/commands/plugins/inspect.ts)_ - -## `ketool plugins install PLUGIN` - -Installs a plugin into ketool. - -``` -USAGE - $ ketool plugins install PLUGIN... [--json] [-f] [-h] [-s | -v] - -ARGUMENTS - PLUGIN... Plugin to install. - -FLAGS - -f, --force Force npm to fetch remote resources even if a local copy exists on disk. - -h, --help Show CLI help. - -s, --silent Silences npm output. - -v, --verbose Show verbose npm output. - -GLOBAL FLAGS - --json Format output as json. - -DESCRIPTION - Installs a plugin into ketool. - - Uses npm to install plugins. - - Installation of a user-installed plugin will override a core plugin. - - Use the KETOOL_NPM_LOG_LEVEL environment variable to set the npm loglevel. - Use the KETOOL_NPM_REGISTRY environment variable to set the npm registry. - -ALIASES - $ ketool plugins add - -EXAMPLES - Install a plugin from npm registry. - - $ ketool plugins install myplugin - - Install a plugin from a github url. - - $ ketool plugins install https://github.com/someuser/someplugin - - Install a plugin from a github slug. - - $ ketool plugins install someuser/someplugin -``` - -_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.15/src/commands/plugins/install.ts)_ - -## `ketool plugins link PATH` - -Links a plugin into the CLI for development. - -``` -USAGE - $ ketool plugins link PATH [-h] [--install] [-v] - -ARGUMENTS - PATH [default: .] path to plugin - -FLAGS - -h, --help Show CLI help. - -v, --verbose - --[no-]install Install dependencies after linking the plugin. - -DESCRIPTION - Links a plugin into the CLI for development. - - Installation of a linked plugin will override a user-installed or core plugin. - - e.g. If you have a user-installed or core plugin that has a 'hello' command, installing a linked plugin with a 'hello' - command will override the user-installed or core plugin implementation. This is useful for development work. - - -EXAMPLES - $ ketool plugins link myplugin -``` - -_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.15/src/commands/plugins/link.ts)_ - -## `ketool plugins remove [PLUGIN]` - -Removes a plugin from the CLI. - -``` -USAGE - $ ketool plugins remove [PLUGIN...] [-h] [-v] - -ARGUMENTS - PLUGIN... plugin to uninstall - -FLAGS - -h, --help Show CLI help. - -v, --verbose - -DESCRIPTION - Removes a plugin from the CLI. - -ALIASES - $ ketool plugins unlink - $ ketool plugins remove - -EXAMPLES - $ ketool plugins remove myplugin -``` - -## `ketool plugins reset` - -Remove all user-installed and linked plugins. - -``` -USAGE - $ ketool plugins reset [--hard] [--reinstall] - -FLAGS - --hard Delete node_modules and package manager related files in addition to uninstalling plugins. - --reinstall Reinstall all plugins after uninstalling. -``` - -_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.15/src/commands/plugins/reset.ts)_ - -## `ketool plugins uninstall [PLUGIN]` - -Removes a plugin from the CLI. - -``` -USAGE - $ ketool plugins uninstall [PLUGIN...] [-h] [-v] - -ARGUMENTS - PLUGIN... plugin to uninstall - -FLAGS - -h, --help Show CLI help. - -v, --verbose - -DESCRIPTION - Removes a plugin from the CLI. - -ALIASES - $ ketool plugins unlink - $ ketool plugins remove - -EXAMPLES - $ ketool plugins uninstall myplugin -``` - -_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.15/src/commands/plugins/uninstall.ts)_ - -## `ketool plugins unlink [PLUGIN]` - -Removes a plugin from the CLI. - -``` -USAGE - $ ketool plugins unlink [PLUGIN...] [-h] [-v] - -ARGUMENTS - PLUGIN... plugin to uninstall - -FLAGS - -h, --help Show CLI help. - -v, --verbose - -DESCRIPTION - Removes a plugin from the CLI. - -ALIASES - $ ketool plugins unlink - $ ketool plugins remove - -EXAMPLES - $ ketool plugins unlink myplugin -``` - -## `ketool plugins update` - -Update installed plugins. - -``` -USAGE - $ ketool plugins update [-h] [-v] - -FLAGS - -h, --help Show CLI help. - -v, --verbose - -DESCRIPTION - Update installed plugins. -``` - -_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.15/src/commands/plugins/update.ts)_ diff --git a/config/default.json b/config/default.json new file mode 100644 index 0000000..0861587 --- /dev/null +++ b/config/default.json @@ -0,0 +1,4 @@ +{ + "baseurl": "https://localhost:8080", + "token": "" +} diff --git a/package-lock.json b/package-lock.json index a6abdec..d570ada 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,8 @@ "dependencies": { "@oclif/core": "^4", "@oclif/plugin-help": "^6", - "@oclif/plugin-plugins": "^5" + "config": "^3.3.12", + "typed-rest-client": "^2.1.0" }, "bin": { "ketool": "bin/run.js" @@ -20,6 +21,7 @@ "@oclif/prettier-config": "^0.2.1", "@oclif/test": "^4", "@types/chai": "^4", + "@types/config": "^3.3.5", "@types/mocha": "^10", "@types/node": "^18", "chai": "^4", @@ -1596,28 +1598,6 @@ "node": ">=18.0.0" } }, - "node_modules/@oclif/plugin-plugins": { - "version": "5.4.15", - "resolved": "https://registry.npmjs.org/@oclif/plugin-plugins/-/plugin-plugins-5.4.15.tgz", - "integrity": "sha512-0cnTFaRWdXkWgKTrwgjoggcq/A3MaIl1GkDs3BFFjesYlFEs5Fb2HcN42rY+2ja4jBkXrjXBkLS+9faAtdCH6A==", - "license": "MIT", - "dependencies": { - "@oclif/core": "^4.0.28", - "ansis": "^3.3.2", - "debug": "^4.3.7", - "npm": "^10.9.0", - "npm-package-arg": "^11.0.3", - "npm-run-path": "^5.3.0", - "object-treeify": "^4.0.1", - "semver": "^7.6.3", - "validate-npm-package-name": "^5.0.1", - "which": "^4.0.0", - "yarn": "^1.22.22" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@oclif/plugin-warn-if-update-available": { "version": "3.1.19", "resolved": "https://registry.npmjs.org/@oclif/plugin-warn-if-update-available/-/plugin-warn-if-update-available-3.1.19.tgz", @@ -2513,6 +2493,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/config": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@types/config/-/config-3.3.5.tgz", + "integrity": "sha512-itq2HtXQBrNUKwMNZnb9mBRE3T99VYCdl1gjST9rq+9kFaB1iMMGuDeZnP88qid73DnpAMKH9ZolqDpS1Lz7+w==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/http-cache-semantics": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", @@ -3223,7 +3210,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", @@ -3408,6 +3394,7 @@ "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, "funding": [ { "type": "github", @@ -3515,6 +3502,18 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "license": "MIT" }, + "node_modules/config": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/config/-/config-3.3.12.tgz", + "integrity": "sha512-Vmx389R/QVM3foxqBzXO8t2tUikYZP64Q6vQxGrsMpREeJc/aWRnPRERXWsYzOHAumx/AOoILWe6nU3ZJL+6Sw==", + "license": "MIT", + "dependencies": { + "json5": "^2.2.3" + }, + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/config-chain": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", @@ -3526,6 +3525,18 @@ "proto-list": "~1.2.1" } }, + "node_modules/config/node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/confusing-browser-globals": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", @@ -3747,7 +3758,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", @@ -3779,6 +3789,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/des.js": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", + "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, "node_modules/detect-indent": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.1.tgz", @@ -3958,7 +3978,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, "license": "MIT", "dependencies": { "get-intrinsic": "^1.2.4" @@ -3971,7 +3990,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -4782,6 +4800,7 @@ "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, "license": "MIT", "engines": { "node": ">= 4.9.1" @@ -4940,6 +4959,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, "license": "ISC" }, "node_modules/fsevents": { @@ -4961,7 +4981,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5020,7 +5039,6 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -5124,6 +5142,7 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -5156,6 +5175,7 @@ "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" @@ -5234,7 +5254,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, "license": "MIT", "dependencies": { "get-intrinsic": "^1.1.3" @@ -5273,6 +5292,7 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, "license": "ISC" }, "node_modules/graphemer": { @@ -5305,7 +5325,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" @@ -5318,7 +5337,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -5331,7 +5349,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -5360,7 +5377,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -5394,6 +5410,7 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "dev": true, "license": "ISC", "dependencies": { "lru-cache": "^10.0.1" @@ -5491,6 +5508,7 @@ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, "license": "ISC", "dependencies": { "once": "^1.3.0", @@ -5507,6 +5525,7 @@ "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, "license": "ISC" }, "node_modules/internal-slot": { @@ -5964,15 +5983,6 @@ "dev": true, "license": "MIT" }, - "node_modules/isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", - "license": "ISC", - "engines": { - "node": ">=16" - } - }, "node_modules/jake": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", @@ -6013,6 +6023,12 @@ "node": "*" } }, + "node_modules/js-md4": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/js-md4/-/js-md4-0.3.2.tgz", + "integrity": "sha512-/GDnfQYsltsjRswQhN9fhv3EMw2sCpUdrdxyWDOUK7eyD++r3gRhzgiQgc/x4MAv2i1iuQ4lxO5mvqM3vj4bwA==", + "license": "MIT" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -6064,6 +6080,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, "license": "MIT" }, "node_modules/json-schema-traverse": { @@ -6230,6 +6247,7 @@ "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, "license": "ISC" }, "node_modules/make-error": { @@ -6284,6 +6302,12 @@ "node": ">=4" } }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "license": "ISC" + }, "node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -6403,6 +6427,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "hosted-git-info": "^7.0.0", @@ -6436,3117 +6461,174 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/npm": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/npm/-/npm-10.9.0.tgz", - "integrity": "sha512-ZanDioFylI9helNhl2LNd+ErmVD+H5I53ry41ixlLyCBgkuYb+58CvbAp99hW+zr5L9W4X7CchSoeqKdngOLSw==", - "bundleDependencies": [ - "@isaacs/string-locale-compare", - "@npmcli/arborist", - "@npmcli/config", - "@npmcli/fs", - "@npmcli/map-workspaces", - "@npmcli/package-json", - "@npmcli/promise-spawn", - "@npmcli/redact", - "@npmcli/run-script", - "@sigstore/tuf", - "abbrev", - "archy", - "cacache", - "chalk", - "ci-info", - "cli-columns", - "fastest-levenshtein", - "fs-minipass", - "glob", - "graceful-fs", - "hosted-git-info", - "ini", - "init-package-json", - "is-cidr", - "json-parse-even-better-errors", - "libnpmaccess", - "libnpmdiff", - "libnpmexec", - "libnpmfund", - "libnpmhook", - "libnpmorg", - "libnpmpack", - "libnpmpublish", - "libnpmsearch", - "libnpmteam", - "libnpmversion", - "make-fetch-happen", - "minimatch", - "minipass", - "minipass-pipeline", - "ms", - "node-gyp", - "nopt", - "normalize-package-data", - "npm-audit-report", - "npm-install-checks", - "npm-package-arg", - "npm-pick-manifest", - "npm-profile", - "npm-registry-fetch", - "npm-user-validate", - "p-map", - "pacote", - "parse-conflict-json", - "proc-log", - "qrcode-terminal", - "read", - "semver", - "spdx-expression-parse", - "ssri", - "supports-color", - "tar", - "text-table", - "tiny-relative-date", - "treeverse", - "validate-npm-package-name", - "which", - "write-file-atomic" - ], - "license": "Artistic-2.0", - "workspaces": [ - "docs", - "smoke-tests", - "mock-globals", - "mock-registry", - "workspaces/*" - ], - "dependencies": { - "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/arborist": "^8.0.0", - "@npmcli/config": "^9.0.0", - "@npmcli/fs": "^4.0.0", - "@npmcli/map-workspaces": "^4.0.1", - "@npmcli/package-json": "^6.0.1", - "@npmcli/promise-spawn": "^8.0.1", - "@npmcli/redact": "^3.0.0", - "@npmcli/run-script": "^9.0.1", - "@sigstore/tuf": "^2.3.4", - "abbrev": "^3.0.0", - "archy": "~1.0.0", - "cacache": "^19.0.1", - "chalk": "^5.3.0", - "ci-info": "^4.0.0", - "cli-columns": "^4.0.0", - "fastest-levenshtein": "^1.0.16", - "fs-minipass": "^3.0.3", - "glob": "^10.4.5", - "graceful-fs": "^4.2.11", - "hosted-git-info": "^8.0.0", - "ini": "^5.0.0", - "init-package-json": "^7.0.1", - "is-cidr": "^5.1.0", - "json-parse-even-better-errors": "^4.0.0", - "libnpmaccess": "^9.0.0", - "libnpmdiff": "^7.0.0", - "libnpmexec": "^9.0.0", - "libnpmfund": "^6.0.0", - "libnpmhook": "^11.0.0", - "libnpmorg": "^7.0.0", - "libnpmpack": "^8.0.0", - "libnpmpublish": "^10.0.0", - "libnpmsearch": "^8.0.0", - "libnpmteam": "^7.0.0", - "libnpmversion": "^7.0.0", - "make-fetch-happen": "^14.0.1", - "minimatch": "^9.0.5", - "minipass": "^7.1.1", - "minipass-pipeline": "^1.2.4", - "ms": "^2.1.2", - "node-gyp": "^10.2.0", - "nopt": "^8.0.0", - "normalize-package-data": "^7.0.0", - "npm-audit-report": "^6.0.0", - "npm-install-checks": "^7.1.0", - "npm-package-arg": "^12.0.0", - "npm-pick-manifest": "^10.0.0", - "npm-profile": "^11.0.1", - "npm-registry-fetch": "^18.0.1", - "npm-user-validate": "^3.0.0", - "p-map": "^4.0.0", - "pacote": "^19.0.0", - "parse-conflict-json": "^4.0.0", - "proc-log": "^5.0.0", - "qrcode-terminal": "^0.12.0", - "read": "^4.0.0", - "semver": "^7.6.3", - "spdx-expression-parse": "^4.0.0", - "ssri": "^12.0.0", - "supports-color": "^9.4.0", - "tar": "^6.2.1", - "text-table": "~0.2.0", - "tiny-relative-date": "^1.3.0", - "treeverse": "^3.0.0", - "validate-npm-package-name": "^6.0.0", - "which": "^5.0.0", - "write-file-atomic": "^6.0.0" - }, - "bin": { - "npm": "bin/npm-cli.js", - "npx": "bin/npx-cli.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm-package-arg": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.3.tgz", - "integrity": "sha512-sHGJy8sOC1YraBywpzQlIKBE4pBbGbiF95U6Auspzyem956E0+FtDtsx1ZxlOJkQCZ1AFXAY/yuvtFYrOxF+Bw==", - "license": "ISC", - "dependencies": { - "hosted-git-info": "^7.0.0", - "proc-log": "^4.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", "license": "MIT", - "dependencies": { - "path-key": "^4.0.0" - }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.4" } }, - "node_modules/npm/node_modules/@isaacs/cliui": { - "version": "8.0.2", - "inBundle": true, - "license": "ISC", + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "license": "MIT", "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" }, "engines": { - "node": ">=12" - } - }, - "node_modules/npm/node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=12" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/npm/node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "inBundle": true, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, "license": "MIT", "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">=12" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/npm/node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "inBundle": true, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^6.0.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">= 0.4" } }, - "node_modules/npm/node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "inBundle": true, - "license": "ISC", + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, + "license": "MIT", "dependencies": { - "minipass": "^7.0.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/npm/node_modules/@isaacs/string-locale-compare": { - "version": "1.1.0", - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/@npmcli/agent": { - "version": "3.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "agent-base": "^7.1.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.1", - "lru-cache": "^10.0.1", - "socks-proxy-agent": "^8.0.3" + "node": ">= 0.4" }, - "engines": { - "node": "^18.17.0 || >=20.5.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/npm/node_modules/@npmcli/arborist": { - "version": "8.0.0", - "inBundle": true, - "license": "ISC", + "node_modules/oclif": { + "version": "4.15.9", + "resolved": "https://registry.npmjs.org/oclif/-/oclif-4.15.9.tgz", + "integrity": "sha512-+qFTMht3OK/dP1dLARbaExswdcGDYC4iOBrqFNoc9Vm2zifOgbNuQJsMwTniatS2xmIa3YMevrLU67SxVHgF+g==", + "dev": true, + "license": "MIT", "dependencies": { - "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/fs": "^4.0.0", - "@npmcli/installed-package-contents": "^3.0.0", - "@npmcli/map-workspaces": "^4.0.1", - "@npmcli/metavuln-calculator": "^8.0.0", - "@npmcli/name-from-folder": "^3.0.0", - "@npmcli/node-gyp": "^4.0.0", - "@npmcli/package-json": "^6.0.1", - "@npmcli/query": "^4.0.0", - "@npmcli/redact": "^3.0.0", - "@npmcli/run-script": "^9.0.1", - "bin-links": "^5.0.0", - "cacache": "^19.0.1", - "common-ancestor-path": "^1.0.1", - "hosted-git-info": "^8.0.0", - "json-parse-even-better-errors": "^4.0.0", - "json-stringify-nice": "^1.1.4", - "lru-cache": "^10.2.2", - "minimatch": "^9.0.4", - "nopt": "^8.0.0", - "npm-install-checks": "^7.1.0", - "npm-package-arg": "^12.0.0", - "npm-pick-manifest": "^10.0.0", - "npm-registry-fetch": "^18.0.1", - "pacote": "^19.0.0", - "parse-conflict-json": "^4.0.0", - "proc-log": "^5.0.0", - "proggy": "^3.0.0", - "promise-all-reject-late": "^1.0.0", - "promise-call-limit": "^3.0.1", - "read-package-json-fast": "^4.0.0", - "semver": "^7.3.7", - "ssri": "^12.0.0", - "treeverse": "^3.0.0", - "walk-up-path": "^3.0.1" + "@aws-sdk/client-cloudfront": "^3.665.0", + "@aws-sdk/client-s3": "^3.670.0", + "@inquirer/confirm": "^3.1.22", + "@inquirer/input": "^2.2.4", + "@inquirer/select": "^2.5.0", + "@oclif/core": "^4.0.28", + "@oclif/plugin-help": "^6.2.14", + "@oclif/plugin-not-found": "^3.2.21", + "@oclif/plugin-warn-if-update-available": "^3.1.11", + "async-retry": "^1.3.3", + "chalk": "^4", + "change-case": "^4", + "debug": "^4.3.4", + "ejs": "^3.1.10", + "find-yarn-workspace-root": "^2.0.0", + "fs-extra": "^8.1", + "github-slugger": "^2", + "got": "^13", + "lodash": "^4.17.21", + "normalize-package-data": "^6", + "semver": "^7.6.3", + "sort-package-json": "^2.10.1", + "tiny-jsonc": "^1.0.1", + "validate-npm-package-name": "^5.0.1" }, "bin": { - "arborist": "bin/index.js" + "oclif": "bin/run.js" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">=18.0.0" } }, - "node_modules/npm/node_modules/@npmcli/config": { - "version": "9.0.0", - "inBundle": true, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, "license": "ISC", "dependencies": { - "@npmcli/map-workspaces": "^4.0.1", - "@npmcli/package-json": "^6.0.1", - "ci-info": "^4.0.0", - "ini": "^5.0.0", - "nopt": "^8.0.0", - "proc-log": "^5.0.0", - "semver": "^7.3.5", - "walk-up-path": "^3.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" + "wrappy": "1" } }, - "node_modules/npm/node_modules/@npmcli/fs": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC", + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", "dependencies": { - "semver": "^7.3.5" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">= 0.8.0" } }, - "node_modules/npm/node_modules/@npmcli/git": { - "version": "6.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/promise-spawn": "^8.0.0", - "ini": "^5.0.0", - "lru-cache": "^10.0.1", - "npm-pick-manifest": "^10.0.0", - "proc-log": "^5.0.0", - "promise-inflight": "^1.0.1", - "promise-retry": "^2.0.1", - "semver": "^7.3.5", - "which": "^5.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } + "node_modules/optionator/node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" }, - "node_modules/npm/node_modules/@npmcli/installed-package-contents": { - "version": "3.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-bundled": "^4.0.0", - "npm-normalize-package-bin": "^4.0.0" - }, - "bin": { - "installed-package-contents": "bin/index.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/map-workspaces": { - "version": "4.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/name-from-folder": "^3.0.0", - "@npmcli/package-json": "^6.0.0", - "glob": "^10.2.2", - "minimatch": "^9.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/metavuln-calculator": { - "version": "8.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "cacache": "^19.0.0", - "json-parse-even-better-errors": "^4.0.0", - "pacote": "^19.0.0", - "proc-log": "^5.0.0", - "semver": "^7.3.5" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/name-from-folder": { - "version": "3.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/node-gyp": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/package-json": { - "version": "6.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^6.0.0", - "glob": "^10.2.2", - "hosted-git-info": "^8.0.0", - "json-parse-even-better-errors": "^4.0.0", - "normalize-package-data": "^7.0.0", - "proc-log": "^5.0.0", - "semver": "^7.5.3" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/promise-spawn": { - "version": "8.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "which": "^5.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/query": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "postcss-selector-parser": "^6.1.2" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/redact": { - "version": "3.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/run-script": { - "version": "9.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/node-gyp": "^4.0.0", - "@npmcli/package-json": "^6.0.0", - "@npmcli/promise-spawn": "^8.0.0", - "node-gyp": "^10.0.0", - "proc-log": "^5.0.0", - "which": "^5.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "inBundle": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/npm/node_modules/@sigstore/bundle": { - "version": "2.3.2", - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/protobuf-specs": "^0.3.2" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/core": { - "version": "1.1.0", - "inBundle": true, - "license": "Apache-2.0", - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/protobuf-specs": { - "version": "0.3.2", - "inBundle": true, - "license": "Apache-2.0", - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/sign": { - "version": "2.3.2", - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^2.3.2", - "@sigstore/core": "^1.0.0", - "@sigstore/protobuf-specs": "^0.3.2", - "make-fetch-happen": "^13.0.1", - "proc-log": "^4.2.0", - "promise-retry": "^2.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/sign/node_modules/@npmcli/agent": { - "version": "2.2.2", - "inBundle": true, - "license": "ISC", - "dependencies": { - "agent-base": "^7.1.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.1", - "lru-cache": "^10.0.1", - "socks-proxy-agent": "^8.0.3" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/sign/node_modules/@npmcli/fs": { - "version": "3.1.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/sign/node_modules/cacache": { - "version": "18.0.4", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^10.0.1", - "minipass": "^7.0.3", - "minipass-collect": "^2.0.1", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/sign/node_modules/make-fetch-happen": { - "version": "13.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/agent": "^2.0.0", - "cacache": "^18.0.0", - "http-cache-semantics": "^4.1.1", - "is-lambda": "^1.0.1", - "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "proc-log": "^4.2.0", - "promise-retry": "^2.0.1", - "ssri": "^10.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/sign/node_modules/minipass-fetch": { - "version": "3.0.5", - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/npm/node_modules/@sigstore/sign/node_modules/proc-log": { - "version": "4.2.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/sign/node_modules/ssri": { - "version": "10.0.6", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/sign/node_modules/unique-filename": { - "version": "3.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "unique-slug": "^4.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/sign/node_modules/unique-slug": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/tuf": { - "version": "2.3.4", - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/protobuf-specs": "^0.3.2", - "tuf-js": "^2.2.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/verify": { - "version": "1.2.1", - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^2.3.2", - "@sigstore/core": "^1.1.0", - "@sigstore/protobuf-specs": "^0.3.2" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@tufjs/canonical-json": { - "version": "2.0.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@tufjs/models": { - "version": "2.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "@tufjs/canonical-json": "2.0.0", - "minimatch": "^9.0.4" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/abbrev": { - "version": "3.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/agent-base": { - "version": "7.1.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/npm/node_modules/aggregate-error": { - "version": "3.1.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/ansi-regex": { - "version": "5.0.1", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/ansi-styles": { - "version": "6.2.1", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/npm/node_modules/aproba": { - "version": "2.0.0", - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/archy": { - "version": "1.0.0", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/balanced-match": { - "version": "1.0.2", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/bin-links": { - "version": "5.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "cmd-shim": "^7.0.0", - "npm-normalize-package-bin": "^4.0.0", - "proc-log": "^5.0.0", - "read-cmd-shim": "^5.0.0", - "write-file-atomic": "^6.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/binary-extensions": { - "version": "2.3.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/brace-expansion": { - "version": "2.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/npm/node_modules/cacache": { - "version": "19.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^4.0.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^10.0.1", - "minipass": "^7.0.3", - "minipass-collect": "^2.0.1", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^7.0.2", - "ssri": "^12.0.0", - "tar": "^7.4.3", - "unique-filename": "^4.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/cacache/node_modules/chownr": { - "version": "3.0.0", - "inBundle": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/npm/node_modules/cacache/node_modules/minizlib": { - "version": "3.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.0.4", - "rimraf": "^5.0.5" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/npm/node_modules/cacache/node_modules/mkdirp": { - "version": "3.0.1", - "inBundle": true, - "license": "MIT", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/cacache/node_modules/p-map": { - "version": "7.0.2", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/cacache/node_modules/tar": { - "version": "7.4.3", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.0.1", - "mkdirp": "^3.0.1", - "yallist": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/npm/node_modules/cacache/node_modules/yallist": { - "version": "5.0.0", - "inBundle": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/npm/node_modules/chalk": { - "version": "5.3.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/npm/node_modules/chownr": { - "version": "2.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/ci-info": { - "version": "4.0.0", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/cidr-regex": { - "version": "4.1.1", - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "ip-regex": "^5.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/npm/node_modules/clean-stack": { - "version": "2.2.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/npm/node_modules/cli-columns": { - "version": "4.0.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/npm/node_modules/cmd-shim": { - "version": "7.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/color-convert": { - "version": "2.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/npm/node_modules/color-name": { - "version": "1.1.4", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/common-ancestor-path": { - "version": "1.0.1", - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/cross-spawn": { - "version": "7.0.3", - "inBundle": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/cross-spawn/node_modules/which": { - "version": "2.0.2", - "inBundle": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/cssesc": { - "version": "3.0.0", - "inBundle": true, - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm/node_modules/debug": { - "version": "4.3.6", - "inBundle": true, - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/npm/node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/diff": { - "version": "5.2.0", - "inBundle": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/npm/node_modules/eastasianwidth": { - "version": "0.2.0", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/emoji-regex": { - "version": "8.0.0", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/encoding": { - "version": "0.1.13", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/npm/node_modules/env-paths": { - "version": "2.2.1", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/npm/node_modules/err-code": { - "version": "2.0.3", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/exponential-backoff": { - "version": "3.1.1", - "inBundle": true, - "license": "Apache-2.0" - }, - "node_modules/npm/node_modules/fastest-levenshtein": { - "version": "1.0.16", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 4.9.1" - } - }, - "node_modules/npm/node_modules/foreground-child": { - "version": "3.3.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/fs-minipass": { - "version": "3.0.3", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/glob": { - "version": "10.4.5", - "inBundle": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/graceful-fs": { - "version": "4.2.11", - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/hosted-git-info": { - "version": "8.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^10.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/http-cache-semantics": { - "version": "4.1.1", - "inBundle": true, - "license": "BSD-2-Clause" - }, - "node_modules/npm/node_modules/http-proxy-agent": { - "version": "7.0.2", - "inBundle": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/npm/node_modules/https-proxy-agent": { - "version": "7.0.5", - "inBundle": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/npm/node_modules/iconv-lite": { - "version": "0.6.3", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm/node_modules/ignore-walk": { - "version": "7.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minimatch": "^9.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/imurmurhash": { - "version": "0.1.4", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/npm/node_modules/indent-string": { - "version": "4.0.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/ini": { - "version": "5.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/init-package-json": { - "version": "7.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/package-json": "^6.0.0", - "npm-package-arg": "^12.0.0", - "promzard": "^2.0.0", - "read": "^4.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "^6.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/ip-address": { - "version": "9.0.5", - "inBundle": true, - "license": "MIT", - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/npm/node_modules/ip-regex": { - "version": "5.0.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/is-cidr": { - "version": "5.1.0", - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "cidr-regex": "^4.1.1" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/npm/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/is-lambda": { - "version": "1.0.1", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/isexe": { - "version": "2.0.0", - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/jackspeak": { - "version": "3.4.3", - "inBundle": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/npm/node_modules/jsbn": { - "version": "1.1.0", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/json-parse-even-better-errors": { - "version": "4.0.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/json-stringify-nice": { - "version": "1.1.4", - "inBundle": true, - "license": "ISC", - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/jsonparse": { - "version": "1.3.1", - "engines": [ - "node >= 0.2.0" - ], - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/just-diff": { - "version": "6.0.2", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/just-diff-apply": { - "version": "5.5.0", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/libnpmaccess": { - "version": "9.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-package-arg": "^12.0.0", - "npm-registry-fetch": "^18.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmdiff": { - "version": "7.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^8.0.0", - "@npmcli/installed-package-contents": "^3.0.0", - "binary-extensions": "^2.3.0", - "diff": "^5.1.0", - "minimatch": "^9.0.4", - "npm-package-arg": "^12.0.0", - "pacote": "^19.0.0", - "tar": "^6.2.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmexec": { - "version": "9.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^8.0.0", - "@npmcli/run-script": "^9.0.1", - "ci-info": "^4.0.0", - "npm-package-arg": "^12.0.0", - "pacote": "^19.0.0", - "proc-log": "^5.0.0", - "read": "^4.0.0", - "read-package-json-fast": "^4.0.0", - "semver": "^7.3.7", - "walk-up-path": "^3.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmfund": { - "version": "6.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^8.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmhook": { - "version": "11.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^18.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmorg": { - "version": "7.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^18.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmpack": { - "version": "8.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^8.0.0", - "@npmcli/run-script": "^9.0.1", - "npm-package-arg": "^12.0.0", - "pacote": "^19.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmpublish": { - "version": "10.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "ci-info": "^4.0.0", - "normalize-package-data": "^7.0.0", - "npm-package-arg": "^12.0.0", - "npm-registry-fetch": "^18.0.1", - "proc-log": "^5.0.0", - "semver": "^7.3.7", - "sigstore": "^2.2.0", - "ssri": "^12.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmsearch": { - "version": "8.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-registry-fetch": "^18.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmteam": { - "version": "7.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^18.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmversion": { - "version": "7.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^6.0.1", - "@npmcli/run-script": "^9.0.1", - "json-parse-even-better-errors": "^4.0.0", - "proc-log": "^5.0.0", - "semver": "^7.3.7" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/lru-cache": { - "version": "10.4.3", - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/make-fetch-happen": { - "version": "14.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/agent": "^3.0.0", - "cacache": "^19.0.1", - "http-cache-semantics": "^4.1.1", - "minipass": "^7.0.2", - "minipass-fetch": "^4.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "proc-log": "^5.0.0", - "promise-retry": "^2.0.1", - "ssri": "^12.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/minimatch": { - "version": "9.0.5", - "inBundle": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/minipass": { - "version": "7.1.2", - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/npm/node_modules/minipass-collect": { - "version": "2.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/npm/node_modules/minipass-fetch": { - "version": "4.0.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^3.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/npm/node_modules/minipass-fetch/node_modules/minizlib": { - "version": "3.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.0.4", - "rimraf": "^5.0.5" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/npm/node_modules/minipass-flush": { - "version": "1.0.5", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/minipass-flush/node_modules/minipass": { - "version": "3.3.6", - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-pipeline": { - "version": "1.2.4", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-pipeline/node_modules/minipass": { - "version": "3.3.6", - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-sized": { - "version": "1.0.3", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-sized/node_modules/minipass": { - "version": "3.3.6", - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minizlib": { - "version": "2.1.2", - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/mkdirp": { - "version": "1.0.4", - "inBundle": true, - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/ms": { - "version": "2.1.3", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/mute-stream": { - "version": "2.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/negotiator": { - "version": "0.6.3", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/npm/node_modules/node-gyp": { - "version": "10.2.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^10.3.10", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^13.0.0", - "nopt": "^7.0.0", - "proc-log": "^4.1.0", - "semver": "^7.3.5", - "tar": "^6.2.1", - "which": "^4.0.0" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/@npmcli/agent": { - "version": "2.2.2", - "inBundle": true, - "license": "ISC", - "dependencies": { - "agent-base": "^7.1.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.1", - "lru-cache": "^10.0.1", - "socks-proxy-agent": "^8.0.3" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/@npmcli/fs": { - "version": "3.1.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/abbrev": { - "version": "2.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/cacache": { - "version": "18.0.4", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^10.0.1", - "minipass": "^7.0.3", - "minipass-collect": "^2.0.1", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/isexe": { - "version": "3.1.1", - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=16" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/make-fetch-happen": { - "version": "13.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/agent": "^2.0.0", - "cacache": "^18.0.0", - "http-cache-semantics": "^4.1.1", - "is-lambda": "^1.0.1", - "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "proc-log": "^4.2.0", - "promise-retry": "^2.0.1", - "ssri": "^10.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/minipass-fetch": { - "version": "3.0.5", - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/nopt": { - "version": "7.2.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "abbrev": "^2.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/proc-log": { - "version": "4.2.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/ssri": { - "version": "10.0.6", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/unique-filename": { - "version": "3.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "unique-slug": "^4.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/unique-slug": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/which": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "isexe": "^3.1.1" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/nopt": { - "version": "8.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "abbrev": "^2.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/nopt/node_modules/abbrev": { - "version": "2.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/normalize-package-data": { - "version": "7.0.0", - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^8.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-audit-report": { - "version": "6.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-bundled": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-normalize-package-bin": "^4.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-install-checks": { - "version": "7.1.0", - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "semver": "^7.1.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-normalize-package-bin": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-package-arg": { - "version": "12.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "hosted-git-info": "^8.0.0", - "proc-log": "^5.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^6.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-packlist": { - "version": "9.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "ignore-walk": "^7.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-pick-manifest": { - "version": "10.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-install-checks": "^7.1.0", - "npm-normalize-package-bin": "^4.0.0", - "npm-package-arg": "^12.0.0", - "semver": "^7.3.5" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-profile": { - "version": "11.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-registry-fetch": "^18.0.0", - "proc-log": "^5.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-registry-fetch": { - "version": "18.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/redact": "^3.0.0", - "jsonparse": "^1.3.1", - "make-fetch-happen": "^14.0.0", - "minipass": "^7.0.2", - "minipass-fetch": "^4.0.0", - "minizlib": "^3.0.1", - "npm-package-arg": "^12.0.0", - "proc-log": "^5.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-registry-fetch/node_modules/minizlib": { - "version": "3.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.0.4", - "rimraf": "^5.0.5" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/npm/node_modules/npm-user-validate": { - "version": "3.0.0", - "inBundle": true, - "license": "BSD-2-Clause", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/p-map": { - "version": "4.0.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/package-json-from-dist": { - "version": "1.0.0", - "inBundle": true, - "license": "BlueOak-1.0.0" - }, - "node_modules/npm/node_modules/pacote": { - "version": "19.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^6.0.0", - "@npmcli/installed-package-contents": "^3.0.0", - "@npmcli/package-json": "^6.0.0", - "@npmcli/promise-spawn": "^8.0.0", - "@npmcli/run-script": "^9.0.0", - "cacache": "^19.0.0", - "fs-minipass": "^3.0.0", - "minipass": "^7.0.2", - "npm-package-arg": "^12.0.0", - "npm-packlist": "^9.0.0", - "npm-pick-manifest": "^10.0.0", - "npm-registry-fetch": "^18.0.0", - "proc-log": "^5.0.0", - "promise-retry": "^2.0.1", - "sigstore": "^2.2.0", - "ssri": "^12.0.0", - "tar": "^6.1.11" - }, - "bin": { - "pacote": "bin/index.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/parse-conflict-json": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "json-parse-even-better-errors": "^4.0.0", - "just-diff": "^6.0.0", - "just-diff-apply": "^5.2.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/path-key": { - "version": "3.1.1", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/path-scurry": { - "version": "1.11.1", - "inBundle": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/postcss-selector-parser": { - "version": "6.1.2", - "inBundle": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm/node_modules/proc-log": { - "version": "5.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/proggy": { - "version": "3.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/promise-all-reject-late": { - "version": "1.0.1", - "inBundle": true, - "license": "ISC", - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/promise-call-limit": { - "version": "3.0.1", - "inBundle": true, - "license": "ISC", - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/promise-inflight": { - "version": "1.0.1", - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/promise-retry": { - "version": "2.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/promzard": { - "version": "2.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "read": "^4.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/qrcode-terminal": { - "version": "0.12.0", - "inBundle": true, - "bin": { - "qrcode-terminal": "bin/qrcode-terminal.js" - } - }, - "node_modules/npm/node_modules/read": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "mute-stream": "^2.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/read-cmd-shim": { - "version": "5.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/read-package-json-fast": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "json-parse-even-better-errors": "^4.0.0", - "npm-normalize-package-bin": "^4.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/retry": { - "version": "0.12.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/npm/node_modules/rimraf": { - "version": "5.0.10", - "inBundle": true, - "license": "ISC", - "dependencies": { - "glob": "^10.3.7" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/safer-buffer": { - "version": "2.1.2", - "inBundle": true, - "license": "MIT", - "optional": true - }, - "node_modules/npm/node_modules/semver": { - "version": "7.6.3", - "inBundle": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/shebang-command": { - "version": "2.0.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/shebang-regex": { - "version": "3.0.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/signal-exit": { - "version": "4.1.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/sigstore": { - "version": "2.3.1", - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^2.3.2", - "@sigstore/core": "^1.0.0", - "@sigstore/protobuf-specs": "^0.3.2", - "@sigstore/sign": "^2.3.2", - "@sigstore/tuf": "^2.3.4", - "@sigstore/verify": "^1.2.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/smart-buffer": { - "version": "4.2.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/npm/node_modules/socks": { - "version": "2.8.3", - "inBundle": true, - "license": "MIT", - "dependencies": { - "ip-address": "^9.0.5", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/npm/node_modules/socks-proxy-agent": { - "version": "8.0.4", - "inBundle": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.8.3" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/npm/node_modules/spdx-correct": { - "version": "3.2.0", - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/npm/node_modules/spdx-correct/node_modules/spdx-expression-parse": { - "version": "3.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/npm/node_modules/spdx-exceptions": { - "version": "2.5.0", - "inBundle": true, - "license": "CC-BY-3.0" - }, - "node_modules/npm/node_modules/spdx-expression-parse": { - "version": "4.0.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/npm/node_modules/spdx-license-ids": { - "version": "3.0.18", - "inBundle": true, - "license": "CC0-1.0" - }, - "node_modules/npm/node_modules/sprintf-js": { - "version": "1.1.3", - "inBundle": true, - "license": "BSD-3-Clause" - }, - "node_modules/npm/node_modules/ssri": { - "version": "12.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/string-width": { - "version": "4.2.3", - "inBundle": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "inBundle": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/strip-ansi": { - "version": "6.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/supports-color": { - "version": "9.4.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/npm/node_modules/tar": { - "version": "6.2.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/tar/node_modules/fs-minipass": { - "version": "2.1.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/text-table": { - "version": "0.2.0", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/tiny-relative-date": { - "version": "1.3.0", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/treeverse": { - "version": "3.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/tuf-js": { - "version": "2.2.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "@tufjs/models": "2.0.1", - "debug": "^4.3.4", - "make-fetch-happen": "^13.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/tuf-js/node_modules/@npmcli/agent": { - "version": "2.2.2", - "inBundle": true, - "license": "ISC", - "dependencies": { - "agent-base": "^7.1.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.1", - "lru-cache": "^10.0.1", - "socks-proxy-agent": "^8.0.3" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/tuf-js/node_modules/@npmcli/fs": { - "version": "3.1.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/tuf-js/node_modules/cacache": { - "version": "18.0.4", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^10.0.1", - "minipass": "^7.0.3", - "minipass-collect": "^2.0.1", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/tuf-js/node_modules/make-fetch-happen": { - "version": "13.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/agent": "^2.0.0", - "cacache": "^18.0.0", - "http-cache-semantics": "^4.1.1", - "is-lambda": "^1.0.1", - "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "proc-log": "^4.2.0", - "promise-retry": "^2.0.1", - "ssri": "^10.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/tuf-js/node_modules/minipass-fetch": { - "version": "3.0.5", - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/npm/node_modules/tuf-js/node_modules/proc-log": { - "version": "4.2.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/tuf-js/node_modules/ssri": { - "version": "10.0.6", - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/tuf-js/node_modules/unique-filename": { - "version": "3.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "unique-slug": "^4.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/tuf-js/node_modules/unique-slug": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/unique-filename": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "unique-slug": "^5.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/unique-slug": { - "version": "5.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/util-deprecate": { - "version": "1.0.2", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/validate-npm-package-license": { - "version": "3.0.4", - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/npm/node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": { - "version": "3.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/npm/node_modules/validate-npm-package-name": { - "version": "6.0.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/walk-up-path": { - "version": "3.0.1", - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/which": { - "version": "5.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "isexe": "^3.1.1" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/which/node_modules/isexe": { - "version": "3.1.1", - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=16" - } - }, - "node_modules/npm/node_modules/wrap-ansi": { - "version": "8.1.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/npm/node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/npm/node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/npm/node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.0.1", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/npm/node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "9.2.2", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/wrap-ansi/node_modules/string-width": { - "version": "5.1.2", - "inBundle": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.1.0", - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/npm/node_modules/write-file-atomic": { - "version": "6.0.0", - "inBundle": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/yallist": { - "version": "4.0.0", - "inBundle": true, - "license": "ISC" - }, - "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object-treeify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/object-treeify/-/object-treeify-4.0.1.tgz", - "integrity": "sha512-Y6tg5rHfsefSkfKujv2SwHulInROy/rCL5F4w0QOWxut8AnxYxf0YmNhTh95Zfyxpsudo66uqkux0ACFnyMSgQ==", - "license": "MIT", - "engines": { - "node": ">= 16" - } - }, - "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", - "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/oclif": { - "version": "4.15.9", - "resolved": "https://registry.npmjs.org/oclif/-/oclif-4.15.9.tgz", - "integrity": "sha512-+qFTMht3OK/dP1dLARbaExswdcGDYC4iOBrqFNoc9Vm2zifOgbNuQJsMwTniatS2xmIa3YMevrLU67SxVHgF+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@aws-sdk/client-cloudfront": "^3.665.0", - "@aws-sdk/client-s3": "^3.670.0", - "@inquirer/confirm": "^3.1.22", - "@inquirer/input": "^2.2.4", - "@inquirer/select": "^2.5.0", - "@oclif/core": "^4.0.28", - "@oclif/plugin-help": "^6.2.14", - "@oclif/plugin-not-found": "^3.2.21", - "@oclif/plugin-warn-if-update-available": "^3.1.11", - "async-retry": "^1.3.3", - "chalk": "^4", - "change-case": "^4", - "debug": "^4.3.4", - "ejs": "^3.1.10", - "find-yarn-workspace-root": "^2.0.0", - "fs-extra": "^8.1", - "github-slugger": "^2", - "got": "^13", - "lodash": "^4.17.21", - "normalize-package-data": "^6", - "semver": "^7.6.3", - "sort-package-json": "^2.10.1", - "tiny-jsonc": "^1.0.1", - "validate-npm-package-name": "^5.0.1" - }, - "bin": { - "oclif": "bin/run.js" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/optionator/node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" - }, - "node_modules/p-cancelable": { + "node_modules/p-cancelable": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", @@ -9763,15 +6845,6 @@ "node": ">= 0.8.0" } }, - "node_modules/proc-log": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", - "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/proto-list": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", @@ -9789,6 +6862,21 @@ "node": ">=6" } }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -10373,7 +7461,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", @@ -10511,7 +7598,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.7", @@ -10623,6 +7709,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, "license": "Apache-2.0", "dependencies": { "spdx-expression-parse": "^3.0.0", @@ -10633,12 +7720,14 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, "license": "CC-BY-3.0" }, "node_modules/spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, "license": "MIT", "dependencies": { "spdx-exceptions": "^2.1.0", @@ -10649,6 +7738,7 @@ "version": "3.0.20", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", + "dev": true, "license": "CC0-1.0" }, "node_modules/string-width": { @@ -10814,6 +7904,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, "license": "MIT" }, "node_modules/tiny-jsonc": { @@ -10921,6 +8012,15 @@ "dev": true, "license": "0BSD" }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "license": "MIT", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -11046,6 +8146,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/typed-rest-client": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-2.1.0.tgz", + "integrity": "sha512-Nel9aPbgSzRxfs1+4GoSB4wexCF+4Axlk7OSGVQCMa+4fWcyxIsN/YNmkp0xTT2iQzMD98h8yFLav/cNaULmRA==", + "license": "MIT", + "dependencies": { + "des.js": "^1.1.0", + "js-md4": "^0.3.2", + "qs": "^6.10.3", + "tunnel": "0.0.6", + "underscore": "^1.12.1" + }, + "engines": { + "node": ">= 16.0.0" + } + }, "node_modules/typescript": { "version": "5.6.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", @@ -11076,6 +8192,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/underscore": { + "version": "1.13.7", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", + "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==", + "license": "MIT" + }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", @@ -11148,6 +8270,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, "license": "Apache-2.0", "dependencies": { "spdx-correct": "^3.0.0", @@ -11158,26 +8281,12 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", + "dev": true, "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/which": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", - "license": "ISC", - "dependencies": { - "isexe": "^3.1.1" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^16.13.0 || >=18.0.0" - } - }, "node_modules/which-boxed-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", @@ -11271,6 +8380,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, "license": "ISC" }, "node_modules/y18n": { @@ -11338,20 +8448,6 @@ "node": ">=8" } }, - "node_modules/yarn": { - "version": "1.22.22", - "resolved": "https://registry.npmjs.org/yarn/-/yarn-1.22.22.tgz", - "integrity": "sha512-prL3kGtyG7o9Z9Sv8IPfBNrWTDmXB4Qbes8A9rEzt6wkJV8mUvoirjU0Mp3GGAU06Y0XQyA3/2/RQFVuK7MTfg==", - "hasInstallScript": true, - "license": "BSD-2-Clause", - "bin": { - "yarn": "bin/yarn.js", - "yarnpkg": "bin/yarn.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", diff --git a/package.json b/package.json index 9e58d46..2e74c24 100644 --- a/package.json +++ b/package.json @@ -10,12 +10,14 @@ "dependencies": { "@oclif/core": "^4", "@oclif/plugin-help": "^6", - "@oclif/plugin-plugins": "^5" + "config": "^3.3.12", + "typed-rest-client": "^2.1.0" }, "devDependencies": { "@oclif/prettier-config": "^0.2.1", "@oclif/test": "^4", "@types/chai": "^4", + "@types/config": "^3.3.5", "@types/mocha": "^10", "@types/node": "^18", "chai": "^4", @@ -49,8 +51,7 @@ "dirname": "ketool", "commands": "./dist/commands", "plugins": [ - "@oclif/plugin-help", - "@oclif/plugin-plugins" + "@oclif/plugin-help" ], "topicSeparator": " ", "topics": { diff --git a/src/client.ts b/src/client.ts new file mode 100644 index 0000000..d5dd959 --- /dev/null +++ b/src/client.ts @@ -0,0 +1,85 @@ +import * as rm from 'typed-rest-client/RestClient.js' +import Config from './config.js' + + +export namespace KeClient { + export type ObjectResponse = { + id: number + abspath: string + owner: string + display_name: string + description: string + type_object: string + parent_object: string + created: string + updated: string + fields: { + [key: string]: any + } + extra_properties: { + [key: string]: any + } + user_permissions: { + [key: string]: any + } + group_permissions: { + [key: string]: any + } + } + export type ObjectsResponse = { + count: number, + results: [ObjectResponse] + } + + function request_options(token?: string): rm.IRequestOptions { + return { + 'additionalHeaders': { + 'Authorization': `Token ${token}` + } + } + } + + export async function get(config: Config, path: string): Promise { + let rest: rm.RestClient = new rm.RestClient('ke-client', config.baseurl) + let resp: rm.IRestResponse = await rest.get(path, request_options(config.token)) + if (resp.statusCode == 404) { + return null + } else if (resp.statusCode != 200) { + throw new Error(`StatusCode: ${resp.statusCode}`) + } + return resp.result + } + + export async function get_all(config: Config, path: string): Promise { + let rest: rm.RestClient = new rm.RestClient('ke-client', config.baseurl) + let resp: rm.IRestResponse = await rest.get(path, request_options(config.token)) + if (resp.statusCode == 404) { + return null + } else if (resp.statusCode != 200) { + throw new Error(`StatusCode: ${resp.statusCode}`) + } + return resp.result + } + + export async function create(config: Config, path: string, name: string, data: any): Promise { + let rest: rm.RestClient = new rm.RestClient('ke-client', config.baseurl) + let resp: rm.IRestResponse = await rest.create(path, data, request_options(config.token)) + if (resp.statusCode == 400) { + + } else if (resp.statusCode != 201) { + throw new Error(`StatusCode: ${resp.statusCode}`) + } + return resp.result + } + + export async function del(config: Config, path: string): Promise { + let rest: rm.RestClient = new rm.RestClient('ke-client', config.baseurl) + let resp: rm.IRestResponse = await rest.del(path, request_options(config.token)) + if (resp.statusCode != 204) { + throw new Error(`StatusCode: ${resp.statusCode}`) + } + return resp.result + } +} + +export default KeClient diff --git a/src/commands/hello/index.ts b/src/commands/hello/index.ts deleted file mode 100644 index 6fe09e1..0000000 --- a/src/commands/hello/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -import {Args, Command, Flags} from '@oclif/core' - -export default class Hello extends Command { - static args = { - person: Args.string({description: 'Person to say hello to', required: true}), - } - - static description = 'Say hello' - - static examples = [ - `<%= config.bin %> <%= command.id %> friend --from oclif -hello friend from oclif! (./src/commands/hello/index.ts) -`, - ] - - static flags = { - from: Flags.string({char: 'f', description: 'Who is saying hello', required: true}), - } - - async run(): Promise { - const {args, flags} = await this.parse(Hello) - - this.log(`hello ${args.person} from ${flags.from}! (./src/commands/hello/index.ts)`) - } -} diff --git a/src/commands/hello/world.ts b/src/commands/hello/world.ts deleted file mode 100644 index 8111043..0000000 --- a/src/commands/hello/world.ts +++ /dev/null @@ -1,19 +0,0 @@ -import {Command} from '@oclif/core' - -export default class World extends Command { - static args = {} - - static description = 'Say hello world' - - static examples = [ - `<%= config.bin %> <%= command.id %> -hello world! (./src/commands/hello/world.ts) -`, - ] - - static flags = {} - - async run(): Promise { - this.log('hello world! (./src/commands/hello/world.ts)') - } -} diff --git a/src/commands/mkdir.ts b/src/commands/mkdir.ts new file mode 100644 index 0000000..f66f780 --- /dev/null +++ b/src/commands/mkdir.ts @@ -0,0 +1,72 @@ +import {Args, Command, Flags} from '@oclif/core' +import {common as common_flags} from '../flags.js' +import path from 'path' +import Config from '../config.js' +import KeClient from '../client.js' +import {DIRECTORY_TYPE} from '../const.js' + + +export default class Mkdir extends Command { + static override args = { + directory: Args.string({ + description: 'path of the directory to be created', + required: true, + }), + } + static strict = false + + static override description = 'Create the directories, if they do not already exist.' + + static override examples = [ + '<%= config.bin %> <%= command.id %>', + ] + + static override flags = { + ...common_flags, + // flag with a value (-c, --cwd=VALUE) + cwd: Flags.string({char: 'c', description: 'set current working directory to VALUE'}), + parent: Flags.boolean({char: 'p', description: 'no error if existing, make parent directories as needed'}), + verbose: Flags.boolean({char: 'v', description: 'print a message for each created directory'}), + } + + public async run(): Promise { + const {argv, flags} = await this.parse(Mkdir) + let cwd = '/' + if (flags.cwd) { + // cwd のパラメータチェック + if (!path.isAbsolute(flags.cwd)) { + throw new Error(`cwd should be absolute path: ${flags.cwd}`) + } + cwd = flags.cwd + } + const config = new Config(flags) + for (let i = 0; i < argv.length; i++) { + const {dir, base} = path.parse(path.resolve(cwd, argv[i] as string)) + await this.make_directory(config, dir, base, flags.parent, flags.verbose) + } + } + + private async make_directory(config: Config, parent_dir: string, name: string, parent: boolean = false, verbose: boolean = false) { + // parent_dir の存在チェック + let result = await KeClient.get(config, parent_dir) + if (result == null) { + if (!parent) { + throw new Error(`cannot create directory: parent directory '${parent_dir}' is not found`) + } + const {dir, base} = path.parse(parent_dir) + result = await this.make_directory(config, dir, base, parent, verbose) + } + if (result!.type_object != DIRECTORY_TYPE) { + throw new Error(`cannot create directory: parent directory '${parent_dir}' is not directory`) + } + let data = { + 'type_object': DIRECTORY_TYPE, + 'name': name + } + result = await KeClient.create(config, parent_dir, name, data) + if (result && verbose) { + this.log(`created directory: ${result.abspath}`) + } + return result + } +} diff --git a/src/commands/rmdir.ts b/src/commands/rmdir.ts new file mode 100644 index 0000000..1c468e0 --- /dev/null +++ b/src/commands/rmdir.ts @@ -0,0 +1,74 @@ +import {Args, Command, Flags} from '@oclif/core' +import {common as common_flags} from '../flags.js' +import path from 'path' +import Config from '../config.js' +import KeClient from '../client.js' +import {DIRECTORY_TYPE} from '../const.js' + + +export default class Rmdir extends Command { + static override args = { + directory: Args.string({ + description: 'path of the directory to be removed', + required: true, + }), + } + static strict = false + + static override description = 'Remove the directories, if they are empty.' + + static override examples = [ + '<%= config.bin %> <%= command.id %>', + ] + + static override flags = { + ...common_flags, + // flag with a value (-c, --cwd=VALUE) + cwd: Flags.string({char: 'c', description: 'set current working directory to VALUE'}), + parent: Flags.boolean({char: 'p', description: 'remove DIRECTORY and its ancestors'}), + verbose: Flags.boolean({char: 'v', description: 'print a message for each removed directory'}), + } + + public async run(): Promise { + const {argv, flags} = await this.parse(Rmdir) + let cwd = '/' + if (flags.cwd) { + // cwd のパラメータチェック + if (!path.isAbsolute(flags.cwd)) { + throw new Error(`cwd should be absolute path: ${flags.cwd}`) + } + cwd = path.normalize(flags.cwd) + } + const config = new Config(flags) + for (let i = 0; i < argv.length; i++) { + let result = await this.remove_directory(config, cwd, argv[i] as string, flags.parent, flags.verbose) + } + } + + private async remove_directory(config: Config, cwd: string, target: string, parent: boolean = false, verbose: boolean = false) { + const target_dir = path.resolve(cwd, target) + let result = await KeClient.get(config, target_dir) + if (result == null) { + throw new Error(`failed to remove directory: '${target_dir}' is not found`) + } + if (result.type_object != DIRECTORY_TYPE) { + throw new Error(`failed to remove directory: '${target_dir}' is not a directory`) + } + // ディレクトリが空かどうかチェックする + let results = await KeClient.get_all(config, `${target_dir}.children`) + if (results!.count > 0) { + throw new Error(`failed to remove directory: '${target_dir}' is not empty`) + } + await KeClient.del(config, target_dir) + if (verbose) { + this.log(`removed directory: ${target_dir}`) + } + if (parent) { + const {dir, base} = path.parse(target_dir) + if (dir != cwd) { + await this.remove_directory(config, cwd, dir, parent, verbose) + } + } + return result + } +} diff --git a/src/common-flags.ts b/src/common-flags.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 0000000..77a5d19 --- /dev/null +++ b/src/config.ts @@ -0,0 +1,15 @@ +import { createRequire } from 'module' +const require = createRequire(import.meta.url) + + +export default class Config { + baseurl?: string + token?: string + + constructor(flags: any) { + const config = require('config') + + this.baseurl = flags.baseurl || config.get('baseurl') + this.token = flags.username || config.get('token') + } +} diff --git a/src/const.ts b/src/const.ts new file mode 100644 index 0000000..bd7f733 --- /dev/null +++ b/src/const.ts @@ -0,0 +1 @@ +export const DIRECTORY_TYPE = '/system/types/Directory' diff --git a/src/flags.ts b/src/flags.ts new file mode 100644 index 0000000..7c6053e --- /dev/null +++ b/src/flags.ts @@ -0,0 +1,7 @@ +import {Args, Command, Flags} from '@oclif/core' + + +export const common = { + baseurl: Flags.string({char: 'u', description: 'base URL of the Kompira Enterprise server'}), + token: Flags.string({char: 't', description: 'API access token of the Kompira Enterprise server'}) +} diff --git a/test/commands/hello/index.test.ts b/test/commands/hello/index.test.ts deleted file mode 100644 index dad0ac3..0000000 --- a/test/commands/hello/index.test.ts +++ /dev/null @@ -1,9 +0,0 @@ -import {runCommand} from '@oclif/test' -import {expect} from 'chai' - -describe('hello', () => { - it('runs hello', async () => { - const {stdout} = await runCommand('hello friend --from oclif') - expect(stdout).to.contain('hello friend from oclif!') - }) -}) diff --git a/test/commands/hello/world.test.ts b/test/commands/hello/world.test.ts deleted file mode 100644 index 0f5e90f..0000000 --- a/test/commands/hello/world.test.ts +++ /dev/null @@ -1,9 +0,0 @@ -import {runCommand} from '@oclif/test' -import {expect} from 'chai' - -describe('hello world', () => { - it('runs hello world cmd', async () => { - const {stdout} = await runCommand('hello world') - expect(stdout).to.contain('hello world!') - }) -}) diff --git a/test/commands/mkdir.test.ts b/test/commands/mkdir.test.ts new file mode 100644 index 0000000..be3ea60 --- /dev/null +++ b/test/commands/mkdir.test.ts @@ -0,0 +1,14 @@ +import {runCommand} from '@oclif/test' +import {expect} from 'chai' + +describe('mkdir', () => { + it('runs mkdir cmd', async () => { + const {stdout} = await runCommand('mkdir') + expect(stdout).to.contain('hello world') + }) + + it('runs mkdir --name oclif', async () => { + const {stdout} = await runCommand('mkdir --name oclif') + expect(stdout).to.contain('hello oclif') + }) +}) diff --git a/test/commands/rmdir.test.ts b/test/commands/rmdir.test.ts new file mode 100644 index 0000000..6a804b8 --- /dev/null +++ b/test/commands/rmdir.test.ts @@ -0,0 +1,14 @@ +import {runCommand} from '@oclif/test' +import {expect} from 'chai' + +describe('rmdir', () => { + it('runs rmdir cmd', async () => { + const {stdout} = await runCommand('rmdir') + expect(stdout).to.contain('hello world') + }) + + it('runs rmdir --name oclif', async () => { + const {stdout} = await runCommand('rmdir --name oclif') + expect(stdout).to.contain('hello oclif') + }) +}) diff --git a/tsconfig.tsbuildinfo b/tsconfig.tsbuildinfo deleted file mode 100644 index 9df1082..0000000 --- a/tsconfig.tsbuildinfo +++ /dev/null @@ -1 +0,0 @@ -{"root":["./src/index.ts","./src/commands/hello/index.ts","./src/commands/hello/world.ts"],"version":"5.6.3"} \ No newline at end of file From 32f6f84ed1f75e51a41dd8c3701b938749a87c23 Mon Sep 17 00:00:00 2001 From: Kenta HATTORI Date: Sun, 13 Oct 2024 01:08:24 +0900 Subject: [PATCH 02/11] Add: rm commands --- README.md | 62 +++++++++++++++++++++++++++----------- src/client.ts | 12 ++++---- src/commands/rm.ts | 65 ++++++++++++++++++++++++++++++++++++++++ src/commands/rmdir.ts | 2 +- test/commands/rm.test.ts | 14 +++++++++ 5 files changed, 130 insertions(+), 25 deletions(-) create mode 100644 src/commands/rm.ts create mode 100644 test/commands/rm.test.ts diff --git a/README.md b/README.md index fb0817a..ddc947a 100644 --- a/README.md +++ b/README.md @@ -29,17 +29,36 @@ USAGE # Commands -* [`ketool mkdir DIRECTORY`](#ketool-mkdir) -* [`ketool rmdir DIRECTORY`](#ketool-rmdir) * [`ketool help [COMMAND]`](#ketool-help-command) +* [`ketool mkdir DIRECTORY`](#ketool-mkdir-directory) +* [`ketool rm OBJECT`](#ketool-rm-object) +* [`ketool rmdir DIRECTORY`](#ketool-rmdir-directory) -## `ketool mkdir DIRECTORY` +## `ketool help [COMMAND]` -Say hello +Display help for ketool. ``` +USAGE + $ ketool help [COMMAND...] [-n] + +ARGUMENTS + COMMAND... Command to show help for. + +FLAGS + -n, --nested-commands Include all nested commands in the output. + +DESCRIPTION + Display help for ketool. +``` + +_See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v6.2.15/src/commands/help.ts)_ + +## `ketool mkdir DIRECTORY` + Create the directories, if they do not already exist. +``` USAGE $ ketool mkdir DIRECTORY... [-u ] [-t ] [-c ] [-p] [-v] @@ -62,20 +81,21 @@ EXAMPLES _See code: [src/commands/mkdir.ts](https://github.com/fixpoint/ketool/blob/v0.0.0/src/commands/mkdir.ts)_ -## `ketool rmdir DIRECTORY` +## `ketool rm OBJECT` Remove the directories, if they are empty. ``` USAGE - $ ketool rmdir DIRECTORY... [-u ] [-t ] [-c ] [-p] [-v] + $ ketool rm OBJECT... [-u ] [-t ] [-c ] [-f] [-r] [-v] ARGUMENTS - DIRECTORY... path of the directory to be removed + OBJECT... path of the object to be removed FLAGS -c, --cwd= set current working directory to VALUE - -p, --parent remove DIRECTORY and its ancestors + -f, --force ignore nonexistent objects and arguments + -r, --recurcive remove directories and their contents recursively -t, --token= API access token of the Kompira Enterprise server -u, --baseurl= base URL of the Kompira Enterprise server -v, --verbose print a message for each removed directory @@ -84,29 +104,35 @@ DESCRIPTION Remove the directories, if they are empty. EXAMPLES - $ ketool rmdir + $ ketool rm ``` -_See code: [src/commands/rmdir.ts](https://github.com/fixpoint/ketool/blob/v0.0.0/src/commands/rmdir.ts)_ +_See code: [src/commands/rm.ts](https://github.com/fixpoint/ketool/blob/v0.0.0/src/commands/rm.ts)_ -## `ketool help [COMMAND]` +## `ketool rmdir DIRECTORY` -Display help for ketool. +Remove the directories, if they are empty. ``` USAGE - $ ketool help [COMMAND...] [-n] + $ ketool rmdir DIRECTORY... [-u ] [-t ] [-c ] [-p] [-v] ARGUMENTS - COMMAND... Command to show help for. + DIRECTORY... path of the directory to be removed FLAGS - -n, --nested-commands Include all nested commands in the output. + -c, --cwd= set current working directory to VALUE + -p, --parent remove DIRECTORY and its ancestors + -t, --token= API access token of the Kompira Enterprise server + -u, --baseurl= base URL of the Kompira Enterprise server + -v, --verbose print a message for each removed directory DESCRIPTION - Display help for ketool. -``` + Remove the directories, if they are empty. -_See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v6.2.15/src/commands/help.ts)_ +EXAMPLES + $ ketool rmdir +``` +_See code: [src/commands/rmdir.ts](https://github.com/fixpoint/ketool/blob/v0.0.0/src/commands/rmdir.ts)_ diff --git a/src/client.ts b/src/client.ts index d5dd959..c200fff 100644 --- a/src/client.ts +++ b/src/client.ts @@ -64,21 +64,21 @@ export namespace KeClient { export async function create(config: Config, path: string, name: string, data: any): Promise { let rest: rm.RestClient = new rm.RestClient('ke-client', config.baseurl) let resp: rm.IRestResponse = await rest.create(path, data, request_options(config.token)) - if (resp.statusCode == 400) { - - } else if (resp.statusCode != 201) { + if (resp.statusCode != 201) { throw new Error(`StatusCode: ${resp.statusCode}`) } return resp.result } - export async function del(config: Config, path: string): Promise { + export async function del(config: Config, path: string, force: boolean = false): Promise { let rest: rm.RestClient = new rm.RestClient('ke-client', config.baseurl) let resp: rm.IRestResponse = await rest.del(path, request_options(config.token)) - if (resp.statusCode != 204) { + if (force && resp.statusCode == 404) { + return false + } else if (resp.statusCode != 204) { throw new Error(`StatusCode: ${resp.statusCode}`) } - return resp.result + return true } } diff --git a/src/commands/rm.ts b/src/commands/rm.ts new file mode 100644 index 0000000..391a424 --- /dev/null +++ b/src/commands/rm.ts @@ -0,0 +1,65 @@ +import {Args, Command, Flags} from '@oclif/core' +import {common as common_flags} from '../flags.js' +import path from 'path' +import Config from '../config.js' +import KeClient from '../client.js' +import {DIRECTORY_TYPE} from '../const.js' + + +export default class Rm extends Command { + static override args = { + object: Args.string({ + description: 'path of the object to be removed', + required: true, + }), + } + static strict = false + + static override description = 'Remove the directories, if they are empty.' + + static override examples = [ + '<%= config.bin %> <%= command.id %>', + ] + + static override flags = { + ...common_flags, + // flag with a value (-c, --cwd=VALUE) + cwd: Flags.string({char: 'c', description: 'set current working directory to VALUE'}), + force: Flags.boolean({char: 'f', description: 'ignore nonexistent objects and arguments'}), + recurcive: Flags.boolean({char: 'r', description: 'remove directories and their contents recursively'}), + verbose: Flags.boolean({char: 'v', description: 'print a message for each removed directory'}), + } + + public async run(): Promise { + const {argv, flags} = await this.parse(Rm) + let cwd = '/' + if (flags.cwd) { + // cwd のパラメータチェック + if (!path.isAbsolute(flags.cwd)) { + throw new Error(`cwd should be absolute path: ${flags.cwd}`) + } + cwd = path.normalize(flags.cwd) + } + const config = new Config(flags) + for (let i = 0; i < argv.length; i++) { + const target = path.resolve(cwd, argv[i] as string) + await this.remove_object(config, target, flags.force, flags.recursive, flags.verbose) + } + } + + private async remove_object(config: Config, target: string, force: boolean = false, recursive: boolean = false, verbose: boolean = false) { + if (!force) { + let result = await KeClient.get(config, target) + if (result == null) { + throw new Error(`failed to remove: '${target}' is not found`) + } + if (result.type_object == DIRECTORY_TYPE) { + throw new Error(`failed to remove: '${target}' is a directory`) + } + } + let removed = await KeClient.del(config, target, force) + if (verbose && removed) { + this.log(`removed: ${target}`) + } + } +} diff --git a/src/commands/rmdir.ts b/src/commands/rmdir.ts index 1c468e0..5e5f353 100644 --- a/src/commands/rmdir.ts +++ b/src/commands/rmdir.ts @@ -41,7 +41,7 @@ export default class Rmdir extends Command { } const config = new Config(flags) for (let i = 0; i < argv.length; i++) { - let result = await this.remove_directory(config, cwd, argv[i] as string, flags.parent, flags.verbose) + await this.remove_directory(config, cwd, argv[i] as string, flags.parent, flags.verbose) } } diff --git a/test/commands/rm.test.ts b/test/commands/rm.test.ts new file mode 100644 index 0000000..087458f --- /dev/null +++ b/test/commands/rm.test.ts @@ -0,0 +1,14 @@ +import {runCommand} from '@oclif/test' +import {expect} from 'chai' + +describe('rm', () => { + it('runs rm cmd', async () => { + const {stdout} = await runCommand('rm') + expect(stdout).to.contain('hello world') + }) + + it('runs rm --name oclif', async () => { + const {stdout} = await runCommand('rm --name oclif') + expect(stdout).to.contain('hello oclif') + }) +}) From 90eb853afe30fa88d9d1d0898ad1bdbc45b0e307 Mon Sep 17 00:00:00 2001 From: Kenta HATTORI Date: Fri, 25 Oct 2024 07:29:52 +0900 Subject: [PATCH 03/11] Removed unused file --- src/common-flags.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/common-flags.ts diff --git a/src/common-flags.ts b/src/common-flags.ts deleted file mode 100644 index e69de29..0000000 From 730f0955ac2b7b037892a8677013a7f5b7fd8273 Mon Sep 17 00:00:00 2001 From: Kenta HATTORI Date: Sat, 26 Oct 2024 14:26:09 +0900 Subject: [PATCH 04/11] Add: put command --- README.md | 40 ++++++++- package-lock.json | 30 +++++++ package.json | 2 + src/client.ts | 22 ++++- src/commands/mkdir.ts | 17 ++-- src/commands/put.ts | 174 ++++++++++++++++++++++++++++++++++++++ src/commands/rm.ts | 14 ++- src/commands/rmdir.ts | 14 ++- src/common.ts | 31 +++++++ src/const.ts | 1 + src/flags.ts | 3 +- test/commands/put.test.ts | 14 +++ 12 files changed, 327 insertions(+), 35 deletions(-) create mode 100644 src/commands/put.ts create mode 100644 src/common.ts create mode 100644 test/commands/put.test.ts diff --git a/README.md b/README.md index ddc947a..959d9f0 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ USAGE * [`ketool help [COMMAND]`](#ketool-help-command) * [`ketool mkdir DIRECTORY`](#ketool-mkdir-directory) +* [`ketool put SOURCE`](#ketool-put-source) * [`ketool rm OBJECT`](#ketool-rm-object) * [`ketool rmdir DIRECTORY`](#ketool-rmdir-directory) @@ -60,13 +61,14 @@ Create the directories, if they do not already exist. ``` USAGE - $ ketool mkdir DIRECTORY... [-u ] [-t ] [-c ] [-p] [-v] + $ ketool mkdir DIRECTORY... [-u ] [-t ] [-k] [-c ] [-p] [-v] ARGUMENTS DIRECTORY... path of the directory to be created FLAGS -c, --cwd= set current working directory to VALUE + -k, --insecure allow insecure SSL connection -p, --parent no error if existing, make parent directories as needed -t, --token= API access token of the Kompira Enterprise server -u, --baseurl= base URL of the Kompira Enterprise server @@ -81,13 +83,43 @@ EXAMPLES _See code: [src/commands/mkdir.ts](https://github.com/fixpoint/ketool/blob/v0.0.0/src/commands/mkdir.ts)_ +## `ketool put SOURCE` + +put files or directories to Kompira server + +``` +USAGE + $ ketool put SOURCE... [-u ] [-t ] [-k] [-d ] [-c ] [-r] [-o] [-v] + +ARGUMENTS + SOURCE... source file or directory + +FLAGS + -c, --cwd= set current working directory to VALUE + -d, --dest= specify destination object or directory (create if none exists) + -k, --insecure allow insecure SSL connection + -o, --overwrite overwrite an existing object + -r, --recursive put directories recursively + -t, --token= API access token of the Kompira Enterprise server + -u, --baseurl= base URL of the Kompira Enterprise server + -v, --verbose explain what is being down + +DESCRIPTION + put files or directories to Kompira server + +EXAMPLES + $ ketool put +``` + +_See code: [src/commands/put.ts](https://github.com/fixpoint/ketool/blob/v0.0.0/src/commands/put.ts)_ + ## `ketool rm OBJECT` Remove the directories, if they are empty. ``` USAGE - $ ketool rm OBJECT... [-u ] [-t ] [-c ] [-f] [-r] [-v] + $ ketool rm OBJECT... [-u ] [-t ] [-k] [-c ] [-f] [-r] [-v] ARGUMENTS OBJECT... path of the object to be removed @@ -95,6 +127,7 @@ ARGUMENTS FLAGS -c, --cwd= set current working directory to VALUE -f, --force ignore nonexistent objects and arguments + -k, --insecure allow insecure SSL connection -r, --recurcive remove directories and their contents recursively -t, --token= API access token of the Kompira Enterprise server -u, --baseurl= base URL of the Kompira Enterprise server @@ -115,13 +148,14 @@ Remove the directories, if they are empty. ``` USAGE - $ ketool rmdir DIRECTORY... [-u ] [-t ] [-c ] [-p] [-v] + $ ketool rmdir DIRECTORY... [-u ] [-t ] [-k] [-c ] [-p] [-v] ARGUMENTS DIRECTORY... path of the directory to be removed FLAGS -c, --cwd= set current working directory to VALUE + -k, --insecure allow insecure SSL connection -p, --parent remove DIRECTORY and its ancestors -t, --token= API access token of the Kompira Enterprise server -u, --baseurl= base URL of the Kompira Enterprise server diff --git a/package-lock.json b/package-lock.json index d570ada..dd1035e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@oclif/core": "^4", "@oclif/plugin-help": "^6", "config": "^3.3.12", + "mime-types": "^2.1.35", "typed-rest-client": "^2.1.0" }, "bin": { @@ -22,6 +23,7 @@ "@oclif/test": "^4", "@types/chai": "^4", "@types/config": "^3.3.5", + "@types/mime-types": "^2.1.4", "@types/mocha": "^10", "@types/node": "^18", "chai": "^4", @@ -2521,6 +2523,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/mime-types": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.4.tgz", + "integrity": "sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/mocha": { "version": "10.0.9", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.9.tgz", @@ -6279,6 +6288,27 @@ "node": ">=8.6" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/mimic-response": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", diff --git a/package.json b/package.json index 2e74c24..56cc85e 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "@oclif/core": "^4", "@oclif/plugin-help": "^6", "config": "^3.3.12", + "mime-types": "^2.1.35", "typed-rest-client": "^2.1.0" }, "devDependencies": { @@ -18,6 +19,7 @@ "@oclif/test": "^4", "@types/chai": "^4", "@types/config": "^3.3.5", + "@types/mime-types": "^2.1.4", "@types/mocha": "^10", "@types/node": "^18", "chai": "^4", diff --git a/src/client.ts b/src/client.ts index c200fff..eaa4968 100644 --- a/src/client.ts +++ b/src/client.ts @@ -61,13 +61,31 @@ export namespace KeClient { return resp.result } - export async function create(config: Config, path: string, name: string, data: any): Promise { + export async function create(config: Config, path: string, data: any): Promise { let rest: rm.RestClient = new rm.RestClient('ke-client', config.baseurl) let resp: rm.IRestResponse = await rest.create(path, data, request_options(config.token)) if (resp.statusCode != 201) { throw new Error(`StatusCode: ${resp.statusCode}`) } - return resp.result + return resp.result as ObjectResponse + } + + export async function update(config: Config, path: string, data: any): Promise { + let rest: rm.RestClient = new rm.RestClient('ke-client', config.baseurl) + let resp: rm.IRestResponse = await rest.update(path, data, request_options(config.token)) + if (resp.statusCode != 200) { + throw new Error(`StatusCode: ${resp.statusCode}`) + } + return resp.result as ObjectResponse + } + + export async function replace(config: Config, path: string, data: any): Promise { + let rest: rm.RestClient = new rm.RestClient('ke-client', config.baseurl) + let resp: rm.IRestResponse = await rest.replace(path, data, request_options(config.token)) + if (resp.statusCode != 200) { + throw new Error(`StatusCode: ${resp.statusCode}`) + } + return resp.result as ObjectResponse } export async function del(config: Config, path: string, force: boolean = false): Promise { diff --git a/src/commands/mkdir.ts b/src/commands/mkdir.ts index f66f780..2dd300f 100644 --- a/src/commands/mkdir.ts +++ b/src/commands/mkdir.ts @@ -1,8 +1,10 @@ import {Args, Command, Flags} from '@oclif/core' -import {common as common_flags} from '../flags.js' import path from 'path' + +import {common as common_flags} from '../flags.js' import Config from '../config.js' import KeClient from '../client.js' +import {check_cwd, check_insecure} from '../common.js' import {DIRECTORY_TYPE} from '../const.js' @@ -31,21 +33,14 @@ export default class Mkdir extends Command { public async run(): Promise { const {argv, flags} = await this.parse(Mkdir) - let cwd = '/' - if (flags.cwd) { - // cwd のパラメータチェック - if (!path.isAbsolute(flags.cwd)) { - throw new Error(`cwd should be absolute path: ${flags.cwd}`) - } - cwd = flags.cwd - } const config = new Config(flags) + check_insecure(flags.insecure) + let cwd = await check_cwd(config, flags.cwd) for (let i = 0; i < argv.length; i++) { const {dir, base} = path.parse(path.resolve(cwd, argv[i] as string)) await this.make_directory(config, dir, base, flags.parent, flags.verbose) } } - private async make_directory(config: Config, parent_dir: string, name: string, parent: boolean = false, verbose: boolean = false) { // parent_dir の存在チェック let result = await KeClient.get(config, parent_dir) @@ -63,7 +58,7 @@ export default class Mkdir extends Command { 'type_object': DIRECTORY_TYPE, 'name': name } - result = await KeClient.create(config, parent_dir, name, data) + result = await KeClient.create(config, parent_dir, data) if (result && verbose) { this.log(`created directory: ${result.abspath}`) } diff --git a/src/commands/put.ts b/src/commands/put.ts new file mode 100644 index 0000000..1560349 --- /dev/null +++ b/src/commands/put.ts @@ -0,0 +1,174 @@ +import {Args, Command, Flags} from '@oclif/core' +import fs from 'fs/promises' +import path from 'path' +import mime from 'mime-types' +import assert from 'assert' + +import {common as common_flags} from '../flags.js' +import Config from '../config.js' +import KeClient from '../client.js' +import {check_cwd, check_insecure} from '../common.js' +import {DIRECTORY_TYPE, TEXT_TYPE} from '../const.js' + + +type PutOptions = { + recursive?: boolean + overwrite?: boolean + verbose?: boolean +} + +type SourceDesc = { + type: 'dir' | 'file' + path: string + name: string + ext: string +} + +type Resp = KeClient.ObjectResponse + +export default class Put extends Command { + static override args = { + source: Args.string({description: 'source file or directory', required: true}), + } + static strict = false + + static override description = 'put files or directories to Kompira server' + + static override examples = [ + '<%= config.bin %> <%= command.id %>', + ] + + static override flags = { + ...common_flags, + dest: Flags.string({char: 'd', description: 'specify destination object or directory (create if none exists)'}), + // flag with a value (-c, --cwd=VALUE) + cwd: Flags.string({char: 'c', description: 'set current working directory to VALUE'}), + recursive: Flags.boolean({char: 'r', description: 'put directories recursively'}), + overwrite: Flags.boolean({char: 'o', description: 'overwrite an existing object'}), + verbose: Flags.boolean({char: 'v', description: 'explain what is being down'}), + } + + public async run(): Promise { + const {argv, flags} = await this.parse(Put) + const config = new Config(flags) + + check_insecure(flags.insecure) + let cwd = await check_cwd(config, flags.cwd) + let dest = path.normalize(path.join(cwd, flags.dest || '')) + let sources = await this.check_sources(argv as string[], path.resolve('.')) + let target: KeClient.ObjectResponse | string | null = await KeClient.get(config, dest) + + if (argv.length == 1) { + let source = sources[0] + if (!target) { + ({dir: dest, base: target} = path.parse(dest)) + } else if (target.type_object == DIRECTORY_TYPE) { + target = await KeClient.get(config, path.join(target.abspath, source.name)) || source.name + } else { + dest = path.dirname(dest) + } + await this.do_put(config, dest, source, target, flags) + } else { + if (target == null) { + // target が存在しない場合はコピーできない + throw Error(`target '${dest}' is not found`) + } else if (target!.type_object != DIRECTORY_TYPE) { + // コピー先がディレクトリ以外の場合はコピーできない + throw Error(`target '${dest}' is not a directory`) + } + // dest 配下にsources をコピー + for (const source of sources) { + await this.do_put(config, dest, source, source.name, flags) + } + } + } + + private async check_sources(sources: string[], cwd: string): Promise { + let source_descs: SourceDesc[] = [] + for (let source of sources) { + source = path.normalize(path.join(cwd, source)) + try { + const stat = await fs.stat(source) + const {name, ext} = path.parse(source) + if (stat.isDirectory()) { + source_descs.push({type: 'dir', path: source, name: name, ext: ext}) + } else if (stat.isFile()) { + source_descs.push({type: 'file', path: source, name: name, ext: ext}) + } else { + this.log(`put: invalid source '${source} type: should be file or directory`) + } + } catch (err) { + if (err instanceof Error) { + this.log(`put: cannot stat '${source}': ${err.message}`) + } else { + this.log(`put: cannot stat '${source}': Unknown error`) + } + } + } + return source_descs + } + + private async do_put(config: Config, dest: string, source: SourceDesc, target: KeClient.ObjectResponse | string, options: PutOptions) { + let dest_dir = null + if (target instanceof Object) { + if (target.type_object == DIRECTORY_TYPE && source.type == 'dir') { + dest_dir = target.abspath + } else if (target.type_object == TEXT_TYPE && source.type == 'file') { + if (options.overwrite) { + let text = await fs.readFile(source.path, { encoding: 'utf8' }) + let data = { + 'fields': { + 'text': text, + 'ext': source.ext.replace(/^\.+/, ''), + 'contentType': mime.lookup(source.path) + } + } + let result = await KeClient.update(config, target.abspath, data) + if (options.verbose) { + this.log(`updated text: ${result.abspath}`) + } + } + } else { + this.log(`put: cannot overwrite ${target.abspath}: type '${target.type_object}' mismatch`) + return + } + } else if (source.type == 'dir') { + let data = { + 'type_object': DIRECTORY_TYPE, + 'name': target as string, + } + let result = await KeClient.create(config, dest, data) + if (options.verbose) { + this.log(`created directory: ${result.abspath}`) + } + dest_dir = result.abspath + } else if (source.type == 'file') { + let text = await fs.readFile(source.path, { encoding: 'utf8' }) + let data = { + 'type_object': TEXT_TYPE, + 'name': target as string, + 'fields': { + 'text': text, + 'ext': source.ext.replace(/^\.+/, ''), + 'contentType': mime.lookup(source.path) + } + } + let result = await KeClient.create(config, dest, data) + if (options.verbose) { + this.log(`created text: ${result.abspath}`) + } + } else { + assert(false, `invalid source.type: ${source.type}`) + } + + if (options.recursive && dest_dir) { + // ファイル一覧を取得 + let dirs = await fs.readdir(source.path) + let sources = await this.check_sources(dirs, source.path) + for (const source of sources) { + target = await KeClient.get(config, path.join(dest_dir, source.name)) || source.name + await this.do_put(config, dest_dir, source, target, options) + } + } + } +} diff --git a/src/commands/rm.ts b/src/commands/rm.ts index 391a424..bf5d760 100644 --- a/src/commands/rm.ts +++ b/src/commands/rm.ts @@ -1,8 +1,10 @@ import {Args, Command, Flags} from '@oclif/core' -import {common as common_flags} from '../flags.js' import path from 'path' + +import {common as common_flags} from '../flags.js' import Config from '../config.js' import KeClient from '../client.js' +import {check_cwd, check_insecure} from '../common.js' import {DIRECTORY_TYPE} from '../const.js' @@ -32,15 +34,9 @@ export default class Rm extends Command { public async run(): Promise { const {argv, flags} = await this.parse(Rm) - let cwd = '/' - if (flags.cwd) { - // cwd のパラメータチェック - if (!path.isAbsolute(flags.cwd)) { - throw new Error(`cwd should be absolute path: ${flags.cwd}`) - } - cwd = path.normalize(flags.cwd) - } const config = new Config(flags) + check_insecure(flags.insecure) + let cwd = await check_cwd(config, flags.cwd) for (let i = 0; i < argv.length; i++) { const target = path.resolve(cwd, argv[i] as string) await this.remove_object(config, target, flags.force, flags.recursive, flags.verbose) diff --git a/src/commands/rmdir.ts b/src/commands/rmdir.ts index 5e5f353..57726ee 100644 --- a/src/commands/rmdir.ts +++ b/src/commands/rmdir.ts @@ -1,8 +1,10 @@ import {Args, Command, Flags} from '@oclif/core' -import {common as common_flags} from '../flags.js' import path from 'path' + +import {common as common_flags} from '../flags.js' import Config from '../config.js' import KeClient from '../client.js' +import {check_cwd, check_insecure} from '../common.js' import {DIRECTORY_TYPE} from '../const.js' @@ -31,15 +33,9 @@ export default class Rmdir extends Command { public async run(): Promise { const {argv, flags} = await this.parse(Rmdir) - let cwd = '/' - if (flags.cwd) { - // cwd のパラメータチェック - if (!path.isAbsolute(flags.cwd)) { - throw new Error(`cwd should be absolute path: ${flags.cwd}`) - } - cwd = path.normalize(flags.cwd) - } const config = new Config(flags) + check_insecure(flags.insecure) + let cwd = await check_cwd(config, flags.cwd) for (let i = 0; i < argv.length; i++) { await this.remove_directory(config, cwd, argv[i] as string, flags.parent, flags.verbose) } diff --git a/src/common.ts b/src/common.ts new file mode 100644 index 0000000..e12687c --- /dev/null +++ b/src/common.ts @@ -0,0 +1,31 @@ +import path from 'path' +import Config from './config.js' +import KeClient from './client.js' +import {DIRECTORY_TYPE} from './const.js' + + +export async function check_cwd(config: Config, cwd?: string): Promise { + if (cwd) { + // cwd のパラメータチェック + if (!path.isAbsolute(cwd)) { + throw new Error(`cwd should be absolute path: ${cwd}`) + } + let result = await KeClient.get(config, cwd) + if (result == null) { + throw new Error(`cwd '${cwd}' does not exist`) + } + if (result!.type_object != DIRECTORY_TYPE) { + throw new Error(`cwd '${cwd}' is not directory`) + } + return path.normalize(cwd) + } else { + return '/' + } +} + + +export function check_insecure(insecure?: boolean): void { + if (insecure) { + process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0' + } +} diff --git a/src/const.ts b/src/const.ts index bd7f733..85a196b 100644 --- a/src/const.ts +++ b/src/const.ts @@ -1 +1,2 @@ export const DIRECTORY_TYPE = '/system/types/Directory' +export const TEXT_TYPE = '/system/types/Text' diff --git a/src/flags.ts b/src/flags.ts index 7c6053e..b9ad3ee 100644 --- a/src/flags.ts +++ b/src/flags.ts @@ -3,5 +3,6 @@ import {Args, Command, Flags} from '@oclif/core' export const common = { baseurl: Flags.string({char: 'u', description: 'base URL of the Kompira Enterprise server'}), - token: Flags.string({char: 't', description: 'API access token of the Kompira Enterprise server'}) + token: Flags.string({char: 't', description: 'API access token of the Kompira Enterprise server'}), + insecure: Flags.boolean({char: 'k', description: 'allow insecure SSL connection'}), } diff --git a/test/commands/put.test.ts b/test/commands/put.test.ts new file mode 100644 index 0000000..665851d --- /dev/null +++ b/test/commands/put.test.ts @@ -0,0 +1,14 @@ +import {runCommand} from '@oclif/test' +import {expect} from 'chai' + +describe('put', () => { + it('runs put cmd', async () => { + const {stdout} = await runCommand('put') + expect(stdout).to.contain('hello world') + }) + + it('runs put --name oclif', async () => { + const {stdout} = await runCommand('put --name oclif') + expect(stdout).to.contain('hello oclif') + }) +}) From 7fc196eabbd5ff01f31b61433ad106010cbe609b Mon Sep 17 00:00:00 2001 From: Kenta HATTORI Date: Sat, 26 Oct 2024 19:56:37 +0900 Subject: [PATCH 05/11] Resolve lint errors --- src/client.ts | 170 ++++++++++++++++++++------------------- src/commands/mkdir.ts | 66 ++++++++++------ src/commands/put.ts | 179 ++++++++++++++++++++++-------------------- src/commands/rm.ts | 47 ++++++----- src/commands/rmdir.ts | 68 +++++++++------- src/common.ts | 44 ++++++----- src/config.ts | 12 ++- src/flags.ts | 4 +- 8 files changed, 328 insertions(+), 262 deletions(-) diff --git a/src/client.ts b/src/client.ts index eaa4968..5c926bf 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1,103 +1,113 @@ import * as rm from 'typed-rest-client/RestClient.js' + import Config from './config.js' -export namespace KeClient { - export type ObjectResponse = { - id: number - abspath: string - owner: string - display_name: string - description: string - type_object: string - parent_object: string - created: string - updated: string - fields: { - [key: string]: any - } - extra_properties: { - [key: string]: any - } - user_permissions: { - [key: string]: any - } - group_permissions: { - [key: string]: any - } +export type ObjectResponse = { + abspath: string + created: string + description: string + display_name: string + extra_properties: { + [key: string]: object } - export type ObjectsResponse = { - count: number, - results: [ObjectResponse] + fields: { + [key: string]: object } + group_permissions: { + [key: string]: object + } + id: number + owner: string + parent_object: string + type_object: string + updated: string + user_permissions: { + [key: string]: object + } +} - function request_options(token?: string): rm.IRequestOptions { - return { - 'additionalHeaders': { - 'Authorization': `Token ${token}` - } +export type ObjectsResponse = { + count: number, + results: [ObjectResponse] +} + +function requestOpts(token?: string): rm.IRequestOptions { + return { + 'additionalHeaders': { + 'Authorization': `Token ${token}` } } +} - export async function get(config: Config, path: string): Promise { - let rest: rm.RestClient = new rm.RestClient('ke-client', config.baseurl) - let resp: rm.IRestResponse = await rest.get(path, request_options(config.token)) - if (resp.statusCode == 404) { - return null - } else if (resp.statusCode != 200) { - throw new Error(`StatusCode: ${resp.statusCode}`) - } - return resp.result +export async function get(config: Config, path: string): Promise { + const rest: rm.RestClient = new rm.RestClient('ke-client', config.baseurl) + const resp: rm.IRestResponse = await rest.get(path, requestOpts(config.token)) + if (resp.statusCode === 404) { + return null } - export async function get_all(config: Config, path: string): Promise { - let rest: rm.RestClient = new rm.RestClient('ke-client', config.baseurl) - let resp: rm.IRestResponse = await rest.get(path, request_options(config.token)) - if (resp.statusCode == 404) { - return null - } else if (resp.statusCode != 200) { - throw new Error(`StatusCode: ${resp.statusCode}`) - } - return resp.result + if (resp.statusCode !== 200) { + throw new Error(`StatusCode: ${resp.statusCode}`) } - export async function create(config: Config, path: string, data: any): Promise { - let rest: rm.RestClient = new rm.RestClient('ke-client', config.baseurl) - let resp: rm.IRestResponse = await rest.create(path, data, request_options(config.token)) - if (resp.statusCode != 201) { - throw new Error(`StatusCode: ${resp.statusCode}`) - } - return resp.result as ObjectResponse + return resp.result +} + +export async function getAll(config: Config, path: string): Promise { + const rest: rm.RestClient = new rm.RestClient('ke-client', config.baseurl) + const resp: rm.IRestResponse = await rest.get(path, requestOpts(config.token)) + if (resp.statusCode === 404) { + return null } - export async function update(config: Config, path: string, data: any): Promise { - let rest: rm.RestClient = new rm.RestClient('ke-client', config.baseurl) - let resp: rm.IRestResponse = await rest.update(path, data, request_options(config.token)) - if (resp.statusCode != 200) { - throw new Error(`StatusCode: ${resp.statusCode}`) - } - return resp.result as ObjectResponse + if (resp.statusCode !== 200) { + throw new Error(`StatusCode: ${resp.statusCode}`) } - export async function replace(config: Config, path: string, data: any): Promise { - let rest: rm.RestClient = new rm.RestClient('ke-client', config.baseurl) - let resp: rm.IRestResponse = await rest.replace(path, data, request_options(config.token)) - if (resp.statusCode != 200) { - throw new Error(`StatusCode: ${resp.statusCode}`) - } - return resp.result as ObjectResponse + return resp.result +} + +export async function create(config: Config, path: string, data: object): Promise { + const rest: rm.RestClient = new rm.RestClient('ke-client', config.baseurl) + const resp: rm.IRestResponse = await rest.create(path, data, requestOpts(config.token)) + if (resp.statusCode !== 201) { + throw new Error(`StatusCode: ${resp.statusCode}`) } - export async function del(config: Config, path: string, force: boolean = false): Promise { - let rest: rm.RestClient = new rm.RestClient('ke-client', config.baseurl) - let resp: rm.IRestResponse = await rest.del(path, request_options(config.token)) - if (force && resp.statusCode == 404) { - return false - } else if (resp.statusCode != 204) { - throw new Error(`StatusCode: ${resp.statusCode}`) - } - return true + return resp.result as ObjectResponse +} + +export async function update(config: Config, path: string, data: object): Promise { + const rest: rm.RestClient = new rm.RestClient('ke-client', config.baseurl) + const resp: rm.IRestResponse = await rest.update(path, data, requestOpts(config.token)) + if (resp.statusCode !== 200) { + throw new Error(`StatusCode: ${resp.statusCode}`) + } + + return resp.result as ObjectResponse +} + +export async function replace(config: Config, path: string, data: object): Promise { + const rest: rm.RestClient = new rm.RestClient('ke-client', config.baseurl) + const resp: rm.IRestResponse = await rest.replace(path, data, requestOpts(config.token)) + if (resp.statusCode !== 200) { + throw new Error(`StatusCode: ${resp.statusCode}`) } + + return resp.result as ObjectResponse } -export default KeClient +export async function del(config: Config, path: string, force: boolean = false): Promise { + const rest: rm.RestClient = new rm.RestClient('ke-client', config.baseurl) + const resp: rm.IRestResponse = await rest.del(path, requestOpts(config.token)) + if (force && resp.statusCode === 404) { + return false + } + + if (resp.statusCode !== 204) { + throw new Error(`StatusCode: ${resp.statusCode}`) + } + + return true +} diff --git a/src/commands/mkdir.ts b/src/commands/mkdir.ts index 2dd300f..16057f0 100644 --- a/src/commands/mkdir.ts +++ b/src/commands/mkdir.ts @@ -1,11 +1,17 @@ import {Args, Command, Flags} from '@oclif/core' -import path from 'path' +import path from 'node:path' -import {common as common_flags} from '../flags.js' +import * as KeClient from '../client.js' +import {checkCwd, checkInsecure} from '../common.js' import Config from '../config.js' -import KeClient from '../client.js' -import {check_cwd, check_insecure} from '../common.js' import {DIRECTORY_TYPE} from '../const.js' +import {common as commonFlags} from '../flags.js' + + +type MkdirOptions = { + parent?: boolean + verbose?: boolean +} export default class Mkdir extends Command { @@ -15,7 +21,6 @@ export default class Mkdir extends Command { required: true, }), } - static strict = false static override description = 'Create the directories, if they do not already exist.' @@ -24,44 +29,53 @@ export default class Mkdir extends Command { ] static override flags = { - ...common_flags, + ...commonFlags, // flag with a value (-c, --cwd=VALUE) cwd: Flags.string({char: 'c', description: 'set current working directory to VALUE'}), parent: Flags.boolean({char: 'p', description: 'no error if existing, make parent directories as needed'}), verbose: Flags.boolean({char: 'v', description: 'print a message for each created directory'}), } + static strict = false + public async run(): Promise { const {argv, flags} = await this.parse(Mkdir) const config = new Config(flags) - check_insecure(flags.insecure) - let cwd = await check_cwd(config, flags.cwd) - for (let i = 0; i < argv.length; i++) { - const {dir, base} = path.parse(path.resolve(cwd, argv[i] as string)) - await this.make_directory(config, dir, base, flags.parent, flags.verbose) - } + checkInsecure(flags.insecure) + const cwd = await checkCwd(config, flags.cwd) + await Promise.all( + argv.map((arg) => { + const {base, dir} = path.parse(path.resolve(cwd, arg as string)) + return this.makeDir(config, dir, base, flags) + }) + ) } - private async make_directory(config: Config, parent_dir: string, name: string, parent: boolean = false, verbose: boolean = false) { - // parent_dir の存在チェック - let result = await KeClient.get(config, parent_dir) - if (result == null) { - if (!parent) { - throw new Error(`cannot create directory: parent directory '${parent_dir}' is not found`) + + private async makeDir(config: Config, parentDir: string, name: string, options: MkdirOptions) { + // parentDir の存在チェック + let result = await KeClient.get(config, parentDir) + if (result === null) { + if (!options.parent) { + throw new Error(`cannot create directory: parent directory '${parentDir}' is not found`) } - const {dir, base} = path.parse(parent_dir) - result = await this.make_directory(config, dir, base, parent, verbose) + + const {base, dir} = path.parse(parentDir) + result = await this.makeDir(config, dir, base, options) } - if (result!.type_object != DIRECTORY_TYPE) { - throw new Error(`cannot create directory: parent directory '${parent_dir}' is not directory`) + + if (result!.type_object !== DIRECTORY_TYPE) { + throw new Error(`cannot create directory: parent directory '${parentDir}' is not directory`) } - let data = { + + const data = { + name, 'type_object': DIRECTORY_TYPE, - 'name': name } - result = await KeClient.create(config, parent_dir, data) - if (result && verbose) { + result = await KeClient.create(config, parentDir, data) + if (result && options.verbose) { this.log(`created directory: ${result.abspath}`) } + return result } } diff --git a/src/commands/put.ts b/src/commands/put.ts index 1560349..de34288 100644 --- a/src/commands/put.ts +++ b/src/commands/put.ts @@ -1,36 +1,34 @@ import {Args, Command, Flags} from '@oclif/core' -import fs from 'fs/promises' -import path from 'path' -import mime from 'mime-types' -import assert from 'assert' +import {lookup as mimeLookup} from 'mime-types' +import assert from 'node:assert' +import fs from 'node:fs/promises' +import path from 'node:path' -import {common as common_flags} from '../flags.js' +import * as KeClient from '../client.js' +import {checkCwd, checkInsecure} from '../common.js' import Config from '../config.js' -import KeClient from '../client.js' -import {check_cwd, check_insecure} from '../common.js' import {DIRECTORY_TYPE, TEXT_TYPE} from '../const.js' +import {common as commonFlags} from '../flags.js' type PutOptions = { - recursive?: boolean overwrite?: boolean + recursive?: boolean verbose?: boolean } type SourceDesc = { - type: 'dir' | 'file' - path: string - name: string ext: string + name: string + path: string + type: 'dir' | 'file' } -type Resp = KeClient.ObjectResponse export default class Put extends Command { static override args = { source: Args.string({description: 'source file or directory', required: true}), } - static strict = false static override description = 'put files or directories to Kompira server' @@ -39,91 +37,98 @@ export default class Put extends Command { ] static override flags = { - ...common_flags, - dest: Flags.string({char: 'd', description: 'specify destination object or directory (create if none exists)'}), + ...commonFlags, // flag with a value (-c, --cwd=VALUE) cwd: Flags.string({char: 'c', description: 'set current working directory to VALUE'}), - recursive: Flags.boolean({char: 'r', description: 'put directories recursively'}), + dest: Flags.string({char: 'd', description: 'specify destination object or directory (create if none exists)'}), overwrite: Flags.boolean({char: 'o', description: 'overwrite an existing object'}), + recursive: Flags.boolean({char: 'r', description: 'put directories recursively'}), verbose: Flags.boolean({char: 'v', description: 'explain what is being down'}), } + static strict = false + public async run(): Promise { const {argv, flags} = await this.parse(Put) const config = new Config(flags) - check_insecure(flags.insecure) - let cwd = await check_cwd(config, flags.cwd) + checkInsecure(flags.insecure) + const cwd = await checkCwd(config, flags.cwd) let dest = path.normalize(path.join(cwd, flags.dest || '')) - let sources = await this.check_sources(argv as string[], path.resolve('.')) - let target: KeClient.ObjectResponse | string | null = await KeClient.get(config, dest) + const sources = await this.checkSources(argv as string[], path.resolve('.')) + let target: KeClient.ObjectResponse | null | string = await KeClient.get(config, dest) - if (argv.length == 1) { - let source = sources[0] + if (argv.length === 1) { + const source = sources[0] if (!target) { - ({dir: dest, base: target} = path.parse(dest)) - } else if (target.type_object == DIRECTORY_TYPE) { + ({base: target, dir: dest} = path.parse(dest)) + } else if (target.type_object === DIRECTORY_TYPE) { target = await KeClient.get(config, path.join(target.abspath, source.name)) || source.name } else { dest = path.dirname(dest) } - await this.do_put(config, dest, source, target, flags) + + await this.putObject(config, dest, source, target, flags) } else { - if (target == null) { + if (target === null) { // target が存在しない場合はコピーできない - throw Error(`target '${dest}' is not found`) - } else if (target!.type_object != DIRECTORY_TYPE) { + throw new Error(`target '${dest}' is not found`) + } else if (target!.type_object !== DIRECTORY_TYPE) { // コピー先がディレクトリ以外の場合はコピーできない - throw Error(`target '${dest}' is not a directory`) + throw new Error(`target '${dest}' is not a directory`) } + // dest 配下にsources をコピー - for (const source of sources) { - await this.do_put(config, dest, source, source.name, flags) - } + await Promise.all( + sources.map((src) => this.putObject(config, dest, src, src.name, flags)) + ) } } - private async check_sources(sources: string[], cwd: string): Promise { - let source_descs: SourceDesc[] = [] - for (let source of sources) { - source = path.normalize(path.join(cwd, source)) - try { - const stat = await fs.stat(source) - const {name, ext} = path.parse(source) - if (stat.isDirectory()) { - source_descs.push({type: 'dir', path: source, name: name, ext: ext}) - } else if (stat.isFile()) { - source_descs.push({type: 'file', path: source, name: name, ext: ext}) - } else { - this.log(`put: invalid source '${source} type: should be file or directory`) - } - } catch (err) { - if (err instanceof Error) { - this.log(`put: cannot stat '${source}': ${err.message}`) - } else { - this.log(`put: cannot stat '${source}': Unknown error`) + private async checkSources(sources: string[], cwd: string): Promise { + const srcDescs: SourceDesc[] = [] + await Promise.all( + sources.map(async (src) => { + const source = path.normalize(path.join(cwd, src)) + try { + const stat = await fs.stat(source) + const {ext, name} = path.parse(source) + if (stat.isDirectory()) { + srcDescs.push({ext, name, path: source, type: 'dir'}) + } else if (stat.isFile()) { + srcDescs.push({ext, name, path: source, type: 'file'}) + } else { + this.log(`put: invalid source '${source} type: should be file or directory`) + } + } catch (error) { + if (error instanceof Error) { + this.log(`put: cannot stat '${source}': ${error.message}`) + } else { + this.log(`put: cannot stat '${source}': Unknown error`) + } } - } - } - return source_descs + }) + ) + + return srcDescs } - private async do_put(config: Config, dest: string, source: SourceDesc, target: KeClient.ObjectResponse | string, options: PutOptions) { - let dest_dir = null + private async putObject(config: Config, dest: string, source: SourceDesc, target: KeClient.ObjectResponse | string, options: PutOptions) { + let destDir = null if (target instanceof Object) { - if (target.type_object == DIRECTORY_TYPE && source.type == 'dir') { - dest_dir = target.abspath - } else if (target.type_object == TEXT_TYPE && source.type == 'file') { + if (target.type_object === DIRECTORY_TYPE && source.type === 'dir') { + destDir = target.abspath + } else if (target.type_object === TEXT_TYPE && source.type === 'file') { if (options.overwrite) { - let text = await fs.readFile(source.path, { encoding: 'utf8' }) - let data = { + const text = await fs.readFile(source.path, { encoding: 'utf8' }) + const data = { 'fields': { - 'text': text, + 'contentType': mimeLookup(source.path), 'ext': source.ext.replace(/^\.+/, ''), - 'contentType': mime.lookup(source.path) + text, } } - let result = await KeClient.update(config, target.abspath, data) + const result = await KeClient.update(config, target.abspath, data) if (options.verbose) { this.log(`updated text: ${result.abspath}`) } @@ -132,28 +137,29 @@ export default class Put extends Command { this.log(`put: cannot overwrite ${target.abspath}: type '${target.type_object}' mismatch`) return } - } else if (source.type == 'dir') { - let data = { - 'type_object': DIRECTORY_TYPE, + } else if (source.type === 'dir') { + const data = { 'name': target as string, + 'type_object': DIRECTORY_TYPE, } - let result = await KeClient.create(config, dest, data) + const result = await KeClient.create(config, dest, data) if (options.verbose) { this.log(`created directory: ${result.abspath}`) } - dest_dir = result.abspath - } else if (source.type == 'file') { - let text = await fs.readFile(source.path, { encoding: 'utf8' }) - let data = { - 'type_object': TEXT_TYPE, - 'name': target as string, + + destDir = result.abspath + } else if (source.type === 'file') { + const text = await fs.readFile(source.path, { encoding: 'utf8' }) + const data = { 'fields': { - 'text': text, + 'contentType': mimeLookup(source.path), 'ext': source.ext.replace(/^\.+/, ''), - 'contentType': mime.lookup(source.path) - } + text, + }, + 'name': target as string, + 'type_object': TEXT_TYPE, } - let result = await KeClient.create(config, dest, data) + const result = await KeClient.create(config, dest, data) if (options.verbose) { this.log(`created text: ${result.abspath}`) } @@ -161,14 +167,17 @@ export default class Put extends Command { assert(false, `invalid source.type: ${source.type}`) } - if (options.recursive && dest_dir) { + if (options.recursive && destDir) { // ファイル一覧を取得 - let dirs = await fs.readdir(source.path) - let sources = await this.check_sources(dirs, source.path) - for (const source of sources) { - target = await KeClient.get(config, path.join(dest_dir, source.name)) || source.name - await this.do_put(config, dest_dir, source, target, options) - } + const dirs = await fs.readdir(source.path) + const sources = await this.checkSources(dirs, source.path) + + await Promise.all( + sources.map(async (src) => { + target = await KeClient.get(config, path.join(destDir, src.name)) || src.name + await this.putObject(config, destDir, src, target, options) + }) + ) } } } diff --git a/src/commands/rm.ts b/src/commands/rm.ts index bf5d760..091de38 100644 --- a/src/commands/rm.ts +++ b/src/commands/rm.ts @@ -1,11 +1,18 @@ import {Args, Command, Flags} from '@oclif/core' -import path from 'path' +import path from 'node:path' -import {common as common_flags} from '../flags.js' +import * as KeClient from '../client.js' +import {checkCwd, checkInsecure} from '../common.js' import Config from '../config.js' -import KeClient from '../client.js' -import {check_cwd, check_insecure} from '../common.js' import {DIRECTORY_TYPE} from '../const.js' +import {common as commonFlags} from '../flags.js' + + +type RmOptions = { + force?: boolean + recursive?: boolean + verbose?: boolean +} export default class Rm extends Command { @@ -15,7 +22,6 @@ export default class Rm extends Command { required: true, }), } - static strict = false static override description = 'Remove the directories, if they are empty.' @@ -24,7 +30,7 @@ export default class Rm extends Command { ] static override flags = { - ...common_flags, + ...commonFlags, // flag with a value (-c, --cwd=VALUE) cwd: Flags.string({char: 'c', description: 'set current working directory to VALUE'}), force: Flags.boolean({char: 'f', description: 'ignore nonexistent objects and arguments'}), @@ -32,29 +38,32 @@ export default class Rm extends Command { verbose: Flags.boolean({char: 'v', description: 'print a message for each removed directory'}), } + static strict = false + public async run(): Promise { const {argv, flags} = await this.parse(Rm) const config = new Config(flags) - check_insecure(flags.insecure) - let cwd = await check_cwd(config, flags.cwd) - for (let i = 0; i < argv.length; i++) { - const target = path.resolve(cwd, argv[i] as string) - await this.remove_object(config, target, flags.force, flags.recursive, flags.verbose) - } + checkInsecure(flags.insecure) + const cwd = await checkCwd(config, flags.cwd) + await Promise.all( + argv.map((arg) => this.removeObject(config, path.resolve(cwd, arg as string), flags)) + ) } - private async remove_object(config: Config, target: string, force: boolean = false, recursive: boolean = false, verbose: boolean = false) { - if (!force) { - let result = await KeClient.get(config, target) - if (result == null) { + private async removeObject(config: Config, target: string, options: RmOptions) { + if (!options.force) { + const result = await KeClient.get(config, target) + if (result === null) { throw new Error(`failed to remove: '${target}' is not found`) } - if (result.type_object == DIRECTORY_TYPE) { + + if (result.type_object === DIRECTORY_TYPE) { throw new Error(`failed to remove: '${target}' is a directory`) } } - let removed = await KeClient.del(config, target, force) - if (verbose && removed) { + + const removed = await KeClient.del(config, target, options.force) + if (options.verbose && removed) { this.log(`removed: ${target}`) } } diff --git a/src/commands/rmdir.ts b/src/commands/rmdir.ts index 57726ee..e329613 100644 --- a/src/commands/rmdir.ts +++ b/src/commands/rmdir.ts @@ -1,11 +1,17 @@ import {Args, Command, Flags} from '@oclif/core' -import path from 'path' +import path from 'node:path' -import {common as common_flags} from '../flags.js' +import * as KeClient from '../client.js' +import {checkCwd, checkInsecure} from '../common.js' import Config from '../config.js' -import KeClient from '../client.js' -import {check_cwd, check_insecure} from '../common.js' import {DIRECTORY_TYPE} from '../const.js' +import {common as commonFlags} from '../flags.js' + + +type RmdirOptions = { + parent?: boolean + verbose?: boolean +} export default class Rmdir extends Command { @@ -15,7 +21,6 @@ export default class Rmdir extends Command { required: true, }), } - static strict = false static override description = 'Remove the directories, if they are empty.' @@ -24,47 +29,56 @@ export default class Rmdir extends Command { ] static override flags = { - ...common_flags, + ...commonFlags, // flag with a value (-c, --cwd=VALUE) cwd: Flags.string({char: 'c', description: 'set current working directory to VALUE'}), parent: Flags.boolean({char: 'p', description: 'remove DIRECTORY and its ancestors'}), verbose: Flags.boolean({char: 'v', description: 'print a message for each removed directory'}), } + static strict = false + public async run(): Promise { const {argv, flags} = await this.parse(Rmdir) const config = new Config(flags) - check_insecure(flags.insecure) - let cwd = await check_cwd(config, flags.cwd) - for (let i = 0; i < argv.length; i++) { - await this.remove_directory(config, cwd, argv[i] as string, flags.parent, flags.verbose) - } + checkInsecure(flags.insecure) + const cwd = await checkCwd(config, flags.cwd) + + await Promise.all( + argv.map((arg) => this.removeDirectory(config, cwd, arg as string, flags)) + ) } - private async remove_directory(config: Config, cwd: string, target: string, parent: boolean = false, verbose: boolean = false) { - const target_dir = path.resolve(cwd, target) - let result = await KeClient.get(config, target_dir) - if (result == null) { - throw new Error(`failed to remove directory: '${target_dir}' is not found`) + private async removeDirectory(config: Config, cwd: string, target: string, options: RmdirOptions) { + const targetDir = path.resolve(cwd, target) + const result = await KeClient.get(config, targetDir) + + if (result === null) { + throw new Error(`failed to remove directory: '${targetDir}' is not found`) } - if (result.type_object != DIRECTORY_TYPE) { - throw new Error(`failed to remove directory: '${target_dir}' is not a directory`) + + if (result.type_object !== DIRECTORY_TYPE) { + throw new Error(`failed to remove directory: '${targetDir}' is not a directory`) } + // ディレクトリが空かどうかチェックする - let results = await KeClient.get_all(config, `${target_dir}.children`) + const results = await KeClient.getAll(config, `${targetDir}.children`) if (results!.count > 0) { - throw new Error(`failed to remove directory: '${target_dir}' is not empty`) + throw new Error(`failed to remove directory: '${targetDir}' is not empty`) } - await KeClient.del(config, target_dir) - if (verbose) { - this.log(`removed directory: ${target_dir}`) + + await KeClient.del(config, targetDir) + if (options.verbose) { + this.log(`removed directory: ${targetDir}`) } - if (parent) { - const {dir, base} = path.parse(target_dir) - if (dir != cwd) { - await this.remove_directory(config, cwd, dir, parent, verbose) + + if (options.parent) { + const {dir} = path.parse(targetDir) + if (dir !== cwd) { + await this.removeDirectory(config, cwd, dir, options) } } + return result } } diff --git a/src/common.ts b/src/common.ts index e12687c..12cb811 100644 --- a/src/common.ts +++ b/src/common.ts @@ -1,31 +1,35 @@ -import path from 'path' +import path from 'node:path' + +import * as KeClient from './client.js' import Config from './config.js' -import KeClient from './client.js' import {DIRECTORY_TYPE} from './const.js' -export async function check_cwd(config: Config, cwd?: string): Promise { - if (cwd) { - // cwd のパラメータチェック - if (!path.isAbsolute(cwd)) { - throw new Error(`cwd should be absolute path: ${cwd}`) - } - let result = await KeClient.get(config, cwd) - if (result == null) { - throw new Error(`cwd '${cwd}' does not exist`) - } - if (result!.type_object != DIRECTORY_TYPE) { - throw new Error(`cwd '${cwd}' is not directory`) - } - return path.normalize(cwd) - } else { - return '/' +export async function checkCwd(config: Config, cwd?: string): Promise { + if (cwd) { + // cwd のパラメータチェック + if (!path.isAbsolute(cwd)) { + throw new Error(`cwd should be absolute path: ${cwd}`) + } + + const result = await KeClient.get(config, cwd) + if (result === null) { + throw new Error(`cwd '${cwd}' does not exist`) + } + + if (result!.type_object !== DIRECTORY_TYPE) { + throw new Error(`cwd '${cwd}' is not directory`) } + + return path.normalize(cwd) + } + + return '/' } -export function check_insecure(insecure?: boolean): void { +export function checkInsecure(insecure?: boolean): void { if (insecure) { - process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0' + process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' } } diff --git a/src/config.ts b/src/config.ts index 77a5d19..cd5da7c 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,15 +1,21 @@ -import { createRequire } from 'module' +import { createRequire } from 'node:module' const require = createRequire(import.meta.url) +type ConfigOptions = { + baseurl?: string + token?: string +} + + export default class Config { baseurl?: string token?: string - constructor(flags: any) { + constructor(flags: ConfigOptions) { const config = require('config') this.baseurl = flags.baseurl || config.get('baseurl') - this.token = flags.username || config.get('token') + this.token = flags.token || config.get('token') } } diff --git a/src/flags.ts b/src/flags.ts index b9ad3ee..0128cfb 100644 --- a/src/flags.ts +++ b/src/flags.ts @@ -1,8 +1,8 @@ -import {Args, Command, Flags} from '@oclif/core' +import {Flags} from '@oclif/core' export const common = { baseurl: Flags.string({char: 'u', description: 'base URL of the Kompira Enterprise server'}), - token: Flags.string({char: 't', description: 'API access token of the Kompira Enterprise server'}), insecure: Flags.boolean({char: 'k', description: 'allow insecure SSL connection'}), + token: Flags.string({char: 't', description: 'API access token of the Kompira Enterprise server'}), } From 316100308a60d8cbab058dee0ab9519bed34baa1 Mon Sep 17 00:00:00 2001 From: Kenta HATTORI Date: Sat, 26 Oct 2024 19:56:51 +0900 Subject: [PATCH 06/11] Update test cases --- test/commands/mkdir.test.ts | 25 +++++++++++++++++++------ test/commands/put.test.ts | 20 ++++++++++++++------ test/commands/rm.test.ts | 20 ++++++++++++++------ test/commands/rmdir.test.ts | 20 ++++++++++++++------ 4 files changed, 61 insertions(+), 24 deletions(-) diff --git a/test/commands/mkdir.test.ts b/test/commands/mkdir.test.ts index be3ea60..6fd9215 100644 --- a/test/commands/mkdir.test.ts +++ b/test/commands/mkdir.test.ts @@ -2,13 +2,26 @@ import {runCommand} from '@oclif/test' import {expect} from 'chai' describe('mkdir', () => { - it('runs mkdir cmd', async () => { - const {stdout} = await runCommand('mkdir') - expect(stdout).to.contain('hello world') + before(async () => { + await runCommand('rm testdir --cwd /root -rfk') + await runCommand('mkdir testdir --cwd /root -k') + }) + after(async () => { + await runCommand('rm testdir --cwd /root -rfk') + }) + + it('runs mkdir', async () => { + const {error} = await runCommand('mkdir') + expect(error?.oclif?.exit).to.equal(2) + }) + + it('runs mkdir --help', async () => { + const {stdout} = await runCommand('mkdir --help') + expect(stdout).to.contain('USAGE') }) - it('runs mkdir --name oclif', async () => { - const {stdout} = await runCommand('mkdir --name oclif') - expect(stdout).to.contain('hello oclif') + it('runs mkdir somedir --cwd /root/testdir -kv', async() => { + const {stdout} = await runCommand('mkdir somedir --cwd /root/testdir -kv') + expect(stdout).to.contain('created directory: /root/testdir/somedir') }) }) diff --git a/test/commands/put.test.ts b/test/commands/put.test.ts index 665851d..7d382ac 100644 --- a/test/commands/put.test.ts +++ b/test/commands/put.test.ts @@ -2,13 +2,21 @@ import {runCommand} from '@oclif/test' import {expect} from 'chai' describe('put', () => { - it('runs put cmd', async () => { - const {stdout} = await runCommand('put') - expect(stdout).to.contain('hello world') + before(async () => { + await runCommand('rm testdir --cwd /root -rfk') + await runCommand('mkdir testdir --cwd /root -k') + }) + after(async () => { + await runCommand('rm testdir --cwd /root -rfk') + }) + + it('runs put', async () => { + const {error} = await runCommand('put') + expect(error?.oclif?.exit).to.equal(2) }) - it('runs put --name oclif', async () => { - const {stdout} = await runCommand('put --name oclif') - expect(stdout).to.contain('hello oclif') + it('runs put --help', async () => { + const {stdout} = await runCommand('put --help') + expect(stdout).to.contain('USAGE') }) }) diff --git a/test/commands/rm.test.ts b/test/commands/rm.test.ts index 087458f..22184f9 100644 --- a/test/commands/rm.test.ts +++ b/test/commands/rm.test.ts @@ -2,13 +2,21 @@ import {runCommand} from '@oclif/test' import {expect} from 'chai' describe('rm', () => { - it('runs rm cmd', async () => { - const {stdout} = await runCommand('rm') - expect(stdout).to.contain('hello world') + before(async () => { + await runCommand('rm testdir --cwd /root -rfk') + await runCommand('mkdir testdir --cwd /root -k') + }) + after(async () => { + await runCommand('rm testdir --cwd /root -rfk') + }) + + it('runs rm', async () => { + const {error} = await runCommand('rm') + expect(error?.oclif?.exit).to.equal(2) }) - it('runs rm --name oclif', async () => { - const {stdout} = await runCommand('rm --name oclif') - expect(stdout).to.contain('hello oclif') + it('runs rm --help oclif', async () => { + const {stdout} = await runCommand('rm --help') + expect(stdout).to.contain('USAGE') }) }) diff --git a/test/commands/rmdir.test.ts b/test/commands/rmdir.test.ts index 6a804b8..5ad2e44 100644 --- a/test/commands/rmdir.test.ts +++ b/test/commands/rmdir.test.ts @@ -2,13 +2,21 @@ import {runCommand} from '@oclif/test' import {expect} from 'chai' describe('rmdir', () => { - it('runs rmdir cmd', async () => { - const {stdout} = await runCommand('rmdir') - expect(stdout).to.contain('hello world') + before(async () => { + await runCommand('rm testdir --cwd /root -rfk') + await runCommand('mkdir testdir --cwd /root -k') + }) + after(async () => { + await runCommand('rm testdir --cwd /root -rfk') + }) + + it('runs rmdir', async () => { + const {error} = await runCommand('rmdir') + expect(error?.oclif?.exit).to.equal(2) }) - it('runs rmdir --name oclif', async () => { - const {stdout} = await runCommand('rmdir --name oclif') - expect(stdout).to.contain('hello oclif') + it('runs rmdir --help', async () => { + const {stdout} = await runCommand('rmdir --help') + expect(stdout).to.contain('USAGE') }) }) From 3ed9b0c5b342a639d0ecbf3a55aaa581a6c9261e Mon Sep 17 00:00:00 2001 From: Kenta HATTORI Date: Sat, 26 Oct 2024 20:14:10 +0900 Subject: [PATCH 07/11] Add conf field to command class --- src/commands/mkdir.ts | 16 +++++++++------- src/commands/put.ts | 27 ++++++++++++++------------- src/commands/rm.ts | 14 ++++++++------ src/commands/rmdir.ts | 18 ++++++++++-------- 4 files changed, 41 insertions(+), 34 deletions(-) diff --git a/src/commands/mkdir.ts b/src/commands/mkdir.ts index 16057f0..fbead7d 100644 --- a/src/commands/mkdir.ts +++ b/src/commands/mkdir.ts @@ -38,29 +38,31 @@ export default class Mkdir extends Command { static strict = false + private conf!: Config + public async run(): Promise { const {argv, flags} = await this.parse(Mkdir) - const config = new Config(flags) + this.conf = new Config(flags) checkInsecure(flags.insecure) - const cwd = await checkCwd(config, flags.cwd) + const cwd = await checkCwd(this.conf, flags.cwd) await Promise.all( argv.map((arg) => { const {base, dir} = path.parse(path.resolve(cwd, arg as string)) - return this.makeDir(config, dir, base, flags) + return this.makeDir(dir, base, flags) }) ) } - private async makeDir(config: Config, parentDir: string, name: string, options: MkdirOptions) { + private async makeDir(parentDir: string, name: string, options: MkdirOptions) { // parentDir の存在チェック - let result = await KeClient.get(config, parentDir) + let result = await KeClient.get(this.conf, parentDir) if (result === null) { if (!options.parent) { throw new Error(`cannot create directory: parent directory '${parentDir}' is not found`) } const {base, dir} = path.parse(parentDir) - result = await this.makeDir(config, dir, base, options) + result = await this.makeDir(dir, base, options) } if (result!.type_object !== DIRECTORY_TYPE) { @@ -71,7 +73,7 @@ export default class Mkdir extends Command { name, 'type_object': DIRECTORY_TYPE, } - result = await KeClient.create(config, parentDir, data) + result = await KeClient.create(this.conf, parentDir, data) if (result && options.verbose) { this.log(`created directory: ${result.abspath}`) } diff --git a/src/commands/put.ts b/src/commands/put.ts index de34288..ad555f7 100644 --- a/src/commands/put.ts +++ b/src/commands/put.ts @@ -48,27 +48,28 @@ export default class Put extends Command { static strict = false + private conf!: Config + public async run(): Promise { const {argv, flags} = await this.parse(Put) - const config = new Config(flags) - + this.conf = new Config(flags) checkInsecure(flags.insecure) - const cwd = await checkCwd(config, flags.cwd) + const cwd = await checkCwd(this.conf, flags.cwd) let dest = path.normalize(path.join(cwd, flags.dest || '')) const sources = await this.checkSources(argv as string[], path.resolve('.')) - let target: KeClient.ObjectResponse | null | string = await KeClient.get(config, dest) + let target: KeClient.ObjectResponse | null | string = await KeClient.get(this.conf, dest) if (argv.length === 1) { const source = sources[0] if (!target) { ({base: target, dir: dest} = path.parse(dest)) } else if (target.type_object === DIRECTORY_TYPE) { - target = await KeClient.get(config, path.join(target.abspath, source.name)) || source.name + target = await KeClient.get(this.conf, path.join(target.abspath, source.name)) || source.name } else { dest = path.dirname(dest) } - await this.putObject(config, dest, source, target, flags) + await this.putObject(dest, source, target, flags) } else { if (target === null) { // target が存在しない場合はコピーできない @@ -80,7 +81,7 @@ export default class Put extends Command { // dest 配下にsources をコピー await Promise.all( - sources.map((src) => this.putObject(config, dest, src, src.name, flags)) + sources.map((src) => this.putObject(dest, src, src.name, flags)) ) } } @@ -113,7 +114,7 @@ export default class Put extends Command { return srcDescs } - private async putObject(config: Config, dest: string, source: SourceDesc, target: KeClient.ObjectResponse | string, options: PutOptions) { + private async putObject(dest: string, source: SourceDesc, target: KeClient.ObjectResponse | string, options: PutOptions) { let destDir = null if (target instanceof Object) { if (target.type_object === DIRECTORY_TYPE && source.type === 'dir') { @@ -128,7 +129,7 @@ export default class Put extends Command { text, } } - const result = await KeClient.update(config, target.abspath, data) + const result = await KeClient.update(this.conf, target.abspath, data) if (options.verbose) { this.log(`updated text: ${result.abspath}`) } @@ -142,7 +143,7 @@ export default class Put extends Command { 'name': target as string, 'type_object': DIRECTORY_TYPE, } - const result = await KeClient.create(config, dest, data) + const result = await KeClient.create(this.conf, dest, data) if (options.verbose) { this.log(`created directory: ${result.abspath}`) } @@ -159,7 +160,7 @@ export default class Put extends Command { 'name': target as string, 'type_object': TEXT_TYPE, } - const result = await KeClient.create(config, dest, data) + const result = await KeClient.create(this.conf, dest, data) if (options.verbose) { this.log(`created text: ${result.abspath}`) } @@ -174,8 +175,8 @@ export default class Put extends Command { await Promise.all( sources.map(async (src) => { - target = await KeClient.get(config, path.join(destDir, src.name)) || src.name - await this.putObject(config, destDir, src, target, options) + target = await KeClient.get(this.conf, path.join(destDir, src.name)) || src.name + await this.putObject(destDir, src, target, options) }) ) } diff --git a/src/commands/rm.ts b/src/commands/rm.ts index 091de38..cb14809 100644 --- a/src/commands/rm.ts +++ b/src/commands/rm.ts @@ -40,19 +40,21 @@ export default class Rm extends Command { static strict = false + private conf!: Config + public async run(): Promise { const {argv, flags} = await this.parse(Rm) - const config = new Config(flags) + this.conf = new Config(flags) checkInsecure(flags.insecure) - const cwd = await checkCwd(config, flags.cwd) + const cwd = await checkCwd(this.conf, flags.cwd) await Promise.all( - argv.map((arg) => this.removeObject(config, path.resolve(cwd, arg as string), flags)) + argv.map((arg) => this.removeObject(path.resolve(cwd, arg as string), flags)) ) } - private async removeObject(config: Config, target: string, options: RmOptions) { + private async removeObject(target: string, options: RmOptions) { if (!options.force) { - const result = await KeClient.get(config, target) + const result = await KeClient.get(this.conf, target) if (result === null) { throw new Error(`failed to remove: '${target}' is not found`) } @@ -62,7 +64,7 @@ export default class Rm extends Command { } } - const removed = await KeClient.del(config, target, options.force) + const removed = await KeClient.del(this.conf, target, options.force) if (options.verbose && removed) { this.log(`removed: ${target}`) } diff --git a/src/commands/rmdir.ts b/src/commands/rmdir.ts index e329613..8e09279 100644 --- a/src/commands/rmdir.ts +++ b/src/commands/rmdir.ts @@ -38,20 +38,22 @@ export default class Rmdir extends Command { static strict = false + private conf!: Config + public async run(): Promise { const {argv, flags} = await this.parse(Rmdir) - const config = new Config(flags) + this.conf = new Config(flags) checkInsecure(flags.insecure) - const cwd = await checkCwd(config, flags.cwd) + const cwd = await checkCwd(this.conf, flags.cwd) await Promise.all( - argv.map((arg) => this.removeDirectory(config, cwd, arg as string, flags)) + argv.map((arg) => this.removeDirectory(cwd, arg as string, flags)) ) } - private async removeDirectory(config: Config, cwd: string, target: string, options: RmdirOptions) { + private async removeDirectory(cwd: string, target: string, options: RmdirOptions) { const targetDir = path.resolve(cwd, target) - const result = await KeClient.get(config, targetDir) + const result = await KeClient.get(this.conf, targetDir) if (result === null) { throw new Error(`failed to remove directory: '${targetDir}' is not found`) @@ -62,12 +64,12 @@ export default class Rmdir extends Command { } // ディレクトリが空かどうかチェックする - const results = await KeClient.getAll(config, `${targetDir}.children`) + const results = await KeClient.getAll(this.conf, `${targetDir}.children`) if (results!.count > 0) { throw new Error(`failed to remove directory: '${targetDir}' is not empty`) } - await KeClient.del(config, targetDir) + await KeClient.del(this.conf, targetDir) if (options.verbose) { this.log(`removed directory: ${targetDir}`) } @@ -75,7 +77,7 @@ export default class Rmdir extends Command { if (options.parent) { const {dir} = path.parse(targetDir) if (dir !== cwd) { - await this.removeDirectory(config, cwd, dir, options) + await this.removeDirectory(cwd, dir, options) } } From 3e85615f23de0a04f33c5f465920ecfc4c911671 Mon Sep 17 00:00:00 2001 From: Kenta HATTORI Date: Sat, 26 Oct 2024 22:11:23 +0900 Subject: [PATCH 08/11] Add test cases --- test/commands/put.test.ts | 5 +++++ test/commands/rm.test.ts | 6 ++++++ test/commands/rmdir.test.ts | 6 ++++++ test/data/test.txt | 1 + 4 files changed, 18 insertions(+) create mode 100644 test/data/test.txt diff --git a/test/commands/put.test.ts b/test/commands/put.test.ts index 7d382ac..cd9d647 100644 --- a/test/commands/put.test.ts +++ b/test/commands/put.test.ts @@ -19,4 +19,9 @@ describe('put', () => { const {stdout} = await runCommand('put --help') expect(stdout).to.contain('USAGE') }) + + it('runs put ./test/data/test.txt --cwd /root/testdir -kv', async () => { + const {stdout} = await runCommand('put ./test/data/test.txt --cwd /root/testdir -kv') + expect(stdout).to.contain('created text: /root/testdir/test') + }) }) diff --git a/test/commands/rm.test.ts b/test/commands/rm.test.ts index 22184f9..cff4574 100644 --- a/test/commands/rm.test.ts +++ b/test/commands/rm.test.ts @@ -5,6 +5,7 @@ describe('rm', () => { before(async () => { await runCommand('rm testdir --cwd /root -rfk') await runCommand('mkdir testdir --cwd /root -k') + await runCommand('put ./test/data/test.txt --cwd /root/testdir -k') }) after(async () => { await runCommand('rm testdir --cwd /root -rfk') @@ -19,4 +20,9 @@ describe('rm', () => { const {stdout} = await runCommand('rm --help') expect(stdout).to.contain('USAGE') }) + + it('runs rm test --cwd /root/testdir -kv', async () => { + const {stdout} = await runCommand('rm test --cwd /root/testdir -kv') + expect(stdout).to.contain('removed: /root/testdir/test') + }) }) diff --git a/test/commands/rmdir.test.ts b/test/commands/rmdir.test.ts index 5ad2e44..653fcd3 100644 --- a/test/commands/rmdir.test.ts +++ b/test/commands/rmdir.test.ts @@ -19,4 +19,10 @@ describe('rmdir', () => { const {stdout} = await runCommand('rmdir --help') expect(stdout).to.contain('USAGE') }) + + it('runs rmdir somedir --cwd /root/testdir -k', async () => { + await runCommand('mkdir somedir --cwd /root/testdir -kv') + const {stdout} = await runCommand('rmdir somedir --cwd /root/testdir -kv') + expect(stdout).to.contain('removed directory: /root/testdir/somedir') + }) }) diff --git a/test/data/test.txt b/test/data/test.txt new file mode 100644 index 0000000..a042389 --- /dev/null +++ b/test/data/test.txt @@ -0,0 +1 @@ +hello world! From ce41ab90e7e9d1fb92cabbd9cf8ba02b819bda14 Mon Sep 17 00:00:00 2001 From: Kenta HATTORI Date: Sat, 26 Oct 2024 22:16:17 +0900 Subject: [PATCH 09/11] Changed to continue processing on error --- src/commands/rm.ts | 6 ++++-- src/commands/rmdir.ts | 9 ++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/commands/rm.ts b/src/commands/rm.ts index cb14809..924bb28 100644 --- a/src/commands/rm.ts +++ b/src/commands/rm.ts @@ -56,11 +56,13 @@ export default class Rm extends Command { if (!options.force) { const result = await KeClient.get(this.conf, target) if (result === null) { - throw new Error(`failed to remove: '${target}' is not found`) + this.warn(`failed to remove: '${target}' is not found`) + return } if (result.type_object === DIRECTORY_TYPE) { - throw new Error(`failed to remove: '${target}' is a directory`) + this.warn(`failed to remove: '${target}' is a directory`) + return } } diff --git a/src/commands/rmdir.ts b/src/commands/rmdir.ts index 8e09279..7fc40ff 100644 --- a/src/commands/rmdir.ts +++ b/src/commands/rmdir.ts @@ -56,17 +56,20 @@ export default class Rmdir extends Command { const result = await KeClient.get(this.conf, targetDir) if (result === null) { - throw new Error(`failed to remove directory: '${targetDir}' is not found`) + this.warn(`failed to remove directory: '${targetDir}' is not found`) + return } if (result.type_object !== DIRECTORY_TYPE) { - throw new Error(`failed to remove directory: '${targetDir}' is not a directory`) + this.warn(`failed to remove directory: '${targetDir}' is not a directory`) + return } // ディレクトリが空かどうかチェックする const results = await KeClient.getAll(this.conf, `${targetDir}.children`) if (results!.count > 0) { - throw new Error(`failed to remove directory: '${targetDir}' is not empty`) + this.warn(`failed to remove directory: '${targetDir}' is not empty`) + return } await KeClient.del(this.conf, targetDir) From 14cb24f1bf7d13662ed519b912029aa6596739ff Mon Sep 17 00:00:00 2001 From: Kenta HATTORI Date: Sat, 26 Oct 2024 22:16:57 +0900 Subject: [PATCH 10/11] Fixed bug --- src/commands/put.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/commands/put.ts b/src/commands/put.ts index ad555f7..03cf434 100644 --- a/src/commands/put.ts +++ b/src/commands/put.ts @@ -57,6 +57,11 @@ export default class Put extends Command { const cwd = await checkCwd(this.conf, flags.cwd) let dest = path.normalize(path.join(cwd, flags.dest || '')) const sources = await this.checkSources(argv as string[], path.resolve('.')) + + if (sources.length === 0) { + return + } + let target: KeClient.ObjectResponse | null | string = await KeClient.get(this.conf, dest) if (argv.length === 1) { @@ -81,7 +86,10 @@ export default class Put extends Command { // dest 配下にsources をコピー await Promise.all( - sources.map((src) => this.putObject(dest, src, src.name, flags)) + sources.map(async (src) => { + const target = await KeClient.get(this.conf, path.join(dest, src.name)) || src.name + await this.putObject(dest, src, target, flags) + }) ) } } @@ -116,6 +124,7 @@ export default class Put extends Command { private async putObject(dest: string, source: SourceDesc, target: KeClient.ObjectResponse | string, options: PutOptions) { let destDir = null + if (target instanceof Object) { if (target.type_object === DIRECTORY_TYPE && source.type === 'dir') { destDir = target.abspath @@ -175,7 +184,7 @@ export default class Put extends Command { await Promise.all( sources.map(async (src) => { - target = await KeClient.get(this.conf, path.join(destDir, src.name)) || src.name + const target = await KeClient.get(this.conf, path.join(destDir, src.name)) || src.name await this.putObject(destDir, src, target, options) }) ) From c58d9d9747fe6e0ebf850dfe93663afe08ccc4cd Mon Sep 17 00:00:00 2001 From: Kenta HATTORI Date: Sat, 26 Oct 2024 22:43:12 +0900 Subject: [PATCH 11/11] Bump version up to 0.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 56cc85e..c3267de 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "ketool", "description": "Development tools for Kompira Enterprise", - "version": "0.0.0", + "version": "0.1.0", "author": "Kenta HATTORI", "bin": { "ketool": "./bin/run.js"