+32
-10
@@ -182,20 +182,42 @@ "use strict"; | ||
| * Resolve multiple secrets by path in parallel. | ||
| * Returns a map of path → value. Paths that fail are omitted. | ||
| * | ||
| * const { "openai.OPENAI_API_KEY": openaiKey } = | ||
| * await kr.getMany(["openai.OPENAI_API_KEY", "stripe.STRIPE_SECRET_KEY"]); | ||
| * @param paths Array of dotted secret paths to resolve. | ||
| * @param opts.strict If `true`, throws if any path fails instead of returning | ||
| * partial results. Default `false` — failures are surfaced in `result._errors`. | ||
| * | ||
| * // Non-strict (default): inspect _errors to detect partial failures | ||
| * const result = await kr.getMany(["openai.OPENAI_API_KEY", "stripe.STRIPE_SECRET_KEY"]); | ||
| * if (result._errors) console.warn("Some secrets failed:", result._errors); | ||
| * | ||
| * // Strict: throws LockZeroError if any path fails — prevents silent partial boot | ||
| * const result = await kr.getMany(["openai.OPENAI_API_KEY", "stripe.STRIPE_SECRET_KEY"], { strict: true }); | ||
| */ | ||
| async getMany(paths) { | ||
| async getMany(paths, opts) { | ||
| if (!Array.isArray(paths)) throw new Error("LockZero: paths must be an array"); | ||
| const entries = await Promise.allSettled( | ||
| paths.map(async (p) => [p, await this.get(p)]) | ||
| const strict = opts?.strict ?? false; | ||
| const settled = await Promise.allSettled( | ||
| paths.map(async (p) => ({ path: p, value: await this.get(p) })) | ||
| ); | ||
| const result = {}; | ||
| for (const entry of entries) { | ||
| const errors = {}; | ||
| for (let i = 0; i < settled.length; i++) { | ||
| const entry = settled[i]; | ||
| const path = paths[i]; | ||
| if (entry.status === "fulfilled") { | ||
| const [k, v] = entry.value; | ||
| result[k] = v; | ||
| result[path] = entry.value.value; | ||
| } else { | ||
| errors[path] = entry.reason instanceof Error ? entry.reason.message : String(entry.reason); | ||
| } | ||
| } | ||
| return result; | ||
| if (strict && Object.keys(errors).length > 0) { | ||
| const failed = Object.keys(errors).join(", "); | ||
| throw new LockZeroError( | ||
| `LockZero.getMany strict: failed to resolve ${Object.keys(errors).length} path(s): ${failed}`, | ||
| 0, | ||
| errors | ||
| ); | ||
| } | ||
| const out = result; | ||
| if (Object.keys(errors).length > 0) out._errors = errors; | ||
| return out; | ||
| } | ||
@@ -202,0 +224,0 @@ /** |
+19
-7
@@ -8,3 +8,3 @@ /** | ||
| * | ||
| * const kr = new LockZero({ apiKey: "kr_live_..." }); | ||
| * const kr = new LockZero({ apiKey: "lz_live_..." }); | ||
| * await kr.inject("openai"); // sets process.env.OPENAI_API_KEY, etc. | ||
@@ -18,3 +18,3 @@ * await kr.inject("stripe"); | ||
| type LockZeroOptions = { | ||
| /** kr_live_... API key from your LockZero workspace. Defaults to process.env.LOCKZERO_API_KEY. */ | ||
| /** lz_live_... API key from your LockZero workspace. Defaults to process.env.LOCKZERO_API_KEY. */ | ||
| apiKey?: string; | ||
@@ -31,3 +31,6 @@ /** Override base URL — defaults to https://lockzero.io */ | ||
| type BundleResult = Record<string, string>; | ||
| type ManyResult = Record<string, string>; | ||
| /** getMany result — resolved paths are string values; `_errors` is populated in non-strict mode when one or more paths fail. */ | ||
| type ManyResult = Record<string, string> & { | ||
| _errors?: Record<string, string>; | ||
| }; | ||
| type DynamicCredential = { | ||
@@ -95,8 +98,17 @@ leaseId: string; | ||
| * Resolve multiple secrets by path in parallel. | ||
| * Returns a map of path → value. Paths that fail are omitted. | ||
| * | ||
| * const { "openai.OPENAI_API_KEY": openaiKey } = | ||
| * await kr.getMany(["openai.OPENAI_API_KEY", "stripe.STRIPE_SECRET_KEY"]); | ||
| * @param paths Array of dotted secret paths to resolve. | ||
| * @param opts.strict If `true`, throws if any path fails instead of returning | ||
| * partial results. Default `false` — failures are surfaced in `result._errors`. | ||
| * | ||
| * // Non-strict (default): inspect _errors to detect partial failures | ||
| * const result = await kr.getMany(["openai.OPENAI_API_KEY", "stripe.STRIPE_SECRET_KEY"]); | ||
| * if (result._errors) console.warn("Some secrets failed:", result._errors); | ||
| * | ||
| * // Strict: throws LockZeroError if any path fails — prevents silent partial boot | ||
| * const result = await kr.getMany(["openai.OPENAI_API_KEY", "stripe.STRIPE_SECRET_KEY"], { strict: true }); | ||
| */ | ||
| getMany(paths: string[]): Promise<ManyResult>; | ||
| getMany(paths: string[], opts?: { | ||
| strict?: boolean; | ||
| }): Promise<ManyResult>; | ||
| /** | ||
@@ -103,0 +115,0 @@ * Inject multiple namespaces in parallel. |
+19
-7
@@ -8,3 +8,3 @@ /** | ||
| * | ||
| * const kr = new LockZero({ apiKey: "kr_live_..." }); | ||
| * const kr = new LockZero({ apiKey: "lz_live_..." }); | ||
| * await kr.inject("openai"); // sets process.env.OPENAI_API_KEY, etc. | ||
@@ -18,3 +18,3 @@ * await kr.inject("stripe"); | ||
| type LockZeroOptions = { | ||
| /** kr_live_... API key from your LockZero workspace. Defaults to process.env.LOCKZERO_API_KEY. */ | ||
| /** lz_live_... API key from your LockZero workspace. Defaults to process.env.LOCKZERO_API_KEY. */ | ||
| apiKey?: string; | ||
@@ -31,3 +31,6 @@ /** Override base URL — defaults to https://lockzero.io */ | ||
| type BundleResult = Record<string, string>; | ||
| type ManyResult = Record<string, string>; | ||
| /** getMany result — resolved paths are string values; `_errors` is populated in non-strict mode when one or more paths fail. */ | ||
| type ManyResult = Record<string, string> & { | ||
| _errors?: Record<string, string>; | ||
| }; | ||
| type DynamicCredential = { | ||
@@ -95,8 +98,17 @@ leaseId: string; | ||
| * Resolve multiple secrets by path in parallel. | ||
| * Returns a map of path → value. Paths that fail are omitted. | ||
| * | ||
| * const { "openai.OPENAI_API_KEY": openaiKey } = | ||
| * await kr.getMany(["openai.OPENAI_API_KEY", "stripe.STRIPE_SECRET_KEY"]); | ||
| * @param paths Array of dotted secret paths to resolve. | ||
| * @param opts.strict If `true`, throws if any path fails instead of returning | ||
| * partial results. Default `false` — failures are surfaced in `result._errors`. | ||
| * | ||
| * // Non-strict (default): inspect _errors to detect partial failures | ||
| * const result = await kr.getMany(["openai.OPENAI_API_KEY", "stripe.STRIPE_SECRET_KEY"]); | ||
| * if (result._errors) console.warn("Some secrets failed:", result._errors); | ||
| * | ||
| * // Strict: throws LockZeroError if any path fails — prevents silent partial boot | ||
| * const result = await kr.getMany(["openai.OPENAI_API_KEY", "stripe.STRIPE_SECRET_KEY"], { strict: true }); | ||
| */ | ||
| getMany(paths: string[]): Promise<ManyResult>; | ||
| getMany(paths: string[], opts?: { | ||
| strict?: boolean; | ||
| }): Promise<ManyResult>; | ||
| /** | ||
@@ -103,0 +115,0 @@ * Inject multiple namespaces in parallel. |
+32
-10
@@ -155,20 +155,42 @@ // src/index.ts | ||
| * Resolve multiple secrets by path in parallel. | ||
| * Returns a map of path → value. Paths that fail are omitted. | ||
| * | ||
| * const { "openai.OPENAI_API_KEY": openaiKey } = | ||
| * await kr.getMany(["openai.OPENAI_API_KEY", "stripe.STRIPE_SECRET_KEY"]); | ||
| * @param paths Array of dotted secret paths to resolve. | ||
| * @param opts.strict If `true`, throws if any path fails instead of returning | ||
| * partial results. Default `false` — failures are surfaced in `result._errors`. | ||
| * | ||
| * // Non-strict (default): inspect _errors to detect partial failures | ||
| * const result = await kr.getMany(["openai.OPENAI_API_KEY", "stripe.STRIPE_SECRET_KEY"]); | ||
| * if (result._errors) console.warn("Some secrets failed:", result._errors); | ||
| * | ||
| * // Strict: throws LockZeroError if any path fails — prevents silent partial boot | ||
| * const result = await kr.getMany(["openai.OPENAI_API_KEY", "stripe.STRIPE_SECRET_KEY"], { strict: true }); | ||
| */ | ||
| async getMany(paths) { | ||
| async getMany(paths, opts) { | ||
| if (!Array.isArray(paths)) throw new Error("LockZero: paths must be an array"); | ||
| const entries = await Promise.allSettled( | ||
| paths.map(async (p) => [p, await this.get(p)]) | ||
| const strict = opts?.strict ?? false; | ||
| const settled = await Promise.allSettled( | ||
| paths.map(async (p) => ({ path: p, value: await this.get(p) })) | ||
| ); | ||
| const result = {}; | ||
| for (const entry of entries) { | ||
| const errors = {}; | ||
| for (let i = 0; i < settled.length; i++) { | ||
| const entry = settled[i]; | ||
| const path = paths[i]; | ||
| if (entry.status === "fulfilled") { | ||
| const [k, v] = entry.value; | ||
| result[k] = v; | ||
| result[path] = entry.value.value; | ||
| } else { | ||
| errors[path] = entry.reason instanceof Error ? entry.reason.message : String(entry.reason); | ||
| } | ||
| } | ||
| return result; | ||
| if (strict && Object.keys(errors).length > 0) { | ||
| const failed = Object.keys(errors).join(", "); | ||
| throw new LockZeroError( | ||
| `LockZero.getMany strict: failed to resolve ${Object.keys(errors).length} path(s): ${failed}`, | ||
| 0, | ||
| errors | ||
| ); | ||
| } | ||
| const out = result; | ||
| if (Object.keys(errors).length > 0) out._errors = errors; | ||
| return out; | ||
| } | ||
@@ -175,0 +197,0 @@ /** |
+1
-1
| { | ||
| "name": "lockzero", | ||
| "version": "0.1.0", | ||
| "version": "0.1.1", | ||
| "description": "LockZero SDK — pull secrets into your app at runtime without storing credentials", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
+1
-1
@@ -39,3 +39,3 @@ # lockzero — Node.js SDK | ||
| type LockZeroOptions = { | ||
| apiKey?: string; // kr_live_... from your workspace; defaults to LOCKZERO_API_KEY | ||
| apiKey?: string; // lz_live_... from your workspace; defaults to LOCKZERO_API_KEY | ||
| baseUrl?: string; // default: https://lockzero.io | ||
@@ -42,0 +42,0 @@ timeoutMs?: number; // default: 10_000 |
34884
11.74%650
9.43%