@super-repo/envx 0.4.0 → 0.4.1-b.3
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 +2 -2
- package/dist/auto.js +1 -1
- package/dist/chunks/auto-preload-CrSuZDg1.js +75 -0
- package/dist/chunks/auto-preload-CrSuZDg1.js.map +1 -0
- package/dist/chunks/aws-DgcXfw-Y.js +54 -0
- package/dist/chunks/aws-DgcXfw-Y.js.map +1 -0
- package/dist/chunks/azure-Cmh5-dPn.js +62 -0
- package/dist/chunks/azure-Cmh5-dPn.js.map +1 -0
- package/dist/chunks/{commands-KUyDszno.js → commands-CblelhOH.js} +2 -2
- package/dist/chunks/commands-CblelhOH.js.map +1 -0
- package/dist/chunks/doppler-BkQsajIp.js +50 -0
- package/dist/chunks/doppler-BkQsajIp.js.map +1 -0
- package/dist/chunks/gcp-Dq7QncPS.js +53 -0
- package/dist/chunks/gcp-Dq7QncPS.js.map +1 -0
- package/dist/chunks/infisical-CO073rdx.js +57 -0
- package/dist/chunks/infisical-CO073rdx.js.map +1 -0
- package/dist/chunks/{src-Ln2uXfYC.js → libs-DewxofWa.js} +0 -0
- package/dist/chunks/libs-DewxofWa.js.map +1 -0
- package/dist/chunks/op-CG9UWJIj.js +76 -0
- package/dist/chunks/op-CG9UWJIj.js.map +1 -0
- package/dist/chunks/runtime-BIEf_Dgo.js +102 -0
- package/dist/chunks/runtime-BIEf_Dgo.js.map +1 -0
- package/dist/chunks/{src-BM4EdT3z.js → src-C3xPGIyj.js} +2 -2
- package/dist/chunks/src-C3xPGIyj.js.map +1 -0
- package/dist/chunks/types-COrFYR0z.js +62 -0
- package/dist/chunks/types-COrFYR0z.js.map +1 -0
- package/dist/chunks/vault-BWdO9DFO.js +54 -0
- package/dist/chunks/vault-BWdO9DFO.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/commands/index.js +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/libs/audit.d.ts +62 -0
- package/dist/libs/audit.d.ts.map +1 -0
- package/dist/libs/config.d.ts +185 -0
- package/dist/libs/config.d.ts.map +1 -0
- package/dist/libs/crypto.d.ts +34 -0
- package/dist/libs/crypto.d.ts.map +1 -0
- package/dist/libs/decrypt.d.ts +10 -0
- package/dist/libs/decrypt.d.ts.map +1 -0
- package/dist/libs/encrypt.d.ts +21 -0
- package/dist/libs/encrypt.d.ts.map +1 -0
- package/dist/libs/env.d.ts +178 -0
- package/dist/libs/env.d.ts.map +1 -0
- package/dist/libs/expand.d.ts +51 -0
- package/dist/libs/expand.d.ts.map +1 -0
- package/dist/libs/index.d.ts +22 -0
- package/dist/libs/index.d.ts.map +1 -0
- package/dist/libs/index.js +2 -0
- package/dist/libs/keys.d.ts +92 -0
- package/dist/libs/keys.d.ts.map +1 -0
- package/dist/libs/match.d.ts +7 -0
- package/dist/libs/match.d.ts.map +1 -0
- package/dist/libs/parser.d.ts +33 -0
- package/dist/libs/parser.d.ts.map +1 -0
- package/dist/libs/rotate.d.ts +24 -0
- package/dist/libs/rotate.d.ts.map +1 -0
- package/dist/libs/types.d.ts +42 -0
- package/dist/libs/types.d.ts.map +1 -0
- package/dist/plugins/auto-preload.d.ts +50 -0
- package/dist/plugins/auto-preload.d.ts.map +1 -0
- package/dist/plugins/auto-preload.js +2 -0
- package/dist/plugins/aws.d.ts +52 -0
- package/dist/plugins/aws.d.ts.map +1 -0
- package/dist/plugins/aws.js +2 -0
- package/dist/plugins/azure.d.ts +46 -0
- package/dist/plugins/azure.d.ts.map +1 -0
- package/dist/plugins/azure.js +2 -0
- package/dist/plugins/doppler.d.ts +36 -0
- package/dist/plugins/doppler.d.ts.map +1 -0
- package/dist/plugins/doppler.js +2 -0
- package/dist/plugins/gcp.d.ts +48 -0
- package/dist/plugins/gcp.d.ts.map +1 -0
- package/dist/plugins/gcp.js +2 -0
- package/dist/plugins/index.d.ts +11 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +11 -0
- package/dist/plugins/infisical.d.ts +51 -0
- package/dist/plugins/infisical.d.ts.map +1 -0
- package/dist/plugins/infisical.js +2 -0
- package/dist/plugins/op.d.ts +52 -0
- package/dist/plugins/op.d.ts.map +1 -0
- package/dist/plugins/op.js +2 -0
- package/dist/plugins/runtime.d.ts +95 -0
- package/dist/plugins/runtime.d.ts.map +1 -0
- package/dist/plugins/runtime.js +2 -0
- package/dist/plugins/types.d.ts +54 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/plugins/vault.d.ts +47 -0
- package/dist/plugins/vault.d.ts.map +1 -0
- package/dist/plugins/vault.js +2 -0
- package/docs/plugins/custom-providers.md +26 -0
- package/docs/plugins/library-api.md +52 -0
- package/docs/plugins/overview.md +96 -0
- package/docs/plugins/providers.md +149 -0
- package/docs/plugins/recipes.md +77 -0
- package/docs/plugins/runtime.md +88 -0
- package/docs/security-models.md +3 -3
- package/package.json +51 -11
- package/dist/bin/dotenvx.d.ts +0 -1
- package/dist/bin/dotenvx.d.ts.map +0 -1
- package/dist/bin/dotenvx.js +0 -2
- package/dist/chunks/commands-KUyDszno.js.map +0 -1
- package/dist/chunks/src-BM4EdT3z.js.map +0 -1
- package/dist/chunks/src-Ln2uXfYC.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"src-C3xPGIyj.js","names":[],"sources":["../../src/index.ts"],"sourcesContent":["// #region -- Programmatic Entry Point ----------------------\n\nimport {\n loadEnv,\n loadDotenvxConfig,\n type DotenvxConfig,\n type LoadEnvOptions,\n} from \"./libs/index.js\";\n\n// Re-export the lib surface that consumers depend on (especially the\n// `auditFiles` API used by czar's `envxAuditPlugin`). The libs/ folder\n// is the bundled implementation; `@super-repo/envx-common` is a private\n// workspace package vite inlines into the published bundle. Either way,\n// every public API has to be reachable from this file.\nexport {\n // Audit (plaintext-secret scanner)\n auditFiles,\n BUILT_IN_PATTERNS,\n type AuditFinding,\n type AuditOptions,\n type SecretPattern,\n // Crypto primitives\n ENCRYPTED_PREFIX,\n generateKeyPair,\n encryptValueAsymmetric,\n decryptValueAsymmetric,\n isEncrypted,\n // High-level operations\n encryptFiles,\n decryptFiles,\n rotateFiles,\n // Env-file parser\n parseEnv,\n serializeEnv,\n toRecord,\n // Variable expansion\n expandRecord,\n expandEnvSrc,\n // Config + path resolution\n defineConfig,\n loadDotenvxConfig,\n findWorkspaceRoot,\n resolveCwdOrWorkspace,\n resolveEnvPaths,\n detectEnvironment,\n // Keys-file management\n readKeysFile,\n writeKeysFile,\n defaultKeysPath,\n} from \"./libs/index.js\";\n\nexport type {\n DotenvxConfig,\n LoadEnvOptions,\n ProcessedEnv,\n ProcessingError,\n ErrorCode,\n RunOptions,\n RunResult,\n ExpandOptions,\n ExpandResult,\n EnvLine,\n KvLine,\n RawLine,\n} from \"./libs/index.js\";\n\n/**\n * Load env files into `process.env` and return it.\n *\n * Modeled after the `dotenv` API but with explicit scoping. Three call\n * shapes:\n *\n * ```ts\n * import envx from \"@super-repo/envx\";\n *\n * envx(); // load `.env` (auto-detect from NODE_ENV / VERCEL_ENV / NETLIFY)\n * envx(\"prod\"); // load `.env` with cascade=prod (.env, .env.prod, .env.local, .env.prod.local)\n * envx({ envFiles: [\"vault/.env.prod\"], envPath: \"vault\", quiet: false }); // full options\n * ```\n *\n * In all cases `process.env` is mutated and returned for ergonomic\n * destructuring. Config file discovery (`envx.config.{ts,js,json}` /\n * `package.json` `envx.config`) runs automatically; programmatic\n * options layer on top of the discovered config, with caller-supplied\n * fields winning per-field.\n */\n/**\n * Programmatic options accept everything `LoadEnvOptions` does plus an\n * optional `profile` name. When set, the matching `config.profiles[name]`\n * is merged onto the base config (per-field) before the user options\n * take over.\n */\nexport type EnvxProgrammaticOptions = LoadEnvOptions & { readonly profile?: string };\n\nfunction envx(): NodeJS.ProcessEnv;\nfunction envx(scope: string): NodeJS.ProcessEnv;\nfunction envx(opts: EnvxProgrammaticOptions): NodeJS.ProcessEnv;\nfunction envx(arg?: string | EnvxProgrammaticOptions): NodeJS.ProcessEnv {\n const { config: baseConfig } = loadDotenvxConfig();\n const userOpts: EnvxProgrammaticOptions =\n arg === undefined\n ? {}\n : typeof arg === \"string\"\n ? { cascade: arg }\n : arg;\n let cfg: DotenvxConfig = baseConfig;\n if (userOpts.profile) {\n const profile = cfg.profiles?.[userOpts.profile];\n if (!profile) {\n throw new Error(\n `[ENVX_UNKNOWN_PROFILE] '${userOpts.profile}' not found (available: ${\n Object.keys(cfg.profiles ?? {}).join(\", \") || \"none\"\n })`,\n );\n }\n cfg = { ...cfg, ...profile };\n }\n // Strip `profile` before passing to mergeOpts — it's not a LoadEnvOptions field.\n const { profile: _drop, ...rest } = userOpts;\n void _drop;\n loadEnv(mergeOpts(cfg, rest));\n return process.env;\n}\n\n/**\n * Per-field merge: caller-supplied option wins, falling through to the\n * matching config field, falling through to whatever default `loadEnv`\n * has built in. Fields the caller doesn't pass and the config doesn't\n * set are simply omitted from the merged options object.\n */\nfunction mergeOpts(\n config: DotenvxConfig,\n user: LoadEnvOptions,\n): LoadEnvOptions {\n const out: { -readonly [K in keyof LoadEnvOptions]: LoadEnvOptions[K] } = {};\n\n // env-file selection\n if (user.envFiles !== undefined) out.envFiles = user.envFiles;\n else if (config.envFiles !== undefined) out.envFiles = [...config.envFiles];\n\n if (user.envPath !== undefined) out.envPath = user.envPath;\n else if (config.envPath !== undefined) out.envPath = config.envPath;\n\n if (user.cascade !== undefined) out.cascade = user.cascade;\n else if (config.cascade !== undefined) out.cascade = config.cascade;\n\n if (user.vault !== undefined) out.vault = user.vault;\n\n if (user.variables !== undefined) out.variables = user.variables;\n\n // load behavior\n if (user.override !== undefined) out.override = user.override;\n else if (config.override !== undefined) out.override = config.override;\n\n if (user.quiet !== undefined) out.quiet = user.quiet;\n else if (config.quiet !== undefined) out.quiet = config.quiet;\n\n // auto-detection\n if (user.autoDetect !== undefined) out.autoDetect = user.autoDetect;\n else if (config.autoDetect !== undefined) out.autoDetect = config.autoDetect;\n\n if (user.nodeEnvMap !== undefined) out.nodeEnvMap = user.nodeEnvMap;\n else if (config.nodeEnvMap !== undefined) out.nodeEnvMap = config.nodeEnvMap;\n\n // post-load behavior\n if (user.required !== undefined) out.required = user.required;\n else if (config.required !== undefined) out.required = config.required;\n\n if (user.expand !== undefined) out.expand = user.expand;\n else if (config.expand !== undefined) out.expand = config.expand;\n\n if (user.defaults !== undefined) out.defaults = user.defaults;\n else if (config.defaults !== undefined) out.defaults = config.defaults;\n\n // advanced\n if (user.workspaceRoot !== undefined) out.workspaceRoot = user.workspaceRoot;\n else if (config.workspaceRoot !== undefined) out.workspaceRoot = config.workspaceRoot;\n\n if (user.schema !== undefined) out.schema = user.schema;\n else if (config.schema !== undefined) out.schema = config.schema;\n\n if (user.resolvers !== undefined) out.resolvers = user.resolvers;\n else if (config.resolvers !== undefined) out.resolvers = config.resolvers;\n\n if (user.publicPrefixes !== undefined) out.publicPrefixes = user.publicPrefixes;\n else if (config.publicPrefixes !== undefined) out.publicPrefixes = config.publicPrefixes;\n\n if (user.publicSource !== undefined) out.publicSource = user.publicSource;\n else if (config.publicSource !== undefined) out.publicSource = config.publicSource;\n\n return out;\n}\n\nexport default envx;\nexport { envx };\n\n// Re-export the types callers will need to type their own wrappers.\nexport type { LoadEnvOptions };\n\n// #endregion -----------------------------------------------\n"],"mappings":";;AAiGA,SAAS,KAAK,KAA2D;CACvE,MAAM,EAAE,QAAQ,eAAe,mBAAmB;CAClD,MAAM,WACJ,QAAQ,KAAA,IACJ,EAAE,GACF,OAAO,QAAQ,WACb,EAAE,SAAS,KAAK,GAChB;CACR,IAAI,MAAqB;CACzB,IAAI,SAAS,SAAS;EACpB,MAAM,UAAU,IAAI,WAAW,SAAS;EACxC,IAAI,CAAC,SACH,MAAM,IAAI,MACR,2BAA2B,SAAS,QAAQ,0BAC1C,OAAO,KAAK,IAAI,YAAY,EAAE,CAAC,CAAC,KAAK,KAAK,IAAI,OAC/C,GACF;EAEH,MAAM;GAAE,GAAG;GAAK,GAAG;GAAS;;CAG9B,MAAM,EAAE,SAAS,OAAO,GAAG,SAAS;CAEpC,QAAQ,UAAU,KAAK,KAAK,CAAC;CAC7B,OAAO,QAAQ;;;;;;;;AASjB,SAAS,UACP,QACA,MACgB;CAChB,MAAM,MAAoE,EAAE;CAG5E,IAAI,KAAK,aAAa,KAAA,GAAW,IAAI,WAAW,KAAK;MAChD,IAAI,OAAO,aAAa,KAAA,GAAW,IAAI,WAAW,CAAC,GAAG,OAAO,SAAS;CAE3E,IAAI,KAAK,YAAY,KAAA,GAAW,IAAI,UAAU,KAAK;MAC9C,IAAI,OAAO,YAAY,KAAA,GAAW,IAAI,UAAU,OAAO;CAE5D,IAAI,KAAK,YAAY,KAAA,GAAW,IAAI,UAAU,KAAK;MAC9C,IAAI,OAAO,YAAY,KAAA,GAAW,IAAI,UAAU,OAAO;CAE5D,IAAI,KAAK,UAAU,KAAA,GAAW,IAAI,QAAQ,KAAK;CAE/C,IAAI,KAAK,cAAc,KAAA,GAAW,IAAI,YAAY,KAAK;CAGvD,IAAI,KAAK,aAAa,KAAA,GAAW,IAAI,WAAW,KAAK;MAChD,IAAI,OAAO,aAAa,KAAA,GAAW,IAAI,WAAW,OAAO;CAE9D,IAAI,KAAK,UAAU,KAAA,GAAW,IAAI,QAAQ,KAAK;MAC1C,IAAI,OAAO,UAAU,KAAA,GAAW,IAAI,QAAQ,OAAO;CAGxD,IAAI,KAAK,eAAe,KAAA,GAAW,IAAI,aAAa,KAAK;MACpD,IAAI,OAAO,eAAe,KAAA,GAAW,IAAI,aAAa,OAAO;CAElE,IAAI,KAAK,eAAe,KAAA,GAAW,IAAI,aAAa,KAAK;MACpD,IAAI,OAAO,eAAe,KAAA,GAAW,IAAI,aAAa,OAAO;CAGlE,IAAI,KAAK,aAAa,KAAA,GAAW,IAAI,WAAW,KAAK;MAChD,IAAI,OAAO,aAAa,KAAA,GAAW,IAAI,WAAW,OAAO;CAE9D,IAAI,KAAK,WAAW,KAAA,GAAW,IAAI,SAAS,KAAK;MAC5C,IAAI,OAAO,WAAW,KAAA,GAAW,IAAI,SAAS,OAAO;CAE1D,IAAI,KAAK,aAAa,KAAA,GAAW,IAAI,WAAW,KAAK;MAChD,IAAI,OAAO,aAAa,KAAA,GAAW,IAAI,WAAW,OAAO;CAG9D,IAAI,KAAK,kBAAkB,KAAA,GAAW,IAAI,gBAAgB,KAAK;MAC1D,IAAI,OAAO,kBAAkB,KAAA,GAAW,IAAI,gBAAgB,OAAO;CAExE,IAAI,KAAK,WAAW,KAAA,GAAW,IAAI,SAAS,KAAK;MAC5C,IAAI,OAAO,WAAW,KAAA,GAAW,IAAI,SAAS,OAAO;CAE1D,IAAI,KAAK,cAAc,KAAA,GAAW,IAAI,YAAY,KAAK;MAClD,IAAI,OAAO,cAAc,KAAA,GAAW,IAAI,YAAY,OAAO;CAEhE,IAAI,KAAK,mBAAmB,KAAA,GAAW,IAAI,iBAAiB,KAAK;MAC5D,IAAI,OAAO,mBAAmB,KAAA,GAAW,IAAI,iBAAiB,OAAO;CAE1E,IAAI,KAAK,iBAAiB,KAAA,GAAW,IAAI,eAAe,KAAK;MACxD,IAAI,OAAO,iBAAiB,KAAA,GAAW,IAAI,eAAe,OAAO;CAEtE,OAAO"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
//#region src/plugins/types.ts
|
|
2
|
+
/**
|
|
3
|
+
* Internal factory used by every plugin to wire up the preload / resolve
|
|
4
|
+
* / cache trio. Plugin authors hand it a `fetchOne(id)` and we handle
|
|
5
|
+
* the cache + parallelism. Keeps the per-provider files focused on the
|
|
6
|
+
* SDK call.
|
|
7
|
+
*/
|
|
8
|
+
function buildProvider(name, fetchOne) {
|
|
9
|
+
const cache = /* @__PURE__ */ new Map();
|
|
10
|
+
return {
|
|
11
|
+
name,
|
|
12
|
+
cache,
|
|
13
|
+
fetch: fetchOne,
|
|
14
|
+
async preload(ids) {
|
|
15
|
+
const todo = [...new Set(ids)].filter((id) => !cache.has(id));
|
|
16
|
+
if (todo.length === 0) return;
|
|
17
|
+
const results = await Promise.all(todo.map(async (id) => {
|
|
18
|
+
try {
|
|
19
|
+
return {
|
|
20
|
+
id,
|
|
21
|
+
value: await fetchOne(id),
|
|
22
|
+
ok: true
|
|
23
|
+
};
|
|
24
|
+
} catch (e) {
|
|
25
|
+
return {
|
|
26
|
+
id,
|
|
27
|
+
error: e,
|
|
28
|
+
ok: false
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
}));
|
|
32
|
+
const errors = [];
|
|
33
|
+
for (const r of results) if (r.ok) cache.set(r.id, r.value);
|
|
34
|
+
else errors.push({
|
|
35
|
+
id: r.id,
|
|
36
|
+
error: r.error
|
|
37
|
+
});
|
|
38
|
+
if (errors.length > 0) {
|
|
39
|
+
const summary = errors.map((e) => ` ${e.id}: ${e.error.message}`).join("\n");
|
|
40
|
+
throw new Error(`[ENVX_PLUGIN_${name.toUpperCase()}] failed to preload ${String(errors.length)} secret(s):\n${summary}`);
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
resolve(id) {
|
|
44
|
+
return cache.get(id);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Thrown by every plugin's lazy SDK loader when the consumer hasn't
|
|
50
|
+
* installed the relevant SDK package. The message includes the
|
|
51
|
+
* `pnpm add <pkg>` line so users get the exact remediation.
|
|
52
|
+
*/
|
|
53
|
+
var MissingSdkError = class extends Error {
|
|
54
|
+
constructor(plugin, sdk) {
|
|
55
|
+
super(`[ENVX_PLUGIN_MISSING_SDK] the '${plugin}' plugin needs '${sdk}'.\n install it: pnpm add ${sdk}\n (or your equivalent — npm / yarn / bun)`);
|
|
56
|
+
this.name = "MissingSdkError";
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
//#endregion
|
|
60
|
+
export { buildProvider as n, MissingSdkError as t };
|
|
61
|
+
|
|
62
|
+
//# sourceMappingURL=types-COrFYR0z.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-COrFYR0z.js","names":[],"sources":["../../src/plugins/types.ts"],"sourcesContent":["// #region -- Plugin Contract -------------------------------\n\n/**\n * The shape every plugin returns. envx's `resolvers:` config is sync\n * (we don't want loadEnv to become async-everywhere), but every real\n * secret-store SDK is async — so plugins split the concern in two:\n *\n * 1. `preload(ids)` — async batch fetch, populates an in-memory cache.\n * 2. `resolve(id)` — sync cache lookup. This is what envx wires into `resolvers`.\n *\n * Call `preload(...)` once during your bootstrap (top-level `await` in an\n * async entry, or a small `await main()` wrapper), then hand `resolve` to\n * envx. The cache is per-provider-instance — instantiate once and share.\n */\nexport interface SecretProvider {\n /** Stable provider name. Matches the prefix in `${name:id}` env-file refs. */\n readonly name: string;\n\n /**\n * Fetch and cache the named secrets. Safe to call multiple times — the\n * implementation should de-duplicate and skip already-cached IDs.\n * Errors fetching individual secrets are surfaced as exceptions so\n * the bootstrap fails fast (rather than silently leaving secrets unset).\n */\n preload(ids: readonly string[]): Promise<void>;\n\n /**\n * Fetch a single secret directly from the backend, bypassing the\n * plugin's cache. Used by the runtime/edge accessor (which owns its\n * own TTL cache and can't accept a \"stuck-forever\" plugin cache).\n */\n fetch(id: string): Promise<string>;\n\n /**\n * Read a previously preloaded value. Returns `undefined` for unknown\n * IDs so envx leaves the literal `${name:id}` in place — that way\n * misconfigurations surface visibly instead of producing an empty\n * string at runtime.\n */\n resolve(id: string): string | undefined;\n\n /** Direct access to the cache for tooling (testing, debugging, snapshotting). */\n readonly cache: ReadonlyMap<string, string>;\n}\n\n// #endregion -----------------------------------------------\n\n// #region -- Common factory helper -------------------------\n\n/**\n * Internal factory used by every plugin to wire up the preload / resolve\n * / cache trio. Plugin authors hand it a `fetchOne(id)` and we handle\n * the cache + parallelism. Keeps the per-provider files focused on the\n * SDK call.\n */\nexport function buildProvider(\n name: string,\n fetchOne: (id: string) => Promise<string>,\n): SecretProvider {\n const cache = new Map<string, string>();\n\n return {\n name,\n cache,\n fetch: fetchOne,\n async preload(ids: readonly string[]): Promise<void> {\n const todo = [...new Set(ids)].filter((id) => !cache.has(id));\n if (todo.length === 0) return;\n const results = await Promise.all(\n todo.map(async (id) => {\n try {\n const value = await fetchOne(id);\n return { id, value, ok: true as const };\n } catch (e) {\n return { id, error: e as Error, ok: false as const };\n }\n }),\n );\n const errors: Array<{ id: string; error: Error }> = [];\n for (const r of results) {\n if (r.ok) cache.set(r.id, r.value);\n else errors.push({ id: r.id, error: r.error });\n }\n if (errors.length > 0) {\n const summary = errors\n .map((e) => ` ${e.id}: ${e.error.message}`)\n .join(\"\\n\");\n throw new Error(\n `[ENVX_PLUGIN_${name.toUpperCase()}] failed to preload ${String(\n errors.length,\n )} secret(s):\\n${summary}`,\n );\n }\n },\n resolve(id: string): string | undefined {\n return cache.get(id);\n },\n };\n}\n\n// #endregion -----------------------------------------------\n\n// #region -- Missing-SDK error -----------------------------\n\n/**\n * Thrown by every plugin's lazy SDK loader when the consumer hasn't\n * installed the relevant SDK package. The message includes the\n * `pnpm add <pkg>` line so users get the exact remediation.\n */\nexport class MissingSdkError extends Error {\n constructor(plugin: string, sdk: string) {\n super(\n `[ENVX_PLUGIN_MISSING_SDK] the '${plugin}' plugin needs '${sdk}'.\\n` +\n ` install it: pnpm add ${sdk}\\n` +\n ` (or your equivalent — npm / yarn / bun)`,\n );\n this.name = \"MissingSdkError\";\n }\n}\n\n// #endregion -----------------------------------------------\n"],"mappings":";;;;;;;AAuDA,SAAgB,cACd,MACA,UACgB;CAChB,MAAM,wBAAQ,IAAI,KAAqB;CAEvC,OAAO;EACL;EACA;EACA,OAAO;EACP,MAAM,QAAQ,KAAuC;GACnD,MAAM,OAAO,CAAC,GAAG,IAAI,IAAI,IAAI,CAAC,CAAC,QAAQ,OAAO,CAAC,MAAM,IAAI,GAAG,CAAC;GAC7D,IAAI,KAAK,WAAW,GAAG;GACvB,MAAM,UAAU,MAAM,QAAQ,IAC5B,KAAK,IAAI,OAAO,OAAO;IACrB,IAAI;KAEF,OAAO;MAAE;MAAI,OAAA,MADO,SAAS,GAAG;MACZ,IAAI;MAAe;aAChC,GAAG;KACV,OAAO;MAAE;MAAI,OAAO;MAAY,IAAI;MAAgB;;KAEtD,CACH;GACD,MAAM,SAA8C,EAAE;GACtD,KAAK,MAAM,KAAK,SACd,IAAI,EAAE,IAAI,MAAM,IAAI,EAAE,IAAI,EAAE,MAAM;QAC7B,OAAO,KAAK;IAAE,IAAI,EAAE;IAAI,OAAO,EAAE;IAAO,CAAC;GAEhD,IAAI,OAAO,SAAS,GAAG;IACrB,MAAM,UAAU,OACb,KAAK,MAAM,KAAK,EAAE,GAAG,IAAI,EAAE,MAAM,UAAU,CAC3C,KAAK,KAAK;IACb,MAAM,IAAI,MACR,gBAAgB,KAAK,aAAa,CAAC,sBAAsB,OACvD,OAAO,OACR,CAAC,eAAe,UAClB;;;EAGL,QAAQ,IAAgC;GACtC,OAAO,MAAM,IAAI,GAAG;;EAEvB;;;;;;;AAYH,IAAa,kBAAb,cAAqC,MAAM;CACzC,YAAY,QAAgB,KAAa;EACvC,MACE,kCAAkC,OAAO,kBAAkB,IAAI,6BACnC,IAAI,6CAEjC;EACD,KAAK,OAAO"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { n as buildProvider } from "./types-COrFYR0z.js";
|
|
2
|
+
//#region src/plugins/vault.ts
|
|
3
|
+
/**
|
|
4
|
+
* HashiCorp Vault (KV v1 / v2) provider.
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { hcVault } from "@super-repo/envx/plugins/vault";
|
|
8
|
+
*
|
|
9
|
+
* const vault = hcVault({
|
|
10
|
+
* endpoint: process.env.VAULT_ADDR!,
|
|
11
|
+
* token: process.env.VAULT_TOKEN!,
|
|
12
|
+
* mount: "secret",
|
|
13
|
+
* });
|
|
14
|
+
* await vault.preload(["prod/db", "prod/api"]);
|
|
15
|
+
*
|
|
16
|
+
* envx({ resolvers: { [vault.name]: vault.resolve } });
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* Reference shape:
|
|
20
|
+
*
|
|
21
|
+
* ```
|
|
22
|
+
* # KV v2 path: <mount>/data/<id>, returns the "value" field by default.
|
|
23
|
+
* # Or pin a specific JSON field: ${vault:prod/db#username}
|
|
24
|
+
* DB_URL=${vault:prod/db}
|
|
25
|
+
* USER=${vault:prod/db#username}
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* No SDK install required — uses native `fetch` (Node 20+).
|
|
29
|
+
*/
|
|
30
|
+
function hcVault(opts) {
|
|
31
|
+
const name = opts.name ?? "vault";
|
|
32
|
+
const mount = opts.mount ?? "secret";
|
|
33
|
+
const kvVersion = opts.kvVersion ?? 2;
|
|
34
|
+
const doFetch = opts.fetchImpl ?? fetch;
|
|
35
|
+
return buildProvider(name, async (idWithField) => {
|
|
36
|
+
const hash = idWithField.indexOf("#");
|
|
37
|
+
const id = hash >= 0 ? idWithField.slice(0, hash) : idWithField;
|
|
38
|
+
const field = hash >= 0 ? idWithField.slice(hash + 1) : "value";
|
|
39
|
+
const segment = kvVersion === 2 ? "data/" : "";
|
|
40
|
+
const url = `${opts.endpoint.replace(/\/$/, "")}/v1/${mount}/${segment}${id}`;
|
|
41
|
+
const r = await doFetch(url, { headers: { "X-Vault-Token": opts.token } });
|
|
42
|
+
if (!r.ok) throw new Error(`vault GET ${url} → ${String(r.status)} ${r.statusText}`);
|
|
43
|
+
const body = await r.json();
|
|
44
|
+
const data = kvVersion === 2 ? body.data?.data ?? {} : body.data ?? {};
|
|
45
|
+
const value = data[field];
|
|
46
|
+
if (typeof value === "string") return value;
|
|
47
|
+
if (value === void 0) throw new Error(`vault: '${id}' has no field '${field}' (available: ${Object.keys(data).join(", ") || "none"})`);
|
|
48
|
+
return JSON.stringify(value);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
export { hcVault as t };
|
|
53
|
+
|
|
54
|
+
//# sourceMappingURL=vault-BWdO9DFO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vault-BWdO9DFO.js","names":[],"sources":["../../src/plugins/vault.ts"],"sourcesContent":["import { buildProvider, type SecretProvider } from \"./types.js\";\n\n// #region -- HashiCorp Vault -------------------------------\n\nexport interface HcVaultOptions {\n /** Vault server URL, e.g. \"https://vault.example.com:8200\". */\n readonly endpoint: string;\n /** Vault token (from `VAULT_TOKEN`, machine identity, etc.). */\n readonly token: string;\n /**\n * KV v2 mount path (default: `\"secret\"`). KV v1 callers should set\n * `kvVersion: 1`.\n */\n readonly mount?: string;\n /** KV engine version. Default `2`. */\n readonly kvVersion?: 1 | 2;\n /** Override the global fetch (testing). */\n readonly fetchImpl?: typeof fetch;\n /** Provider name, defaults to `\"vault\"`. */\n readonly name?: string;\n}\n\n/**\n * HashiCorp Vault (KV v1 / v2) provider.\n *\n * ```ts\n * import { hcVault } from \"@super-repo/envx/plugins/vault\";\n *\n * const vault = hcVault({\n * endpoint: process.env.VAULT_ADDR!,\n * token: process.env.VAULT_TOKEN!,\n * mount: \"secret\",\n * });\n * await vault.preload([\"prod/db\", \"prod/api\"]);\n *\n * envx({ resolvers: { [vault.name]: vault.resolve } });\n * ```\n *\n * Reference shape:\n *\n * ```\n * # KV v2 path: <mount>/data/<id>, returns the \"value\" field by default.\n * # Or pin a specific JSON field: ${vault:prod/db#username}\n * DB_URL=${vault:prod/db}\n * USER=${vault:prod/db#username}\n * ```\n *\n * No SDK install required — uses native `fetch` (Node 20+).\n */\nexport function hcVault(opts: HcVaultOptions): SecretProvider {\n const name = opts.name ?? \"vault\";\n const mount = opts.mount ?? \"secret\";\n const kvVersion = opts.kvVersion ?? 2;\n const doFetch = opts.fetchImpl ?? fetch;\n\n return buildProvider(name, async (idWithField) => {\n // `id` may include `#<field>` to pick a specific JSON field.\n const hash = idWithField.indexOf(\"#\");\n const id = hash >= 0 ? idWithField.slice(0, hash) : idWithField;\n const field = hash >= 0 ? idWithField.slice(hash + 1) : \"value\";\n\n const segment = kvVersion === 2 ? \"data/\" : \"\";\n const url = `${opts.endpoint.replace(/\\/$/, \"\")}/v1/${mount}/${segment}${id}`;\n\n const r = await doFetch(url, {\n headers: { \"X-Vault-Token\": opts.token },\n });\n if (!r.ok) {\n throw new Error(`vault GET ${url} → ${String(r.status)} ${r.statusText}`);\n }\n const body = (await r.json()) as {\n data?: Record<string, unknown> | { data?: Record<string, unknown> };\n };\n // KV v2 nests under data.data; v1 puts it directly under data.\n const data =\n kvVersion === 2\n ? ((body.data as { data?: Record<string, unknown> } | undefined)\n ?.data ?? {})\n : (body.data ?? {});\n const value = (data as Record<string, unknown>)[field];\n if (typeof value === \"string\") return value;\n if (value === undefined) {\n throw new Error(\n `vault: '${id}' has no field '${field}' (available: ${Object.keys(data).join(\", \") || \"none\"})`,\n );\n }\n return JSON.stringify(value);\n });\n}\n\n// #endregion -----------------------------------------------\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDA,SAAgB,QAAQ,MAAsC;CAC5D,MAAM,OAAO,KAAK,QAAQ;CAC1B,MAAM,QAAQ,KAAK,SAAS;CAC5B,MAAM,YAAY,KAAK,aAAa;CACpC,MAAM,UAAU,KAAK,aAAa;CAElC,OAAO,cAAc,MAAM,OAAO,gBAAgB;EAEhD,MAAM,OAAO,YAAY,QAAQ,IAAI;EACrC,MAAM,KAAK,QAAQ,IAAI,YAAY,MAAM,GAAG,KAAK,GAAG;EACpD,MAAM,QAAQ,QAAQ,IAAI,YAAY,MAAM,OAAO,EAAE,GAAG;EAExD,MAAM,UAAU,cAAc,IAAI,UAAU;EAC5C,MAAM,MAAM,GAAG,KAAK,SAAS,QAAQ,OAAO,GAAG,CAAC,MAAM,MAAM,GAAG,UAAU;EAEzE,MAAM,IAAI,MAAM,QAAQ,KAAK,EAC3B,SAAS,EAAE,iBAAiB,KAAK,OAAO,EACzC,CAAC;EACF,IAAI,CAAC,EAAE,IACL,MAAM,IAAI,MAAM,aAAa,IAAI,KAAK,OAAO,EAAE,OAAO,CAAC,GAAG,EAAE,aAAa;EAE3E,MAAM,OAAQ,MAAM,EAAE,MAAM;EAI5B,MAAM,OACJ,cAAc,IACR,KAAK,MACH,QAAQ,EAAE,GACb,KAAK,QAAQ,EAAE;EACtB,MAAM,QAAS,KAAiC;EAChD,IAAI,OAAO,UAAU,UAAU,OAAO;EACtC,IAAI,UAAU,KAAA,GACZ,MAAM,IAAI,MACR,WAAW,GAAG,kBAAkB,MAAM,gBAAgB,OAAO,KAAK,KAAK,CAAC,KAAK,KAAK,IAAI,OAAO,GAC9F;EAEH,OAAO,KAAK,UAAU,MAAM;GAC5B"}
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { t as createCli } from "./chunks/commands-
|
|
2
|
+
import { t as createCli } from "./chunks/commands-CblelhOH.js";
|
|
3
3
|
import { hideBin } from "yargs/helpers";
|
|
4
4
|
//#region src/cli.ts
|
|
5
5
|
await createCli(hideBin(process.argv)).parseAsync();
|
package/dist/commands/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as createCli } from "../chunks/commands-
|
|
1
|
+
import { t as createCli } from "../chunks/commands-CblelhOH.js";
|
|
2
2
|
export { createCli };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { LoadEnvOptions } from '
|
|
2
|
-
export { auditFiles, BUILT_IN_PATTERNS, type AuditFinding, type AuditOptions, type SecretPattern, ENCRYPTED_PREFIX, generateKeyPair, encryptValueAsymmetric, decryptValueAsymmetric, isEncrypted, encryptFiles, decryptFiles, rotateFiles, parseEnv, serializeEnv, toRecord, expandRecord, expandEnvSrc, defineConfig, loadDotenvxConfig, findWorkspaceRoot, resolveCwdOrWorkspace, resolveEnvPaths, detectEnvironment, readKeysFile, writeKeysFile, defaultKeysPath, } from '
|
|
3
|
-
export type { DotenvxConfig, LoadEnvOptions, ProcessedEnv, ProcessingError, ErrorCode, RunOptions, RunResult, ExpandOptions, ExpandResult, EnvLine, KvLine, RawLine, } from '
|
|
1
|
+
import { LoadEnvOptions } from './libs/index.js';
|
|
2
|
+
export { auditFiles, BUILT_IN_PATTERNS, type AuditFinding, type AuditOptions, type SecretPattern, ENCRYPTED_PREFIX, generateKeyPair, encryptValueAsymmetric, decryptValueAsymmetric, isEncrypted, encryptFiles, decryptFiles, rotateFiles, parseEnv, serializeEnv, toRecord, expandRecord, expandEnvSrc, defineConfig, loadDotenvxConfig, findWorkspaceRoot, resolveCwdOrWorkspace, resolveEnvPaths, detectEnvironment, readKeysFile, writeKeysFile, defaultKeysPath, } from './libs/index.js';
|
|
3
|
+
export type { DotenvxConfig, LoadEnvOptions, ProcessedEnv, ProcessingError, ErrorCode, RunOptions, RunResult, ExpandOptions, ExpandResult, EnvLine, KvLine, RawLine, } from './libs/index.js';
|
|
4
4
|
/**
|
|
5
5
|
* Load env files into `process.env` and return it.
|
|
6
6
|
*
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,iBAAiB,CAAC;AAOzB,OAAO,EAEL,UAAU,EACV,iBAAiB,EACjB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,aAAa,EAElB,gBAAgB,EAChB,eAAe,EACf,sBAAsB,EACtB,sBAAsB,EACtB,WAAW,EAEX,YAAY,EACZ,YAAY,EACZ,WAAW,EAEX,QAAQ,EACR,YAAY,EACZ,QAAQ,EAER,YAAY,EACZ,YAAY,EAEZ,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,iBAAiB,EAEjB,YAAY,EACZ,aAAa,EACb,eAAe,GAChB,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EACV,aAAa,EACb,cAAc,EACd,YAAY,EACZ,eAAe,EACf,SAAS,EACT,UAAU,EACV,SAAS,EACT,aAAa,EACb,YAAY,EACZ,OAAO,EACP,MAAM,EACN,OAAO,GACR,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;;;;;;;;;;;GAmBG;AACH;;;;;GAKG;AACH,MAAM,MAAM,uBAAuB,GAAG,cAAc,GAAG;IAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAErF,iBAAS,IAAI,IAAI,MAAM,CAAC,UAAU,CAAC;AACnC,iBAAS,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC;AAChD,iBAAS,IAAI,CAAC,IAAI,EAAE,uBAAuB,GAAG,MAAM,CAAC,UAAU,CAAC;AAiGhE,eAAe,IAAI,CAAC;AACpB,OAAO,EAAE,IAAI,EAAE,CAAC;AAGhB,YAAY,EAAE,cAAc,EAAE,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as envx } from "./chunks/src-
|
|
1
|
+
import { B as ENCRYPTED_PREFIX, C as readKeysFile, E as detectEnvironment, F as expandRecord, H as encryptValueAsymmetric, L as parseEnv, M as resolveEnvPaths, O as findWorkspaceRoot, P as expandEnvSrc, R as serializeEnv, U as generateKeyPair, V as decryptValueAsymmetric, W as isEncrypted, _ as defaultKeysPath, a as auditFiles, c as encryptFiles, i as BUILT_IN_PATTERNS, j as resolveCwdOrWorkspace, n as defineConfig, o as rotateFiles, r as loadDotenvxConfig, s as decryptFiles, w as writeKeysFile, z as toRecord } from "./chunks/libs-DewxofWa.js";
|
|
2
|
+
import { t as envx } from "./chunks/src-C3xPGIyj.js";
|
|
3
3
|
export { BUILT_IN_PATTERNS, ENCRYPTED_PREFIX, auditFiles, decryptFiles, decryptValueAsymmetric, envx as default, envx, defaultKeysPath, defineConfig, detectEnvironment, encryptFiles, encryptValueAsymmetric, expandEnvSrc, expandRecord, findWorkspaceRoot, generateKeyPair, isEncrypted, loadDotenvxConfig, parseEnv, readKeysFile, resolveCwdOrWorkspace, resolveEnvPaths, rotateFiles, serializeEnv, toRecord, writeKeysFile };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in plaintext-secret detectors. Each entry is a stable id, a
|
|
3
|
+
* human label, and a regex. We deliberately bias toward known formats
|
|
4
|
+
* (AWS, Stripe, GitHub, JWT, Slack, generic high-entropy hex/base64)
|
|
5
|
+
* over generic entropy so the false-positive rate stays low. Users can
|
|
6
|
+
* register additional patterns through {@link auditFiles}'s `extra`
|
|
7
|
+
* option.
|
|
8
|
+
*
|
|
9
|
+
* Patterns must NOT use the `g` flag — we rely on per-line matching.
|
|
10
|
+
*/
|
|
11
|
+
export interface SecretPattern {
|
|
12
|
+
readonly id: string;
|
|
13
|
+
readonly label: string;
|
|
14
|
+
readonly regex: RegExp;
|
|
15
|
+
}
|
|
16
|
+
export declare const BUILT_IN_PATTERNS: readonly SecretPattern[];
|
|
17
|
+
export interface AuditFinding {
|
|
18
|
+
readonly file: string;
|
|
19
|
+
readonly line: number;
|
|
20
|
+
readonly patternId: string;
|
|
21
|
+
readonly label: string;
|
|
22
|
+
readonly snippet: string;
|
|
23
|
+
}
|
|
24
|
+
export interface AuditOptions {
|
|
25
|
+
/** Roots to scan. Defaults to `["."]`. */
|
|
26
|
+
readonly roots?: readonly string[];
|
|
27
|
+
/** Extra patterns to match alongside the built-ins. */
|
|
28
|
+
readonly extra?: readonly SecretPattern[];
|
|
29
|
+
/** Globs (or directory names) to skip. */
|
|
30
|
+
readonly ignore?: readonly string[];
|
|
31
|
+
/** Cap on findings — stop walking after this many. 0 = no cap. */
|
|
32
|
+
readonly max?: number;
|
|
33
|
+
/**
|
|
34
|
+
* When `true`, scan `*.test.{ts,js,…}` and `*.spec.{ts,js,…}` files.
|
|
35
|
+
* Default: `false` — test files routinely embed shape-valid example
|
|
36
|
+
* credentials (the canonical AWS docs example, GitHub-PAT fixtures,
|
|
37
|
+
* Stripe-test values) and scanning them produces noise, not signal.
|
|
38
|
+
*/
|
|
39
|
+
readonly scanTests?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* When `true` (default), audit honors the project's `.gitignore` and
|
|
42
|
+
* `.git/info/exclude`: any file or directory matched by those rules
|
|
43
|
+
* is skipped. The `.git` directory is always skipped regardless.
|
|
44
|
+
*
|
|
45
|
+
* Strict adherence — `.env` files in `.gitignore` are skipped too. To
|
|
46
|
+
* scan a specific gitignored path, pass it as an explicit root
|
|
47
|
+
* (`auditFiles({ roots: [".env"] })`) or set this option to `false`.
|
|
48
|
+
*
|
|
49
|
+
* No-op outside a git repo (no `.git` directory found walking up).
|
|
50
|
+
*/
|
|
51
|
+
readonly respectGitignore?: boolean;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Walk one or more directories looking for plaintext secret patterns.
|
|
55
|
+
* Reads only text-like files (extension allowlist) so we don't blow
|
|
56
|
+
* memory on a stray binary blob.
|
|
57
|
+
*/
|
|
58
|
+
export declare function auditFiles(opts?: AuditOptions): {
|
|
59
|
+
readonly findings: AuditFinding[];
|
|
60
|
+
readonly filesScanned: number;
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=audit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/libs/audit.ts"],"names":[],"mappings":"AAMA;;;;;;;;;GASG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,iBAAiB,EAAE,SAAS,aAAa,EAYrD,CAAC;AAMF,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,0CAA0C;IAC1C,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,uDAAuD;IACvD,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;IAC1C,0CAA0C;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,kEAAkE;IAClE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CACrC;AA8DD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,GAAE,YAAiB,GAAG;IACnD,QAAQ,CAAC,QAAQ,EAAE,YAAY,EAAE,CAAC;IAClC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B,CAqHA"}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mapping shape: per-file allowlist of keys (or globs). Used to decide
|
|
3
|
+
* which env file an inline key belongs in, and to constrain
|
|
4
|
+
* encrypt/decrypt to the right scope.
|
|
5
|
+
*
|
|
6
|
+
* {
|
|
7
|
+
* '.env.shared': ['DATABASE_URL', 'REDIS_URL'],
|
|
8
|
+
* '.env.app': ['APP_*'],
|
|
9
|
+
* }
|
|
10
|
+
*/
|
|
11
|
+
export type EnvFileMapping = Readonly<Record<string, readonly string[]>>;
|
|
12
|
+
export interface DotenvxConfig {
|
|
13
|
+
/** Default env files to load when --env is not supplied. */
|
|
14
|
+
readonly envFiles?: readonly string[];
|
|
15
|
+
/**
|
|
16
|
+
* Subdirectory where env files live (e.g. "vault"). Cwd-first; falls
|
|
17
|
+
* back to `<workspaceRoot>/<envPath>` if the cwd path doesn't exist.
|
|
18
|
+
* Equivalent to passing `--vault` (which is a shortcut for `envPath: "vault"`).
|
|
19
|
+
*/
|
|
20
|
+
readonly envPath?: string;
|
|
21
|
+
/**
|
|
22
|
+
* When `true`, envx expands each base env file into four layered
|
|
23
|
+
* paths (most-specific-first): `.env.<env>.local`, `.env.local`,
|
|
24
|
+
* `.env.<env>`, `.env` — where `<env>` is the auto-detected
|
|
25
|
+
* environment name (see `detectEnvironment()` / `nodeEnvMap`).
|
|
26
|
+
*
|
|
27
|
+
* `false` (or omitted) disables cascading. If you need to force a
|
|
28
|
+
* specific cascade name regardless of detection, pass `--cascade
|
|
29
|
+
* <name>` on the CLI; the explicit string overrides this flag.
|
|
30
|
+
*/
|
|
31
|
+
readonly cascade?: boolean;
|
|
32
|
+
/** Path to the keys file. Cwd-first with workspace-root fallback. */
|
|
33
|
+
readonly envKeysFile?: string;
|
|
34
|
+
/** Per-file allowlist of keys (literal names or globs). */
|
|
35
|
+
readonly mapping?: EnvFileMapping;
|
|
36
|
+
/** Override existing process.env when loading. */
|
|
37
|
+
readonly override?: boolean;
|
|
38
|
+
/** Suppress dotenv-style logging. */
|
|
39
|
+
readonly quiet?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Toggle auto-detection of the deployment environment from
|
|
42
|
+
* `VERCEL_ENV` / Netlify `CONTEXT` / `NODE_ENV`. When `false`, envx
|
|
43
|
+
* never rewrites the `.env` suffix from platform signals — explicit
|
|
44
|
+
* `--env` / `envFiles` are the only inputs. Default: `true`.
|
|
45
|
+
*/
|
|
46
|
+
readonly autoDetect?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Override the `NODE_ENV → suffix` mapping used during auto-detection.
|
|
49
|
+
* Keys are lowercased `NODE_ENV` values; values are the suffix to
|
|
50
|
+
* append after `.env.` (e.g. `staging` → `.env.staging`).
|
|
51
|
+
*
|
|
52
|
+
* Built-in defaults:
|
|
53
|
+
* { production: "prod", development: "dev", local: "local" }
|
|
54
|
+
*
|
|
55
|
+
* Anything not in the map (e.g. `NODE_ENV=qa`) passes through
|
|
56
|
+
* lowercased verbatim — `qa` becomes `.env.qa`. Set an entry to
|
|
57
|
+
* empty string `""` to force "no suffix" (just `.env`) for that
|
|
58
|
+
* NODE_ENV value.
|
|
59
|
+
*/
|
|
60
|
+
readonly nodeEnvMap?: Readonly<Record<string, string>>;
|
|
61
|
+
/**
|
|
62
|
+
* Keys that MUST be set in `process.env` after envx finishes loading.
|
|
63
|
+
* If any are still unset, envx logs the missing names and exits with
|
|
64
|
+
* a non-zero status. Use this to fail fast in CI / production rather
|
|
65
|
+
* than discovering an unset `DATABASE_URL` deep in app startup.
|
|
66
|
+
*/
|
|
67
|
+
readonly required?: readonly string[];
|
|
68
|
+
/**
|
|
69
|
+
* Auto-resolve `${VAR}` / `$VAR` / `${VAR:-default}` / `${VAR:?msg}`
|
|
70
|
+
* references in loaded values. When `true`, envx runs the same
|
|
71
|
+
* expansion logic as `envx expand` against `process.env` after files
|
|
72
|
+
* load. Default: `false` (values are loaded verbatim, like dotenv).
|
|
73
|
+
*/
|
|
74
|
+
readonly expand?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Fallback values applied AFTER env files (and `variables`) finish
|
|
77
|
+
* loading, only for keys that are still unset. Different from
|
|
78
|
+
* `variables`, which always overrides. Useful for non-secret
|
|
79
|
+
* defaults that belong in code rather than `.env*` files.
|
|
80
|
+
*/
|
|
81
|
+
readonly defaults?: Readonly<Record<string, string>>;
|
|
82
|
+
/**
|
|
83
|
+
* Explicit workspace root, skipping `findWorkspaceRoot()` walk-up.
|
|
84
|
+
* Useful when the auto-detection picks the wrong directory (Bazel,
|
|
85
|
+
* custom CI sandboxes, weird symlink layouts). The path is taken
|
|
86
|
+
* verbatim — relative paths resolve against cwd at load time.
|
|
87
|
+
*/
|
|
88
|
+
readonly workspaceRoot?: string;
|
|
89
|
+
/**
|
|
90
|
+
* Optional Zod schema (or any object exposing a `safeParse`-style API)
|
|
91
|
+
* used to validate `process.env` after loading completes. On failure,
|
|
92
|
+
* envx logs each issue and exits with a non-zero status.
|
|
93
|
+
*
|
|
94
|
+
* Duck-typed as `unknown` so the libs package doesn't take a hard
|
|
95
|
+
* runtime dep on zod — the schema only needs a method named
|
|
96
|
+
* `safeParse(input) → { success, error?, data? }`.
|
|
97
|
+
*
|
|
98
|
+
* Only accepted from `.ts` / `.js` configs (JSON cannot carry a
|
|
99
|
+
* function-bearing object).
|
|
100
|
+
*/
|
|
101
|
+
readonly schema?: unknown;
|
|
102
|
+
/**
|
|
103
|
+
* Named profiles. When `--profile <name>` is passed (or a programmatic
|
|
104
|
+
* `profile` option), the profile's fields override the base config
|
|
105
|
+
* per-field. Profiles let one config file orchestrate multiple
|
|
106
|
+
* environments (staging, prod, ci, …) without juggling files.
|
|
107
|
+
*/
|
|
108
|
+
readonly profiles?: Readonly<Record<string, Omit<DotenvxConfig, "profiles">>>;
|
|
109
|
+
/**
|
|
110
|
+
* Map of provider key → resolver function for external secret refs
|
|
111
|
+
* like `${aws-secrets:my-secret-id}` embedded in env-file values.
|
|
112
|
+
* Resolvers run after files load but before `expand`. Synchronous
|
|
113
|
+
* for simplicity; wrap async SDK calls in your config (e.g. cache
|
|
114
|
+
* the value before calling envx).
|
|
115
|
+
*/
|
|
116
|
+
readonly resolvers?: Readonly<Record<string, (id: string) => string | undefined>>;
|
|
117
|
+
/**
|
|
118
|
+
* Framework prefixes that should receive a copy of every "public"
|
|
119
|
+
* variable. Common values: `["VITE_", "NEXT_PUBLIC_", "REACT_APP_",
|
|
120
|
+
* "PUBLIC_"]`.
|
|
121
|
+
*
|
|
122
|
+
* envx walks `process.env` after expansion, finds every key that
|
|
123
|
+
* starts with `publicSource` (default `"PUBLIC_"`), strips the
|
|
124
|
+
* source prefix, and re-exports the value under each prefix in
|
|
125
|
+
* this list. So `PUBLIC_API_URL=...` automatically becomes
|
|
126
|
+
* `VITE_API_URL`, `NEXT_PUBLIC_API_URL`, `REACT_APP_API_URL`
|
|
127
|
+
* — without you maintaining three near-identical entries by hand.
|
|
128
|
+
*
|
|
129
|
+
* Existing keys are never overwritten — if a target like
|
|
130
|
+
* `NEXT_PUBLIC_API_URL` is already set, envx leaves it alone.
|
|
131
|
+
*/
|
|
132
|
+
readonly publicPrefixes?: readonly string[];
|
|
133
|
+
/**
|
|
134
|
+
* Source prefix that marks a variable as "public". Default: `"PUBLIC_"`.
|
|
135
|
+
* Anything in the env file starting with this prefix gets mirrored
|
|
136
|
+
* under `publicPrefixes`. The source key is preserved unchanged so
|
|
137
|
+
* server-side code can still read `process.env.PUBLIC_FOO` if it
|
|
138
|
+
* wants to.
|
|
139
|
+
*/
|
|
140
|
+
readonly publicSource?: string;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Identity helper for typed `envx.config.{ts,js}` files. Mirrors the
|
|
144
|
+
* `defineConfig` convention used by Vite, Vitest, czar, and rune — at
|
|
145
|
+
* runtime it just returns the object, but it gives editors full
|
|
146
|
+
* autocomplete and type-checking for `DotenvxConfig` without the
|
|
147
|
+
* caller needing to write `satisfies DotenvxConfig` everywhere.
|
|
148
|
+
*
|
|
149
|
+
* ```ts
|
|
150
|
+
* // envx.config.ts
|
|
151
|
+
* import { defineConfig } from "@super-repo/envx";
|
|
152
|
+
*
|
|
153
|
+
* export default defineConfig({
|
|
154
|
+
* envFiles: [".env", ".env.local"],
|
|
155
|
+
* cascade: true,
|
|
156
|
+
* required: ["DATABASE_URL"],
|
|
157
|
+
* });
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
160
|
+
export declare function defineConfig(config: DotenvxConfig): DotenvxConfig;
|
|
161
|
+
export interface LoadConfigOptions {
|
|
162
|
+
/** Explicit config path (highest precedence). */
|
|
163
|
+
readonly configPath?: string;
|
|
164
|
+
/** Where to start the search. Defaults to process.cwd(). */
|
|
165
|
+
readonly cwd?: string;
|
|
166
|
+
}
|
|
167
|
+
export interface LoadedConfig {
|
|
168
|
+
/** Resolved config values. Always present (defaults merged in). */
|
|
169
|
+
readonly config: DotenvxConfig;
|
|
170
|
+
/** Absolute path the config was loaded from, or null if defaults. */
|
|
171
|
+
readonly source: string | null;
|
|
172
|
+
/** Source kind: how the config was discovered. */
|
|
173
|
+
readonly origin: "explicit" | "package.json" | "auto" | "defaults";
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Resolve the dotenvx config in this order:
|
|
177
|
+
*
|
|
178
|
+
* 1. `opts.configPath` (typically from `--config <path>`).
|
|
179
|
+
* 2. `package.json` → `dotenvx.config` (string path) — walks upward
|
|
180
|
+
* from `cwd` to find the nearest package.json.
|
|
181
|
+
* 3. The first `dotenvx.config.{ts,js,json,…}` discovered at `cwd`.
|
|
182
|
+
* 4. Built-in defaults (returns `source: null`, `origin: "defaults"`).
|
|
183
|
+
*/
|
|
184
|
+
export declare function loadDotenvxConfig(opts?: LoadConfigOptions): LoadedConfig;
|
|
185
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/libs/config.ts"],"names":[],"mappings":"AAgCA;;;;;;;;;GASG;AACH,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC,CAAC;AAEzE,MAAM,WAAW,aAAa;IAC5B,4DAA4D;IAC5D,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;;;;;OASG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,qEAAqE;IACrE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,2DAA2D;IAC3D,QAAQ,CAAC,OAAO,CAAC,EAAE,cAAc,CAAC;IAClC,kDAAkD;IAClD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,qCAAqC;IACrC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACvD;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACrD;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;IAC9E;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAC3B,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC,CACnD,CAAC;IACF;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C;;;;;;OAMG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,aAAa,CAEjE;AAMD,MAAM,WAAW,iBAAiB;IAChC,iDAAiD;IACjD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,4DAA4D;IAC5D,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,mEAAmE;IACnE,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,qEAAqE;IACrE,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kDAAkD;IAClD,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,cAAc,GAAG,MAAM,GAAG,UAAU,CAAC;CACpE;AAWD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,GAAE,iBAAsB,GAC3B,YAAY,CA+Bd"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Visual prefix for encrypted values. Matches upstream `dotenvx` so
|
|
3
|
+
* encrypted entries are recognizable in diffs and across tools.
|
|
4
|
+
*
|
|
5
|
+
* "encrypted:" + base64(<eciesjs blob>)
|
|
6
|
+
*
|
|
7
|
+
* The blob layout is delegated to `eciesjs` (secp256k1 + AES-256-GCM)
|
|
8
|
+
* so files encrypted by either envx or dotenvx round-trip under the
|
|
9
|
+
* other given the matching private key.
|
|
10
|
+
*/
|
|
11
|
+
export declare const ENCRYPTED_PREFIX = "encrypted:";
|
|
12
|
+
/** Returns true if `value` looks like one of our ciphertext blobs. */
|
|
13
|
+
export declare function isEncrypted(value: string): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Generate a fresh secp256k1 keypair, returned as hex strings:
|
|
16
|
+
* - publicKey: 33-byte compressed public key (66 hex chars)
|
|
17
|
+
* - privateKey: 32-byte scalar (64 hex chars)
|
|
18
|
+
*
|
|
19
|
+
* Wire-format compatible with the upstream `dotenvx` convention so files
|
|
20
|
+
* encrypted by either tool can be decrypted by the other.
|
|
21
|
+
*/
|
|
22
|
+
export declare function generateKeyPair(): {
|
|
23
|
+
publicKey: string;
|
|
24
|
+
privateKey: string;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* ECIES-encrypt `plaintext` to a recipient's compressed secp256k1 public
|
|
28
|
+
* key (hex). Anyone with `publicKeyHex` can encrypt; only the matching
|
|
29
|
+
* private-key holder can decrypt.
|
|
30
|
+
*/
|
|
31
|
+
export declare function encryptValueAsymmetric(plaintext: string, publicKeyHex: string): string;
|
|
32
|
+
/** ECIES-decrypt a `encrypted:<base64>` blob using the recipient's secp256k1 private key (hex). */
|
|
33
|
+
export declare function decryptValueAsymmetric(blob: string, privateKeyHex: string): string;
|
|
34
|
+
//# sourceMappingURL=crypto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/libs/crypto.ts"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,eAAe,CAAC;AAM7C,sEAAsE;AACtE,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAElD;AAMD;;;;;;;GAOG;AACH,wBAAgB,eAAe,IAAI;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAQ3E;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAOtF;AAED,mGAAmG;AACnG,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAWlF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { RunOptions, RunResult } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Decrypt selected values across one or more env files. Pure: returns
|
|
4
|
+
* new file contents but does not write to disk. Errors per-file (missing
|
|
5
|
+
* env file, missing private key, bad ciphertext) surface in the
|
|
6
|
+
* `processed.error` field so a single broken file doesn't kill the
|
|
7
|
+
* whole batch.
|
|
8
|
+
*/
|
|
9
|
+
export declare function decryptFiles(opts: RunOptions): RunResult;
|
|
10
|
+
//# sourceMappingURL=decrypt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decrypt.d.ts","sourceRoot":"","sources":["../../src/libs/decrypt.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAiC,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAIvF;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,CAyHxD"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ENCRYPTED_PREFIX } from './crypto.js';
|
|
2
|
+
import { RunOptions, RunResult } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Encrypt selected values across one or more env files using
|
|
5
|
+
* asymmetric ECIES (secp256k1 + AES-256-GCM via eciesjs). Pure: returns
|
|
6
|
+
* new file contents but does not write to disk. Use {@link writeProcessed}
|
|
7
|
+
* to persist.
|
|
8
|
+
*
|
|
9
|
+
* On first encrypt of a fresh file: generates a secp256k1 keypair,
|
|
10
|
+
* prepends the public-key banner + `ENVX_PUBLIC_KEY*` header to the
|
|
11
|
+
* env file, and writes the matching private key to `.env.keys` under
|
|
12
|
+
* `ENVX_PRIVATE_KEY*`. Subsequent calls reuse the existing keypair.
|
|
13
|
+
*
|
|
14
|
+
* Files that already have a `*PUBLIC_KEY*` header are encrypted with
|
|
15
|
+
* that public key; the matching private key in `.env.keys` is only
|
|
16
|
+
* needed for decryption. Anyone with read access to the env file can
|
|
17
|
+
* encrypt new values — only the private-key holder can decrypt.
|
|
18
|
+
*/
|
|
19
|
+
export declare function encryptFiles(opts: RunOptions): RunResult;
|
|
20
|
+
export { ENCRYPTED_PREFIX };
|
|
21
|
+
//# sourceMappingURL=encrypt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encrypt.d.ts","sourceRoot":"","sources":["../../src/libs/encrypt.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,gBAAgB,EAIjB,MAAM,aAAa,CAAC;AAarB,OAAO,KAAK,EAAgB,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAItE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,CAuHxD;AA+CD,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
|