@ant.sh/colony 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.
Files changed (62) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +172 -0
  3. package/dist/cjs/cli.js +281 -0
  4. package/dist/cjs/cli.js.map +7 -0
  5. package/dist/cjs/index.js +383 -0
  6. package/dist/cjs/index.js.map +7 -0
  7. package/dist/cjs/package.json +3 -0
  8. package/dist/cjs/parser.js +319 -0
  9. package/dist/cjs/parser.js.map +7 -0
  10. package/dist/cjs/providers/aws.js +115 -0
  11. package/dist/cjs/providers/aws.js.map +7 -0
  12. package/dist/cjs/providers/openbao.js +49 -0
  13. package/dist/cjs/providers/openbao.js.map +7 -0
  14. package/dist/cjs/providers/vault-base.js +98 -0
  15. package/dist/cjs/providers/vault-base.js.map +7 -0
  16. package/dist/cjs/providers/vault.js +49 -0
  17. package/dist/cjs/providers/vault.js.map +7 -0
  18. package/dist/cjs/resolver.js +247 -0
  19. package/dist/cjs/resolver.js.map +7 -0
  20. package/dist/cjs/secrets.js +238 -0
  21. package/dist/cjs/secrets.js.map +7 -0
  22. package/dist/cjs/strings.js +99 -0
  23. package/dist/cjs/strings.js.map +7 -0
  24. package/dist/cjs/util.js +74 -0
  25. package/dist/cjs/util.js.map +7 -0
  26. package/dist/esm/cli.js +281 -0
  27. package/dist/esm/cli.js.map +7 -0
  28. package/dist/esm/index.d.ts +342 -0
  29. package/dist/esm/index.js +347 -0
  30. package/dist/esm/index.js.map +7 -0
  31. package/dist/esm/package.json +3 -0
  32. package/dist/esm/parser.js +286 -0
  33. package/dist/esm/parser.js.map +7 -0
  34. package/dist/esm/providers/aws.js +82 -0
  35. package/dist/esm/providers/aws.js.map +7 -0
  36. package/dist/esm/providers/openbao.js +26 -0
  37. package/dist/esm/providers/openbao.js.map +7 -0
  38. package/dist/esm/providers/vault-base.js +75 -0
  39. package/dist/esm/providers/vault-base.js.map +7 -0
  40. package/dist/esm/providers/vault.js +26 -0
  41. package/dist/esm/providers/vault.js.map +7 -0
  42. package/dist/esm/resolver.js +224 -0
  43. package/dist/esm/resolver.js.map +7 -0
  44. package/dist/esm/secrets.js +209 -0
  45. package/dist/esm/secrets.js.map +7 -0
  46. package/dist/esm/strings.js +75 -0
  47. package/dist/esm/strings.js.map +7 -0
  48. package/dist/esm/util.js +47 -0
  49. package/dist/esm/util.js.map +7 -0
  50. package/package.json +66 -0
  51. package/src/cli.js +353 -0
  52. package/src/index.d.ts +342 -0
  53. package/src/index.js +473 -0
  54. package/src/parser.js +381 -0
  55. package/src/providers/aws.js +112 -0
  56. package/src/providers/openbao.js +32 -0
  57. package/src/providers/vault-base.js +92 -0
  58. package/src/providers/vault.js +31 -0
  59. package/src/resolver.js +286 -0
  60. package/src/secrets.js +313 -0
  61. package/src/strings.js +84 -0
  62. package/src/util.js +49 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/index.js"],
4
+ "sourcesContent": ["import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport fg from \"fast-glob\";\nimport { parseColony } from \"./parser.js\";\nimport { resolveRules } from \"./resolver.js\";\nimport {\n applySecretsDeep,\n SecretCache,\n hasGlobalProviders,\n registerSecretProvider,\n unregisterSecretProvider,\n clearSecretProviders,\n} from \"./secrets.js\";\n\n// Re-export secrets functions\nexport { registerSecretProvider, unregisterSecretProvider, clearSecretProviders };\n\n// Re-export providers\nexport { AwsSecretsProvider } from \"./providers/aws.js\";\nexport { VaultProvider } from \"./providers/vault.js\";\nexport { OpenBaoProvider } from \"./providers/openbao.js\";\n\n/**\n * @param {object} opts\n * @param {string} opts.entry\n * @param {string[]=} opts.dims\n * @param {Record<string,string>=} opts.ctx\n * @param {Record<string,string>=} opts.vars\n * @param {(cfg: any) => any=} opts.schema // optional validation hook (e.g. zod.parse)\n * @param {object=} opts.sandbox // security options\n * @param {string=} opts.sandbox.basePath // restrict includes to this directory\n * @param {string[]=} opts.sandbox.allowedEnvVars // whitelist of allowed env vars (null = allow all)\n * @param {number=} opts.sandbox.maxIncludeDepth // max depth for includes (default 50)\n * @param {boolean=} opts.warnOnSkippedIncludes // warn when skipping already-visited includes\n * @param {object=} opts.secrets // secrets provider options\n * @param {Array=} opts.secrets.providers // secret providers (e.g. AwsSecretsProvider)\n * @param {string[]=} opts.secrets.allowedSecrets // whitelist of allowed secret patterns\n * @param {object=} opts.secrets.cache // cache options\n * @param {string=} opts.secrets.onNotFound // 'empty' | 'warn' | 'error' (default: 'warn')\n * @returns {Promise<object>}\n */\nexport async function loadColony(opts) {\n const entry = opts?.entry;\n if (!entry) throw new Error(\"loadColony: opts.entry is required\");\n\n const sandbox = opts.sandbox ?? {};\n const basePath = sandbox.basePath ? path.resolve(sandbox.basePath) : null;\n const maxIncludeDepth = sandbox.maxIncludeDepth ?? 50;\n const maxFileSize = sandbox.maxFileSize ?? null;\n const warnOnSkippedIncludes = opts.warnOnSkippedIncludes ?? false;\n\n const visited = new Set();\n const warnings = [];\n const files = await expandIncludes(entry, visited, {\n basePath,\n maxIncludeDepth,\n maxFileSize,\n warnOnSkippedIncludes,\n warnings,\n });\n\n const parsed = [];\n for (const file of files) {\n const text = await fs.readFile(file, \"utf8\");\n parsed.push(parseColony(text, { filePath: file }));\n }\n\n const dims =\n (Array.isArray(opts.dims) && opts.dims.length ? opts.dims : null) ??\n parsed.find((p) => p.dims?.length)?.dims ??\n [\"env\"];\n\n // ctx precedence: opts.ctx overrides, else @envDefaults, else sensible defaults\n const envDefaults = mergeEnvDefaults(parsed.map((p) => p.envDefaults ?? {}));\n const ctx = {\n ...envDefaults,\n env: process.env.NODE_ENV ?? \"dev\",\n ...opts.ctx,\n };\n\n const vars = { ROOT: process.cwd(), ...(opts.vars ?? {}) };\n\n // Collect requires from all parsed files\n const requires = parsed.flatMap((p) => p.requires ?? []);\n\n const allRules = parsed.flatMap((p) => p.rules);\n\n const allowedEnvVars = sandbox.allowedEnvVars ?? null;\n const allowedVars = sandbox.allowedVars ?? null;\n let cfg = resolveRules({ rules: allRules, dims, ctx, vars, allowedEnvVars, allowedVars, warnings });\n\n // Apply secrets if providers are configured\n const secretsOpts = opts.secrets ?? {};\n if (secretsOpts.providers?.length || hasGlobalProviders()) {\n const cacheOpts = secretsOpts.cache ?? {};\n const cache = cacheOpts.enabled !== false\n ? new SecretCache(cacheOpts.maxSize ?? 100)\n : null;\n\n const secretified = await applySecretsDeep(cfg, {\n providers: secretsOpts.providers ?? [],\n allowedSecrets: secretsOpts.allowedSecrets ?? null,\n cache,\n cacheTtl: cacheOpts.ttl ?? 300000,\n onNotFound: secretsOpts.onNotFound ?? \"warn\",\n warnings,\n });\n\n // Copy config methods to new object\n copyConfigMethods(secretified, cfg, warnings);\n cfg = secretified;\n }\n\n // Enforce @require after resolution\n const missing = [];\n for (const reqKey of requires) {\n if (cfg.get(reqKey) === undefined) missing.push(reqKey);\n }\n if (missing.length) {\n throw new Error(\n `COLONY @require failed (missing keys):\\n` +\n missing.map((k) => ` - ${k}`).join(\"\\n\")\n );\n }\n\n // Attach warnings as non-enumerable\n Object.defineProperty(cfg, \"_warnings\", { enumerable: false, value: warnings });\n\n // Optional schema validation hook (supports both sync and async)\n if (typeof opts.schema === \"function\") {\n const result = opts.schema(cfg);\n\n // Handle async schema validators (e.g., async Zod, Joi)\n if (result && typeof result.then === \"function\") {\n const validated = await result;\n if (validated && validated !== cfg) {\n copyConfigMethods(validated, cfg, warnings);\n return validated;\n }\n } else if (result && result !== cfg) {\n copyConfigMethods(result, cfg, warnings);\n return result;\n }\n }\n\n return cfg;\n}\n\n/**\n * Copy non-enumerable config methods to validated object\n */\nfunction copyConfigMethods(target, source, warnings) {\n Object.defineProperties(target, {\n get: { enumerable: false, value: source.get },\n explain: { enumerable: false, value: source.explain },\n toJSON: { enumerable: false, value: source.toJSON },\n keys: { enumerable: false, value: source.keys },\n diff: { enumerable: false, value: source.diff },\n _trace: { enumerable: false, value: source._trace },\n _warnings: { enumerable: false, value: warnings },\n });\n}\n\nfunction mergeEnvDefaults(list) {\n const out = {};\n for (const m of list) {\n for (const [k, v] of Object.entries(m)) out[k] = v;\n }\n return out;\n}\n\nasync function expandIncludes(entry, visited, { basePath, maxIncludeDepth, maxFileSize, warnOnSkippedIncludes, warnings }) {\n const absEntry = path.resolve(entry);\n const out = [];\n await dfs(absEntry, 0);\n return out;\n\n async function dfs(file, depth) {\n if (depth > maxIncludeDepth) {\n throw new Error(`COLONY: Max include depth (${maxIncludeDepth}) exceeded at: ${file}`);\n }\n\n const abs = path.resolve(file);\n\n if (visited.has(abs)) {\n if (warnOnSkippedIncludes) {\n warnings.push({ type: \"skipped_include\", file: abs, message: `Skipping already-visited include: ${abs}` });\n }\n return;\n }\n visited.add(abs);\n\n // Check file size if limit is set\n if (maxFileSize !== null) {\n const stat = await fs.stat(abs);\n if (stat.size > maxFileSize) {\n throw new Error(`COLONY: File size (${stat.size} bytes) exceeds maxFileSize (${maxFileSize} bytes): ${abs}`);\n }\n }\n\n const text = await fs.readFile(abs, \"utf8\");\n const { includes } = parseColony(text, { filePath: abs, parseOnlyDirectives: true });\n\n for (const inc of includes) {\n const incAbs = path.resolve(path.dirname(abs), inc);\n\n // Security: validate path is within basePath if set\n if (basePath !== null) {\n const normalizedInc = path.normalize(incAbs);\n if (!normalizedInc.startsWith(basePath + path.sep) && normalizedInc !== basePath) {\n throw new Error(\n `COLONY: Path traversal blocked. Include \"${inc}\" resolves to \"${normalizedInc}\" which is outside basePath \"${basePath}\"`\n );\n }\n }\n\n const matches = await fg(incAbs.replace(/\\\\/g, \"/\"), { dot: true });\n // Sort alphabetically for deterministic ordering across platforms/filesystems\n for (const m of matches.sort((a, b) => a.localeCompare(b))) {\n // Also validate glob matches against basePath\n if (basePath !== null) {\n const normalizedMatch = path.normalize(m);\n if (!normalizedMatch.startsWith(basePath + path.sep) && normalizedMatch !== basePath) {\n throw new Error(\n `COLONY: Path traversal blocked. Glob match \"${m}\" is outside basePath \"${basePath}\"`\n );\n }\n }\n await dfs(m, depth + 1);\n }\n }\n\n out.push(abs);\n }\n}\n\n/**\n * Validate syntax of colony files without resolving\n * @param {string} entry - Entry file path\n * @returns {Promise<{valid: boolean, files: string[], errors: Array<{file: string, error: string}>}>}\n */\nexport async function validateColony(entry) {\n const visited = new Set();\n const files = [];\n const errors = [];\n\n await validateDfs(path.resolve(entry));\n\n return {\n valid: errors.length === 0,\n files,\n errors,\n };\n\n async function validateDfs(file) {\n const abs = path.resolve(file);\n if (visited.has(abs)) return;\n visited.add(abs);\n\n try {\n const text = await fs.readFile(abs, \"utf8\");\n const { includes } = parseColony(text, { filePath: abs });\n files.push(abs);\n\n for (const inc of includes) {\n const incAbs = path.resolve(path.dirname(abs), inc);\n const matches = await fg(incAbs.replace(/\\\\/g, \"/\"), { dot: true });\n for (const m of matches.sort((a, b) => a.localeCompare(b))) {\n await validateDfs(m);\n }\n }\n } catch (e) {\n errors.push({ file: abs, error: e.message });\n }\n }\n}\n\n/**\n * Dry-run: list all files that would be included\n * @param {string} entry - Entry file path\n * @returns {Promise<string[]>}\n */\nexport async function dryRunIncludes(entry) {\n const visited = new Set();\n const files = [];\n await dryRunDfs(path.resolve(entry));\n return files;\n\n async function dryRunDfs(file) {\n const abs = path.resolve(file);\n if (visited.has(abs)) return;\n visited.add(abs);\n\n const text = await fs.readFile(abs, \"utf8\");\n const { includes } = parseColony(text, { filePath: abs, parseOnlyDirectives: true });\n\n for (const inc of includes) {\n const incAbs = path.resolve(path.dirname(abs), inc);\n const matches = await fg(incAbs.replace(/\\\\/g, \"/\"), { dot: true });\n for (const m of matches.sort((a, b) => a.localeCompare(b))) {\n await dryRunDfs(m);\n }\n }\n\n files.push(abs);\n }\n}\n\n/**\n * Compare two configs loaded with different contexts\n * @param {object} opts - Same options as loadColony, but with ctx1 and ctx2\n * @param {Record<string,string>} opts.ctx1 - First context\n * @param {Record<string,string>} opts.ctx2 - Second context\n * @returns {Promise<{cfg1: object, cfg2: object, diff: object}>}\n */\nexport async function diffColony(opts) {\n const { ctx1, ctx2, ...baseOpts } = opts;\n\n if (!ctx1 || !ctx2) {\n throw new Error(\"diffColony: both ctx1 and ctx2 are required\");\n }\n\n const cfg1 = await loadColony({ ...baseOpts, ctx: ctx1 });\n const cfg2 = await loadColony({ ...baseOpts, ctx: ctx2 });\n\n return {\n cfg1,\n cfg2,\n diff: cfg1.diff(cfg2),\n };\n}\n\n/**\n * Lint colony files for potential issues\n * @param {object} opts\n * @param {string} opts.entry - Entry file path\n * @param {string[]=} opts.dims - Dimension names\n * @returns {Promise<{issues: Array<{type: string, severity: string, message: string, file?: string, line?: number}>}>}\n */\nexport async function lintColony(opts) {\n const entry = opts?.entry;\n if (!entry) throw new Error(\"lintColony: opts.entry is required\");\n\n const issues = [];\n const visited = new Set();\n const allRules = [];\n const allFiles = [];\n let foundDims = null;\n\n // Collect all rules from all files\n await collectRules(path.resolve(entry));\n\n async function collectRules(file) {\n const abs = path.resolve(file);\n if (visited.has(abs)) return;\n visited.add(abs);\n\n try {\n const text = await fs.readFile(abs, \"utf8\");\n const parsed = parseColony(text, { filePath: abs });\n allFiles.push(abs);\n\n // Capture dims from first file that has them\n if (!foundDims && parsed.dims?.length) {\n foundDims = parsed.dims;\n }\n\n for (const rule of parsed.rules) {\n allRules.push({ ...rule, filePath: abs });\n }\n\n for (const inc of parsed.includes) {\n const incAbs = path.resolve(path.dirname(abs), inc);\n const matches = await fg(incAbs.replace(/\\\\/g, \"/\"), { dot: true });\n for (const m of matches.sort((a, b) => a.localeCompare(b))) {\n await collectRules(m);\n }\n }\n } catch (e) {\n issues.push({\n type: \"parse_error\",\n severity: \"error\",\n message: e.message,\n file: abs,\n });\n }\n }\n\n // Get dims from options, or from parsed files, or default\n const dims = opts.dims ?? foundDims ?? [\"env\"];\n\n // Check for shadowed rules (same key, same scope, different values)\n const rulesByKey = new Map();\n for (const rule of allRules) {\n const scope = rule.keySegments.slice(0, dims.length).join(\".\");\n const keyPath = rule.keySegments.slice(dims.length).join(\".\");\n const key = `${scope}|${keyPath}`;\n\n if (!rulesByKey.has(key)) {\n rulesByKey.set(key, []);\n }\n rulesByKey.get(key).push(rule);\n }\n\n for (const [key, rules] of rulesByKey.entries()) {\n if (rules.length > 1) {\n // Check if they're in different files or same file\n const locations = rules.map((r) => `${r.filePath}:${r.line}`);\n const uniqueLocations = new Set(locations);\n\n if (uniqueLocations.size > 1) {\n const [scope, keyPath] = key.split(\"|\");\n issues.push({\n type: \"shadowed_rule\",\n severity: \"warning\",\n message: `Rule \"${scope}.${keyPath}\" is defined ${rules.length} times. Later rule wins.`,\n file: rules[rules.length - 1].filePath,\n line: rules[rules.length - 1].line,\n });\n }\n }\n }\n\n // Check for potentially unused wildcard rules\n // (rules with all wildcards that might be overridden by more specific rules)\n for (const rule of allRules) {\n const scope = rule.keySegments.slice(0, dims.length);\n const keyPath = rule.keySegments.slice(dims.length).join(\".\");\n\n if (scope.every((s) => s === \"*\")) {\n // Check if there are more specific rules for the same key\n const moreSpecific = allRules.filter((r) => {\n const rKeyPath = r.keySegments.slice(dims.length).join(\".\");\n if (rKeyPath !== keyPath) return false;\n const rScope = r.keySegments.slice(0, dims.length);\n return rScope.some((s) => s !== \"*\") && r !== rule;\n });\n\n if (moreSpecific.length > 0) {\n issues.push({\n type: \"overridden_wildcard\",\n severity: \"info\",\n message: `Wildcard rule for \"${keyPath}\" is overridden by ${moreSpecific.length} more specific rule(s)`,\n file: rule.filePath,\n line: rule.line,\n });\n }\n }\n }\n\n // Check for empty includes\n for (const file of allFiles) {\n try {\n const text = await fs.readFile(file, \"utf8\");\n const parsed = parseColony(text, { filePath: file });\n\n for (const inc of parsed.includes) {\n const incAbs = path.resolve(path.dirname(file), inc);\n const matches = await fg(incAbs.replace(/\\\\/g, \"/\"), { dot: true });\n if (matches.length === 0) {\n issues.push({\n type: \"empty_include\",\n severity: \"warning\",\n message: `Include pattern \"${inc}\" matches no files`,\n file,\n });\n }\n }\n } catch {}\n }\n\n return { issues };\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }
@@ -0,0 +1,286 @@
1
+ import JSON5 from "json5";
2
+ const RX_DIMS = /^@dims\s+([^;]+);/;
3
+ const RX_INCLUDE = /^@include\s+(.+);/;
4
+ const RX_REQUIRE = /^@require\s+([^;]+);/;
5
+ const RX_ENVDEFAULTS = /^@envDefaults\s+([^;]+);/;
6
+ const RX_RULE = /^(.+?)\s*(\:=|\|\=|\+\=|\-\=|\=)\s*([\s\S]+)\s*;$/;
7
+ const RX_HEREDOC_START = /<<([A-Z_][A-Z0-9_]*)\s*$/;
8
+ function stripBlockComments(text) {
9
+ const result = [];
10
+ const lineMap = [];
11
+ let inComment = false;
12
+ let commentDepth = 0;
13
+ const lines = text.split(/\r?\n/);
14
+ for (let i = 0; i < lines.length; i++) {
15
+ const originalLineNo = i + 1;
16
+ let line = lines[i];
17
+ let cleanLine = "";
18
+ let j = 0;
19
+ while (j < line.length) {
20
+ if (!inComment) {
21
+ if (line[j] === "/" && line[j + 1] === "*") {
22
+ inComment = true;
23
+ commentDepth = 1;
24
+ j += 2;
25
+ continue;
26
+ }
27
+ cleanLine += line[j];
28
+ j++;
29
+ } else {
30
+ if (line[j] === "/" && line[j + 1] === "*") {
31
+ commentDepth++;
32
+ j += 2;
33
+ } else if (line[j] === "*" && line[j + 1] === "/") {
34
+ commentDepth--;
35
+ if (commentDepth === 0) {
36
+ inComment = false;
37
+ }
38
+ j += 2;
39
+ } else {
40
+ j++;
41
+ }
42
+ }
43
+ }
44
+ result.push(cleanLine);
45
+ lineMap.push(originalLineNo);
46
+ }
47
+ return { text: result.join("\n"), lineMap };
48
+ }
49
+ function parseKeyPath(keyRaw) {
50
+ const segments = [];
51
+ let current = "";
52
+ let i = 0;
53
+ while (i < keyRaw.length) {
54
+ if (keyRaw[i] === "\\" && keyRaw[i + 1] === ".") {
55
+ current += ".";
56
+ i += 2;
57
+ } else if (keyRaw[i] === ".") {
58
+ if (current.trim()) segments.push(current.trim());
59
+ current = "";
60
+ i++;
61
+ } else {
62
+ current += keyRaw[i];
63
+ i++;
64
+ }
65
+ }
66
+ if (current.trim()) segments.push(current.trim());
67
+ return segments;
68
+ }
69
+ function formatParseError(message, lines, lineNo, col, filePath) {
70
+ const idx = lineNo - 1;
71
+ const contextLines = [];
72
+ for (let i = Math.max(0, idx - 2); i < idx; i++) {
73
+ contextLines.push(` ${String(i + 1).padStart(4)} | ${lines[i]}`);
74
+ }
75
+ if (idx >= 0 && idx < lines.length) {
76
+ contextLines.push(`> ${String(lineNo).padStart(4)} | ${lines[idx]}`);
77
+ if (typeof col === "number" && col >= 0) {
78
+ const padding = " ".repeat(col + 9);
79
+ contextLines.push(`${padding}^`);
80
+ }
81
+ }
82
+ if (idx + 1 < lines.length) {
83
+ contextLines.push(` ${String(idx + 2).padStart(4)} | ${lines[idx + 1]}`);
84
+ }
85
+ return `${filePath}:${lineNo}: ${message}
86
+
87
+ ${contextLines.join("\n")}`;
88
+ }
89
+ function parseColony(text, { filePath = "<memory>", parseOnlyDirectives = false } = {}) {
90
+ const { text: cleanedText, lineMap } = stripBlockComments(text);
91
+ const lines = cleanedText.split(/\r?\n/);
92
+ const originalLines = text.split(/\r?\n/);
93
+ const rules = [];
94
+ const includes = [];
95
+ const requires = [];
96
+ const envDefaults = {};
97
+ let dims = null;
98
+ let buf = "";
99
+ let bufStartLine = 0;
100
+ let bufStartOriginalLine = 0;
101
+ let inHeredoc = false;
102
+ let heredocDelimiter = "";
103
+ let heredocContent = "";
104
+ let heredocStartLine = 0;
105
+ let heredocKey = "";
106
+ let heredocOp = "";
107
+ const getOriginalLine = (lineNo) => lineMap[lineNo - 1] || lineNo;
108
+ const flush = () => {
109
+ const raw = buf.trim();
110
+ buf = "";
111
+ if (!raw) return;
112
+ const origLine = bufStartOriginalLine;
113
+ const mDims = raw.match(RX_DIMS);
114
+ if (mDims) {
115
+ dims = mDims[1].split(",").map((s) => s.trim()).filter(Boolean);
116
+ return;
117
+ }
118
+ const mInc = raw.match(RX_INCLUDE);
119
+ if (mInc) {
120
+ includes.push(stripQuotes(mInc[1].trim()));
121
+ return;
122
+ }
123
+ const mReq = raw.match(RX_REQUIRE);
124
+ if (mReq) {
125
+ const keys = mReq[1].split(",").map((s) => s.trim()).filter(Boolean);
126
+ requires.push(...keys);
127
+ return;
128
+ }
129
+ const mEnvDef = raw.match(RX_ENVDEFAULTS);
130
+ if (mEnvDef) {
131
+ const parts = mEnvDef[1].split(",").map((s) => s.trim()).filter(Boolean);
132
+ for (const p of parts) {
133
+ const idx = p.indexOf("=");
134
+ if (idx === -1) {
135
+ throw new Error(formatParseError(
136
+ `Bad @envDefaults entry: ${p}`,
137
+ originalLines,
138
+ origLine,
139
+ void 0,
140
+ filePath
141
+ ));
142
+ }
143
+ const k = p.slice(0, idx).trim();
144
+ const vRaw = p.slice(idx + 1).trim();
145
+ envDefaults[k] = stripQuotes(vRaw);
146
+ }
147
+ return;
148
+ }
149
+ if (parseOnlyDirectives) return;
150
+ const mRule = raw.match(RX_RULE);
151
+ if (!mRule) {
152
+ throw new Error(formatParseError(
153
+ "Invalid statement",
154
+ originalLines,
155
+ origLine,
156
+ void 0,
157
+ filePath
158
+ ));
159
+ }
160
+ const keyRaw = mRule[1].trim();
161
+ const op = mRule[2];
162
+ const valueRaw = mRule[3].trim();
163
+ const keySegments = parseKeyPath(keyRaw);
164
+ if (keySegments.length === 0) {
165
+ throw new Error(formatParseError(
166
+ "Empty key",
167
+ originalLines,
168
+ origLine,
169
+ 0,
170
+ filePath
171
+ ));
172
+ }
173
+ const value = parseValue(valueRaw, { filePath, line: origLine, lines: originalLines });
174
+ rules.push({
175
+ filePath,
176
+ line: origLine,
177
+ col: 0,
178
+ keyRaw,
179
+ keySegments,
180
+ op,
181
+ value
182
+ });
183
+ };
184
+ for (let i = 0; i < lines.length; i++) {
185
+ const lineNo = i + 1;
186
+ const originalLineNo = getOriginalLine(lineNo);
187
+ const line = lines[i];
188
+ const trimmed = line.trim();
189
+ if (inHeredoc) {
190
+ if (trimmed === heredocDelimiter) {
191
+ const keySegments = parseKeyPath(heredocKey);
192
+ if (keySegments.length === 0) {
193
+ throw new Error(formatParseError(
194
+ "Empty key in heredoc",
195
+ originalLines,
196
+ heredocStartLine,
197
+ 0,
198
+ filePath
199
+ ));
200
+ }
201
+ rules.push({
202
+ filePath,
203
+ line: heredocStartLine,
204
+ col: 0,
205
+ keyRaw: heredocKey,
206
+ keySegments,
207
+ op: heredocOp,
208
+ value: heredocContent
209
+ });
210
+ inHeredoc = false;
211
+ heredocContent = "";
212
+ continue;
213
+ }
214
+ heredocContent += (heredocContent ? "\n" : "") + line;
215
+ continue;
216
+ }
217
+ if (!trimmed || trimmed.startsWith("#") || trimmed.startsWith("//")) continue;
218
+ const heredocMatch = trimmed.match(/^(.+?)\s*(\:=|\|\=|\+\=|\-\=|\=)\s*<<([A-Z_][A-Z0-9_]*)$/);
219
+ if (heredocMatch) {
220
+ inHeredoc = true;
221
+ heredocKey = heredocMatch[1].trim();
222
+ heredocOp = heredocMatch[2];
223
+ heredocDelimiter = heredocMatch[3];
224
+ heredocStartLine = originalLineNo;
225
+ heredocContent = "";
226
+ continue;
227
+ }
228
+ if (!buf) {
229
+ bufStartLine = lineNo;
230
+ bufStartOriginalLine = originalLineNo;
231
+ }
232
+ buf += (buf ? "\n" : "") + line;
233
+ if (trimmed.endsWith(";")) flush();
234
+ }
235
+ if (inHeredoc) {
236
+ throw new Error(formatParseError(
237
+ `Unterminated heredoc (missing ${heredocDelimiter})`,
238
+ originalLines,
239
+ heredocStartLine,
240
+ void 0,
241
+ filePath
242
+ ));
243
+ }
244
+ if (buf.trim()) {
245
+ throw new Error(formatParseError(
246
+ "Unterminated statement (missing ';')",
247
+ originalLines,
248
+ bufStartOriginalLine,
249
+ void 0,
250
+ filePath
251
+ ));
252
+ }
253
+ return { dims, includes, requires, envDefaults, rules };
254
+ }
255
+ function parseValue(raw, { filePath, line, lines }) {
256
+ const r = raw.trim();
257
+ if (/^(true|false|null)$/.test(r)) return JSON5.parse(r);
258
+ if (/^-?\d+(\.\d+)?$/.test(r)) return Number(r);
259
+ const starts = r[0];
260
+ const ends = r[r.length - 1];
261
+ const looksJsonish = starts === "{" && ends === "}" || starts === "[" && ends === "]" || starts === `"` && ends === `"` || starts === `'` && ends === `'`;
262
+ if (looksJsonish) {
263
+ try {
264
+ return JSON5.parse(r);
265
+ } catch (e) {
266
+ throw new Error(formatParseError(
267
+ `Bad JSON5 value: ${e.message}`,
268
+ lines,
269
+ line,
270
+ void 0,
271
+ filePath
272
+ ));
273
+ }
274
+ }
275
+ return r;
276
+ }
277
+ function stripQuotes(s) {
278
+ if (s.startsWith('"') && s.endsWith('"') || s.startsWith("'") && s.endsWith("'")) {
279
+ return s.slice(1, -1);
280
+ }
281
+ return s;
282
+ }
283
+ export {
284
+ parseColony
285
+ };
286
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/parser.js"],
4
+ "sourcesContent": ["import JSON5 from \"json5\";\n\nconst RX_DIMS = /^@dims\\s+([^;]+);/;\nconst RX_INCLUDE = /^@include\\s+(.+);/;\nconst RX_REQUIRE = /^@require\\s+([^;]+);/;\nconst RX_ENVDEFAULTS = /^@envDefaults\\s+([^;]+);/;\n\n// Rule: <scoped.key.path> <op> <value>;\n// Using [\\s\\S] instead of . to match newlines in multi-line values\nconst RX_RULE = /^(.+?)\\s*(\\:=|\\|\\=|\\+\\=|\\-\\=|\\=)\\s*([\\s\\S]+)\\s*;$/;\n\n// Heredoc: <<EOF ... EOF\nconst RX_HEREDOC_START = /<<([A-Z_][A-Z0-9_]*)\\s*$/;\n\n/**\n * Remove block comments from text (slash-star to star-slash)\n * @param {string} text\n * @returns {{ text: string, lineMap: number[] }} - cleaned text and mapping from new line numbers to original\n */\nfunction stripBlockComments(text) {\n const result = [];\n const lineMap = []; // lineMap[newLineNo] = originalLineNo\n let inComment = false;\n let commentDepth = 0;\n const lines = text.split(/\\r?\\n/);\n\n for (let i = 0; i < lines.length; i++) {\n const originalLineNo = i + 1;\n let line = lines[i];\n let cleanLine = \"\";\n let j = 0;\n\n while (j < line.length) {\n if (!inComment) {\n // Check for comment start\n if (line[j] === \"/\" && line[j + 1] === \"*\") {\n inComment = true;\n commentDepth = 1;\n j += 2;\n continue;\n }\n cleanLine += line[j];\n j++;\n } else {\n // Inside block comment\n if (line[j] === \"/\" && line[j + 1] === \"*\") {\n commentDepth++;\n j += 2;\n } else if (line[j] === \"*\" && line[j + 1] === \"/\") {\n commentDepth--;\n if (commentDepth === 0) {\n inComment = false;\n }\n j += 2;\n } else {\n j++;\n }\n }\n }\n\n result.push(cleanLine);\n lineMap.push(originalLineNo);\n }\n\n return { text: result.join(\"\\n\"), lineMap };\n}\n\n/**\n * Parse a key path with escaped dots\n * \"foo\\.bar.baz\" => [\"foo.bar\", \"baz\"]\n * @param {string} keyRaw\n * @returns {string[]}\n */\nfunction parseKeyPath(keyRaw) {\n const segments = [];\n let current = \"\";\n let i = 0;\n\n while (i < keyRaw.length) {\n if (keyRaw[i] === \"\\\\\" && keyRaw[i + 1] === \".\") {\n // Escaped dot - include literal dot\n current += \".\";\n i += 2;\n } else if (keyRaw[i] === \".\") {\n // Segment separator\n if (current.trim()) segments.push(current.trim());\n current = \"\";\n i++;\n } else {\n current += keyRaw[i];\n i++;\n }\n }\n\n if (current.trim()) segments.push(current.trim());\n return segments;\n}\n\n/**\n * Format a parse error with line context and caret\n * @param {string} message\n * @param {string[]} lines\n * @param {number} lineNo - 1-indexed line number\n * @param {number=} col - 0-indexed column (optional)\n * @param {string} filePath\n * @returns {string}\n */\nfunction formatParseError(message, lines, lineNo, col, filePath) {\n const idx = lineNo - 1;\n const contextLines = [];\n\n // Show up to 2 lines before\n for (let i = Math.max(0, idx - 2); i < idx; i++) {\n contextLines.push(` ${String(i + 1).padStart(4)} | ${lines[i]}`);\n }\n\n // Show the error line\n if (idx >= 0 && idx < lines.length) {\n contextLines.push(`> ${String(lineNo).padStart(4)} | ${lines[idx]}`);\n\n // Show caret if column is specified\n if (typeof col === \"number\" && col >= 0) {\n const padding = \" \".repeat(col + 9); // account for \"> XXXX | \"\n contextLines.push(`${padding}^`);\n }\n }\n\n // Show up to 1 line after\n if (idx + 1 < lines.length) {\n contextLines.push(` ${String(idx + 2).padStart(4)} | ${lines[idx + 1]}`);\n }\n\n return `${filePath}:${lineNo}: ${message}\\n\\n${contextLines.join(\"\\n\")}`;\n}\n\nexport function parseColony(text, { filePath = \"<memory>\", parseOnlyDirectives = false } = {}) {\n // Strip block comments first, keeping track of original line numbers\n const { text: cleanedText, lineMap } = stripBlockComments(text);\n const lines = cleanedText.split(/\\r?\\n/);\n const originalLines = text.split(/\\r?\\n/);\n\n const rules = [];\n const includes = [];\n const requires = [];\n const envDefaults = {};\n let dims = null;\n\n let buf = \"\";\n let bufStartLine = 0;\n let bufStartOriginalLine = 0;\n\n // Heredoc state\n let inHeredoc = false;\n let heredocDelimiter = \"\";\n let heredocContent = \"\";\n let heredocStartLine = 0;\n let heredocKey = \"\";\n let heredocOp = \"\";\n\n const getOriginalLine = (lineNo) => lineMap[lineNo - 1] || lineNo;\n\n const flush = () => {\n const raw = buf.trim();\n buf = \"\";\n if (!raw) return;\n\n const origLine = bufStartOriginalLine;\n\n const mDims = raw.match(RX_DIMS);\n if (mDims) {\n dims = mDims[1].split(\",\").map((s) => s.trim()).filter(Boolean);\n return;\n }\n\n const mInc = raw.match(RX_INCLUDE);\n if (mInc) {\n includes.push(stripQuotes(mInc[1].trim()));\n return;\n }\n\n const mReq = raw.match(RX_REQUIRE);\n if (mReq) {\n const keys = mReq[1]\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n requires.push(...keys);\n return;\n }\n\n const mEnvDef = raw.match(RX_ENVDEFAULTS);\n if (mEnvDef) {\n const parts = mEnvDef[1]\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n\n for (const p of parts) {\n const idx = p.indexOf(\"=\");\n if (idx === -1) {\n throw new Error(formatParseError(\n `Bad @envDefaults entry: ${p}`,\n originalLines,\n origLine,\n undefined,\n filePath\n ));\n }\n const k = p.slice(0, idx).trim();\n const vRaw = p.slice(idx + 1).trim();\n envDefaults[k] = stripQuotes(vRaw);\n }\n return;\n }\n\n if (parseOnlyDirectives) return;\n\n const mRule = raw.match(RX_RULE);\n if (!mRule) {\n throw new Error(formatParseError(\n \"Invalid statement\",\n originalLines,\n origLine,\n undefined,\n filePath\n ));\n }\n\n const keyRaw = mRule[1].trim();\n const op = mRule[2];\n const valueRaw = mRule[3].trim();\n\n const keySegments = parseKeyPath(keyRaw);\n if (keySegments.length === 0) {\n throw new Error(formatParseError(\n \"Empty key\",\n originalLines,\n origLine,\n 0,\n filePath\n ));\n }\n\n const value = parseValue(valueRaw, { filePath, line: origLine, lines: originalLines });\n\n rules.push({\n filePath,\n line: origLine,\n col: 0,\n keyRaw,\n keySegments,\n op,\n value,\n });\n };\n\n for (let i = 0; i < lines.length; i++) {\n const lineNo = i + 1;\n const originalLineNo = getOriginalLine(lineNo);\n const line = lines[i];\n const trimmed = line.trim();\n\n // Handle heredoc mode\n if (inHeredoc) {\n if (trimmed === heredocDelimiter) {\n // End of heredoc\n const keySegments = parseKeyPath(heredocKey);\n if (keySegments.length === 0) {\n throw new Error(formatParseError(\n \"Empty key in heredoc\",\n originalLines,\n heredocStartLine,\n 0,\n filePath\n ));\n }\n\n rules.push({\n filePath,\n line: heredocStartLine,\n col: 0,\n keyRaw: heredocKey,\n keySegments,\n op: heredocOp,\n value: heredocContent,\n });\n\n inHeredoc = false;\n heredocContent = \"\";\n continue;\n }\n\n // Add line to heredoc content\n heredocContent += (heredocContent ? \"\\n\" : \"\") + line;\n continue;\n }\n\n // Skip empty lines and line comments\n if (!trimmed || trimmed.startsWith(\"#\") || trimmed.startsWith(\"//\")) continue;\n\n // Check for heredoc start: key = <<EOF\n const heredocMatch = trimmed.match(/^(.+?)\\s*(\\:=|\\|\\=|\\+\\=|\\-\\=|\\=)\\s*<<([A-Z_][A-Z0-9_]*)$/);\n if (heredocMatch) {\n inHeredoc = true;\n heredocKey = heredocMatch[1].trim();\n heredocOp = heredocMatch[2];\n heredocDelimiter = heredocMatch[3];\n heredocStartLine = originalLineNo;\n heredocContent = \"\";\n continue;\n }\n\n if (!buf) {\n bufStartLine = lineNo;\n bufStartOriginalLine = originalLineNo;\n }\n buf += (buf ? \"\\n\" : \"\") + line;\n\n if (trimmed.endsWith(\";\")) flush();\n }\n\n if (inHeredoc) {\n throw new Error(formatParseError(\n `Unterminated heredoc (missing ${heredocDelimiter})`,\n originalLines,\n heredocStartLine,\n undefined,\n filePath\n ));\n }\n\n if (buf.trim()) {\n throw new Error(formatParseError(\n \"Unterminated statement (missing ';')\",\n originalLines,\n bufStartOriginalLine,\n undefined,\n filePath\n ));\n }\n\n return { dims, includes, requires, envDefaults, rules };\n}\n\nfunction parseValue(raw, { filePath, line, lines }) {\n const r = raw.trim();\n\n if (/^(true|false|null)$/.test(r)) return JSON5.parse(r);\n if (/^-?\\d+(\\.\\d+)?$/.test(r)) return Number(r);\n\n const starts = r[0];\n const ends = r[r.length - 1];\n const looksJsonish =\n (starts === \"{\" && ends === \"}\") ||\n (starts === \"[\" && ends === \"]\") ||\n (starts === `\"` && ends === `\"`) ||\n (starts === `'` && ends === `'`);\n\n if (looksJsonish) {\n try {\n return JSON5.parse(r);\n } catch (e) {\n throw new Error(formatParseError(\n `Bad JSON5 value: ${e.message}`,\n lines,\n line,\n undefined,\n filePath\n ));\n }\n }\n\n return r; // bareword => string\n}\n\nfunction stripQuotes(s) {\n if ((s.startsWith('\"') && s.endsWith('\"')) || (s.startsWith(\"'\") && s.endsWith(\"'\"))) {\n return s.slice(1, -1);\n }\n return s;\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,82 @@
1
+ class AwsSecretsProvider {
2
+ prefix = "AWS";
3
+ /**
4
+ * @param {object} options
5
+ * @param {string=} options.region - AWS region (default: process.env.AWS_REGION or "us-east-1")
6
+ */
7
+ constructor(options = {}) {
8
+ this.region = options.region ?? process.env.AWS_REGION ?? "us-east-1";
9
+ this.client = null;
10
+ this.clientPromise = null;
11
+ this.GetSecretValueCommand = null;
12
+ }
13
+ /**
14
+ * Get or create the AWS client (lazy initialization)
15
+ * @returns {Promise<object>}
16
+ */
17
+ async getClient() {
18
+ if (this.client) return this.client;
19
+ if (this.clientPromise) return this.clientPromise;
20
+ this.clientPromise = (async () => {
21
+ const { SecretsManagerClient, GetSecretValueCommand } = await import("@aws-sdk/client-secrets-manager");
22
+ this.client = new SecretsManagerClient({ region: this.region });
23
+ this.GetSecretValueCommand = GetSecretValueCommand;
24
+ return this.client;
25
+ })();
26
+ return this.clientPromise;
27
+ }
28
+ /**
29
+ * Fetch a secret value
30
+ * @param {string} key - Secret key, optionally with JSON path: "secret-name#json.path"
31
+ * @returns {Promise<string>}
32
+ */
33
+ async fetch(key) {
34
+ const client = await this.getClient();
35
+ const [secretId, jsonPath] = key.split("#");
36
+ const command = new this.GetSecretValueCommand({ SecretId: secretId });
37
+ const response = await client.send(command);
38
+ let value = response.SecretString;
39
+ if (!value && response.SecretBinary) {
40
+ value = Buffer.from(response.SecretBinary).toString("utf-8");
41
+ }
42
+ if (jsonPath && value) {
43
+ try {
44
+ const parsed = JSON.parse(value);
45
+ value = getJsonPath(parsed, jsonPath);
46
+ } catch {
47
+ }
48
+ }
49
+ return value ?? "";
50
+ }
51
+ /**
52
+ * Validate provider configuration
53
+ * @returns {Promise<void>}
54
+ */
55
+ async validate() {
56
+ await this.getClient();
57
+ }
58
+ /**
59
+ * Cleanup resources
60
+ * @returns {Promise<void>}
61
+ */
62
+ async dispose() {
63
+ if (this.client?.destroy) {
64
+ this.client.destroy();
65
+ }
66
+ this.client = null;
67
+ this.clientPromise = null;
68
+ }
69
+ }
70
+ function getJsonPath(obj, path) {
71
+ const parts = path.split(".");
72
+ let current = obj;
73
+ for (const part of parts) {
74
+ if (current === null || current === void 0) return void 0;
75
+ current = current[part];
76
+ }
77
+ return typeof current === "string" ? current : JSON.stringify(current);
78
+ }
79
+ export {
80
+ AwsSecretsProvider
81
+ };
82
+ //# sourceMappingURL=aws.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/providers/aws.js"],
4
+ "sourcesContent": ["/**\n * AWS Secrets Manager provider for colony\n */\n\n/**\n * @class AwsSecretsProvider\n * @property {string} prefix - Provider prefix (\"AWS\")\n */\nexport class AwsSecretsProvider {\n prefix = \"AWS\";\n\n /**\n * @param {object} options\n * @param {string=} options.region - AWS region (default: process.env.AWS_REGION or \"us-east-1\")\n */\n constructor(options = {}) {\n this.region = options.region ?? process.env.AWS_REGION ?? \"us-east-1\";\n this.client = null;\n this.clientPromise = null;\n this.GetSecretValueCommand = null;\n }\n\n /**\n * Get or create the AWS client (lazy initialization)\n * @returns {Promise<object>}\n */\n async getClient() {\n if (this.client) return this.client;\n if (this.clientPromise) return this.clientPromise;\n\n this.clientPromise = (async () => {\n // Dynamic import to avoid requiring AWS SDK if not used\n const { SecretsManagerClient, GetSecretValueCommand } = await import(\n \"@aws-sdk/client-secrets-manager\"\n );\n this.client = new SecretsManagerClient({ region: this.region });\n this.GetSecretValueCommand = GetSecretValueCommand;\n return this.client;\n })();\n\n return this.clientPromise;\n }\n\n /**\n * Fetch a secret value\n * @param {string} key - Secret key, optionally with JSON path: \"secret-name#json.path\"\n * @returns {Promise<string>}\n */\n async fetch(key) {\n const client = await this.getClient();\n\n // Support key with JSON path: secret-name#json.path\n const [secretId, jsonPath] = key.split(\"#\");\n\n const command = new this.GetSecretValueCommand({ SecretId: secretId });\n const response = await client.send(command);\n\n let value = response.SecretString;\n if (!value && response.SecretBinary) {\n value = Buffer.from(response.SecretBinary).toString(\"utf-8\");\n }\n\n // Extract JSON path if specified\n if (jsonPath && value) {\n try {\n const parsed = JSON.parse(value);\n value = getJsonPath(parsed, jsonPath);\n } catch {\n // Not JSON or invalid path, return as-is\n }\n }\n\n return value ?? \"\";\n }\n\n /**\n * Validate provider configuration\n * @returns {Promise<void>}\n */\n async validate() {\n // Try to initialize client to verify SDK is available\n await this.getClient();\n }\n\n /**\n * Cleanup resources\n * @returns {Promise<void>}\n */\n async dispose() {\n if (this.client?.destroy) {\n this.client.destroy();\n }\n this.client = null;\n this.clientPromise = null;\n }\n}\n\n/**\n * Get a value from an object using dot notation path\n * @param {object} obj - Object to traverse\n * @param {string} path - Dot-separated path (e.g., \"database.password\")\n * @returns {string|undefined}\n */\nfunction getJsonPath(obj, path) {\n const parts = path.split(\".\");\n let current = obj;\n for (const part of parts) {\n if (current === null || current === undefined) return undefined;\n current = current[part];\n }\n return typeof current === \"string\" ? current : JSON.stringify(current);\n}\n"],
5
+ "mappings": "AAQO,MAAM,mBAAmB;AAAA,EAC9B,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,EAMT,YAAY,UAAU,CAAC,GAAG;AACxB,SAAK,SAAS,QAAQ,UAAU,QAAQ,IAAI,cAAc;AAC1D,SAAK,SAAS;AACd,SAAK,gBAAgB;AACrB,SAAK,wBAAwB;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,YAAY;AAChB,QAAI,KAAK,OAAQ,QAAO,KAAK;AAC7B,QAAI,KAAK,cAAe,QAAO,KAAK;AAEpC,SAAK,iBAAiB,YAAY;AAEhC,YAAM,EAAE,sBAAsB,sBAAsB,IAAI,MAAM,OAC5D,iCACF;AACA,WAAK,SAAS,IAAI,qBAAqB,EAAE,QAAQ,KAAK,OAAO,CAAC;AAC9D,WAAK,wBAAwB;AAC7B,aAAO,KAAK;AAAA,IACd,GAAG;AAEH,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,MAAM,KAAK;AACf,UAAM,SAAS,MAAM,KAAK,UAAU;AAGpC,UAAM,CAAC,UAAU,QAAQ,IAAI,IAAI,MAAM,GAAG;AAE1C,UAAM,UAAU,IAAI,KAAK,sBAAsB,EAAE,UAAU,SAAS,CAAC;AACrE,UAAM,WAAW,MAAM,OAAO,KAAK,OAAO;AAE1C,QAAI,QAAQ,SAAS;AACrB,QAAI,CAAC,SAAS,SAAS,cAAc;AACnC,cAAQ,OAAO,KAAK,SAAS,YAAY,EAAE,SAAS,OAAO;AAAA,IAC7D;AAGA,QAAI,YAAY,OAAO;AACrB,UAAI;AACF,cAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,gBAAQ,YAAY,QAAQ,QAAQ;AAAA,MACtC,QAAQ;AAAA,MAER;AAAA,IACF;AAEA,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,WAAW;AAEf,UAAM,KAAK,UAAU;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,UAAU;AACd,QAAI,KAAK,QAAQ,SAAS;AACxB,WAAK,OAAO,QAAQ;AAAA,IACtB;AACA,SAAK,SAAS;AACd,SAAK,gBAAgB;AAAA,EACvB;AACF;AAQA,SAAS,YAAY,KAAK,MAAM;AAC9B,QAAM,QAAQ,KAAK,MAAM,GAAG;AAC5B,MAAI,UAAU;AACd,aAAW,QAAQ,OAAO;AACxB,QAAI,YAAY,QAAQ,YAAY,OAAW,QAAO;AACtD,cAAU,QAAQ,IAAI;AAAA,EACxB;AACA,SAAO,OAAO,YAAY,WAAW,UAAU,KAAK,UAAU,OAAO;AACvE;",
6
+ "names": []
7
+ }
@@ -0,0 +1,26 @@
1
+ import { VaultCompatibleProvider } from "./vault-base.js";
2
+ class OpenBaoProvider extends VaultCompatibleProvider {
3
+ /**
4
+ * @param {object} options
5
+ * @param {string=} options.addr - OpenBao address (default: process.env.BAO_ADDR or "http://127.0.0.1:8200")
6
+ * @param {string=} options.token - OpenBao token (default: process.env.BAO_TOKEN)
7
+ * @param {string=} options.namespace - OpenBao namespace (default: process.env.BAO_NAMESPACE)
8
+ * @param {number=} options.timeout - Request timeout in ms (default: 30000)
9
+ */
10
+ constructor(options = {}) {
11
+ super(
12
+ {
13
+ prefix: "OPENBAO",
14
+ addrEnvVar: "BAO_ADDR",
15
+ tokenEnvVar: "BAO_TOKEN",
16
+ namespaceEnvVar: "BAO_NAMESPACE",
17
+ errorPrefix: "OpenBao"
18
+ },
19
+ options
20
+ );
21
+ }
22
+ }
23
+ export {
24
+ OpenBaoProvider
25
+ };
26
+ //# sourceMappingURL=openbao.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/providers/openbao.js"],
4
+ "sourcesContent": ["/**\n * OpenBao provider for colony\n * OpenBao is an API-compatible fork of HashiCorp Vault\n */\n\nimport { VaultCompatibleProvider } from \"./vault-base.js\";\n\n/**\n * @class OpenBaoProvider\n * @property {string} prefix - Provider prefix (\"OPENBAO\")\n */\nexport class OpenBaoProvider extends VaultCompatibleProvider {\n /**\n * @param {object} options\n * @param {string=} options.addr - OpenBao address (default: process.env.BAO_ADDR or \"http://127.0.0.1:8200\")\n * @param {string=} options.token - OpenBao token (default: process.env.BAO_TOKEN)\n * @param {string=} options.namespace - OpenBao namespace (default: process.env.BAO_NAMESPACE)\n * @param {number=} options.timeout - Request timeout in ms (default: 30000)\n */\n constructor(options = {}) {\n super(\n {\n prefix: \"OPENBAO\",\n addrEnvVar: \"BAO_ADDR\",\n tokenEnvVar: \"BAO_TOKEN\",\n namespaceEnvVar: \"BAO_NAMESPACE\",\n errorPrefix: \"OpenBao\",\n },\n options\n );\n }\n}\n"],
5
+ "mappings": "AAKA,SAAS,+BAA+B;AAMjC,MAAM,wBAAwB,wBAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ3D,YAAY,UAAU,CAAC,GAAG;AACxB;AAAA,MACE;AAAA,QACE,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,aAAa;AAAA,QACb,iBAAiB;AAAA,QACjB,aAAa;AAAA,MACf;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,75 @@
1
+ class VaultCompatibleProvider {
2
+ /**
3
+ * @param {object} config
4
+ * @param {string} config.prefix - Provider prefix (e.g., "VAULT", "OPENBAO")
5
+ * @param {string} config.addrEnvVar - Environment variable for address
6
+ * @param {string} config.tokenEnvVar - Environment variable for token
7
+ * @param {string} config.namespaceEnvVar - Environment variable for namespace
8
+ * @param {string} config.errorPrefix - Prefix for error messages
9
+ * @param {object} options - User options
10
+ * @param {string=} options.addr - Server address
11
+ * @param {string=} options.token - Auth token
12
+ * @param {string=} options.namespace - Namespace
13
+ * @param {number=} options.timeout - Request timeout in ms (default: 30000)
14
+ */
15
+ constructor(config, options = {}) {
16
+ this.prefix = config.prefix;
17
+ this.errorPrefix = config.errorPrefix;
18
+ this.addr = options.addr ?? process.env[config.addrEnvVar] ?? "http://127.0.0.1:8200";
19
+ this.token = options.token ?? process.env[config.tokenEnvVar];
20
+ this.namespace = options.namespace ?? process.env[config.namespaceEnvVar];
21
+ this.timeout = options.timeout ?? 3e4;
22
+ this.tokenEnvVar = config.tokenEnvVar;
23
+ }
24
+ /**
25
+ * Fetch a secret value
26
+ * @param {string} key - Secret path, optionally with field: "secret/data/myapp#password"
27
+ * @returns {Promise<string>}
28
+ */
29
+ async fetch(key) {
30
+ const [path, field] = key.split("#");
31
+ const url = `${this.addr}/v1/${path}`;
32
+ const headers = {
33
+ "X-Vault-Token": this.token
34
+ };
35
+ if (this.namespace) {
36
+ headers["X-Vault-Namespace"] = this.namespace;
37
+ }
38
+ const response = await fetch(url, {
39
+ headers,
40
+ signal: AbortSignal.timeout(this.timeout)
41
+ });
42
+ if (response.status === 404) {
43
+ const err = new Error(`Secret not found: ${key}`);
44
+ err.code = "NOT_FOUND";
45
+ throw err;
46
+ }
47
+ if (!response.ok) {
48
+ throw new Error(`${this.errorPrefix} error: ${response.status} ${response.statusText}`);
49
+ }
50
+ const data = await response.json();
51
+ const secretData = data.data?.data ?? data.data;
52
+ if (field) {
53
+ return String(secretData?.[field] ?? "");
54
+ }
55
+ if (typeof secretData === "object" && secretData !== null) {
56
+ const values = Object.values(secretData);
57
+ if (values.length === 1) return String(values[0]);
58
+ return JSON.stringify(secretData);
59
+ }
60
+ return String(secretData ?? "");
61
+ }
62
+ /**
63
+ * Validate provider configuration
64
+ * @returns {Promise<void>}
65
+ */
66
+ async validate() {
67
+ if (!this.token) {
68
+ throw new Error(`${this.tokenEnvVar} is required`);
69
+ }
70
+ }
71
+ }
72
+ export {
73
+ VaultCompatibleProvider
74
+ };
75
+ //# sourceMappingURL=vault-base.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/providers/vault-base.js"],
4
+ "sourcesContent": ["/**\n * Base class for Vault-compatible secret providers (Vault, OpenBao)\n * Both use the same HTTP API, differing only in environment variables and naming.\n */\n\n/**\n * @class VaultCompatibleProvider\n * @property {string} prefix - Provider prefix\n */\nexport class VaultCompatibleProvider {\n /**\n * @param {object} config\n * @param {string} config.prefix - Provider prefix (e.g., \"VAULT\", \"OPENBAO\")\n * @param {string} config.addrEnvVar - Environment variable for address\n * @param {string} config.tokenEnvVar - Environment variable for token\n * @param {string} config.namespaceEnvVar - Environment variable for namespace\n * @param {string} config.errorPrefix - Prefix for error messages\n * @param {object} options - User options\n * @param {string=} options.addr - Server address\n * @param {string=} options.token - Auth token\n * @param {string=} options.namespace - Namespace\n * @param {number=} options.timeout - Request timeout in ms (default: 30000)\n */\n constructor(config, options = {}) {\n this.prefix = config.prefix;\n this.errorPrefix = config.errorPrefix;\n this.addr = options.addr ?? process.env[config.addrEnvVar] ?? \"http://127.0.0.1:8200\";\n this.token = options.token ?? process.env[config.tokenEnvVar];\n this.namespace = options.namespace ?? process.env[config.namespaceEnvVar];\n this.timeout = options.timeout ?? 30000;\n this.tokenEnvVar = config.tokenEnvVar;\n }\n\n /**\n * Fetch a secret value\n * @param {string} key - Secret path, optionally with field: \"secret/data/myapp#password\"\n * @returns {Promise<string>}\n */\n async fetch(key) {\n const [path, field] = key.split(\"#\");\n\n const url = `${this.addr}/v1/${path}`;\n const headers = {\n \"X-Vault-Token\": this.token,\n };\n if (this.namespace) {\n headers[\"X-Vault-Namespace\"] = this.namespace;\n }\n\n const response = await fetch(url, {\n headers,\n signal: AbortSignal.timeout(this.timeout),\n });\n\n if (response.status === 404) {\n const err = new Error(`Secret not found: ${key}`);\n err.code = \"NOT_FOUND\";\n throw err;\n }\n\n if (!response.ok) {\n throw new Error(`${this.errorPrefix} error: ${response.status} ${response.statusText}`);\n }\n\n const data = await response.json();\n\n // KV v2 returns data.data.data, KV v1 returns data.data\n const secretData = data.data?.data ?? data.data;\n\n if (field) {\n return String(secretData?.[field] ?? \"\");\n }\n\n if (typeof secretData === \"object\" && secretData !== null) {\n const values = Object.values(secretData);\n if (values.length === 1) return String(values[0]);\n return JSON.stringify(secretData);\n }\n\n return String(secretData ?? \"\");\n }\n\n /**\n * Validate provider configuration\n * @returns {Promise<void>}\n */\n async validate() {\n if (!this.token) {\n throw new Error(`${this.tokenEnvVar} is required`);\n }\n }\n}\n"],
5
+ "mappings": "AASO,MAAM,wBAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcnC,YAAY,QAAQ,UAAU,CAAC,GAAG;AAChC,SAAK,SAAS,OAAO;AACrB,SAAK,cAAc,OAAO;AAC1B,SAAK,OAAO,QAAQ,QAAQ,QAAQ,IAAI,OAAO,UAAU,KAAK;AAC9D,SAAK,QAAQ,QAAQ,SAAS,QAAQ,IAAI,OAAO,WAAW;AAC5D,SAAK,YAAY,QAAQ,aAAa,QAAQ,IAAI,OAAO,eAAe;AACxE,SAAK,UAAU,QAAQ,WAAW;AAClC,SAAK,cAAc,OAAO;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,MAAM,KAAK;AACf,UAAM,CAAC,MAAM,KAAK,IAAI,IAAI,MAAM,GAAG;AAEnC,UAAM,MAAM,GAAG,KAAK,IAAI,OAAO,IAAI;AACnC,UAAM,UAAU;AAAA,MACd,iBAAiB,KAAK;AAAA,IACxB;AACA,QAAI,KAAK,WAAW;AAClB,cAAQ,mBAAmB,IAAI,KAAK;AAAA,IACtC;AAEA,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC;AAAA,MACA,QAAQ,YAAY,QAAQ,KAAK,OAAO;AAAA,IAC1C,CAAC;AAED,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAM,MAAM,IAAI,MAAM,qBAAqB,GAAG,EAAE;AAChD,UAAI,OAAO;AACX,YAAM;AAAA,IACR;AAEA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,MAAM,GAAG,KAAK,WAAW,WAAW,SAAS,MAAM,IAAI,SAAS,UAAU,EAAE;AAAA,IACxF;AAEA,UAAM,OAAO,MAAM,SAAS,KAAK;AAGjC,UAAM,aAAa,KAAK,MAAM,QAAQ,KAAK;AAE3C,QAAI,OAAO;AACT,aAAO,OAAO,aAAa,KAAK,KAAK,EAAE;AAAA,IACzC;AAEA,QAAI,OAAO,eAAe,YAAY,eAAe,MAAM;AACzD,YAAM,SAAS,OAAO,OAAO,UAAU;AACvC,UAAI,OAAO,WAAW,EAAG,QAAO,OAAO,OAAO,CAAC,CAAC;AAChD,aAAO,KAAK,UAAU,UAAU;AAAA,IAClC;AAEA,WAAO,OAAO,cAAc,EAAE;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,WAAW;AACf,QAAI,CAAC,KAAK,OAAO;AACf,YAAM,IAAI,MAAM,GAAG,KAAK,WAAW,cAAc;AAAA,IACnD;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,26 @@
1
+ import { VaultCompatibleProvider } from "./vault-base.js";
2
+ class VaultProvider extends VaultCompatibleProvider {
3
+ /**
4
+ * @param {object} options
5
+ * @param {string=} options.addr - Vault address (default: process.env.VAULT_ADDR or "http://127.0.0.1:8200")
6
+ * @param {string=} options.token - Vault token (default: process.env.VAULT_TOKEN)
7
+ * @param {string=} options.namespace - Vault namespace (default: process.env.VAULT_NAMESPACE)
8
+ * @param {number=} options.timeout - Request timeout in ms (default: 30000)
9
+ */
10
+ constructor(options = {}) {
11
+ super(
12
+ {
13
+ prefix: "VAULT",
14
+ addrEnvVar: "VAULT_ADDR",
15
+ tokenEnvVar: "VAULT_TOKEN",
16
+ namespaceEnvVar: "VAULT_NAMESPACE",
17
+ errorPrefix: "Vault"
18
+ },
19
+ options
20
+ );
21
+ }
22
+ }
23
+ export {
24
+ VaultProvider
25
+ };
26
+ //# sourceMappingURL=vault.js.map