kiriya 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +58 -0
- package/LICENSE +21 -0
- package/README.md +87 -0
- package/dist/src/config/clean-rules.js +39 -0
- package/dist/src/config/config-keys.js +24 -0
- package/dist/src/config/dependency-directories.js +16 -0
- package/dist/src/config/modules.js +38 -0
- package/dist/src/config/protected-paths.js +32 -0
- package/dist/src/config/rebuildable-directories.js +20 -0
- package/dist/src/core/application/command-registry.js +57 -0
- package/dist/src/core/application/config-values.js +33 -0
- package/dist/src/core/application/path-guard.js +69 -0
- package/dist/src/core/application/paths.js +77 -0
- package/dist/src/core/application/plugin-loader.js +100 -0
- package/dist/src/core/application/process-ending.js +28 -0
- package/dist/src/core/application/root-scope.js +123 -0
- package/dist/src/core/application/safety.js +26 -0
- package/dist/src/core/application/text-input.js +44 -0
- package/dist/src/core/application/walk.js +34 -0
- package/dist/src/core/domain/command.js +8 -0
- package/dist/src/core/domain/encodings.js +70 -0
- package/dist/src/core/domain/errors.js +49 -0
- package/dist/src/core/domain/glob.js +57 -0
- package/dist/src/core/domain/global-options.js +10 -0
- package/dist/src/core/domain/input-schema.js +54 -0
- package/dist/src/core/domain/message.js +7 -0
- package/dist/src/core/domain/module.js +2 -0
- package/dist/src/core/domain/names.js +22 -0
- package/dist/src/core/domain/ports/clipboard.js +2 -0
- package/dist/src/core/domain/ports/clock.js +2 -0
- package/dist/src/core/domain/ports/command-catalog.js +2 -0
- package/dist/src/core/domain/ports/compression.js +2 -0
- package/dist/src/core/domain/ports/config-store.js +2 -0
- package/dist/src/core/domain/ports/confirmation.js +2 -0
- package/dist/src/core/domain/ports/environment.js +2 -0
- package/dist/src/core/domain/ports/file-content.js +2 -0
- package/dist/src/core/domain/ports/file-system.js +2 -0
- package/dist/src/core/domain/ports/hasher.js +2 -0
- package/dist/src/core/domain/ports/network.js +2 -0
- package/dist/src/core/domain/ports/opener.js +2 -0
- package/dist/src/core/domain/ports/passthrough.js +2 -0
- package/dist/src/core/domain/ports/plugin-inventory.js +2 -0
- package/dist/src/core/domain/ports/plugin-source.js +2 -0
- package/dist/src/core/domain/ports/port-table.js +2 -0
- package/dist/src/core/domain/ports/process-runner.js +2 -0
- package/dist/src/core/domain/ports/process-table.js +2 -0
- package/dist/src/core/domain/ports/protected-paths.js +2 -0
- package/dist/src/core/domain/ports/random-source.js +2 -0
- package/dist/src/core/domain/ports/standard-input.js +2 -0
- package/dist/src/core/domain/ports/system-info.js +2 -0
- package/dist/src/core/domain/ports/trash.js +2 -0
- package/dist/src/core/domain/secrets.js +59 -0
- package/dist/src/core/domain/targets.js +41 -0
- package/dist/src/core/domain/text-case.js +39 -0
- package/dist/src/core/domain/values/bytes.js +13 -0
- package/dist/src/core/domain/view.js +2 -0
- package/dist/src/core/infrastructure/node/can-listen.js +10 -0
- package/dist/src/core/infrastructure/node/closed-standard-input.adapter.js +12 -0
- package/dist/src/core/infrastructure/node/config-location.js +27 -0
- package/dist/src/core/infrastructure/node/fs-errors.js +22 -0
- package/dist/src/core/infrastructure/node/json-config-store.adapter.js +69 -0
- package/dist/src/core/infrastructure/node/node-compression.adapter.js +82 -0
- package/dist/src/core/infrastructure/node/node-environment.adapter.js +21 -0
- package/dist/src/core/infrastructure/node/node-file-content.adapter.js +99 -0
- package/dist/src/core/infrastructure/node/node-file-system.adapter.js +169 -0
- package/dist/src/core/infrastructure/node/node-hasher.adapter.js +32 -0
- package/dist/src/core/infrastructure/node/node-network.adapter.js +168 -0
- package/dist/src/core/infrastructure/node/node-plugin-source.adapter.js +89 -0
- package/dist/src/core/infrastructure/node/node-process-runner.adapter.js +48 -0
- package/dist/src/core/infrastructure/node/node-random-source.adapter.js +7 -0
- package/dist/src/core/infrastructure/node/node-standard-input.adapter.js +24 -0
- package/dist/src/core/infrastructure/node/node-system-info.adapter.js +63 -0
- package/dist/src/core/infrastructure/node/process-signals.js +51 -0
- package/dist/src/core/infrastructure/node/run-program.js +65 -0
- package/dist/src/core/infrastructure/node/system-clock.adapter.js +22 -0
- package/dist/src/core/infrastructure/node/typed-programs.js +45 -0
- package/dist/src/core/infrastructure/platform/linux/freedesktop-trash.adapter.js +115 -0
- package/dist/src/core/infrastructure/platform/linux/linux-clipboard.adapter.js +70 -0
- package/dist/src/core/infrastructure/platform/linux/linux-opener.adapter.js +21 -0
- package/dist/src/core/infrastructure/platform/linux/linux-port-table.adapter.js +97 -0
- package/dist/src/core/infrastructure/platform/linux/linux-process-table.adapter.js +61 -0
- package/dist/src/core/infrastructure/platform/macos/macos-clipboard.adapter.js +29 -0
- package/dist/src/core/infrastructure/platform/macos/macos-opener.adapter.js +13 -0
- package/dist/src/core/infrastructure/platform/macos/macos-port-table.adapter.js +86 -0
- package/dist/src/core/infrastructure/platform/macos/macos-process-table.adapter.js +62 -0
- package/dist/src/core/infrastructure/platform/macos/macos-trash.adapter.js +64 -0
- package/dist/src/core/infrastructure/platform/windows/system32.js +6 -0
- package/dist/src/core/infrastructure/platform/windows/windows-clipboard.adapter.js +50 -0
- package/dist/src/core/infrastructure/platform/windows/windows-opener.adapter.js +11 -0
- package/dist/src/core/infrastructure/platform/windows/windows-port-table.adapter.js +38 -0
- package/dist/src/core/infrastructure/platform/windows/windows-process-table.adapter.js +134 -0
- package/dist/src/core/infrastructure/platform/windows/windows-trash.adapter.js +86 -0
- package/dist/src/core/presentation/cli/argv.js +83 -0
- package/dist/src/core/presentation/cli/cli-application.js +201 -0
- package/dist/src/core/presentation/cli/cli-view-format.js +46 -0
- package/dist/src/core/presentation/cli/help.js +202 -0
- package/dist/src/core/presentation/cli/json-output.js +28 -0
- package/dist/src/core/presentation/cli/style.js +21 -0
- package/dist/src/core/presentation/cli/suggest.js +25 -0
- package/dist/src/core/presentation/cli/terminal-confirmation.js +63 -0
- package/dist/src/core/presentation/ended-processes.js +18 -0
- package/dist/src/core/presentation/i18n/translator.js +23 -0
- package/dist/src/core/presentation/list-preview.js +10 -0
- package/dist/src/core/presentation/mcp/elicitation.js +55 -0
- package/dist/src/core/presentation/mcp/mcp-application.js +60 -0
- package/dist/src/core/presentation/mcp/mcp-confirmation.js +59 -0
- package/dist/src/core/presentation/mcp/mcp-server.js +355 -0
- package/dist/src/core/presentation/mcp/protocol.js +32 -0
- package/dist/src/core/presentation/mcp/request-state.js +66 -0
- package/dist/src/core/presentation/mcp/tool-definitions.js +149 -0
- package/dist/src/core/presentation/mcp/tool-results.js +56 -0
- package/dist/src/i18n/locales/en.js +827 -0
- package/dist/src/main.js +154 -0
- package/dist/src/modules/archive/application/archive-sources.js +55 -0
- package/dist/src/modules/archive/application/create-tar.use-case.js +123 -0
- package/dist/src/modules/archive/application/create-zip.use-case.js +106 -0
- package/dist/src/modules/archive/application/extract-tar.use-case.js +240 -0
- package/dist/src/modules/archive/application/extract-zip.use-case.js +181 -0
- package/dist/src/modules/archive/application/tar-reader.js +45 -0
- package/dist/src/modules/archive/application/zip-reader.js +57 -0
- package/dist/src/modules/archive/archive.module.js +27 -0
- package/dist/src/modules/archive/domain/crc32.js +18 -0
- package/dist/src/modules/archive/domain/tar-format.js +97 -0
- package/dist/src/modules/archive/domain/tar-stream.js +223 -0
- package/dist/src/modules/archive/domain/zip-format.js +158 -0
- package/dist/src/modules/archive/presentation/tar.view.js +17 -0
- package/dist/src/modules/archive/presentation/untar.view.js +30 -0
- package/dist/src/modules/archive/presentation/unzip.view.js +24 -0
- package/dist/src/modules/archive/presentation/zip.view.js +17 -0
- package/dist/src/modules/clip/application/copy-text.use-case.js +43 -0
- package/dist/src/modules/clip/application/paste-text.use-case.js +25 -0
- package/dist/src/modules/clip/clip.module.js +16 -0
- package/dist/src/modules/clip/presentation/clip.views.js +7 -0
- package/dist/src/modules/completion/application/print-script.use-case.js +38 -0
- package/dist/src/modules/completion/application/suggest-words.use-case.js +37 -0
- package/dist/src/modules/completion/completion.module.js +14 -0
- package/dist/src/modules/completion/domain/scripts.js +91 -0
- package/dist/src/modules/completion/domain/suggest.js +134 -0
- package/dist/src/modules/completion/presentation/completion.views.js +6 -0
- package/dist/src/modules/config/application/config-commands.js +14 -0
- package/dist/src/modules/config/application/get-setting.use-case.js +25 -0
- package/dist/src/modules/config/application/list-config-keys.use-case.js +26 -0
- package/dist/src/modules/config/application/list-settings.use-case.js +28 -0
- package/dist/src/modules/config/application/set-setting.use-case.js +53 -0
- package/dist/src/modules/config/application/show-config-path.use-case.js +21 -0
- package/dist/src/modules/config/application/unset-setting.use-case.js +28 -0
- package/dist/src/modules/config/config.module.js +28 -0
- package/dist/src/modules/config/presentation/config.views.js +33 -0
- package/dist/src/modules/convert/application/convert-case.use-case.js +38 -0
- package/dist/src/modules/convert/application/convert-codecs.use-case.js +92 -0
- package/dist/src/modules/convert/application/convert-input.js +16 -0
- package/dist/src/modules/convert/application/convert-json.use-case.js +51 -0
- package/dist/src/modules/convert/application/convert-time.use-case.js +39 -0
- package/dist/src/modules/convert/application/decode-jwt.use-case.js +52 -0
- package/dist/src/modules/convert/convert.module.js +29 -0
- package/dist/src/modules/convert/domain/json-syntax.js +135 -0
- package/dist/src/modules/convert/domain/jwt.js +29 -0
- package/dist/src/modules/convert/domain/moments.js +20 -0
- package/dist/src/modules/convert/presentation/convert.views.js +44 -0
- package/dist/src/modules/docker/application/clean-engine.use-case.js +77 -0
- package/dist/src/modules/docker/application/compose-project.js +45 -0
- package/dist/src/modules/docker/application/docker-engine.js +40 -0
- package/dist/src/modules/docker/application/list-containers.use-case.js +69 -0
- package/dist/src/modules/docker/application/run-compose.use-case.js +83 -0
- package/dist/src/modules/docker/application/show-logs.use-case.js +51 -0
- package/dist/src/modules/docker/application/stop-project.use-case.js +56 -0
- package/dist/src/modules/docker/docker.module.js +23 -0
- package/dist/src/modules/docker/domain/compose-file.js +105 -0
- package/dist/src/modules/docker/domain/engine-output.js +65 -0
- package/dist/src/modules/docker/presentation/docker.views.js +63 -0
- package/dist/src/modules/doctor/application/run-checks.use-case.js +128 -0
- package/dist/src/modules/doctor/doctor.module.js +13 -0
- package/dist/src/modules/doctor/domain/versions.js +22 -0
- package/dist/src/modules/doctor/presentation/doctor.view.js +30 -0
- package/dist/src/modules/env/application/check-dotenv.use-case.js +116 -0
- package/dist/src/modules/env/application/inspect-path.use-case.js +71 -0
- package/dist/src/modules/env/application/path-entries.js +28 -0
- package/dist/src/modules/env/application/show-variables.use-case.js +47 -0
- package/dist/src/modules/env/domain/dotenv.js +62 -0
- package/dist/src/modules/env/env.module.js +17 -0
- package/dist/src/modules/env/presentation/env.views.js +43 -0
- package/dist/src/modules/files/application/clean-builds.use-case.js +149 -0
- package/dist/src/modules/files/application/compare-paths.use-case.js +127 -0
- package/dist/src/modules/files/application/copy-paths.use-case.js +101 -0
- package/dist/src/modules/files/application/create-paths.use-case.js +85 -0
- package/dist/src/modules/files/application/delete-paths.use-case.js +127 -0
- package/dist/src/modules/files/application/find-duplicates.use-case.js +105 -0
- package/dist/src/modules/files/application/find-files.use-case.js +131 -0
- package/dist/src/modules/files/application/hash-files.use-case.js +73 -0
- package/dist/src/modules/files/application/list-entries.use-case.js +87 -0
- package/dist/src/modules/files/application/measure-folders.use-case.js +102 -0
- package/dist/src/modules/files/application/move-entry.js +19 -0
- package/dist/src/modules/files/application/move-paths.use-case.js +82 -0
- package/dist/src/modules/files/application/read-text.use-case.js +92 -0
- package/dist/src/modules/files/application/rename-paths.use-case.js +184 -0
- package/dist/src/modules/files/application/replace-text.use-case.js +146 -0
- package/dist/src/modules/files/application/search-text.use-case.js +115 -0
- package/dist/src/modules/files/application/show-info.use-case.js +80 -0
- package/dist/src/modules/files/application/show-tree.use-case.js +75 -0
- package/dist/src/modules/files/application/sync-folders.use-case.js +162 -0
- package/dist/src/modules/files/application/text-files.js +46 -0
- package/dist/src/modules/files/application/transfers.js +35 -0
- package/dist/src/modules/files/domain/case-style.js +18 -0
- package/dist/src/modules/files/domain/filters.js +9 -0
- package/dist/src/modules/files/domain/sync-plan.js +35 -0
- package/dist/src/modules/files/domain/text-encoding.js +75 -0
- package/dist/src/modules/files/domain/values.js +28 -0
- package/dist/src/modules/files/files.module.js +70 -0
- package/dist/src/modules/files/presentation/clean.view.js +15 -0
- package/dist/src/modules/files/presentation/compare.view.js +50 -0
- package/dist/src/modules/files/presentation/copy.view.js +17 -0
- package/dist/src/modules/files/presentation/delete.view.js +16 -0
- package/dist/src/modules/files/presentation/dupes.view.js +20 -0
- package/dist/src/modules/files/presentation/find.view.js +16 -0
- package/dist/src/modules/files/presentation/grep.view.js +27 -0
- package/dist/src/modules/files/presentation/hash.view.js +15 -0
- package/dist/src/modules/files/presentation/info.view.js +36 -0
- package/dist/src/modules/files/presentation/list.view.js +17 -0
- package/dist/src/modules/files/presentation/move.view.js +14 -0
- package/dist/src/modules/files/presentation/new.view.js +8 -0
- package/dist/src/modules/files/presentation/read.view.js +6 -0
- package/dist/src/modules/files/presentation/rename.view.js +16 -0
- package/dist/src/modules/files/presentation/replace.view.js +26 -0
- package/dist/src/modules/files/presentation/size.view.js +24 -0
- package/dist/src/modules/files/presentation/sync.view.js +37 -0
- package/dist/src/modules/files/presentation/tree.view.js +22 -0
- package/dist/src/modules/gen/application/gen-options.js +18 -0
- package/dist/src/modules/gen/application/generate-passwords.use-case.js +39 -0
- package/dist/src/modules/gen/application/generate-tokens.use-case.js +38 -0
- package/dist/src/modules/gen/application/generate-ulids.use-case.js +40 -0
- package/dist/src/modules/gen/application/generate-uuids.use-case.js +32 -0
- package/dist/src/modules/gen/domain/identifiers.js +65 -0
- package/dist/src/modules/gen/domain/secrets.js +43 -0
- package/dist/src/modules/gen/gen.module.js +20 -0
- package/dist/src/modules/git/application/fetch-repositories.use-case.js +50 -0
- package/dist/src/modules/git/application/git-client.js +62 -0
- package/dist/src/modules/git/application/pull-repositories.use-case.js +67 -0
- package/dist/src/modules/git/application/repositories.js +67 -0
- package/dist/src/modules/git/application/show-status.use-case.js +49 -0
- package/dist/src/modules/git/application/switch-branch.use-case.js +118 -0
- package/dist/src/modules/git/domain/repository-status.js +37 -0
- package/dist/src/modules/git/git.module.js +25 -0
- package/dist/src/modules/git/presentation/git.views.js +100 -0
- package/dist/src/modules/net/application/check-connection.use-case.js +71 -0
- package/dist/src/modules/net/application/list-addresses.use-case.js +29 -0
- package/dist/src/modules/net/application/lookup-name.use-case.js +55 -0
- package/dist/src/modules/net/net.module.js +17 -0
- package/dist/src/modules/net/presentation/net.views.js +39 -0
- package/dist/src/modules/open/application/open-target.use-case.js +53 -0
- package/dist/src/modules/open/domain/targets.js +45 -0
- package/dist/src/modules/open/open.module.js +12 -0
- package/dist/src/modules/open/presentation/open.view.js +6 -0
- package/dist/src/modules/port/application/end-port-owners.use-case.js +68 -0
- package/dist/src/modules/port/application/find-free-port.use-case.js +40 -0
- package/dist/src/modules/port/application/find-listeners.use-case.js +34 -0
- package/dist/src/modules/port/application/port-owners.js +25 -0
- package/dist/src/modules/port/domain/port-number.js +8 -0
- package/dist/src/modules/port/port.module.js +17 -0
- package/dist/src/modules/port/presentation/port.views.js +27 -0
- package/dist/src/modules/proc/application/end-processes.use-case.js +77 -0
- package/dist/src/modules/proc/application/find-processes.use-case.js +50 -0
- package/dist/src/modules/proc/application/list-processes.use-case.js +41 -0
- package/dist/src/modules/proc/application/show-tree.use-case.js +40 -0
- package/dist/src/modules/proc/domain/process-tree.js +55 -0
- package/dist/src/modules/proc/presentation/proc.views.js +28 -0
- package/dist/src/modules/proc/proc.module.js +19 -0
- package/dist/src/modules/sys/application/create-report.use-case.js +30 -0
- package/dist/src/modules/sys/application/find-tools.use-case.js +20 -0
- package/dist/src/modules/sys/application/machine-facts.js +44 -0
- package/dist/src/modules/sys/application/show-info.use-case.js +29 -0
- package/dist/src/modules/sys/domain/tools.js +17 -0
- package/dist/src/modules/sys/presentation/sys.views.js +67 -0
- package/dist/src/modules/sys/sys.module.js +17 -0
- package/dist/src/modules/wait/application/poll.js +26 -0
- package/dist/src/modules/wait/application/wait-file.use-case.js +55 -0
- package/dist/src/modules/wait/application/wait-port.use-case.js +76 -0
- package/dist/src/modules/wait/application/wait-url.use-case.js +71 -0
- package/dist/src/modules/wait/domain/reasons.js +14 -0
- package/dist/src/modules/wait/domain/wait-input.js +50 -0
- package/dist/src/modules/wait/presentation/wait.views.js +31 -0
- package/dist/src/modules/wait/wait.module.js +21 -0
- package/package.json +57 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Notable changes to kiriya, newest first. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versions follow
|
|
5
|
+
[semantic versioning](https://semver.org/). Command ids, flags, exit codes and JSON
|
|
6
|
+
output shapes are kiriya's public API.
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.0] - 2026-09-23
|
|
11
|
+
|
|
12
|
+
The first release.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- Core: `--json` on every command, message keys for every string, typed errors
|
|
17
|
+
mapped to exit codes (2 for usage, 130 for an interruption, 1 otherwise), a typed
|
|
18
|
+
confirmation for work that cannot be undone, protected paths, and plugins named in
|
|
19
|
+
the configuration file.
|
|
20
|
+
- `files`: new, list, tree, info, read, find, grep, hash, dupes, compare, copy, move,
|
|
21
|
+
rename, replace, delete (to the trash unless `--permanent`), clean, sync and size.
|
|
22
|
+
- `archive`: zip and unzip; tar and untar for `.tar.gz`, `.tgz` and `.tar`. Extraction
|
|
23
|
+
refuses any archive with an entry that would land outside the target folder.
|
|
24
|
+
- `git`: status, fetch, pull and switch across every repository under a folder.
|
|
25
|
+
- `docker`: ps, up, down, logs, rebuild and clean for the compose project in a folder.
|
|
26
|
+
- `config`: path, keys, list, get, set and unset. The file never holds a secret.
|
|
27
|
+
- `doctor`: what the machine gives kiriya: runtime, configuration, trash, clipboard,
|
|
28
|
+
git, docker and plugins.
|
|
29
|
+
- `gen`: uuid (version 4 or 7), ulid, password and token.
|
|
30
|
+
- `convert`: base64, hex, url, json, jwt (decoded only, never verified or sent),
|
|
31
|
+
time and case.
|
|
32
|
+
- `env`: show, with secret-looking values hidden; path; and check of `.env` against
|
|
33
|
+
`.env.example`.
|
|
34
|
+
- `sys`: info, tools and report.
|
|
35
|
+
- `net`: ip, check and dns.
|
|
36
|
+
- `port`: who, kill and free.
|
|
37
|
+
- `proc`: list, find, kill and tree.
|
|
38
|
+
- `clip`: copy and paste, with Unicode intact.
|
|
39
|
+
- `open`: a file, folder or web address, never running a program.
|
|
40
|
+
- `completion`: tab completion for bash, zsh, fish and PowerShell.
|
|
41
|
+
- `wait`: port, url and file. Wait until a TCP port accepts connections, or stops with `--gone`;
|
|
42
|
+
until a web address answers with a 2xx status, or one `--status` names; or until a file
|
|
43
|
+
appears, or goes with `--gone`. It tries every half second until `--timeout`, 60 seconds by
|
|
44
|
+
default, and exits with 1 when the time runs out.
|
|
45
|
+
- `mcp`: `kiriya mcp` serves every command that changes nothing to AI agents as MCP
|
|
46
|
+
tools over stdio, for the 2026-07-28 protocol and for clients that still open with
|
|
47
|
+
`initialize`. Paths must stay inside the `--root` folders, symlinks included. With
|
|
48
|
+
`kiriya config set mcp.allowWrite true`, commands that change files in ways that can be
|
|
49
|
+
undone are offered too, and with `mcp.allowDestroy true`, commands whose work cannot be
|
|
50
|
+
undone, to clients that support elicitation: each asks the user before it changes
|
|
51
|
+
anything. `config set`, `config unset`, `docker up` and `docker rebuild` are never offered.
|
|
52
|
+
`open`, `clip paste`, `proc list --full` and `wait url` need `mcp.allowWrite`, and no tool that
|
|
53
|
+
changes something may reach inside a `.git` folder. `kiriya mcp` also takes its folders
|
|
54
|
+
as arguments, and each release carries an MCP bundle for Claude's desktop app.
|
|
55
|
+
- Help and docs: `kiriya help <module>` explains what a module is for, shows examples and
|
|
56
|
+
points to its guide. Every module has a guide in `docs/modules/` with a command reference
|
|
57
|
+
written from the commands themselves, and CI fails when the docs and the CLI disagree.
|
|
58
|
+
Plugins may add `about`, `examples` and `guide` to their own help.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sat Paing Oo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# kiriya
|
|
2
|
+
|
|
3
|
+
**One command-line toolbox for everyday developer work that behaves the same on Windows,
|
|
4
|
+
Linux and macOS.**
|
|
5
|
+
|
|
6
|
+
kiriya (ကိရိယာ, Burmese for "tool") saves remembering `del` and `rm`, `netstat -ano` and
|
|
7
|
+
`lsof -i`, `clip` and `pbcopy`, or writing a one-off script for each. It is one Node.js
|
|
8
|
+
program with no runtime dependencies. Every command answers `--json`, changes to many files
|
|
9
|
+
show a plan first, deletions go to the trash, and nothing that cannot be undone happens
|
|
10
|
+
until you type a confirmation. AI agents can use the same commands over MCP, under the same
|
|
11
|
+
rules.
|
|
12
|
+
|
|
13
|
+
> **Status:** in development and not yet published to npm. Every module below is built and
|
|
14
|
+
> tested in CI on Windows, Linux and macOS, with Node.js 22, 24 and the current release.
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
kiriya needs [Node.js](https://nodejs.org/) 22.13 or later. Until its first release, build
|
|
19
|
+
it from source:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
git clone https://github.com/SatPaingOo/kiriya.git
|
|
23
|
+
cd kiriya
|
|
24
|
+
npm ci
|
|
25
|
+
npm run build
|
|
26
|
+
npm link
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
[Getting started](docs/getting-started.md) takes it from there.
|
|
30
|
+
|
|
31
|
+
## Quick start
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
kiriya doctor # what this machine offers kiriya
|
|
35
|
+
kiriya --help # every module
|
|
36
|
+
kiriya help port # one module, with examples
|
|
37
|
+
kiriya port who 3000 # which process holds port 3000
|
|
38
|
+
kiriya files find --name "*.log" --older 30d # the same search in every shell
|
|
39
|
+
kiriya files delete dist --dry-run # the plan, before anything changes
|
|
40
|
+
kiriya git status ~/code --json # every repository under a folder, as JSON
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Modules
|
|
44
|
+
|
|
45
|
+
<!-- kiriya:modules -->
|
|
46
|
+
<!-- Written by `npm run docs` from the command specs. Change the specs, not this part. -->
|
|
47
|
+
|
|
48
|
+
| Module | What it does |
|
|
49
|
+
|---|---|
|
|
50
|
+
| [`archive`](docs/modules/archive.md) | ZIP and tar.gz archives, made and opened the same way on every OS with no zip, tar or 7-Zip installed. |
|
|
51
|
+
| [`clip`](docs/modules/clip.md) | Copy text to the clipboard and paste it back, with Unicode intact on every OS. |
|
|
52
|
+
| [`completion`](docs/modules/completion.md) | Tab completion for kiriya's modules, commands, options and values in bash, zsh, fish and PowerShell. |
|
|
53
|
+
| [`config`](docs/modules/config.md) | kiriya's own settings, such as the plugins to load, in one file per user. |
|
|
54
|
+
| [`convert`](docs/modules/convert.md) | Convert text between base64, hex, URL encoding, JSON, JWT, times and cases, entirely on this machine. |
|
|
55
|
+
| [`docker`](docs/modules/docker.md) | docker compose for the project in the current folder, and a previewed clean-up of the engine. |
|
|
56
|
+
| [`doctor`](docs/modules/doctor.md) | Check what this machine gives kiriya: runtime, configuration, trash, clipboard, git, docker and plugins. |
|
|
57
|
+
| [`env`](docs/modules/env.md) | Environment variables, PATH and .env files, read the same way on every OS. |
|
|
58
|
+
| [`files`](docs/modules/files.md) | Files and folders: create, find, read, search, compare, copy, move, rename and delete, the same on every OS. |
|
|
59
|
+
| [`gen`](docs/modules/gen.md) | Random identifiers, passwords and tokens from the operating system's secure random source. |
|
|
60
|
+
| [`git`](docs/modules/git.md) | Git across every repository under a folder: status, fetch, pull and switch. |
|
|
61
|
+
| [`net`](docs/modules/net.md) | Local addresses, TCP reachability and DNS lookups, the same on every OS. |
|
|
62
|
+
| [`open`](docs/modules/open.md) | Open a file or folder in its default application, or a web address in the browser. |
|
|
63
|
+
| [`port`](docs/modules/port.md) | See which process listens on a TCP port, end it, or find a free port, the same on every OS. |
|
|
64
|
+
| [`proc`](docs/modules/proc.md) | List, find and end processes, and show them as a tree, the same on every OS. |
|
|
65
|
+
| [`sys`](docs/modules/sys.md) | This machine and the developer tools on it, described the same way on every OS. |
|
|
66
|
+
| [`wait`](docs/modules/wait.md) | Wait until a port listens, a web address answers or a file appears, the same way on every OS. |
|
|
67
|
+
<!-- /kiriya:modules -->
|
|
68
|
+
|
|
69
|
+
## AI agents
|
|
70
|
+
|
|
71
|
+
`kiriya mcp` serves these commands to AI agents over the Model Context Protocol. It offers
|
|
72
|
+
only commands that change nothing until you allow more, and asks you before any work that
|
|
73
|
+
cannot be undone. [MCP server](docs/guides/mcp.md) shows how to add it to a client.
|
|
74
|
+
|
|
75
|
+
## Documentation
|
|
76
|
+
|
|
77
|
+
| For | Read |
|
|
78
|
+
|---|---|
|
|
79
|
+
| Using kiriya | [Getting started](docs/getting-started.md) · [Usage](docs/usage.md) · [Modules](docs/modules/README.md) |
|
|
80
|
+
| Guides | [MCP server](docs/guides/mcp.md) · [Tab completion](docs/guides/completion.md) · [Plugins](docs/guides/plugins.md) |
|
|
81
|
+
| Contributing | [CONTRIBUTING.md](CONTRIBUTING.md) · [Architecture](docs/development/architecture.md) · [Design](docs/development/design.md) |
|
|
82
|
+
| Everything | [Documentation index](docs/README.md) |
|
|
83
|
+
|
|
84
|
+
## Project
|
|
85
|
+
|
|
86
|
+
[Changelog](CHANGELOG.md) · [Security policy](SECURITY.md) · [Code of conduct](CODE_OF_CONDUCT.md) ·
|
|
87
|
+
[MIT licence](LICENSE)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rebuildable folders, removed only next to the project file that recreates them,
|
|
3
|
+
* so a hand-written `bin` or `build` folder elsewhere is never touched.
|
|
4
|
+
*/
|
|
5
|
+
export const CLEAN_RULES = [
|
|
6
|
+
{
|
|
7
|
+
directories: [
|
|
8
|
+
"node_modules",
|
|
9
|
+
".next",
|
|
10
|
+
".nuxt",
|
|
11
|
+
".turbo",
|
|
12
|
+
".svelte-kit",
|
|
13
|
+
".parcel-cache",
|
|
14
|
+
"dist",
|
|
15
|
+
"build",
|
|
16
|
+
"coverage",
|
|
17
|
+
],
|
|
18
|
+
sibling: /^package\.json$/,
|
|
19
|
+
reason: "files.clean.reason.node",
|
|
20
|
+
},
|
|
21
|
+
{ directories: ["bin", "obj"], sibling: /\.(cs|fs|vb)proj$/i, reason: "files.clean.reason.dotnet" },
|
|
22
|
+
{
|
|
23
|
+
directories: [".venv", "venv"],
|
|
24
|
+
sibling: /^(pyproject\.toml|requirements\.txt|setup\.py)$/,
|
|
25
|
+
reason: "files.clean.reason.python",
|
|
26
|
+
},
|
|
27
|
+
{ directories: ["target"], sibling: /^(Cargo\.toml|pom\.xml)$/, reason: "files.clean.reason.cargo-maven" },
|
|
28
|
+
{
|
|
29
|
+
directories: [".gradle", "build"],
|
|
30
|
+
sibling: /^(build\.gradle|build\.gradle\.kts|settings\.gradle)$/,
|
|
31
|
+
reason: "files.clean.reason.gradle",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
directories: ["__pycache__", ".pytest_cache", ".ruff_cache", ".mypy_cache"],
|
|
35
|
+
sibling: null,
|
|
36
|
+
reason: "files.clean.reason.python-cache",
|
|
37
|
+
},
|
|
38
|
+
];
|
|
39
|
+
//# sourceMappingURL=clean-rules.js.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** Every setting kiriya reads. Adding a setting means adding an entry here. */
|
|
2
|
+
export const CONFIG_KEYS = [
|
|
3
|
+
{
|
|
4
|
+
key: "mcp.allowDestroy",
|
|
5
|
+
type: "string",
|
|
6
|
+
description: "config.key.mcp-allow-destroy",
|
|
7
|
+
example: "true",
|
|
8
|
+
choices: ["true", "false"],
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
key: "mcp.allowWrite",
|
|
12
|
+
type: "string",
|
|
13
|
+
description: "config.key.mcp-allow-write",
|
|
14
|
+
example: "true",
|
|
15
|
+
choices: ["true", "false"],
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
key: "plugins",
|
|
19
|
+
type: "list",
|
|
20
|
+
description: "config.key.plugins",
|
|
21
|
+
example: "kiriya-plugin-example ./team/kiriya-plugin",
|
|
22
|
+
},
|
|
23
|
+
];
|
|
24
|
+
//# sourceMappingURL=config-keys.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Dependency, build and cache folders. Globs and walks skip them unless --all is given. */
|
|
2
|
+
export const DEPENDENCY_DIRECTORIES = new Set([
|
|
3
|
+
"node_modules",
|
|
4
|
+
".git",
|
|
5
|
+
".venv",
|
|
6
|
+
"venv",
|
|
7
|
+
"site-packages",
|
|
8
|
+
"dist",
|
|
9
|
+
"build",
|
|
10
|
+
".next",
|
|
11
|
+
"obj",
|
|
12
|
+
"bin",
|
|
13
|
+
"__pycache__",
|
|
14
|
+
".pytest_cache",
|
|
15
|
+
]);
|
|
16
|
+
//# sourceMappingURL=dependency-directories.js.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { archiveModule } from "../modules/archive/archive.module.js";
|
|
2
|
+
import { clipModule } from "../modules/clip/clip.module.js";
|
|
3
|
+
import { completionModule } from "../modules/completion/completion.module.js";
|
|
4
|
+
import { configModule } from "../modules/config/config.module.js";
|
|
5
|
+
import { convertModule } from "../modules/convert/convert.module.js";
|
|
6
|
+
import { dockerModule } from "../modules/docker/docker.module.js";
|
|
7
|
+
import { doctorModule } from "../modules/doctor/doctor.module.js";
|
|
8
|
+
import { envModule } from "../modules/env/env.module.js";
|
|
9
|
+
import { filesModule } from "../modules/files/files.module.js";
|
|
10
|
+
import { genModule } from "../modules/gen/gen.module.js";
|
|
11
|
+
import { gitModule } from "../modules/git/git.module.js";
|
|
12
|
+
import { netModule } from "../modules/net/net.module.js";
|
|
13
|
+
import { openModule } from "../modules/open/open.module.js";
|
|
14
|
+
import { portModule } from "../modules/port/port.module.js";
|
|
15
|
+
import { procModule } from "../modules/proc/proc.module.js";
|
|
16
|
+
import { sysModule } from "../modules/sys/sys.module.js";
|
|
17
|
+
import { waitModule } from "../modules/wait/wait.module.js";
|
|
18
|
+
/** Built-in modules, in no particular order; help lists them sorted. Adding a module is one line here. */
|
|
19
|
+
export const BUILT_IN_MODULES = [
|
|
20
|
+
filesModule,
|
|
21
|
+
archiveModule,
|
|
22
|
+
gitModule,
|
|
23
|
+
dockerModule,
|
|
24
|
+
configModule,
|
|
25
|
+
doctorModule,
|
|
26
|
+
genModule,
|
|
27
|
+
convertModule,
|
|
28
|
+
envModule,
|
|
29
|
+
sysModule,
|
|
30
|
+
netModule,
|
|
31
|
+
portModule,
|
|
32
|
+
procModule,
|
|
33
|
+
clipModule,
|
|
34
|
+
openModule,
|
|
35
|
+
completionModule,
|
|
36
|
+
waitModule,
|
|
37
|
+
];
|
|
38
|
+
//# sourceMappingURL=modules.js.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Folders no command may delete, move or overwrite, per OS. Windows folders are
|
|
3
|
+
* named by the environment variable that holds them, since their drive varies.
|
|
4
|
+
*/
|
|
5
|
+
export const PROTECTED_PATHS = {
|
|
6
|
+
windows: {
|
|
7
|
+
/** Nothing inside these. */
|
|
8
|
+
insideVariables: ["SystemRoot", "ProgramFiles", "ProgramFiles(x86)"],
|
|
9
|
+
/** These folders themselves. */
|
|
10
|
+
exactVariables: ["ProgramData", "USERPROFILE"],
|
|
11
|
+
/** Relative to the drive root of the path being checked. */
|
|
12
|
+
exactOnDrive: ["Users"],
|
|
13
|
+
},
|
|
14
|
+
posix: {
|
|
15
|
+
inside: [
|
|
16
|
+
"/bin",
|
|
17
|
+
"/boot",
|
|
18
|
+
"/dev",
|
|
19
|
+
"/etc",
|
|
20
|
+
"/lib",
|
|
21
|
+
"/lib64",
|
|
22
|
+
"/proc",
|
|
23
|
+
"/sbin",
|
|
24
|
+
"/sys",
|
|
25
|
+
"/usr",
|
|
26
|
+
"/System",
|
|
27
|
+
"/Library",
|
|
28
|
+
],
|
|
29
|
+
exact: ["/home", "/Users", "/opt", "/root", "/tmp", "/var"],
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=protected-paths.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Folders `files size` reports as rebuildable: dependencies, build output, caches and downloaded models. */
|
|
2
|
+
export const REBUILDABLE_DIRECTORIES = new Set([
|
|
3
|
+
"node_modules",
|
|
4
|
+
".venv",
|
|
5
|
+
"venv",
|
|
6
|
+
"bin",
|
|
7
|
+
"obj",
|
|
8
|
+
"dist",
|
|
9
|
+
"build",
|
|
10
|
+
".next",
|
|
11
|
+
".turbo",
|
|
12
|
+
"__pycache__",
|
|
13
|
+
".pytest_cache",
|
|
14
|
+
".ruff_cache",
|
|
15
|
+
".hf_cache",
|
|
16
|
+
"models",
|
|
17
|
+
"storage",
|
|
18
|
+
".gradle",
|
|
19
|
+
]);
|
|
20
|
+
//# sourceMappingURL=rebuildable-directories.js.map
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/** The verb of a command id in a module: `files.list` gives `list`, `doctor` in doctor gives "", anything else null. */
|
|
2
|
+
function verbOf(commandId, moduleId) {
|
|
3
|
+
if (commandId === moduleId)
|
|
4
|
+
return "";
|
|
5
|
+
if (!commandId.startsWith(`${moduleId}.`))
|
|
6
|
+
return null;
|
|
7
|
+
const verb = commandId.slice(moduleId.length + 1);
|
|
8
|
+
return verb === "" || verb.includes(".") ? null : verb;
|
|
9
|
+
}
|
|
10
|
+
/** Built-in modules and plugins register here; presentation looks commands up by module and verb. */
|
|
11
|
+
export class CommandRegistry {
|
|
12
|
+
modules = new Map();
|
|
13
|
+
/** Registers every command of a module, or none of them when one is rejected. */
|
|
14
|
+
register(module, ports) {
|
|
15
|
+
if (this.modules.has(module.id))
|
|
16
|
+
throw new Error(`module ${module.id} is registered twice`);
|
|
17
|
+
const entry = {
|
|
18
|
+
id: module.id,
|
|
19
|
+
summary: module.summary,
|
|
20
|
+
about: module.about ?? null,
|
|
21
|
+
examples: module.examples ?? [],
|
|
22
|
+
guide: module.guide ?? null,
|
|
23
|
+
commands: new Map(),
|
|
24
|
+
};
|
|
25
|
+
const registrar = {
|
|
26
|
+
add(command, view) {
|
|
27
|
+
const verb = verbOf(command.spec.id, module.id);
|
|
28
|
+
if (verb === null)
|
|
29
|
+
throw new Error(`command ${command.spec.id} does not belong to module ${module.id}`);
|
|
30
|
+
if (entry.commands.has(verb))
|
|
31
|
+
throw new Error(`command ${command.spec.id} is registered twice`);
|
|
32
|
+
entry.commands.set(verb, {
|
|
33
|
+
command: command,
|
|
34
|
+
view: view,
|
|
35
|
+
verb,
|
|
36
|
+
});
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
module.register(registrar, ports);
|
|
40
|
+
this.modules.set(module.id, entry);
|
|
41
|
+
}
|
|
42
|
+
module(id) {
|
|
43
|
+
return this.modules.get(id);
|
|
44
|
+
}
|
|
45
|
+
/** Modules in code-point order, which is the same on every OS. */
|
|
46
|
+
list() {
|
|
47
|
+
return [...this.modules.values()].sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
|
|
48
|
+
}
|
|
49
|
+
catalog() {
|
|
50
|
+
return this.list().map((module) => ({
|
|
51
|
+
id: module.id,
|
|
52
|
+
summary: module.summary,
|
|
53
|
+
commands: [...module.commands.values()].map((entry) => ({ verb: entry.verb, spec: entry.command.spec })),
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=command-registry.js.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { CONFIG_KEYS } from "../../config/config-keys.js";
|
|
2
|
+
import { OperationFailedError } from "../domain/errors.js";
|
|
3
|
+
import { message } from "../domain/message.js";
|
|
4
|
+
export function configKey(key) {
|
|
5
|
+
return CONFIG_KEYS.find((entry) => entry.key === key);
|
|
6
|
+
}
|
|
7
|
+
/** A setting kiriya knows must hold the type its key declares; settings it does not know are left alone. */
|
|
8
|
+
export function checkConfigTypes(values, file) {
|
|
9
|
+
for (const [key, value] of Object.entries(values)) {
|
|
10
|
+
const known = configKey(key);
|
|
11
|
+
if (known === undefined)
|
|
12
|
+
continue;
|
|
13
|
+
const isList = typeof value !== "string";
|
|
14
|
+
if ((known.type === "list") !== isList) {
|
|
15
|
+
const expected = message(known.type === "list" ? "core.config.type.list" : "core.config.type.string");
|
|
16
|
+
throw new OperationFailedError("core.config.wrong-type", { path: file, field: key, expected });
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** Whether the MCP server may offer tools that change files. Only the exact value `true` allows it. */
|
|
21
|
+
export function mcpAllowsWrite(values) {
|
|
22
|
+
return values["mcp.allowWrite"] === "true";
|
|
23
|
+
}
|
|
24
|
+
/** Whether the MCP server may offer tools whose work cannot be undone. Only the exact value `true` allows it. */
|
|
25
|
+
export function mcpAllowsDestroy(values) {
|
|
26
|
+
return values["mcp.allowDestroy"] === "true";
|
|
27
|
+
}
|
|
28
|
+
/** The plugins the configuration lists, in order; none when the setting is missing or malformed. */
|
|
29
|
+
export function pluginEntries(values) {
|
|
30
|
+
const value = values["plugins"];
|
|
31
|
+
return value === undefined || typeof value === "string" ? [] : value;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=config-values.js.map
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { PROTECTED_PATHS } from "../../config/protected-paths.js";
|
|
3
|
+
import { message } from "../domain/message.js";
|
|
4
|
+
/**
|
|
5
|
+
* Drive roots, the home folder, the working folder and its parents, and
|
|
6
|
+
* operating-system folders. Uses the path rules of the environment's OS, so
|
|
7
|
+
* Windows rules can be tested anywhere.
|
|
8
|
+
*/
|
|
9
|
+
export class PathGuard {
|
|
10
|
+
environment;
|
|
11
|
+
paths;
|
|
12
|
+
caseInsensitive;
|
|
13
|
+
constructor(environment) {
|
|
14
|
+
this.environment = environment;
|
|
15
|
+
this.paths = environment.os === "windows" ? path.win32 : path.posix;
|
|
16
|
+
this.caseInsensitive = environment.os !== "linux";
|
|
17
|
+
}
|
|
18
|
+
reasonFor(target, cwd) {
|
|
19
|
+
const resolved = this.paths.resolve(target);
|
|
20
|
+
if (resolved === this.paths.parse(resolved).root)
|
|
21
|
+
return message("core.guard.drive-root", { path: resolved });
|
|
22
|
+
if (this.same(resolved, this.paths.resolve(this.environment.homeDirectory))) {
|
|
23
|
+
return message("core.guard.home", { path: resolved });
|
|
24
|
+
}
|
|
25
|
+
if (this.isInside(this.paths.resolve(cwd), resolved))
|
|
26
|
+
return message("core.guard.working-folder", { path: resolved });
|
|
27
|
+
for (const folder of this.insideFolders()) {
|
|
28
|
+
if (this.isInside(resolved, folder))
|
|
29
|
+
return message("core.guard.system-folder", { path: resolved, folder });
|
|
30
|
+
}
|
|
31
|
+
for (const folder of this.exactFolders(resolved)) {
|
|
32
|
+
if (this.same(resolved, folder))
|
|
33
|
+
return message("core.guard.system-location", { path: resolved, folder });
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
insideFolders() {
|
|
38
|
+
if (this.environment.os !== "windows")
|
|
39
|
+
return PROTECTED_PATHS.posix.inside;
|
|
40
|
+
return this.fromVariables(PROTECTED_PATHS.windows.insideVariables);
|
|
41
|
+
}
|
|
42
|
+
exactFolders(target) {
|
|
43
|
+
if (this.environment.os !== "windows")
|
|
44
|
+
return PROTECTED_PATHS.posix.exact;
|
|
45
|
+
const root = this.paths.parse(target).root;
|
|
46
|
+
return [
|
|
47
|
+
...this.fromVariables(PROTECTED_PATHS.windows.exactVariables),
|
|
48
|
+
...PROTECTED_PATHS.windows.exactOnDrive.map((name) => this.paths.join(root, name)),
|
|
49
|
+
];
|
|
50
|
+
}
|
|
51
|
+
fromVariables(names) {
|
|
52
|
+
return names
|
|
53
|
+
.map((name) => this.environment.variable(name))
|
|
54
|
+
.filter((value) => value !== undefined && value !== "")
|
|
55
|
+
.map((value) => this.paths.resolve(value));
|
|
56
|
+
}
|
|
57
|
+
normalize(value) {
|
|
58
|
+
return this.caseInsensitive ? value.toLowerCase() : value;
|
|
59
|
+
}
|
|
60
|
+
same(a, b) {
|
|
61
|
+
return this.normalize(a) === this.normalize(b);
|
|
62
|
+
}
|
|
63
|
+
/** True when `child` is `parent` or anywhere below it. */
|
|
64
|
+
isInside(child, parent) {
|
|
65
|
+
const relative = this.paths.relative(this.normalize(parent), this.normalize(child));
|
|
66
|
+
return relative === "" || (!relative.startsWith("..") && !this.paths.isAbsolute(relative));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=path-guard.js.map
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { DEPENDENCY_DIRECTORIES } from "../../config/dependency-directories.js";
|
|
3
|
+
import { NotFoundError, UsageError } from "../domain/errors.js";
|
|
4
|
+
import { globToRegExp, hasGlob } from "../domain/glob.js";
|
|
5
|
+
import { byCodePoint, isHiddenName } from "../domain/names.js";
|
|
6
|
+
import { walk } from "./walk.js";
|
|
7
|
+
/** True when `child` is `parent` or anywhere below it. */
|
|
8
|
+
export function isInside(child, parent) {
|
|
9
|
+
const relative = path.relative(path.resolve(parent), path.resolve(child));
|
|
10
|
+
return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Paths from command arguments. An argument that exists is taken literally;
|
|
14
|
+
* otherwise kiriya expands the glob itself, so a quoted `"src/**\/*.ts"` means
|
|
15
|
+
* the same in PowerShell, cmd and bash. Globs skip hidden and dependency folders
|
|
16
|
+
* unless `all` is set or the pattern names one.
|
|
17
|
+
*/
|
|
18
|
+
export async function expandPaths(fileSystem, args, cwd, all) {
|
|
19
|
+
const found = new Set();
|
|
20
|
+
for (const arg of args) {
|
|
21
|
+
const literal = path.resolve(cwd, arg);
|
|
22
|
+
if ((await fileSystem.lstat(literal)) !== null) {
|
|
23
|
+
found.add(literal);
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (!hasGlob(arg))
|
|
27
|
+
throw new NotFoundError("core.fs.not-found", { path: literal });
|
|
28
|
+
const normalized = path.sep === "\\" ? arg.split("\\").join("/") : arg;
|
|
29
|
+
const segments = normalized.split("/");
|
|
30
|
+
const firstGlob = segments.findIndex((segment) => hasGlob(segment));
|
|
31
|
+
const base = path.resolve(cwd, segments.slice(0, firstGlob).join("/") || ".");
|
|
32
|
+
const rest = segments.slice(firstGlob).join("/");
|
|
33
|
+
const namesHidden = rest.split("/").some((segment) => isHiddenName(segment) || DEPENDENCY_DIRECTORIES.has(segment));
|
|
34
|
+
const pattern = globToRegExp(rest);
|
|
35
|
+
let matched = 0;
|
|
36
|
+
for await (const entry of walk(fileSystem, base, { all: all || namesHidden })) {
|
|
37
|
+
if (pattern.test(entry.rel)) {
|
|
38
|
+
found.add(entry.path);
|
|
39
|
+
matched += 1;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (matched === 0)
|
|
43
|
+
throw new UsageError("core.glob.no-match", { pattern: arg });
|
|
44
|
+
}
|
|
45
|
+
return [...found].sort(byCodePoint);
|
|
46
|
+
}
|
|
47
|
+
/** Drops paths inside another selected folder, so nothing is handled twice. */
|
|
48
|
+
export function outermost(paths) {
|
|
49
|
+
const kept = [];
|
|
50
|
+
for (const candidate of [...paths].sort((a, b) => a.length - b.length)) {
|
|
51
|
+
if (!kept.some((parent) => parent !== candidate && isInside(candidate, parent)))
|
|
52
|
+
kept.push(candidate);
|
|
53
|
+
}
|
|
54
|
+
return kept.sort(byCodePoint);
|
|
55
|
+
}
|
|
56
|
+
/** Total size of a file or folder, counting everything inside; symlinks count as entries, never followed. */
|
|
57
|
+
export async function measure(fileSystem, target) {
|
|
58
|
+
const stat = await fileSystem.lstat(target);
|
|
59
|
+
if (stat === null)
|
|
60
|
+
return { bytes: 0, files: 0, directories: 0 };
|
|
61
|
+
if (stat.kind !== "directory")
|
|
62
|
+
return { bytes: stat.size, files: 1, directories: 0 };
|
|
63
|
+
let bytes = 0;
|
|
64
|
+
let files = 0;
|
|
65
|
+
let directories = 0;
|
|
66
|
+
for await (const entry of walk(fileSystem, target, { all: true })) {
|
|
67
|
+
if (entry.kind === "directory") {
|
|
68
|
+
directories += 1;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
files += 1;
|
|
72
|
+
bytes += (await fileSystem.lstat(entry.path))?.size ?? 0;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return { bytes, files, directories };
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=paths.js.map
|