aquaman-coder 0.12.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.
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Project resolver — maps a working directory to an aquaman project
3
+ * config in `~/.aquaman/projects.yaml`.
4
+ *
5
+ * Each project declares:
6
+ * - one or more paths it owns (longest-prefix wins)
7
+ * - an env map: ENV_VAR_NAME → aquaman://service/key reference
8
+ *
9
+ * The resolver materializes references to real credentials by calling
10
+ * the broker over UDS — see `./broker-client.ts`.
11
+ */
12
+ import * as fs from 'node:fs';
13
+ import * as os from 'node:os';
14
+ import * as path from 'node:path';
15
+ import { parse as yamlParse, stringify as yamlStringify } from 'yaml';
16
+ // Service must be lowercase (matches the daemon's SAFE_SERVICE_NAME).
17
+ // Key allows uppercase to match the daemon's broader SAFE_KEY_NAME so
18
+ // vault entries like `aws/SECRET_ACCESS_KEY` can be referenced.
19
+ const AQUAMAN_REF = /^aquaman:\/\/([a-z0-9][a-z0-9._-]*)\/([a-zA-Z0-9][a-zA-Z0-9._-]*)$/;
20
+ const POSIX_ENV_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
21
+ export function defaultProjectsPath() {
22
+ return path.join(os.homedir(), '.aquaman', 'projects.yaml');
23
+ }
24
+ /**
25
+ * Expand `~` and resolve to an absolute path.
26
+ */
27
+ function expandPath(p) {
28
+ if (p.startsWith('~/') || p === '~') {
29
+ return path.join(os.homedir(), p.slice(1));
30
+ }
31
+ return path.resolve(p);
32
+ }
33
+ /**
34
+ * Load and validate a projects.yaml file. Returns an empty config if
35
+ * the file does not exist. Throws on malformed YAML or invalid refs.
36
+ */
37
+ export function loadProjects(projectsPath = defaultProjectsPath()) {
38
+ if (!fs.existsSync(projectsPath)) {
39
+ return { version: 1, projects: {} };
40
+ }
41
+ const raw = fs.readFileSync(projectsPath, 'utf-8');
42
+ const parsed = yamlParse(raw);
43
+ if (!parsed || typeof parsed !== 'object' || !parsed.projects) {
44
+ return { version: 1, projects: {} };
45
+ }
46
+ // Validate each project — surface bad refs as parse errors.
47
+ for (const [name, cfg] of Object.entries(parsed.projects)) {
48
+ if (!Array.isArray(cfg.paths) || cfg.paths.length === 0) {
49
+ throw new Error(`Project "${name}" has no paths`);
50
+ }
51
+ if (!cfg.env || typeof cfg.env !== 'object') {
52
+ cfg.env = {};
53
+ continue;
54
+ }
55
+ for (const [envKey, ref] of Object.entries(cfg.env)) {
56
+ if (!POSIX_ENV_NAME.test(envKey)) {
57
+ throw new Error(`Project "${name}" has invalid env name "${envKey}". ` +
58
+ `POSIX env names must match /^[A-Za-z_][A-Za-z0-9_]*$/`);
59
+ }
60
+ if (typeof ref !== 'string' || !AQUAMAN_REF.test(ref)) {
61
+ throw new Error(`Project "${name}" env ${envKey} has invalid reference: "${ref}". ` +
62
+ `Expected aquaman://<service>/<key>`);
63
+ }
64
+ }
65
+ }
66
+ return parsed;
67
+ }
68
+ /**
69
+ * Write projects.yaml atomically. Creates parent directory if needed.
70
+ */
71
+ export function saveProjects(file, projectsPath = defaultProjectsPath()) {
72
+ const dir = path.dirname(projectsPath);
73
+ if (!fs.existsSync(dir)) {
74
+ fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
75
+ }
76
+ const yaml = yamlStringify({ version: file.version ?? 1, projects: file.projects });
77
+ const tmp = projectsPath + '.tmp';
78
+ fs.writeFileSync(tmp, yaml, { mode: 0o600 });
79
+ fs.renameSync(tmp, projectsPath);
80
+ }
81
+ /**
82
+ * Try to resolve symlinks; fall back to literal path if the target
83
+ * does not exist. macOS's /var → /private/var symlink trips up naive
84
+ * string matching, hence this helper.
85
+ */
86
+ function realpathOrLiteral(p) {
87
+ try {
88
+ return fs.realpathSync(p);
89
+ }
90
+ catch {
91
+ return p;
92
+ }
93
+ }
94
+ /**
95
+ * Given a working directory, return the matching project config (or
96
+ * null if none matches). Longest-prefix wins so nested projects work.
97
+ */
98
+ export function findProjectForCwd(cwd, file) {
99
+ const absCwd = realpathOrLiteral(path.resolve(cwd));
100
+ let best = null;
101
+ for (const [name, cfg] of Object.entries(file.projects)) {
102
+ for (const declaredPath of cfg.paths) {
103
+ const abs = realpathOrLiteral(expandPath(declaredPath));
104
+ if (absCwd === abs || absCwd.startsWith(abs + path.sep)) {
105
+ if (!best || abs.length > best.prefixLen) {
106
+ best = { name, config: cfg, prefixLen: abs.length };
107
+ }
108
+ }
109
+ }
110
+ }
111
+ if (!best)
112
+ return null;
113
+ return { name: best.name, config: best.config };
114
+ }
115
+ /**
116
+ * Parse an aquaman:// reference into (service, key).
117
+ */
118
+ export function parseRef(ref) {
119
+ const m = AQUAMAN_REF.exec(ref);
120
+ if (!m)
121
+ return null;
122
+ return { service: m[1], key: m[2] };
123
+ }
124
+ //# sourceMappingURL=projects.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projects.js","sourceRoot":"","sources":["../src/projects.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "aquaman-coder",
3
+ "version": "0.12.0",
4
+ "description": "Vault adapter for AI coding agents. Keep API keys, secrets, and .env contents out of your coding agent's memory and transcripts. Supports Claude Code (Codex, OpenCode, Cursor coming soon).",
5
+ "type": "module",
6
+ "bin": {
7
+ "aquaman-coder": "dist/cli/index.js"
8
+ },
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "scripts": {
16
+ "build": "tsc -b",
17
+ "prepublishOnly": "npm run clean && npm run build",
18
+ "clean": "rm -rf dist tsconfig.tsbuildinfo"
19
+ },
20
+ "keywords": [
21
+ "aquaman",
22
+ "aquaman-coder",
23
+ "claude-code",
24
+ "codex",
25
+ "opencode",
26
+ "cursor",
27
+ "credentials",
28
+ "vault",
29
+ "secrets",
30
+ "dotenv",
31
+ "secret-management",
32
+ "credential-isolation",
33
+ "coding-agent",
34
+ "ai-agent",
35
+ "1password",
36
+ "keychain",
37
+ "bitwarden"
38
+ ],
39
+ "author": "tech4242",
40
+ "license": "MIT",
41
+ "dependencies": {
42
+ "aquaman-proxy": "0.12.0",
43
+ "commander": "^11.0.0",
44
+ "yaml": "^2.3.4"
45
+ },
46
+ "devDependencies": {
47
+ "@types/node": "^20.10.0",
48
+ "typescript": "^5.3.0"
49
+ },
50
+ "files": [
51
+ "dist",
52
+ "LICENSE",
53
+ "README.md"
54
+ ],
55
+ "repository": {
56
+ "type": "git",
57
+ "url": "https://github.com/tech4242/aquaman.git",
58
+ "directory": "packages/coder"
59
+ },
60
+ "engines": {
61
+ "node": ">=18.0.0"
62
+ },
63
+ "homepage": "https://github.com/tech4242/aquaman/tree/main/packages/coder#readme",
64
+ "bugs": {
65
+ "url": "https://github.com/tech4242/aquaman/issues"
66
+ }
67
+ }