@aigne/afs-cli 1.11.0-beta.1 → 1.11.0-beta.11
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/README.md +262 -15
- package/dist/_virtual/rolldown_runtime.cjs +29 -0
- package/dist/_virtual/rolldown_runtime.mjs +7 -0
- package/dist/cli.cjs +40 -0
- package/dist/cli.d.cts +2 -0
- package/dist/cli.d.mts +2 -1
- package/dist/cli.mjs +36 -24
- package/dist/cli.mjs.map +1 -0
- package/dist/config/afs-loader.cjs +578 -0
- package/dist/config/afs-loader.d.cts +19 -0
- package/dist/config/afs-loader.d.cts.map +1 -0
- package/dist/config/afs-loader.d.mts +19 -0
- package/dist/config/afs-loader.d.mts.map +1 -0
- package/dist/config/afs-loader.mjs +576 -0
- package/dist/config/afs-loader.mjs.map +1 -0
- package/dist/config/env.cjs +46 -0
- package/dist/config/env.mjs +46 -0
- package/dist/config/env.mjs.map +1 -0
- package/dist/config/loader.cjs +219 -0
- package/dist/config/loader.mjs +217 -0
- package/dist/config/loader.mjs.map +1 -0
- package/dist/config/mount-commands.cjs +226 -0
- package/dist/config/mount-commands.d.cts +14 -0
- package/dist/config/mount-commands.d.cts.map +1 -0
- package/dist/config/mount-commands.d.mts +14 -0
- package/dist/config/mount-commands.d.mts.map +1 -0
- package/dist/config/mount-commands.mjs +220 -0
- package/dist/config/mount-commands.mjs.map +1 -0
- package/dist/config/schema.cjs +99 -0
- package/dist/config/schema.mjs +98 -0
- package/dist/config/schema.mjs.map +1 -0
- package/dist/core/commands/delete.cjs +41 -0
- package/dist/core/commands/delete.d.cts +18 -0
- package/dist/core/commands/delete.d.cts.map +1 -0
- package/dist/core/commands/delete.d.mts +18 -0
- package/dist/core/commands/delete.d.mts.map +1 -0
- package/dist/core/commands/delete.mjs +42 -0
- package/dist/core/commands/delete.mjs.map +1 -0
- package/dist/core/commands/exec.cjs +98 -0
- package/dist/core/commands/exec.d.cts +26 -0
- package/dist/core/commands/exec.d.cts.map +1 -0
- package/dist/core/commands/exec.d.mts +26 -0
- package/dist/core/commands/exec.d.mts.map +1 -0
- package/dist/core/commands/exec.mjs +99 -0
- package/dist/core/commands/exec.mjs.map +1 -0
- package/dist/core/commands/explain.cjs +278 -0
- package/dist/core/commands/explain.d.cts +25 -0
- package/dist/core/commands/explain.d.cts.map +1 -0
- package/dist/core/commands/explain.d.mts +25 -0
- package/dist/core/commands/explain.d.mts.map +1 -0
- package/dist/core/commands/explain.mjs +279 -0
- package/dist/core/commands/explain.mjs.map +1 -0
- package/dist/core/commands/explore.cjs +30 -0
- package/dist/core/commands/explore.d.mts +2 -0
- package/dist/core/commands/explore.mjs +31 -0
- package/dist/core/commands/explore.mjs.map +1 -0
- package/dist/core/commands/index.cjs +36 -0
- package/dist/core/commands/index.d.cts +21 -0
- package/dist/core/commands/index.d.cts.map +1 -0
- package/dist/core/commands/index.d.mts +24 -0
- package/dist/core/commands/index.d.mts.map +1 -0
- package/dist/core/commands/index.mjs +37 -0
- package/dist/core/commands/index.mjs.map +1 -0
- package/dist/core/commands/ls.cjs +57 -0
- package/dist/core/commands/ls.d.cts +21 -0
- package/dist/core/commands/ls.d.cts.map +1 -0
- package/dist/core/commands/ls.d.mts +21 -0
- package/dist/core/commands/ls.d.mts.map +1 -0
- package/dist/core/commands/ls.mjs +58 -0
- package/dist/core/commands/ls.mjs.map +1 -0
- package/dist/core/commands/mount.cjs +222 -0
- package/dist/core/commands/mount.d.cts +35 -0
- package/dist/core/commands/mount.d.cts.map +1 -0
- package/dist/core/commands/mount.d.mts +35 -0
- package/dist/core/commands/mount.d.mts.map +1 -0
- package/dist/core/commands/mount.mjs +223 -0
- package/dist/core/commands/mount.mjs.map +1 -0
- package/dist/core/commands/read.cjs +48 -0
- package/dist/core/commands/read.d.cts +17 -0
- package/dist/core/commands/read.d.cts.map +1 -0
- package/dist/core/commands/read.d.mts +17 -0
- package/dist/core/commands/read.d.mts.map +1 -0
- package/dist/core/commands/read.mjs +49 -0
- package/dist/core/commands/read.mjs.map +1 -0
- package/dist/core/commands/search.cjs +40 -0
- package/dist/core/commands/search.d.mts +2 -0
- package/dist/core/commands/search.mjs +41 -0
- package/dist/core/commands/search.mjs.map +1 -0
- package/dist/core/commands/serve.cjs +267 -0
- package/dist/core/commands/serve.d.mts +2 -0
- package/dist/core/commands/serve.mjs +267 -0
- package/dist/core/commands/serve.mjs.map +1 -0
- package/dist/core/commands/stat.cjs +53 -0
- package/dist/core/commands/stat.d.cts +17 -0
- package/dist/core/commands/stat.d.cts.map +1 -0
- package/dist/core/commands/stat.d.mts +17 -0
- package/dist/core/commands/stat.d.mts.map +1 -0
- package/dist/core/commands/stat.mjs +54 -0
- package/dist/core/commands/stat.mjs.map +1 -0
- package/dist/core/commands/types.cjs +18 -0
- package/dist/core/commands/types.d.cts +54 -0
- package/dist/core/commands/types.d.cts.map +1 -0
- package/dist/core/commands/types.d.mts +54 -0
- package/dist/core/commands/types.d.mts.map +1 -0
- package/dist/core/commands/types.mjs +19 -0
- package/dist/core/commands/types.mjs.map +1 -0
- package/dist/core/commands/write.cjs +70 -0
- package/dist/core/commands/write.d.cts +20 -0
- package/dist/core/commands/write.d.cts.map +1 -0
- package/dist/core/commands/write.d.mts +20 -0
- package/dist/core/commands/write.d.mts.map +1 -0
- package/dist/core/commands/write.mjs +71 -0
- package/dist/core/commands/write.mjs.map +1 -0
- package/dist/core/executor/index.cjs +196 -0
- package/dist/core/executor/index.d.cts +77 -0
- package/dist/core/executor/index.d.cts.map +1 -0
- package/dist/core/executor/index.d.mts +77 -0
- package/dist/core/executor/index.d.mts.map +1 -0
- package/dist/core/executor/index.mjs +195 -0
- package/dist/core/executor/index.mjs.map +1 -0
- package/dist/core/formatters/delete.cjs +37 -0
- package/dist/core/formatters/delete.d.cts +18 -0
- package/dist/core/formatters/delete.d.cts.map +1 -0
- package/dist/core/formatters/delete.d.mts +18 -0
- package/dist/core/formatters/delete.d.mts.map +1 -0
- package/dist/core/formatters/delete.mjs +37 -0
- package/dist/core/formatters/delete.mjs.map +1 -0
- package/dist/core/formatters/exec.cjs +60 -0
- package/dist/core/formatters/exec.d.cts +18 -0
- package/dist/core/formatters/exec.d.cts.map +1 -0
- package/dist/core/formatters/exec.d.mts +18 -0
- package/dist/core/formatters/exec.d.mts.map +1 -0
- package/dist/core/formatters/exec.mjs +60 -0
- package/dist/core/formatters/exec.mjs.map +1 -0
- package/dist/core/formatters/explain.cjs +99 -0
- package/dist/core/formatters/explain.d.cts +11 -0
- package/dist/core/formatters/explain.d.cts.map +1 -0
- package/dist/core/formatters/explain.d.mts +11 -0
- package/dist/core/formatters/explain.d.mts.map +1 -0
- package/dist/core/formatters/explain.mjs +98 -0
- package/dist/core/formatters/explain.mjs.map +1 -0
- package/dist/core/formatters/index.d.mts +9 -0
- package/dist/core/formatters/ls.cjs +179 -0
- package/dist/core/formatters/ls.d.cts +20 -0
- package/dist/core/formatters/ls.d.cts.map +1 -0
- package/dist/core/formatters/ls.d.mts +20 -0
- package/dist/core/formatters/ls.d.mts.map +1 -0
- package/dist/core/formatters/ls.mjs +179 -0
- package/dist/core/formatters/ls.mjs.map +1 -0
- package/dist/core/formatters/mount.cjs +55 -0
- package/dist/core/formatters/mount.d.cts +15 -0
- package/dist/core/formatters/mount.d.cts.map +1 -0
- package/dist/core/formatters/mount.d.mts +15 -0
- package/dist/core/formatters/mount.d.mts.map +1 -0
- package/dist/core/formatters/mount.mjs +55 -0
- package/dist/core/formatters/mount.mjs.map +1 -0
- package/dist/core/formatters/read.cjs +100 -0
- package/dist/core/formatters/read.d.cts +22 -0
- package/dist/core/formatters/read.d.cts.map +1 -0
- package/dist/core/formatters/read.d.mts +22 -0
- package/dist/core/formatters/read.d.mts.map +1 -0
- package/dist/core/formatters/read.mjs +100 -0
- package/dist/core/formatters/read.mjs.map +1 -0
- package/dist/core/formatters/search.cjs +44 -0
- package/dist/core/formatters/search.d.mts +1 -0
- package/dist/core/formatters/search.mjs +44 -0
- package/dist/core/formatters/search.mjs.map +1 -0
- package/dist/core/formatters/stat.cjs +155 -0
- package/dist/core/formatters/stat.d.cts +15 -0
- package/dist/core/formatters/stat.d.cts.map +1 -0
- package/dist/core/formatters/stat.d.mts +15 -0
- package/dist/core/formatters/stat.d.mts.map +1 -0
- package/dist/core/formatters/stat.mjs +155 -0
- package/dist/core/formatters/stat.mjs.map +1 -0
- package/dist/core/formatters/write.cjs +51 -0
- package/dist/core/formatters/write.d.cts +22 -0
- package/dist/core/formatters/write.d.cts.map +1 -0
- package/dist/core/formatters/write.d.mts +22 -0
- package/dist/core/formatters/write.d.mts.map +1 -0
- package/dist/core/formatters/write.mjs +51 -0
- package/dist/core/formatters/write.mjs.map +1 -0
- package/dist/core/helpers/exec-args.cjs +142 -0
- package/dist/core/helpers/exec-args.d.cts +46 -0
- package/dist/core/helpers/exec-args.d.cts.map +1 -0
- package/dist/core/helpers/exec-args.d.mts +46 -0
- package/dist/core/helpers/exec-args.d.mts.map +1 -0
- package/dist/core/helpers/exec-args.mjs +139 -0
- package/dist/core/helpers/exec-args.mjs.map +1 -0
- package/dist/core/helpers/stdin.cjs +41 -0
- package/dist/core/helpers/stdin.d.cts +15 -0
- package/dist/core/helpers/stdin.d.cts.map +1 -0
- package/dist/core/helpers/stdin.d.mts +15 -0
- package/dist/core/helpers/stdin.d.mts.map +1 -0
- package/dist/core/helpers/stdin.mjs +41 -0
- package/dist/core/helpers/stdin.mjs.map +1 -0
- package/dist/core/index.cjs +49 -0
- package/dist/core/index.d.cts +24 -0
- package/dist/core/index.d.mts +25 -0
- package/dist/core/index.mjs +24 -0
- package/dist/core/path-utils.cjs +1 -0
- package/dist/core/path-utils.mjs +3 -0
- package/dist/core/types.d.cts +24 -0
- package/dist/core/types.d.cts.map +1 -0
- package/dist/core/types.d.mts +24 -0
- package/dist/core/types.d.mts.map +1 -0
- package/dist/credential/auth-server.cjs +247 -0
- package/dist/credential/auth-server.mjs +247 -0
- package/dist/credential/auth-server.mjs.map +1 -0
- package/dist/credential/cli-auth-context.cjs +86 -0
- package/dist/credential/cli-auth-context.d.mts +1 -0
- package/dist/credential/cli-auth-context.mjs +86 -0
- package/dist/credential/cli-auth-context.mjs.map +1 -0
- package/dist/credential/index.cjs +5 -0
- package/dist/credential/index.d.mts +4 -0
- package/dist/credential/index.mjs +7 -0
- package/dist/credential/mcp-auth-context.cjs +192 -0
- package/dist/credential/mcp-auth-context.d.mts +1 -0
- package/dist/credential/mcp-auth-context.mjs +192 -0
- package/dist/credential/mcp-auth-context.mjs.map +1 -0
- package/dist/credential/resolver.cjs +127 -0
- package/dist/credential/resolver.d.mts +1 -0
- package/dist/credential/resolver.mjs +127 -0
- package/dist/credential/resolver.mjs.map +1 -0
- package/dist/credential/store.cjs +106 -0
- package/dist/credential/store.d.cts +30 -0
- package/dist/credential/store.d.cts.map +1 -0
- package/dist/credential/store.d.mts +30 -0
- package/dist/credential/store.d.mts.map +1 -0
- package/dist/credential/store.mjs +106 -0
- package/dist/credential/store.mjs.map +1 -0
- package/dist/errors.cjs +18 -0
- package/dist/errors.mjs +18 -0
- package/dist/errors.mjs.map +1 -0
- package/dist/explorer/actions.cjs +311 -0
- package/dist/explorer/actions.mjs +305 -0
- package/dist/explorer/actions.mjs.map +1 -0
- package/dist/explorer/components/dialog.cjs +508 -0
- package/dist/explorer/components/dialog.mjs +509 -0
- package/dist/explorer/components/dialog.mjs.map +1 -0
- package/dist/explorer/components/file-list.cjs +107 -0
- package/dist/explorer/components/file-list.mjs +107 -0
- package/dist/explorer/components/file-list.mjs.map +1 -0
- package/dist/explorer/components/function-bar.cjs +55 -0
- package/dist/explorer/components/function-bar.mjs +55 -0
- package/dist/explorer/components/function-bar.mjs.map +1 -0
- package/dist/explorer/components/index.cjs +5 -0
- package/dist/explorer/components/index.mjs +7 -0
- package/dist/explorer/components/metadata-panel.cjs +219 -0
- package/dist/explorer/components/metadata-panel.mjs +219 -0
- package/dist/explorer/components/metadata-panel.mjs.map +1 -0
- package/dist/explorer/components/status-bar.cjs +53 -0
- package/dist/explorer/components/status-bar.mjs +54 -0
- package/dist/explorer/components/status-bar.mjs.map +1 -0
- package/dist/explorer/keybindings.cjs +214 -0
- package/dist/explorer/keybindings.mjs +213 -0
- package/dist/explorer/keybindings.mjs.map +1 -0
- package/dist/explorer/screen.cjs +251 -0
- package/dist/explorer/screen.d.cts +23 -0
- package/dist/explorer/screen.d.cts.map +1 -0
- package/dist/explorer/screen.d.mts +23 -0
- package/dist/explorer/screen.d.mts.map +1 -0
- package/dist/explorer/screen.mjs +250 -0
- package/dist/explorer/screen.mjs.map +1 -0
- package/dist/explorer/state.cjs +53 -0
- package/dist/explorer/state.mjs +53 -0
- package/dist/explorer/state.mjs.map +1 -0
- package/dist/explorer/theme.cjs +160 -0
- package/dist/explorer/theme.mjs +157 -0
- package/dist/explorer/theme.mjs.map +1 -0
- package/dist/index.cjs +12 -0
- package/dist/index.d.cts +6 -0
- package/dist/index.d.mts +7 -4
- package/dist/index.mjs +7 -2
- package/dist/mcp/http-transport.cjs +87 -0
- package/dist/mcp/http-transport.mjs +87 -0
- package/dist/mcp/http-transport.mjs.map +1 -0
- package/dist/mcp/prompts.cjs +48 -0
- package/dist/mcp/prompts.mjs +48 -0
- package/dist/mcp/prompts.mjs.map +1 -0
- package/dist/mcp/resources.cjs +25 -0
- package/dist/mcp/resources.mjs +25 -0
- package/dist/mcp/resources.mjs.map +1 -0
- package/dist/mcp/server.cjs +74 -0
- package/dist/mcp/server.mjs +73 -0
- package/dist/mcp/server.mjs.map +1 -0
- package/dist/mcp/tools.cjs +152 -0
- package/dist/mcp/tools.mjs +152 -0
- package/dist/mcp/tools.mjs.map +1 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/index.d.cts +10 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/index.d.cts.map +1 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/index.d.mts +10 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/index.d.mts.map +1 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/types.d.cts +46 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/types.d.cts.map +1 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/types.d.mts +46 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/types.d.mts.map +1 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/urlpattern.cjs +902 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/urlpattern.mjs +902 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/urlpattern.mjs.map +1 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/index.cjs +6 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/index.mjs +8 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/index.mjs.map +1 -0
- package/dist/path-utils.cjs +105 -0
- package/dist/path-utils.d.cts +50 -0
- package/dist/path-utils.d.cts.map +1 -0
- package/dist/path-utils.d.mts +50 -0
- package/dist/path-utils.d.mts.map +1 -0
- package/dist/path-utils.mjs +104 -0
- package/dist/path-utils.mjs.map +1 -0
- package/dist/repl.cjs +491 -0
- package/dist/repl.d.cts +15 -0
- package/dist/repl.d.cts.map +1 -0
- package/dist/repl.d.mts +16 -0
- package/dist/repl.d.mts.map +1 -0
- package/dist/repl.mjs +491 -0
- package/dist/repl.mjs.map +1 -0
- package/dist/serve.cjs +146 -0
- package/dist/serve.d.cts +41 -0
- package/dist/serve.d.cts.map +1 -0
- package/dist/serve.d.mts +41 -0
- package/dist/serve.d.mts.map +1 -0
- package/dist/serve.mjs +146 -0
- package/dist/serve.mjs.map +1 -0
- package/dist/ui/header.cjs +12 -0
- package/dist/ui/header.mjs +13 -0
- package/dist/ui/header.mjs.map +1 -0
- package/dist/ui/index.cjs +8 -0
- package/dist/ui/index.mjs +9 -0
- package/dist/ui/index.mjs.map +1 -0
- package/dist/ui/terminal.cjs +88 -0
- package/dist/ui/terminal.mjs +88 -0
- package/dist/ui/terminal.mjs.map +1 -0
- package/dist/version.cjs +9 -0
- package/dist/version.d.cts +5 -0
- package/dist/version.d.cts.map +1 -0
- package/dist/version.d.mts +5 -0
- package/dist/version.d.mts.map +1 -0
- package/dist/version.mjs +9 -0
- package/dist/version.mjs.map +1 -0
- package/package.json +77 -11
- package/.turbo/turbo-build.log +0 -18
- package/.turbo/turbo-check-types.log +0 -4
- package/dist/version--p6A8sKX.mjs +0 -5
- package/src/cli.test.ts +0 -8
- package/src/cli.ts +0 -29
- package/src/index.ts +0 -7
- package/src/version.ts +0 -1
- package/tsconfig.json +0 -16
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
let _aigne_afs_utils_schema = require("@aigne/afs/utils/schema");
|
|
3
|
+
|
|
4
|
+
//#region src/credential/resolver.ts
|
|
5
|
+
/**
|
|
6
|
+
* Execute the 4-step credential resolution flow.
|
|
7
|
+
*
|
|
8
|
+
* Returns all resolved values plus their split into sensitive/non-sensitive
|
|
9
|
+
* for persistence. The caller is responsible for actual persistence.
|
|
10
|
+
*
|
|
11
|
+
* @returns null if user declined/cancelled collection
|
|
12
|
+
*/
|
|
13
|
+
async function resolveCredentials(options) {
|
|
14
|
+
const { mount, schema, authContext, credentialStore, providerAuth, env = process.env } = options;
|
|
15
|
+
const properties = schema.properties;
|
|
16
|
+
if (!properties || typeof properties !== "object" || Object.keys(properties).length === 0) return {
|
|
17
|
+
values: {},
|
|
18
|
+
sensitive: {},
|
|
19
|
+
nonSensitive: {},
|
|
20
|
+
collected: false
|
|
21
|
+
};
|
|
22
|
+
const allFields = Object.keys(properties);
|
|
23
|
+
const requiredWithoutDefault = (schema.required ?? []).filter((f) => properties[f] && properties[f].default === void 0);
|
|
24
|
+
const known = {};
|
|
25
|
+
if (mount.auth !== void 0) known.auth = mount.auth;
|
|
26
|
+
if (mount.token !== void 0) known.token = mount.token;
|
|
27
|
+
if (mount.options) {
|
|
28
|
+
for (const [k, v] of Object.entries(mount.options)) if (v !== void 0) known[k] = v;
|
|
29
|
+
}
|
|
30
|
+
const getAllMissing = (resolved$1) => allFields.filter((f) => resolved$1[f] === void 0);
|
|
31
|
+
const getRequiredMissing = (resolved$1) => requiredWithoutDefault.filter((f) => resolved$1[f] === void 0);
|
|
32
|
+
let missing = getAllMissing(known);
|
|
33
|
+
if (missing.length === 0) {
|
|
34
|
+
const { sensitive: sensitive$1, nonSensitive: nonSensitive$1 } = (0, _aigne_afs_utils_schema.separateSensitiveValues)(schema, known);
|
|
35
|
+
return {
|
|
36
|
+
values: { ...known },
|
|
37
|
+
sensitive: sensitive$1,
|
|
38
|
+
nonSensitive: nonSensitive$1,
|
|
39
|
+
collected: false
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
const resolved = { ...known };
|
|
43
|
+
const envResolved = (0, _aigne_afs_utils_schema.resolveEnvFromSchema)(schema, env);
|
|
44
|
+
for (const [field, value] of Object.entries(envResolved)) if (resolved[field] === void 0) resolved[field] = value;
|
|
45
|
+
const storeResolved = {};
|
|
46
|
+
if (credentialStore) try {
|
|
47
|
+
const stored = await credentialStore.get(mount.uri);
|
|
48
|
+
if (stored) for (const [field, value] of Object.entries(stored)) if (field.startsWith("env:")) {
|
|
49
|
+
if (resolved.env === void 0) resolved.env = {};
|
|
50
|
+
resolved.env[field.slice(4)] = value;
|
|
51
|
+
if (storeResolved.env === void 0) storeResolved.env = {};
|
|
52
|
+
storeResolved.env[field.slice(4)] = value;
|
|
53
|
+
} else {
|
|
54
|
+
if (resolved[field] === void 0) resolved[field] = value;
|
|
55
|
+
storeResolved[field] = value;
|
|
56
|
+
}
|
|
57
|
+
} catch {}
|
|
58
|
+
missing = getRequiredMissing(resolved);
|
|
59
|
+
if (missing.length === 0 && !options.forceCollect) {
|
|
60
|
+
const { sensitive: sensitive$1, nonSensitive: nonSensitive$1 } = (0, _aigne_afs_utils_schema.separateSensitiveValues)(schema, resolved);
|
|
61
|
+
return {
|
|
62
|
+
values: { ...resolved },
|
|
63
|
+
sensitive: sensitive$1,
|
|
64
|
+
nonSensitive: nonSensitive$1,
|
|
65
|
+
collected: false
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
if (!authContext) {
|
|
69
|
+
const { sensitive: sensitive$1, nonSensitive: nonSensitive$1 } = (0, _aigne_afs_utils_schema.separateSensitiveValues)(schema, resolved);
|
|
70
|
+
return {
|
|
71
|
+
values: { ...resolved },
|
|
72
|
+
sensitive: sensitive$1,
|
|
73
|
+
nonSensitive: nonSensitive$1,
|
|
74
|
+
collected: false
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
let collected = null;
|
|
78
|
+
if (providerAuth) collected = await providerAuth({
|
|
79
|
+
...authContext,
|
|
80
|
+
get resolved() {
|
|
81
|
+
return { ...resolved };
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
else {
|
|
85
|
+
const fieldsForForm = allFields.filter((f) => known[f] === void 0);
|
|
86
|
+
const defaults = { ...envResolved };
|
|
87
|
+
for (const [f, v] of Object.entries(storeResolved)) if (defaults[f] === void 0) defaults[f] = v;
|
|
88
|
+
const missingSchema = buildMissingFieldsSchema(schema, fieldsForForm, defaults);
|
|
89
|
+
collected = await authContext.collect(missingSchema);
|
|
90
|
+
}
|
|
91
|
+
if (collected === null) return null;
|
|
92
|
+
for (const [field, value] of Object.entries(collected)) if (value !== void 0) resolved[field] = value;
|
|
93
|
+
const { sensitive, nonSensitive } = (0, _aigne_afs_utils_schema.separateSensitiveValues)(schema, collected);
|
|
94
|
+
return {
|
|
95
|
+
values: { ...resolved },
|
|
96
|
+
sensitive,
|
|
97
|
+
nonSensitive,
|
|
98
|
+
collected: true
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Build a JSON Schema containing only the specified fields from the original schema.
|
|
103
|
+
* Fields with env-resolved values get a `default` so the collection form can pre-fill them.
|
|
104
|
+
*/
|
|
105
|
+
function buildMissingFieldsSchema(schema, fields, envDefaults) {
|
|
106
|
+
const properties = schema.properties ?? {};
|
|
107
|
+
const required = schema.required ?? [];
|
|
108
|
+
const fieldProperties = {};
|
|
109
|
+
const fieldRequired = [];
|
|
110
|
+
for (const field of fields) if (properties[field]) {
|
|
111
|
+
let prop = properties[field];
|
|
112
|
+
if (envDefaults?.[field] !== void 0 && prop.default === void 0) prop = {
|
|
113
|
+
...prop,
|
|
114
|
+
default: envDefaults[field]
|
|
115
|
+
};
|
|
116
|
+
fieldProperties[field] = prop;
|
|
117
|
+
if (required.includes(field)) fieldRequired.push(field);
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
type: "object",
|
|
121
|
+
properties: fieldProperties,
|
|
122
|
+
...fieldRequired.length > 0 ? { required: fieldRequired } : {}
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
//#endregion
|
|
127
|
+
exports.resolveCredentials = resolveCredentials;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import { AuthContext } from "@aigne/afs";
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { resolveEnvFromSchema, separateSensitiveValues } from "@aigne/afs/utils/schema";
|
|
2
|
+
|
|
3
|
+
//#region src/credential/resolver.ts
|
|
4
|
+
/**
|
|
5
|
+
* Execute the 4-step credential resolution flow.
|
|
6
|
+
*
|
|
7
|
+
* Returns all resolved values plus their split into sensitive/non-sensitive
|
|
8
|
+
* for persistence. The caller is responsible for actual persistence.
|
|
9
|
+
*
|
|
10
|
+
* @returns null if user declined/cancelled collection
|
|
11
|
+
*/
|
|
12
|
+
async function resolveCredentials(options) {
|
|
13
|
+
const { mount, schema, authContext, credentialStore, providerAuth, env = process.env } = options;
|
|
14
|
+
const properties = schema.properties;
|
|
15
|
+
if (!properties || typeof properties !== "object" || Object.keys(properties).length === 0) return {
|
|
16
|
+
values: {},
|
|
17
|
+
sensitive: {},
|
|
18
|
+
nonSensitive: {},
|
|
19
|
+
collected: false
|
|
20
|
+
};
|
|
21
|
+
const allFields = Object.keys(properties);
|
|
22
|
+
const requiredWithoutDefault = (schema.required ?? []).filter((f) => properties[f] && properties[f].default === void 0);
|
|
23
|
+
const known = {};
|
|
24
|
+
if (mount.auth !== void 0) known.auth = mount.auth;
|
|
25
|
+
if (mount.token !== void 0) known.token = mount.token;
|
|
26
|
+
if (mount.options) {
|
|
27
|
+
for (const [k, v] of Object.entries(mount.options)) if (v !== void 0) known[k] = v;
|
|
28
|
+
}
|
|
29
|
+
const getAllMissing = (resolved$1) => allFields.filter((f) => resolved$1[f] === void 0);
|
|
30
|
+
const getRequiredMissing = (resolved$1) => requiredWithoutDefault.filter((f) => resolved$1[f] === void 0);
|
|
31
|
+
let missing = getAllMissing(known);
|
|
32
|
+
if (missing.length === 0) {
|
|
33
|
+
const { sensitive: sensitive$1, nonSensitive: nonSensitive$1 } = separateSensitiveValues(schema, known);
|
|
34
|
+
return {
|
|
35
|
+
values: { ...known },
|
|
36
|
+
sensitive: sensitive$1,
|
|
37
|
+
nonSensitive: nonSensitive$1,
|
|
38
|
+
collected: false
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
const resolved = { ...known };
|
|
42
|
+
const envResolved = resolveEnvFromSchema(schema, env);
|
|
43
|
+
for (const [field, value] of Object.entries(envResolved)) if (resolved[field] === void 0) resolved[field] = value;
|
|
44
|
+
const storeResolved = {};
|
|
45
|
+
if (credentialStore) try {
|
|
46
|
+
const stored = await credentialStore.get(mount.uri);
|
|
47
|
+
if (stored) for (const [field, value] of Object.entries(stored)) if (field.startsWith("env:")) {
|
|
48
|
+
if (resolved.env === void 0) resolved.env = {};
|
|
49
|
+
resolved.env[field.slice(4)] = value;
|
|
50
|
+
if (storeResolved.env === void 0) storeResolved.env = {};
|
|
51
|
+
storeResolved.env[field.slice(4)] = value;
|
|
52
|
+
} else {
|
|
53
|
+
if (resolved[field] === void 0) resolved[field] = value;
|
|
54
|
+
storeResolved[field] = value;
|
|
55
|
+
}
|
|
56
|
+
} catch {}
|
|
57
|
+
missing = getRequiredMissing(resolved);
|
|
58
|
+
if (missing.length === 0 && !options.forceCollect) {
|
|
59
|
+
const { sensitive: sensitive$1, nonSensitive: nonSensitive$1 } = separateSensitiveValues(schema, resolved);
|
|
60
|
+
return {
|
|
61
|
+
values: { ...resolved },
|
|
62
|
+
sensitive: sensitive$1,
|
|
63
|
+
nonSensitive: nonSensitive$1,
|
|
64
|
+
collected: false
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
if (!authContext) {
|
|
68
|
+
const { sensitive: sensitive$1, nonSensitive: nonSensitive$1 } = separateSensitiveValues(schema, resolved);
|
|
69
|
+
return {
|
|
70
|
+
values: { ...resolved },
|
|
71
|
+
sensitive: sensitive$1,
|
|
72
|
+
nonSensitive: nonSensitive$1,
|
|
73
|
+
collected: false
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
let collected = null;
|
|
77
|
+
if (providerAuth) collected = await providerAuth({
|
|
78
|
+
...authContext,
|
|
79
|
+
get resolved() {
|
|
80
|
+
return { ...resolved };
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
else {
|
|
84
|
+
const fieldsForForm = allFields.filter((f) => known[f] === void 0);
|
|
85
|
+
const defaults = { ...envResolved };
|
|
86
|
+
for (const [f, v] of Object.entries(storeResolved)) if (defaults[f] === void 0) defaults[f] = v;
|
|
87
|
+
const missingSchema = buildMissingFieldsSchema(schema, fieldsForForm, defaults);
|
|
88
|
+
collected = await authContext.collect(missingSchema);
|
|
89
|
+
}
|
|
90
|
+
if (collected === null) return null;
|
|
91
|
+
for (const [field, value] of Object.entries(collected)) if (value !== void 0) resolved[field] = value;
|
|
92
|
+
const { sensitive, nonSensitive } = separateSensitiveValues(schema, collected);
|
|
93
|
+
return {
|
|
94
|
+
values: { ...resolved },
|
|
95
|
+
sensitive,
|
|
96
|
+
nonSensitive,
|
|
97
|
+
collected: true
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Build a JSON Schema containing only the specified fields from the original schema.
|
|
102
|
+
* Fields with env-resolved values get a `default` so the collection form can pre-fill them.
|
|
103
|
+
*/
|
|
104
|
+
function buildMissingFieldsSchema(schema, fields, envDefaults) {
|
|
105
|
+
const properties = schema.properties ?? {};
|
|
106
|
+
const required = schema.required ?? [];
|
|
107
|
+
const fieldProperties = {};
|
|
108
|
+
const fieldRequired = [];
|
|
109
|
+
for (const field of fields) if (properties[field]) {
|
|
110
|
+
let prop = properties[field];
|
|
111
|
+
if (envDefaults?.[field] !== void 0 && prop.default === void 0) prop = {
|
|
112
|
+
...prop,
|
|
113
|
+
default: envDefaults[field]
|
|
114
|
+
};
|
|
115
|
+
fieldProperties[field] = prop;
|
|
116
|
+
if (required.includes(field)) fieldRequired.push(field);
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
type: "object",
|
|
120
|
+
properties: fieldProperties,
|
|
121
|
+
...fieldRequired.length > 0 ? { required: fieldRequired } : {}
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
//#endregion
|
|
126
|
+
export { resolveCredentials };
|
|
127
|
+
//# sourceMappingURL=resolver.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.mjs","names":["resolved"],"sources":["../../src/credential/resolver.ts"],"sourcesContent":["/**\n * 4-Step Credential Resolution Flow\n *\n * Step 1: Determine missing fields (from provider schema vs known values)\n * Step 2: Silent resolution (config > env > credential store)\n * Step 3: Interactive collection (provider auth() or default collect())\n * Step 4: Unified persistence (sensitive → credentials.toml, non-sensitive → config options)\n */\n\nimport type { AuthContext, JSONSchema7, MountConfig } from \"@aigne/afs\";\nimport { resolveEnvFromSchema, separateSensitiveValues } from \"@aigne/afs/utils/schema\";\nimport type { CredentialStore } from \"./store.js\";\n\nexport interface ResolveCredentialsOptions {\n /** Mount configuration */\n mount: MountConfig;\n /** JSON Schema for this provider (from z.toJSONSchema() or manifest) */\n schema: JSONSchema7;\n /** Auth context for interactive collection (CLI or MCP) */\n authContext?: AuthContext;\n /** Credential store for reading/writing credentials */\n credentialStore?: CredentialStore;\n /** Provider class with optional auth() method */\n providerAuth?: (context: AuthContext) => Promise<Record<string, unknown> | null>;\n /** Environment variables (defaults to process.env) */\n env?: Record<string, string | undefined>;\n /** Force interactive collection even when all fields are resolved silently.\n * Used for retry after health-check failure with stale env/store values. */\n forceCollect?: boolean;\n}\n\nexport interface ResolveCredentialsResult {\n /** All resolved values (merged from all sources) */\n values: Record<string, unknown>;\n /** Values to persist as sensitive credentials */\n sensitive: Record<string, string>;\n /** Values to persist as non-sensitive config options */\n nonSensitive: Record<string, unknown>;\n /** Whether any interactive collection was needed */\n collected: boolean;\n}\n\n/**\n * Execute the 4-step credential resolution flow.\n *\n * Returns all resolved values plus their split into sensitive/non-sensitive\n * for persistence. The caller is responsible for actual persistence.\n *\n * @returns null if user declined/cancelled collection\n */\nexport async function resolveCredentials(\n options: ResolveCredentialsOptions,\n): Promise<ResolveCredentialsResult | null> {\n const { mount, schema, authContext, credentialStore, providerAuth, env = process.env } = options;\n\n const properties = (schema as any).properties;\n if (!properties || typeof properties !== \"object\" || Object.keys(properties).length === 0) {\n // No fields to resolve\n return { values: {}, sensitive: {}, nonSensitive: {}, collected: false };\n }\n\n const allFields = Object.keys(properties);\n const requiredFields = ((schema as any).required ?? []) as string[];\n\n // Only required fields without a schema default truly block silent resolution —\n // optional fields and fields with defaults should not trigger interactive auth.\n const requiredWithoutDefault = requiredFields.filter(\n (f) => properties[f] && properties[f].default === undefined,\n );\n\n // ─── Step 1: Determine known values from mount config ─────────────────\n const known: Record<string, unknown> = {};\n\n // Extract values from mount.auth, mount.token, mount.options\n if (mount.auth !== undefined) known.auth = mount.auth;\n if (mount.token !== undefined) known.token = mount.token;\n if (mount.options) {\n for (const [k, v] of Object.entries(mount.options)) {\n if (v !== undefined) known[k] = v;\n }\n }\n\n // Check which fields are still missing — allFields for Step 1 optimization,\n // requiredWithoutDefault for the Step 2→3 decision on interactive auth.\n const getAllMissing = (resolved: Record<string, unknown>) =>\n allFields.filter((f) => resolved[f] === undefined);\n const getRequiredMissing = (resolved: Record<string, unknown>) =>\n requiredWithoutDefault.filter((f) => resolved[f] === undefined);\n\n let missing = getAllMissing(known);\n if (missing.length === 0) {\n // All fields already provided via config — short circuit\n const { sensitive, nonSensitive } = separateSensitiveValues(schema, known);\n return { values: { ...known }, sensitive, nonSensitive, collected: false };\n }\n\n // ─── Step 2: Silent resolution ────────────────────────────────────────\n const resolved: Record<string, unknown> = { ...known };\n\n // 2a. Environment variables from schema env declarations\n const envResolved = resolveEnvFromSchema(schema, env as Record<string, string | undefined>);\n for (const [field, value] of Object.entries(envResolved)) {\n if (resolved[field] === undefined) {\n resolved[field] = value;\n }\n }\n\n // 2b. Credential store — keyed by URI (credentials belong to the resource, not the path)\n const storeResolved: Record<string, unknown> = {};\n if (credentialStore) {\n try {\n const stored = await credentialStore.get(mount.uri);\n if (stored) {\n for (const [field, value] of Object.entries(stored)) {\n if (field.startsWith(\"env:\")) {\n // Reconstruct env Record from flattened env:KEY credential entries\n if (resolved.env === undefined) resolved.env = {};\n (resolved.env as Record<string, string>)[field.slice(4)] = value;\n if (storeResolved.env === undefined) storeResolved.env = {};\n (storeResolved.env as Record<string, string>)[field.slice(4)] = value;\n } else {\n if (resolved[field] === undefined) {\n resolved[field] = value;\n }\n storeResolved[field] = value;\n }\n }\n }\n } catch {\n // Credential store read failure is non-fatal\n }\n }\n\n missing = getRequiredMissing(resolved);\n if (missing.length === 0 && !options.forceCollect) {\n // All fields resolved silently\n const { sensitive, nonSensitive } = separateSensitiveValues(schema, resolved);\n return { values: { ...resolved }, sensitive, nonSensitive, collected: false };\n }\n\n // ─── Step 3: Interactive collection ───────────────────────────────────\n if (!authContext) {\n // No auth context available — can't collect. Return what we have.\n // Caller should attempt mount with partial values and let the provider error if needed.\n const { sensitive, nonSensitive } = separateSensitiveValues(schema, resolved);\n return { values: { ...resolved }, sensitive, nonSensitive, collected: false };\n }\n\n let collected: Record<string, unknown> | null = null;\n\n if (providerAuth) {\n // Provider has custom auth() — delegate to it\n collected = await providerAuth({\n ...authContext,\n get resolved() {\n return { ...resolved };\n },\n });\n } else {\n // Show all fields not explicitly provided via config/CLI args.\n // Env and store values are pre-filled as defaults so the user can verify/override.\n const fieldsForForm = allFields.filter((f) => known[f] === undefined);\n const defaults: Record<string, unknown> = { ...envResolved };\n for (const [f, v] of Object.entries(storeResolved)) {\n if (defaults[f] === undefined) defaults[f] = v;\n }\n const missingSchema = buildMissingFieldsSchema(schema, fieldsForForm, defaults);\n collected = await authContext.collect(missingSchema);\n }\n\n if (collected === null) {\n // User declined/cancelled\n return null;\n }\n\n // Merge collected values\n for (const [field, value] of Object.entries(collected)) {\n if (value !== undefined) {\n resolved[field] = value;\n }\n }\n\n // ─── Step 4: Split for persistence ────────────────────────────────────\n // Only split the newly collected values (not the ones from config/env/store)\n const { sensitive, nonSensitive } = separateSensitiveValues(schema, collected);\n\n return { values: { ...resolved }, sensitive, nonSensitive, collected: true };\n}\n\n/**\n * Build a JSON Schema containing only the specified fields from the original schema.\n * Fields with env-resolved values get a `default` so the collection form can pre-fill them.\n */\nfunction buildMissingFieldsSchema(\n schema: JSONSchema7,\n fields: string[],\n envDefaults?: Record<string, unknown>,\n): JSONSchema7 {\n const properties = (schema as any).properties ?? {};\n const required = ((schema as any).required ?? []) as string[];\n\n const fieldProperties: Record<string, unknown> = {};\n const fieldRequired: string[] = [];\n\n for (const field of fields) {\n if (properties[field]) {\n let prop = properties[field];\n // Pre-fill with env value so user can see and override\n if (envDefaults?.[field] !== undefined && prop.default === undefined) {\n prop = { ...prop, default: envDefaults[field] };\n }\n fieldProperties[field] = prop;\n if (required.includes(field)) {\n fieldRequired.push(field);\n }\n }\n }\n\n return {\n type: \"object\",\n properties: fieldProperties,\n ...(fieldRequired.length > 0 ? { required: fieldRequired } : {}),\n } as JSONSchema7;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
let node_fs_promises = require("node:fs/promises");
|
|
3
|
+
let node_os = require("node:os");
|
|
4
|
+
let node_path = require("node:path");
|
|
5
|
+
let smol_toml = require("smol-toml");
|
|
6
|
+
|
|
7
|
+
//#region src/credential/store.ts
|
|
8
|
+
/**
|
|
9
|
+
* CredentialStore — TOML-based credential storage.
|
|
10
|
+
*
|
|
11
|
+
* Stores sensitive credentials in ~/.afs-config/credentials.toml.
|
|
12
|
+
* Keys are composite: "configDir#mountPath" for per-project scoping.
|
|
13
|
+
* File permissions are set to 600 on creation.
|
|
14
|
+
* Writes use atomic rename to prevent corruption.
|
|
15
|
+
*/
|
|
16
|
+
const DEFAULT_DIR = ".afs-config";
|
|
17
|
+
const DEFAULT_FILE = "credentials.toml";
|
|
18
|
+
const FILE_MODE = 384;
|
|
19
|
+
/**
|
|
20
|
+
* Create a CredentialStore backed by a TOML file.
|
|
21
|
+
*/
|
|
22
|
+
function createCredentialStore(options) {
|
|
23
|
+
const filePath = options?.path ?? (0, node_path.join)((0, node_os.homedir)(), DEFAULT_DIR, DEFAULT_FILE);
|
|
24
|
+
return {
|
|
25
|
+
async get(key) {
|
|
26
|
+
validateKey(key);
|
|
27
|
+
const data = await readTOML(filePath);
|
|
28
|
+
if (!data) return void 0;
|
|
29
|
+
const section = data[key];
|
|
30
|
+
if (section === void 0 || section === null) return void 0;
|
|
31
|
+
if (typeof section !== "object" || Array.isArray(section)) throw new Error(`Invalid credentials format for URI: values must be key-value pairs`);
|
|
32
|
+
return validateCredentialValues(section);
|
|
33
|
+
},
|
|
34
|
+
async set(key, credentials) {
|
|
35
|
+
validateKey(key);
|
|
36
|
+
validateCredentialValues(credentials);
|
|
37
|
+
const data = await readTOML(filePath) ?? {};
|
|
38
|
+
data[key] = credentials;
|
|
39
|
+
await writeTOMLAtomic(filePath, data);
|
|
40
|
+
},
|
|
41
|
+
async delete(key) {
|
|
42
|
+
validateKey(key);
|
|
43
|
+
const data = await readTOML(filePath);
|
|
44
|
+
if (!data || !(key in data)) return false;
|
|
45
|
+
delete data[key];
|
|
46
|
+
await writeTOMLAtomic(filePath, data);
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function validateKey(key) {
|
|
52
|
+
if (!key || key.trim() === "") throw new Error("Credential key must not be empty");
|
|
53
|
+
}
|
|
54
|
+
function validateCredentialValues(values) {
|
|
55
|
+
for (const [key, value] of Object.entries(values)) if (typeof value !== "string") throw new Error(`Credential value for key "${key}" must be a string, got ${typeof value}`);
|
|
56
|
+
return values;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Read and parse the TOML credential file.
|
|
60
|
+
* Returns null if file does not exist. Throws on parse errors.
|
|
61
|
+
*/
|
|
62
|
+
async function readTOML(filePath) {
|
|
63
|
+
try {
|
|
64
|
+
return (0, smol_toml.parse)(await (0, node_fs_promises.readFile)(filePath, "utf-8"));
|
|
65
|
+
} catch (err) {
|
|
66
|
+
if (err?.code === "ENOENT") return null;
|
|
67
|
+
if (err?.code === "EACCES") throw new Error(`Permission denied reading credentials file: ${filePath}`);
|
|
68
|
+
if (err instanceof Error && !("code" in err)) throw new Error(`Corrupted credentials file: ${err.message}`);
|
|
69
|
+
throw err;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Write TOML data atomically using write-to-temp + rename.
|
|
74
|
+
* Creates parent directory if needed. Sets file permissions to 600 on first creation.
|
|
75
|
+
*/
|
|
76
|
+
async function writeTOMLAtomic(filePath, data) {
|
|
77
|
+
await (0, node_fs_promises.mkdir)((0, node_path.dirname)(filePath), { recursive: true });
|
|
78
|
+
const isNew = !await fileExists(filePath);
|
|
79
|
+
const content = (0, smol_toml.stringify)(data);
|
|
80
|
+
const tmpPath = `${filePath}.tmp.${process.pid}`;
|
|
81
|
+
try {
|
|
82
|
+
await (0, node_fs_promises.writeFile)(tmpPath, content, {
|
|
83
|
+
encoding: "utf-8",
|
|
84
|
+
mode: FILE_MODE
|
|
85
|
+
});
|
|
86
|
+
await (0, node_fs_promises.rename)(tmpPath, filePath);
|
|
87
|
+
} catch (err) {
|
|
88
|
+
try {
|
|
89
|
+
await (0, node_fs_promises.unlink)(tmpPath);
|
|
90
|
+
} catch {}
|
|
91
|
+
if (err?.code === "EACCES") throw new Error(`Permission denied writing credentials file: ${filePath}`);
|
|
92
|
+
throw err;
|
|
93
|
+
}
|
|
94
|
+
if (isNew) await (0, node_fs_promises.chmod)(filePath, FILE_MODE);
|
|
95
|
+
}
|
|
96
|
+
async function fileExists(filePath) {
|
|
97
|
+
try {
|
|
98
|
+
await (0, node_fs_promises.stat)(filePath);
|
|
99
|
+
return true;
|
|
100
|
+
} catch {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
//#endregion
|
|
106
|
+
exports.createCredentialStore = createCredentialStore;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//#region src/credential/store.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* CredentialStore — TOML-based credential storage.
|
|
4
|
+
*
|
|
5
|
+
* Stores sensitive credentials in ~/.afs-config/credentials.toml.
|
|
6
|
+
* Keys are composite: "configDir#mountPath" for per-project scoping.
|
|
7
|
+
* File permissions are set to 600 on creation.
|
|
8
|
+
* Writes use atomic rename to prevent corruption.
|
|
9
|
+
*/
|
|
10
|
+
/** Credential values — all string key-value pairs */
|
|
11
|
+
type Credentials = Record<string, string>;
|
|
12
|
+
interface CredentialStore {
|
|
13
|
+
/** Get credentials by key. Returns undefined if not found or file doesn't exist. */
|
|
14
|
+
get(key: string): Promise<Credentials | undefined>;
|
|
15
|
+
/** Set credentials by key. Creates file with 600 permissions if needed. */
|
|
16
|
+
set(key: string, credentials: Credentials): Promise<void>;
|
|
17
|
+
/** Delete credentials by key. Returns true if deleted, false if not found. */
|
|
18
|
+
delete(key: string): Promise<boolean>;
|
|
19
|
+
}
|
|
20
|
+
interface CredentialStoreOptions {
|
|
21
|
+
/** Path to credentials.toml. Defaults to ~/.afs-config/credentials.toml */
|
|
22
|
+
path?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Create a CredentialStore backed by a TOML file.
|
|
26
|
+
*/
|
|
27
|
+
declare function createCredentialStore(options?: CredentialStoreOptions): CredentialStore;
|
|
28
|
+
//#endregion
|
|
29
|
+
export { CredentialStore, CredentialStoreOptions, Credentials, createCredentialStore };
|
|
30
|
+
//# sourceMappingURL=store.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.cts","names":[],"sources":["../../src/credential/store.ts"],"mappings":";;AAeA;;;;;AAEA;;;KAFY,WAAA,GAAc,MAAA;AAAA,UAET,eAAA;EAKe;EAH9B,GAAA,CAAI,GAAA,WAAc,OAAA,CAAQ,WAAA;EAML;EAHrB,GAAA,CAAI,GAAA,UAAa,WAAA,EAAa,WAAA,GAAc,OAAA;EAGhB;EAA5B,MAAA,CAAO,GAAA,WAAc,OAAA;AAAA;AAAA,UAGN,sBAAA;EATW;EAW1B,IAAA;AAAA;;;;iBAUc,qBAAA,CAAsB,OAAA,GAAU,sBAAA,GAAyB,eAAA"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//#region src/credential/store.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* CredentialStore — TOML-based credential storage.
|
|
4
|
+
*
|
|
5
|
+
* Stores sensitive credentials in ~/.afs-config/credentials.toml.
|
|
6
|
+
* Keys are composite: "configDir#mountPath" for per-project scoping.
|
|
7
|
+
* File permissions are set to 600 on creation.
|
|
8
|
+
* Writes use atomic rename to prevent corruption.
|
|
9
|
+
*/
|
|
10
|
+
/** Credential values — all string key-value pairs */
|
|
11
|
+
type Credentials = Record<string, string>;
|
|
12
|
+
interface CredentialStore {
|
|
13
|
+
/** Get credentials by key. Returns undefined if not found or file doesn't exist. */
|
|
14
|
+
get(key: string): Promise<Credentials | undefined>;
|
|
15
|
+
/** Set credentials by key. Creates file with 600 permissions if needed. */
|
|
16
|
+
set(key: string, credentials: Credentials): Promise<void>;
|
|
17
|
+
/** Delete credentials by key. Returns true if deleted, false if not found. */
|
|
18
|
+
delete(key: string): Promise<boolean>;
|
|
19
|
+
}
|
|
20
|
+
interface CredentialStoreOptions {
|
|
21
|
+
/** Path to credentials.toml. Defaults to ~/.afs-config/credentials.toml */
|
|
22
|
+
path?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Create a CredentialStore backed by a TOML file.
|
|
26
|
+
*/
|
|
27
|
+
declare function createCredentialStore(options?: CredentialStoreOptions): CredentialStore;
|
|
28
|
+
//#endregion
|
|
29
|
+
export { CredentialStore, CredentialStoreOptions, Credentials, createCredentialStore };
|
|
30
|
+
//# sourceMappingURL=store.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.mts","names":[],"sources":["../../src/credential/store.ts"],"mappings":";;AAeA;;;;;AAEA;;;KAFY,WAAA,GAAc,MAAA;AAAA,UAET,eAAA;EAKe;EAH9B,GAAA,CAAI,GAAA,WAAc,OAAA,CAAQ,WAAA;EAML;EAHrB,GAAA,CAAI,GAAA,UAAa,WAAA,EAAa,WAAA,GAAc,OAAA;EAGhB;EAA5B,MAAA,CAAO,GAAA,WAAc,OAAA;AAAA;AAAA,UAGN,sBAAA;EATW;EAW1B,IAAA;AAAA;;;;iBAUc,qBAAA,CAAsB,OAAA,GAAU,sBAAA,GAAyB,eAAA"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { chmod, mkdir, readFile, rename, stat, unlink, writeFile } from "node:fs/promises";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { parse, stringify } from "smol-toml";
|
|
5
|
+
|
|
6
|
+
//#region src/credential/store.ts
|
|
7
|
+
/**
|
|
8
|
+
* CredentialStore — TOML-based credential storage.
|
|
9
|
+
*
|
|
10
|
+
* Stores sensitive credentials in ~/.afs-config/credentials.toml.
|
|
11
|
+
* Keys are composite: "configDir#mountPath" for per-project scoping.
|
|
12
|
+
* File permissions are set to 600 on creation.
|
|
13
|
+
* Writes use atomic rename to prevent corruption.
|
|
14
|
+
*/
|
|
15
|
+
const DEFAULT_DIR = ".afs-config";
|
|
16
|
+
const DEFAULT_FILE = "credentials.toml";
|
|
17
|
+
const FILE_MODE = 384;
|
|
18
|
+
/**
|
|
19
|
+
* Create a CredentialStore backed by a TOML file.
|
|
20
|
+
*/
|
|
21
|
+
function createCredentialStore(options) {
|
|
22
|
+
const filePath = options?.path ?? join(homedir(), DEFAULT_DIR, DEFAULT_FILE);
|
|
23
|
+
return {
|
|
24
|
+
async get(key) {
|
|
25
|
+
validateKey(key);
|
|
26
|
+
const data = await readTOML(filePath);
|
|
27
|
+
if (!data) return void 0;
|
|
28
|
+
const section = data[key];
|
|
29
|
+
if (section === void 0 || section === null) return void 0;
|
|
30
|
+
if (typeof section !== "object" || Array.isArray(section)) throw new Error(`Invalid credentials format for URI: values must be key-value pairs`);
|
|
31
|
+
return validateCredentialValues(section);
|
|
32
|
+
},
|
|
33
|
+
async set(key, credentials) {
|
|
34
|
+
validateKey(key);
|
|
35
|
+
validateCredentialValues(credentials);
|
|
36
|
+
const data = await readTOML(filePath) ?? {};
|
|
37
|
+
data[key] = credentials;
|
|
38
|
+
await writeTOMLAtomic(filePath, data);
|
|
39
|
+
},
|
|
40
|
+
async delete(key) {
|
|
41
|
+
validateKey(key);
|
|
42
|
+
const data = await readTOML(filePath);
|
|
43
|
+
if (!data || !(key in data)) return false;
|
|
44
|
+
delete data[key];
|
|
45
|
+
await writeTOMLAtomic(filePath, data);
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function validateKey(key) {
|
|
51
|
+
if (!key || key.trim() === "") throw new Error("Credential key must not be empty");
|
|
52
|
+
}
|
|
53
|
+
function validateCredentialValues(values) {
|
|
54
|
+
for (const [key, value] of Object.entries(values)) if (typeof value !== "string") throw new Error(`Credential value for key "${key}" must be a string, got ${typeof value}`);
|
|
55
|
+
return values;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Read and parse the TOML credential file.
|
|
59
|
+
* Returns null if file does not exist. Throws on parse errors.
|
|
60
|
+
*/
|
|
61
|
+
async function readTOML(filePath) {
|
|
62
|
+
try {
|
|
63
|
+
return parse(await readFile(filePath, "utf-8"));
|
|
64
|
+
} catch (err) {
|
|
65
|
+
if (err?.code === "ENOENT") return null;
|
|
66
|
+
if (err?.code === "EACCES") throw new Error(`Permission denied reading credentials file: ${filePath}`);
|
|
67
|
+
if (err instanceof Error && !("code" in err)) throw new Error(`Corrupted credentials file: ${err.message}`);
|
|
68
|
+
throw err;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Write TOML data atomically using write-to-temp + rename.
|
|
73
|
+
* Creates parent directory if needed. Sets file permissions to 600 on first creation.
|
|
74
|
+
*/
|
|
75
|
+
async function writeTOMLAtomic(filePath, data) {
|
|
76
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
77
|
+
const isNew = !await fileExists(filePath);
|
|
78
|
+
const content = stringify(data);
|
|
79
|
+
const tmpPath = `${filePath}.tmp.${process.pid}`;
|
|
80
|
+
try {
|
|
81
|
+
await writeFile(tmpPath, content, {
|
|
82
|
+
encoding: "utf-8",
|
|
83
|
+
mode: FILE_MODE
|
|
84
|
+
});
|
|
85
|
+
await rename(tmpPath, filePath);
|
|
86
|
+
} catch (err) {
|
|
87
|
+
try {
|
|
88
|
+
await unlink(tmpPath);
|
|
89
|
+
} catch {}
|
|
90
|
+
if (err?.code === "EACCES") throw new Error(`Permission denied writing credentials file: ${filePath}`);
|
|
91
|
+
throw err;
|
|
92
|
+
}
|
|
93
|
+
if (isNew) await chmod(filePath, FILE_MODE);
|
|
94
|
+
}
|
|
95
|
+
async function fileExists(filePath) {
|
|
96
|
+
try {
|
|
97
|
+
await stat(filePath);
|
|
98
|
+
return true;
|
|
99
|
+
} catch {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
//#endregion
|
|
105
|
+
export { createCredentialStore };
|
|
106
|
+
//# sourceMappingURL=store.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.mjs","names":[],"sources":["../../src/credential/store.ts"],"sourcesContent":["/**\n * CredentialStore — TOML-based credential storage.\n *\n * Stores sensitive credentials in ~/.afs-config/credentials.toml.\n * Keys are composite: \"configDir#mountPath\" for per-project scoping.\n * File permissions are set to 600 on creation.\n * Writes use atomic rename to prevent corruption.\n */\n\nimport { chmod, mkdir, readFile, rename, stat, unlink, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { parse, stringify } from \"smol-toml\";\n\n/** Credential values — all string key-value pairs */\nexport type Credentials = Record<string, string>;\n\nexport interface CredentialStore {\n /** Get credentials by key. Returns undefined if not found or file doesn't exist. */\n get(key: string): Promise<Credentials | undefined>;\n\n /** Set credentials by key. Creates file with 600 permissions if needed. */\n set(key: string, credentials: Credentials): Promise<void>;\n\n /** Delete credentials by key. Returns true if deleted, false if not found. */\n delete(key: string): Promise<boolean>;\n}\n\nexport interface CredentialStoreOptions {\n /** Path to credentials.toml. Defaults to ~/.afs-config/credentials.toml */\n path?: string;\n}\n\nconst DEFAULT_DIR = \".afs-config\";\nconst DEFAULT_FILE = \"credentials.toml\";\nconst FILE_MODE = 0o600;\n\n/**\n * Create a CredentialStore backed by a TOML file.\n */\nexport function createCredentialStore(options?: CredentialStoreOptions): CredentialStore {\n const filePath = options?.path ?? join(homedir(), DEFAULT_DIR, DEFAULT_FILE);\n\n return {\n async get(key: string): Promise<Credentials | undefined> {\n validateKey(key);\n const data = await readTOML(filePath);\n if (!data) return undefined;\n const section = data[key];\n if (section === undefined || section === null) return undefined;\n if (typeof section !== \"object\" || Array.isArray(section)) {\n throw new Error(`Invalid credentials format for URI: values must be key-value pairs`);\n }\n return validateCredentialValues(section as Record<string, unknown>);\n },\n\n async set(key: string, credentials: Credentials): Promise<void> {\n validateKey(key);\n validateCredentialValues(credentials);\n const data = (await readTOML(filePath)) ?? {};\n data[key] = credentials;\n await writeTOMLAtomic(filePath, data);\n },\n\n async delete(key: string): Promise<boolean> {\n validateKey(key);\n const data = await readTOML(filePath);\n if (!data || !(key in data)) return false;\n delete data[key];\n await writeTOMLAtomic(filePath, data);\n return true;\n },\n };\n}\n\nfunction validateKey(key: string): void {\n if (!key || key.trim() === \"\") {\n throw new Error(\"Credential key must not be empty\");\n }\n}\n\nfunction validateCredentialValues(values: Record<string, unknown>): Credentials {\n for (const [key, value] of Object.entries(values)) {\n if (typeof value !== \"string\") {\n throw new Error(`Credential value for key \"${key}\" must be a string, got ${typeof value}`);\n }\n }\n return values as Credentials;\n}\n\n/**\n * Read and parse the TOML credential file.\n * Returns null if file does not exist. Throws on parse errors.\n */\nasync function readTOML(filePath: string): Promise<Record<string, any> | null> {\n try {\n const content = await readFile(filePath, \"utf-8\");\n return parse(content) as Record<string, any>;\n } catch (err: any) {\n if (err?.code === \"ENOENT\") return null;\n if (err?.code === \"EACCES\") {\n throw new Error(`Permission denied reading credentials file: ${filePath}`);\n }\n // smol-toml parse errors\n if (err instanceof Error && !(\"code\" in err)) {\n throw new Error(`Corrupted credentials file: ${err.message}`);\n }\n throw err;\n }\n}\n\n/**\n * Write TOML data atomically using write-to-temp + rename.\n * Creates parent directory if needed. Sets file permissions to 600 on first creation.\n */\nasync function writeTOMLAtomic(filePath: string, data: Record<string, any>): Promise<void> {\n const dir = dirname(filePath);\n await mkdir(dir, { recursive: true });\n\n const isNew = !(await fileExists(filePath));\n const content = stringify(data);\n const tmpPath = `${filePath}.tmp.${process.pid}`;\n\n try {\n await writeFile(tmpPath, content, { encoding: \"utf-8\", mode: FILE_MODE });\n await rename(tmpPath, filePath);\n } catch (err: any) {\n // Clean up temp file on failure\n try {\n await unlink(tmpPath);\n } catch {\n // ignore cleanup errors\n }\n if (err?.code === \"EACCES\") {\n throw new Error(`Permission denied writing credentials file: ${filePath}`);\n }\n throw err;\n }\n\n // Set permissions on first creation only\n if (isNew) {\n await chmod(filePath, FILE_MODE);\n }\n}\n\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await stat(filePath);\n return true;\n } catch {\n return false;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAiCA,MAAM,cAAc;AACpB,MAAM,eAAe;AACrB,MAAM,YAAY;;;;AAKlB,SAAgB,sBAAsB,SAAmD;CACvF,MAAM,WAAW,SAAS,QAAQ,KAAK,SAAS,EAAE,aAAa,aAAa;AAE5E,QAAO;EACL,MAAM,IAAI,KAA+C;AACvD,eAAY,IAAI;GAChB,MAAM,OAAO,MAAM,SAAS,SAAS;AACrC,OAAI,CAAC,KAAM,QAAO;GAClB,MAAM,UAAU,KAAK;AACrB,OAAI,YAAY,UAAa,YAAY,KAAM,QAAO;AACtD,OAAI,OAAO,YAAY,YAAY,MAAM,QAAQ,QAAQ,CACvD,OAAM,IAAI,MAAM,qEAAqE;AAEvF,UAAO,yBAAyB,QAAmC;;EAGrE,MAAM,IAAI,KAAa,aAAyC;AAC9D,eAAY,IAAI;AAChB,4BAAyB,YAAY;GACrC,MAAM,OAAQ,MAAM,SAAS,SAAS,IAAK,EAAE;AAC7C,QAAK,OAAO;AACZ,SAAM,gBAAgB,UAAU,KAAK;;EAGvC,MAAM,OAAO,KAA+B;AAC1C,eAAY,IAAI;GAChB,MAAM,OAAO,MAAM,SAAS,SAAS;AACrC,OAAI,CAAC,QAAQ,EAAE,OAAO,MAAO,QAAO;AACpC,UAAO,KAAK;AACZ,SAAM,gBAAgB,UAAU,KAAK;AACrC,UAAO;;EAEV;;AAGH,SAAS,YAAY,KAAmB;AACtC,KAAI,CAAC,OAAO,IAAI,MAAM,KAAK,GACzB,OAAM,IAAI,MAAM,mCAAmC;;AAIvD,SAAS,yBAAyB,QAA8C;AAC9E,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,CAC/C,KAAI,OAAO,UAAU,SACnB,OAAM,IAAI,MAAM,6BAA6B,IAAI,0BAA0B,OAAO,QAAQ;AAG9F,QAAO;;;;;;AAOT,eAAe,SAAS,UAAuD;AAC7E,KAAI;AAEF,SAAO,MADS,MAAM,SAAS,UAAU,QAAQ,CAC5B;UACd,KAAU;AACjB,MAAI,KAAK,SAAS,SAAU,QAAO;AACnC,MAAI,KAAK,SAAS,SAChB,OAAM,IAAI,MAAM,+CAA+C,WAAW;AAG5E,MAAI,eAAe,SAAS,EAAE,UAAU,KACtC,OAAM,IAAI,MAAM,+BAA+B,IAAI,UAAU;AAE/D,QAAM;;;;;;;AAQV,eAAe,gBAAgB,UAAkB,MAA0C;AAEzF,OAAM,MADM,QAAQ,SAAS,EACZ,EAAE,WAAW,MAAM,CAAC;CAErC,MAAM,QAAQ,CAAE,MAAM,WAAW,SAAS;CAC1C,MAAM,UAAU,UAAU,KAAK;CAC/B,MAAM,UAAU,GAAG,SAAS,OAAO,QAAQ;AAE3C,KAAI;AACF,QAAM,UAAU,SAAS,SAAS;GAAE,UAAU;GAAS,MAAM;GAAW,CAAC;AACzE,QAAM,OAAO,SAAS,SAAS;UACxB,KAAU;AAEjB,MAAI;AACF,SAAM,OAAO,QAAQ;UACf;AAGR,MAAI,KAAK,SAAS,SAChB,OAAM,IAAI,MAAM,+CAA+C,WAAW;AAE5E,QAAM;;AAIR,KAAI,MACF,OAAM,MAAM,UAAU,UAAU;;AAIpC,eAAe,WAAW,UAAoC;AAC5D,KAAI;AACF,QAAM,KAAK,SAAS;AACpB,SAAO;SACD;AACN,SAAO"}
|
package/dist/errors.cjs
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/errors.ts
|
|
3
|
+
/**
|
|
4
|
+
* AFS CLI Exit Codes
|
|
5
|
+
*
|
|
6
|
+
* Exit codes are part of the protocol - agents and scripts depend on them.
|
|
7
|
+
*/
|
|
8
|
+
const ExitCode = {
|
|
9
|
+
OK: 0,
|
|
10
|
+
NOT_FOUND: 1,
|
|
11
|
+
PERMISSION_DENIED: 2,
|
|
12
|
+
CONFLICT: 3,
|
|
13
|
+
PARTIAL: 4,
|
|
14
|
+
RUNTIME_ERROR: 5
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
//#endregion
|
|
18
|
+
exports.ExitCode = ExitCode;
|
package/dist/errors.mjs
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region src/errors.ts
|
|
2
|
+
/**
|
|
3
|
+
* AFS CLI Exit Codes
|
|
4
|
+
*
|
|
5
|
+
* Exit codes are part of the protocol - agents and scripts depend on them.
|
|
6
|
+
*/
|
|
7
|
+
const ExitCode = {
|
|
8
|
+
OK: 0,
|
|
9
|
+
NOT_FOUND: 1,
|
|
10
|
+
PERMISSION_DENIED: 2,
|
|
11
|
+
CONFLICT: 3,
|
|
12
|
+
PARTIAL: 4,
|
|
13
|
+
RUNTIME_ERROR: 5
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
//#endregion
|
|
17
|
+
export { ExitCode };
|
|
18
|
+
//# sourceMappingURL=errors.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.mjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/**\n * AFS CLI Exit Codes\n *\n * Exit codes are part of the protocol - agents and scripts depend on them.\n */\nexport const ExitCode = {\n /** Operation successful */\n OK: 0,\n /** Path or resource not found */\n NOT_FOUND: 1,\n /** Permission denied */\n PERMISSION_DENIED: 2,\n /** Conflict (e.g., concurrent modification) */\n CONFLICT: 3,\n /** Partial success (some operations succeeded, some failed) */\n PARTIAL: 4,\n /** Runtime error */\n RUNTIME_ERROR: 5,\n} as const;\n\nexport type ExitCodeType = (typeof ExitCode)[keyof typeof ExitCode];\n\n/**\n * CLI Error with exit code\n */\nexport class CLIError extends Error {\n constructor(\n message: string,\n public exitCode: ExitCodeType = ExitCode.RUNTIME_ERROR,\n ) {\n super(message);\n this.name = \"CLIError\";\n }\n}\n\n/**\n * Not found error\n */\nexport class NotFoundError extends CLIError {\n constructor(message: string) {\n super(message, ExitCode.NOT_FOUND);\n this.name = \"NotFoundError\";\n }\n}\n\n/**\n * Permission denied error\n */\nexport class PermissionDeniedError extends CLIError {\n constructor(message: string) {\n super(message, ExitCode.PERMISSION_DENIED);\n this.name = \"PermissionDeniedError\";\n }\n}\n"],"mappings":";;;;;;AAKA,MAAa,WAAW;CAEtB,IAAI;CAEJ,WAAW;CAEX,mBAAmB;CAEnB,UAAU;CAEV,SAAS;CAET,eAAe;CAChB"}
|