@lssm/integration.runtime 0.0.0-canary-20251217083314 → 0.0.0-canary-20251220002821

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Chaman Ventures, SASU
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/health.d.ts CHANGED
@@ -18,4 +18,5 @@ declare class IntegrationHealthService {
18
18
  private emitTelemetry;
19
19
  }
20
20
  //#endregion
21
- export { IntegrationHealthCheckExecutor, IntegrationHealthCheckResult, IntegrationHealthService, IntegrationHealthServiceOptions };
21
+ export { IntegrationHealthCheckExecutor, IntegrationHealthCheckResult, IntegrationHealthService, IntegrationHealthServiceOptions };
22
+ //# sourceMappingURL=health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.d.ts","names":[],"sources":["../src/health.ts"],"sourcesContent":[],"mappings":";;;;UAQiB,4BAAA,SAAqC;aACzC;AADb;AAIY,KAAA,8BAAA,GAA8B,CAAA,OAC/B,EAAA,kBACN,EAAA,GAAA,OAAO,CAAA,IAAA,CAAA;AAEK,UAAA,+BAAA,CAA+B;EAKnC,SAAA,CAAA,EAJC,2BAIuB;EAId,GAAA,CAAA,EAAA,GAAA,GAPT,IAOS;;AAOT,cAXD,wBAAA,CAWC;EACD,iBAAA,SAAA;EAAR,iBAAA,KAAA;EAAO,WAAA,CAAA,OAAA,CAAA,EARW,+BAQX;iBAFC,8BACC,iCACT,QAAQ"}
package/dist/health.js CHANGED
@@ -66,4 +66,5 @@ function extractErrorCode(error) {
66
66
  }
67
67
 
68
68
  //#endregion
69
- export { IntegrationHealthService };
69
+ export { IntegrationHealthService };
70
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","names":["result: IntegrationHealthCheckResult"],"sources":["../src/health.ts"],"sourcesContent":["import type { IntegrationConnectionHealth } from '@lssm/lib.contracts/integrations/connection';\n\nimport type {\n IntegrationContext,\n IntegrationInvocationStatus,\n IntegrationTelemetryEmitter,\n} from './runtime';\n\nexport interface IntegrationHealthCheckResult extends IntegrationConnectionHealth {\n metadata?: Record<string, string>;\n}\n\nexport type IntegrationHealthCheckExecutor = (\n context: IntegrationContext\n) => Promise<void>;\n\nexport interface IntegrationHealthServiceOptions {\n telemetry?: IntegrationTelemetryEmitter;\n now?: () => Date;\n}\n\nexport class IntegrationHealthService {\n private readonly telemetry?: IntegrationTelemetryEmitter;\n private readonly nowFn: () => Date;\n\n constructor(options: IntegrationHealthServiceOptions = {}) {\n this.telemetry = options.telemetry;\n this.nowFn = options.now ?? (() => new Date());\n }\n\n async check(\n context: IntegrationContext,\n executor: IntegrationHealthCheckExecutor\n ): Promise<IntegrationHealthCheckResult> {\n const start = this.nowFn();\n try {\n await executor(context);\n const end = this.nowFn();\n const result: IntegrationHealthCheckResult = {\n status: 'connected',\n checkedAt: end,\n latencyMs: end.getTime() - start.getTime(),\n };\n this.emitTelemetry(context, result, 'success');\n return result;\n } catch (error) {\n const end = this.nowFn();\n const message = error instanceof Error ? error.message : 'Unknown error';\n const code = extractErrorCode(error);\n const result: IntegrationHealthCheckResult = {\n status: 'error',\n checkedAt: end,\n latencyMs: end.getTime() - start.getTime(),\n errorMessage: message,\n errorCode: code,\n };\n this.emitTelemetry(context, result, 'error', code, message);\n return result;\n }\n }\n\n private emitTelemetry(\n context: IntegrationContext,\n result: IntegrationHealthCheckResult,\n status: IntegrationInvocationStatus,\n errorCode?: string,\n errorMessage?: string\n ) {\n if (!this.telemetry) return;\n this.telemetry.record({\n tenantId: context.tenantId,\n appId: context.appId,\n environment: context.environment,\n slotId: context.slotId,\n integrationKey: context.spec.meta.key,\n integrationVersion: context.spec.meta.version,\n connectionId: context.connection.meta.id,\n status,\n durationMs: result.latencyMs,\n errorCode,\n errorMessage,\n occurredAt: result.checkedAt ?? this.nowFn(),\n metadata: {\n ...(context.trace\n ? {\n blueprint: `${context.trace.blueprintName}.v${context.trace.blueprintVersion}`,\n configVersion: context.trace.configVersion,\n }\n : {}),\n status: result.status,\n },\n });\n }\n}\n\nfunction extractErrorCode(error: unknown): string | undefined {\n if (!error || typeof error !== 'object') return undefined;\n const candidate = error as { code?: string | number };\n if (candidate.code == null) return undefined;\n return String(candidate.code);\n}\n"],"mappings":";AAqBA,IAAa,2BAAb,MAAsC;CACpC,AAAiB;CACjB,AAAiB;CAEjB,YAAY,UAA2C,EAAE,EAAE;AACzD,OAAK,YAAY,QAAQ;AACzB,OAAK,QAAQ,QAAQ,8BAAc,IAAI,MAAM;;CAG/C,MAAM,MACJ,SACA,UACuC;EACvC,MAAM,QAAQ,KAAK,OAAO;AAC1B,MAAI;AACF,SAAM,SAAS,QAAQ;GACvB,MAAM,MAAM,KAAK,OAAO;GACxB,MAAMA,SAAuC;IAC3C,QAAQ;IACR,WAAW;IACX,WAAW,IAAI,SAAS,GAAG,MAAM,SAAS;IAC3C;AACD,QAAK,cAAc,SAAS,QAAQ,UAAU;AAC9C,UAAO;WACA,OAAO;GACd,MAAM,MAAM,KAAK,OAAO;GACxB,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;GACzD,MAAM,OAAO,iBAAiB,MAAM;GACpC,MAAMA,SAAuC;IAC3C,QAAQ;IACR,WAAW;IACX,WAAW,IAAI,SAAS,GAAG,MAAM,SAAS;IAC1C,cAAc;IACd,WAAW;IACZ;AACD,QAAK,cAAc,SAAS,QAAQ,SAAS,MAAM,QAAQ;AAC3D,UAAO;;;CAIX,AAAQ,cACN,SACA,QACA,QACA,WACA,cACA;AACA,MAAI,CAAC,KAAK,UAAW;AACrB,OAAK,UAAU,OAAO;GACpB,UAAU,QAAQ;GAClB,OAAO,QAAQ;GACf,aAAa,QAAQ;GACrB,QAAQ,QAAQ;GAChB,gBAAgB,QAAQ,KAAK,KAAK;GAClC,oBAAoB,QAAQ,KAAK,KAAK;GACtC,cAAc,QAAQ,WAAW,KAAK;GACtC;GACA,YAAY,OAAO;GACnB;GACA;GACA,YAAY,OAAO,aAAa,KAAK,OAAO;GAC5C,UAAU;IACR,GAAI,QAAQ,QACR;KACE,WAAW,GAAG,QAAQ,MAAM,cAAc,IAAI,QAAQ,MAAM;KAC5D,eAAe,QAAQ,MAAM;KAC9B,GACD,EAAE;IACN,QAAQ,OAAO;IAChB;GACF,CAAC;;;AAIN,SAAS,iBAAiB,OAAoC;AAC5D,KAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;CAChD,MAAM,YAAY;AAClB,KAAI,UAAU,QAAQ,KAAM,QAAO;AACnC,QAAO,OAAO,UAAU,KAAK"}
package/dist/runtime.d.ts CHANGED
@@ -96,4 +96,5 @@ declare class IntegrationCallGuard {
96
96
  declare function ensureConnectionReady(integration: ResolvedIntegration): void;
97
97
  declare function connectionStatusLabel(status: ConnectionStatus): string;
98
98
  //#endregion
99
- export { IntegrationCallContext, IntegrationCallError, IntegrationCallGuard, IntegrationCallGuardOptions, IntegrationCallResult, IntegrationContext, IntegrationInvocationStatus, IntegrationTelemetryEmitter, IntegrationTelemetryEvent, IntegrationTraceMetadata, connectionStatusLabel, ensureConnectionReady };
99
+ export { IntegrationCallContext, IntegrationCallError, IntegrationCallGuard, IntegrationCallGuardOptions, IntegrationCallResult, IntegrationContext, IntegrationInvocationStatus, IntegrationTelemetryEmitter, IntegrationTelemetryEvent, IntegrationTraceMetadata, connectionStatusLabel, ensureConnectionReady };
100
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","names":[],"sources":["../src/runtime.ts"],"sourcesContent":[],"mappings":";;;;;;UAaiB,wBAAA;;EAAA,gBAAA,EAAA,MAAA;EAMA,aAAA,EAAA,MAAA;AAgBjB;AAIY,UApBK,yBAAA,CAoBsB;EAEtB,QAAA,EAAA,MAAA;EAKT,KAAA,EAAA,MAAA;EACM,WAAA,CAAA,EAAA,MAAA;EACI,MAAA,CAAA,EAAA,MAAA;EAET,cAAA,EAAA,MAAA;EACE,kBAAA,EAAA,MAAA;EAAM,YAAA,EAAA,MAAA;EAGA,MAAA,EAAA,SAAA,GAAA,OAAsB;EAWtB,UAAA,CAAA,EAAA,MAAA;EAOA,SAAA,CAAA,EAAA,MAAA;EAER,YAAA,CAAA,EAAA,MAAA;EACC,UAAA,EA5CI,IA4CJ;EAIS,QAAA,CAAA,EA/CN,MA+CM,CAAA,MAAA,EAAA,MAAA,GAAA,MAAA,GAAA,OAAA,CAAA;;AAKF,UAjDA,2BAAA,CAiD2B;EAC9B,MAAA,CAAA,KAAA,EAjDE,yBAiDF,CAAA,EAjD8B,OAiD9B,CAAA,IAAA,CAAA,GAAA,IAAA;;AAKA,KAnDF,2BAAA,GAmDE,SAAA,GAAA,OAAA;AAAI,UAjDD,kBAAA,CAiDC;EAML,QAAA,EAAA,MAAA;EASwB,KAAA,EAAA,MAAA;EACxB,WAAA,CAAA,EAAA,MAAA;EAyBO,MAAA,CAAA,EAAA,MAAA;EAEF,IAAA,EAvFV,eAuFU;EACH,UAAA,EAvFD,qBAuFC;EACE,cAAA,EAvFC,cAuFD;EAAR,eAAA,EAAA,MAAA;EAC0B,KAAA,EAtF1B,wBAsF0B;EAAtB,MAAA,CAAA,EArFF,MAqFE,CAAA,MAAA,EAAA,OAAA,CAAA;;AAAD,UAlFK,sBAAA,CAkFL;EAiPI,QAAA,EAAA,MAAA;EASA,KAAA,EAAA,MAAA;;;;;;;;UAjUC,oBAAA;;;;;;UAOA;;SAER;UACC;;;;mBAIS;;;;UAKF,2BAAA;cACH;;;;0BAIY;cACZ;;cAMD,oBAAA;;;;;;;;8BASwB,0BACxB;2FAyBO,0CAEF,gCACH,2BACN,QAAQ,KACZ,QAAQ,sBAAsB;;;;;;;;;iBAiPnB,qBAAA,cAAmC;iBASnC,qBAAA,SAA8B"}
package/dist/runtime.js CHANGED
@@ -183,4 +183,5 @@ function connectionStatusLabel(status) {
183
183
  }
184
184
 
185
185
  //#endregion
186
- export { IntegrationCallGuard, connectionStatusLabel, ensureConnectionReady };
186
+ export { IntegrationCallGuard, connectionStatusLabel, ensureConnectionReady };
187
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","names":["secretProvider: SecretProvider"],"sources":["../src/runtime.ts"],"sourcesContent":["import { performance } from 'node:perf_hooks';\n\nimport type {\n ResolvedAppConfig,\n ResolvedIntegration,\n} from '@lssm/lib.contracts/app-config/runtime';\nimport type {\n ConnectionStatus,\n IntegrationConnection,\n} from '@lssm/lib.contracts/integrations/connection';\nimport type { IntegrationSpec } from '@lssm/lib.contracts/integrations/spec';\nimport type { SecretProvider, SecretValue } from './secrets/provider';\n\nexport interface IntegrationTraceMetadata {\n blueprintName: string;\n blueprintVersion: number;\n configVersion: number;\n}\n\nexport interface IntegrationTelemetryEvent {\n tenantId: string;\n appId: string;\n environment?: string;\n slotId?: string;\n integrationKey: string;\n integrationVersion: number;\n connectionId: string;\n status: 'success' | 'error';\n durationMs?: number;\n errorCode?: string;\n errorMessage?: string;\n occurredAt: Date;\n metadata?: Record<string, string | number | boolean>;\n}\n\nexport interface IntegrationTelemetryEmitter {\n record(event: IntegrationTelemetryEvent): Promise<void> | void;\n}\n\nexport type IntegrationInvocationStatus = 'success' | 'error';\n\nexport interface IntegrationContext {\n tenantId: string;\n appId: string;\n environment?: string;\n slotId?: string;\n spec: IntegrationSpec;\n connection: IntegrationConnection;\n secretProvider: SecretProvider;\n secretReference: string;\n trace: IntegrationTraceMetadata;\n config?: Record<string, unknown>;\n}\n\nexport interface IntegrationCallContext {\n tenantId: string;\n appId: string;\n environment?: string;\n blueprintName: string;\n blueprintVersion: number;\n configVersion: number;\n slotId: string;\n operation: string;\n}\n\nexport interface IntegrationCallError {\n code: string;\n message: string;\n retryable: boolean;\n cause?: unknown;\n}\n\nexport interface IntegrationCallResult<T> {\n success: boolean;\n data?: T;\n error?: IntegrationCallError;\n metadata: {\n latencyMs: number;\n connectionId: string;\n ownershipMode: IntegrationConnection['ownershipMode'];\n attempts: number;\n };\n}\n\nexport interface IntegrationCallGuardOptions {\n telemetry?: IntegrationTelemetryEmitter;\n maxAttempts?: number;\n backoffMs?: number;\n shouldRetry?: (error: unknown, attempt: number) => boolean;\n sleep?: (ms: number) => Promise<void>;\n now?: () => Date;\n}\n\nconst DEFAULT_MAX_ATTEMPTS = 3;\nconst DEFAULT_BACKOFF_MS = 250;\n\nexport class IntegrationCallGuard {\n private readonly telemetry?: IntegrationTelemetryEmitter;\n private readonly maxAttempts: number;\n private readonly backoffMs: number;\n private readonly shouldRetry: (error: unknown, attempt: number) => boolean;\n private readonly sleep: (ms: number) => Promise<void>;\n private readonly now: () => Date;\n\n constructor(\n private readonly secretProvider: SecretProvider,\n options: IntegrationCallGuardOptions = {}\n ) {\n this.telemetry = options.telemetry;\n this.maxAttempts = Math.max(1, options.maxAttempts ?? DEFAULT_MAX_ATTEMPTS);\n this.backoffMs = options.backoffMs ?? DEFAULT_BACKOFF_MS;\n this.shouldRetry =\n options.shouldRetry ??\n ((error: unknown) =>\n typeof error === 'object' &&\n error !== null &&\n 'retryable' in error &&\n Boolean((error as { retryable?: unknown }).retryable));\n this.sleep =\n options.sleep ??\n ((ms: number) =>\n ms <= 0\n ? Promise.resolve()\n : new Promise((resolve) => setTimeout(resolve, ms)));\n this.now = options.now ?? (() => new Date());\n }\n\n async executeWithGuards<T>(\n slotId: string,\n operation: string,\n _input: unknown,\n resolvedConfig: ResolvedAppConfig,\n executor: (\n connection: IntegrationConnection,\n secrets: Record<string, string>\n ) => Promise<T>\n ): Promise<IntegrationCallResult<T>> {\n const integration = this.findIntegration(slotId, resolvedConfig);\n if (!integration) {\n return this.failure(\n {\n tenantId: resolvedConfig.tenantId,\n appId: resolvedConfig.appId,\n environment: resolvedConfig.environment,\n blueprintName: resolvedConfig.blueprintName,\n blueprintVersion: resolvedConfig.blueprintVersion,\n configVersion: resolvedConfig.configVersion,\n slotId,\n operation,\n },\n undefined,\n {\n code: 'SLOT_NOT_BOUND',\n message: `Integration slot \"${slotId}\" is not bound for tenant \"${resolvedConfig.tenantId}\".`,\n retryable: false,\n },\n 0\n );\n }\n\n const status = integration.connection.status;\n if (status === 'disconnected' || status === 'error') {\n return this.failure(\n this.makeContext(slotId, operation, resolvedConfig),\n integration,\n {\n code: 'CONNECTION_NOT_READY',\n message: `Integration connection \"${integration.connection.meta.label}\" is in status \"${status}\".`,\n retryable: false,\n },\n 0\n );\n }\n\n const secrets = await this.fetchSecrets(integration.connection);\n\n let attempt = 0;\n const started = performance.now();\n while (attempt < this.maxAttempts) {\n attempt += 1;\n try {\n const data = await executor(integration.connection, secrets);\n const duration = performance.now() - started;\n this.emitTelemetry(\n this.makeContext(slotId, operation, resolvedConfig),\n integration,\n 'success',\n duration\n );\n return {\n success: true,\n data,\n metadata: {\n latencyMs: duration,\n connectionId: integration.connection.meta.id,\n ownershipMode: integration.connection.ownershipMode,\n attempts: attempt,\n },\n };\n } catch (error) {\n const duration = performance.now() - started;\n this.emitTelemetry(\n this.makeContext(slotId, operation, resolvedConfig),\n integration,\n 'error',\n duration,\n this.errorCodeFor(error),\n error instanceof Error ? error.message : String(error)\n );\n const retryable = this.shouldRetry(error, attempt);\n if (!retryable || attempt >= this.maxAttempts) {\n return {\n success: false,\n error: {\n code: this.errorCodeFor(error),\n message: error instanceof Error ? error.message : String(error),\n retryable,\n cause: error,\n },\n metadata: {\n latencyMs: duration,\n connectionId: integration.connection.meta.id,\n ownershipMode: integration.connection.ownershipMode,\n attempts: attempt,\n },\n };\n }\n await this.sleep(this.backoffMs);\n }\n }\n\n return {\n success: false,\n error: {\n code: 'UNKNOWN_ERROR',\n message: 'Integration call failed after retries.',\n retryable: false,\n },\n metadata: {\n latencyMs: performance.now() - started,\n connectionId: integration.connection.meta.id,\n ownershipMode: integration.connection.ownershipMode,\n attempts: this.maxAttempts,\n },\n };\n }\n\n private findIntegration(\n slotId: string,\n config: ResolvedAppConfig\n ): ResolvedIntegration | undefined {\n return config.integrations.find(\n (integration) => integration.slot.slotId === slotId\n );\n }\n\n private async fetchSecrets(\n connection: IntegrationConnection\n ): Promise<Record<string, string>> {\n if (!this.secretProvider.canHandle(connection.secretRef)) {\n throw new Error(\n `Secret provider \"${this.secretProvider.id}\" cannot handle reference \"${connection.secretRef}\".`\n );\n }\n const secret = await this.secretProvider.getSecret(connection.secretRef);\n return this.parseSecret(secret);\n }\n\n private parseSecret(secret: SecretValue): Record<string, string> {\n const text = new TextDecoder().decode(secret.data);\n try {\n const parsed = JSON.parse(text);\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n const entries = Object.entries(parsed).filter(\n ([, value]) =>\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n );\n return Object.fromEntries(\n entries.map(([key, value]) => [key, String(value)])\n );\n }\n } catch {\n // raw secret fallback\n }\n return { secret: text };\n }\n\n private emitTelemetry(\n context: IntegrationCallContext,\n integration: ResolvedIntegration | undefined,\n status: 'success' | 'error',\n durationMs: number,\n errorCode?: string,\n errorMessage?: string\n ) {\n if (!this.telemetry || !integration) return;\n this.telemetry.record({\n tenantId: context.tenantId,\n appId: context.appId,\n environment: context.environment,\n slotId: context.slotId,\n integrationKey: integration.connection.meta.integrationKey,\n integrationVersion: integration.connection.meta.integrationVersion,\n connectionId: integration.connection.meta.id,\n status,\n durationMs,\n errorCode,\n errorMessage,\n occurredAt: this.now(),\n metadata: {\n blueprint: `${context.blueprintName}.v${context.blueprintVersion}`,\n configVersion: context.configVersion,\n operation: context.operation,\n },\n });\n }\n\n private failure<T>(\n context: IntegrationCallContext,\n integration: ResolvedIntegration | undefined,\n error: IntegrationCallError,\n attempts: number\n ): IntegrationCallResult<T> {\n if (integration) {\n this.emitTelemetry(\n context,\n integration,\n 'error',\n 0,\n error.code,\n error.message\n );\n }\n return {\n success: false,\n error,\n metadata: {\n latencyMs: 0,\n connectionId: integration?.connection.meta.id ?? 'unknown',\n ownershipMode: integration?.connection.ownershipMode ?? 'managed',\n attempts,\n },\n };\n }\n\n private makeContext(\n slotId: string,\n operation: string,\n config: ResolvedAppConfig\n ): IntegrationCallContext {\n return {\n tenantId: config.tenantId,\n appId: config.appId,\n environment: config.environment,\n blueprintName: config.blueprintName,\n blueprintVersion: config.blueprintVersion,\n configVersion: config.configVersion,\n slotId,\n operation,\n };\n }\n\n private errorCodeFor(error: unknown): string {\n if (\n typeof error === 'object' &&\n error !== null &&\n 'code' in error &&\n typeof (error as { code?: unknown }).code === 'string'\n ) {\n return (error as { code: string }).code;\n }\n return 'PROVIDER_ERROR';\n }\n}\n\nexport function ensureConnectionReady(integration: ResolvedIntegration): void {\n const status = integration.connection.status;\n if (status === 'disconnected' || status === 'error') {\n throw new Error(\n `Integration connection \"${integration.connection.meta.label}\" is in status \"${status}\".`\n );\n }\n}\n\nexport function connectionStatusLabel(status: ConnectionStatus): string {\n switch (status) {\n case 'connected':\n return 'connected';\n case 'disconnected':\n return 'disconnected';\n case 'error':\n return 'error';\n case 'unknown':\n default:\n return 'unknown';\n }\n}\n"],"mappings":"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"}
@@ -28,4 +28,5 @@ declare class EnvSecretProvider implements SecretProvider {
28
28
  private forbiddenError;
29
29
  }
30
30
  //#endregion
31
- export { EnvSecretProvider };
31
+ export { EnvSecretProvider };
32
+ //# sourceMappingURL=env-secret-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-secret-provider.d.ts","names":[],"sources":["../../src/secrets/env-secret-provider.ts"],"sourcesContent":[],"mappings":";;;UASU,wBAAA;;AAHU;AAiBpB;;;EAc6B,OAAA,CAAA,EAtBjB,MAsBiB,CAAA,MAAA,EAAA,MAAA,CAAA;;;;;;;AAwCd,cAtDF,iBAAA,YAA6B,cAsD3B,CAAA;EACD,SAAA,EAAA,GAAA,KAAA;EACD,iBAAA,OAAA;EAAR,WAAA,CAAA,OAAA,CAAA,EAnDkB,wBAmDlB;EAI2B,SAAA,CAAA,SAAA,EAnDT,eAmDS,CAAA,EAAA,OAAA;EAAkB,SAAA,CAAA,SAAA,EA9CrB,eA8CqB,CAAA,EA9CH,OA8CG,CA9CK,WA8CL,CAAA;EA5DR,SAAA,CAAA,SAAA,EA+C3B,eA/C2B,EAAA,QAAA,EAgD5B,kBAhD4B,CAAA,EAiDrC,OAjDqC,CAiD7B,oBAjD6B,CAAA;EAAc,YAAA,CAAA,SAAA,EAsDzC,eAtDyC,EAAA,QAAA,EAuD1C,kBAvD0C,CAAA,EAwDnD,OAxDmD,CAwD3C,oBAxD2C,CAAA;0BA4DxB,kBAAkB"}
@@ -65,7 +65,7 @@ var EnvSecretProvider = class {
65
65
  }
66
66
  deriveEnvKey(path) {
67
67
  if (!path) return void 0;
68
- return path.split(/[\/:\-\.]/).filter(Boolean).map((segment) => segment.replace(/[^a-zA-Z0-9]/g, "_").replace(/_{2,}/g, "_").toUpperCase()).join("_");
68
+ return path.split(/[/:\-.]/).filter(Boolean).map((segment) => segment.replace(/[^a-zA-Z0-9]/g, "_").replace(/_{2,}/g, "_").toUpperCase()).join("_");
69
69
  }
70
70
  forbiddenError(operation, reference) {
71
71
  return new SecretProviderError({
@@ -78,4 +78,5 @@ var EnvSecretProvider = class {
78
78
  };
79
79
 
80
80
  //#endregion
81
- export { EnvSecretProvider };
81
+ export { EnvSecretProvider };
82
+ //# sourceMappingURL=env-secret-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-secret-provider.js","names":[],"sources":["../../src/secrets/env-secret-provider.ts"],"sourcesContent":["import type {\n SecretProvider,\n SecretReference,\n SecretRotationResult,\n SecretValue,\n SecretWritePayload,\n} from './provider';\nimport { parseSecretUri, SecretProviderError } from './provider';\n\ninterface EnvSecretProviderOptions {\n /**\n * Optional map to alias secret references to environment variable names.\n * Useful when referencing secrets from other providers (e.g. gcp://...)\n * while still allowing local overrides.\n */\n aliases?: Record<string, string>;\n}\n\n/**\n * Environment-variable backed secret provider. Read-only by design.\n * Allows overriding other secret providers by deriving environment variable\n * names from secret references (or by using explicit aliases).\n */\nexport class EnvSecretProvider implements SecretProvider {\n readonly id = 'env';\n\n private readonly aliases: Record<string, string>;\n\n constructor(options: EnvSecretProviderOptions = {}) {\n this.aliases = options.aliases ?? {};\n }\n\n canHandle(reference: SecretReference): boolean {\n const envKey = this.resolveEnvKey(reference);\n return envKey !== undefined && process.env[envKey] !== undefined;\n }\n\n async getSecret(reference: SecretReference): Promise<SecretValue> {\n const envKey = this.resolveEnvKey(reference);\n if (!envKey) {\n throw new SecretProviderError({\n message: `Unable to resolve environment variable for reference \"${reference}\".`,\n provider: this.id,\n reference,\n code: 'INVALID',\n });\n }\n\n const value = process.env[envKey];\n if (value === undefined) {\n throw new SecretProviderError({\n message: `Environment variable \"${envKey}\" not found for reference \"${reference}\".`,\n provider: this.id,\n reference,\n code: 'NOT_FOUND',\n });\n }\n\n return {\n data: Buffer.from(value, 'utf-8'),\n version: 'current',\n metadata: {\n source: 'env',\n envKey,\n },\n retrievedAt: new Date(),\n };\n }\n\n async setSecret(\n reference: SecretReference,\n _payload: SecretWritePayload\n ): Promise<SecretRotationResult> {\n throw this.forbiddenError('setSecret', reference);\n }\n\n async rotateSecret(\n reference: SecretReference,\n _payload: SecretWritePayload\n ): Promise<SecretRotationResult> {\n throw this.forbiddenError('rotateSecret', reference);\n }\n\n async deleteSecret(reference: SecretReference): Promise<void> {\n throw this.forbiddenError('deleteSecret', reference);\n }\n\n private resolveEnvKey(reference: SecretReference): string | undefined {\n if (!reference) {\n return undefined;\n }\n\n if (this.aliases[reference]) {\n return this.aliases[reference];\n }\n\n if (!reference.includes('://')) {\n return reference;\n }\n\n try {\n const parsed = parseSecretUri(reference);\n if (parsed.provider === 'env') {\n return parsed.path;\n }\n\n if (parsed.extras?.env) {\n return parsed.extras.env;\n }\n\n return this.deriveEnvKey(parsed.path);\n } catch {\n return reference;\n }\n }\n\n private deriveEnvKey(path: string): string | undefined {\n if (!path) return undefined;\n return path\n .split(/[/:\\-.]/)\n .filter(Boolean)\n .map((segment) =>\n segment\n .replace(/[^a-zA-Z0-9]/g, '_')\n .replace(/_{2,}/g, '_')\n .toUpperCase()\n )\n .join('_');\n }\n\n private forbiddenError(\n operation: string,\n reference: SecretReference\n ): SecretProviderError {\n return new SecretProviderError({\n message: `EnvSecretProvider is read-only. \"${operation}\" is not allowed for ${reference}.`,\n provider: this.id,\n reference,\n code: 'FORBIDDEN',\n });\n }\n}\n"],"mappings":";;;;;;;;AAuBA,IAAa,oBAAb,MAAyD;CACvD,AAAS,KAAK;CAEd,AAAiB;CAEjB,YAAY,UAAoC,EAAE,EAAE;AAClD,OAAK,UAAU,QAAQ,WAAW,EAAE;;CAGtC,UAAU,WAAqC;EAC7C,MAAM,SAAS,KAAK,cAAc,UAAU;AAC5C,SAAO,WAAW,UAAa,QAAQ,IAAI,YAAY;;CAGzD,MAAM,UAAU,WAAkD;EAChE,MAAM,SAAS,KAAK,cAAc,UAAU;AAC5C,MAAI,CAAC,OACH,OAAM,IAAI,oBAAoB;GAC5B,SAAS,yDAAyD,UAAU;GAC5E,UAAU,KAAK;GACf;GACA,MAAM;GACP,CAAC;EAGJ,MAAM,QAAQ,QAAQ,IAAI;AAC1B,MAAI,UAAU,OACZ,OAAM,IAAI,oBAAoB;GAC5B,SAAS,yBAAyB,OAAO,6BAA6B,UAAU;GAChF,UAAU,KAAK;GACf;GACA,MAAM;GACP,CAAC;AAGJ,SAAO;GACL,MAAM,OAAO,KAAK,OAAO,QAAQ;GACjC,SAAS;GACT,UAAU;IACR,QAAQ;IACR;IACD;GACD,6BAAa,IAAI,MAAM;GACxB;;CAGH,MAAM,UACJ,WACA,UAC+B;AAC/B,QAAM,KAAK,eAAe,aAAa,UAAU;;CAGnD,MAAM,aACJ,WACA,UAC+B;AAC/B,QAAM,KAAK,eAAe,gBAAgB,UAAU;;CAGtD,MAAM,aAAa,WAA2C;AAC5D,QAAM,KAAK,eAAe,gBAAgB,UAAU;;CAGtD,AAAQ,cAAc,WAAgD;AACpE,MAAI,CAAC,UACH;AAGF,MAAI,KAAK,QAAQ,WACf,QAAO,KAAK,QAAQ;AAGtB,MAAI,CAAC,UAAU,SAAS,MAAM,CAC5B,QAAO;AAGT,MAAI;GACF,MAAM,SAAS,eAAe,UAAU;AACxC,OAAI,OAAO,aAAa,MACtB,QAAO,OAAO;AAGhB,OAAI,OAAO,QAAQ,IACjB,QAAO,OAAO,OAAO;AAGvB,UAAO,KAAK,aAAa,OAAO,KAAK;UAC/B;AACN,UAAO;;;CAIX,AAAQ,aAAa,MAAkC;AACrD,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,KACJ,MAAM,UAAU,CAChB,OAAO,QAAQ,CACf,KAAK,YACJ,QACG,QAAQ,iBAAiB,IAAI,CAC7B,QAAQ,UAAU,IAAI,CACtB,aAAa,CACjB,CACA,KAAK,IAAI;;CAGd,AAAQ,eACN,WACA,WACqB;AACrB,SAAO,IAAI,oBAAoB;GAC7B,SAAS,oCAAoC,UAAU,uBAAuB,UAAU;GACxF,UAAU,KAAK;GACf;GACA,MAAM;GACP,CAAC"}
@@ -29,4 +29,5 @@ declare class GcpSecretManagerProvider implements SecretProvider {
29
29
  private ensureSecretExists;
30
30
  }
31
31
  //#endregion
32
- export { GcpSecretManagerProvider };
32
+ export { GcpSecretManagerProvider };
33
+ //# sourceMappingURL=gcp-secret-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gcp-secret-manager.d.ts","names":[],"sources":["../../src/secrets/gcp-secret-manager.ts"],"sourcesContent":[],"mappings":";;;;;KAmBK,mBAAA,GAAsB;UAEjB,+BAAA;EAFL,SAAA,CAAA,EAAA,MAAA;EAEK,MAAA,CAAA,EAEC,mBAFD;EAEC,aAAA,CAAA,EACO,qBADP,CAAA,OACoC,0BADpC,CAAA,CAAA,CAAA,CAAA;EACoC,kBAAA,CAAA,EACxB,MAAA,CAAO,MAAA,CAAO,KAAA,CAAM,aAAA,CAAc,EAAA,CAAG,YADb;;AACxB,cAaV,wBAAA,YAAoC,cAbW,CAAA;EAAY,SAAA,EAAA,GAAA,oBAAA;EAa3D,iBAAA,MAAA;EAMU,iBAAA,iBAAA;EAQA,iBAAA,WAAA;EAUR,WAAA,CAAA,OAAA,CAAA,EAlBQ,+BAkBR;EAEG,SAAA,CAAA,SAAA,EAZK,eAYL,CAAA,EAAA,OAAA;EACL,SAAA,CAAA,SAAA,EAHE,eAGF,EAAA,OAyCE,CAzCF,EAAA;IAAR,OAAA,CAAA,EAAA,MAAA;EAyCU,CAAA,EAAA,WAAA,CAAA,EA1CG,WA0CH,CAAA,EAzCV,OAyCU,CAzCF,WAyCE,CAAA;EACF,SAAA,CAAA,SAAA,EADE,eACF,EAAA,OAAA,EAAA,kBAAA,CAAA,EACR,OADQ,CACA,oBADA,CAAA;EACA,YAAA,CAAA,SAAA,EAsCE,eAtCF,EAAA,OAAA,EAuCA,kBAvCA,CAAA,EAwCR,OAxCQ,CAwCA,oBAxCA,CAAA;EAAR,YAAA,CAAA,SAAA,EA4C2B,eA5C3B,CAAA,EA4C6C,OA5C7C,CAAA,IAAA,CAAA;EAsCU,QAAA,cAAA;EACF,QAAA,UAAA;EACA,QAAA,gBAAA;EAAR,QAAA,kBAAA"}
@@ -226,4 +226,5 @@ function deriveErrorCode(error) {
226
226
  }
227
227
 
228
228
  //#endregion
229
- export { GcpSecretManagerProvider };
229
+ export { GcpSecretManagerProvider };
230
+ //# sourceMappingURL=gcp-secret-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gcp-secret-manager.js","names":["DEFAULT_REPLICATION: protos.google.cloud.secretmanager.v1.IReplication"],"sources":["../../src/secrets/gcp-secret-manager.ts"],"sourcesContent":["import {\n protos,\n SecretManagerServiceClient,\n} from '@google-cloud/secret-manager';\nimport type { CallOptions } from 'google-gax';\n\nimport {\n normalizeSecretPayload,\n parseSecretUri,\n SecretProviderError,\n} from './provider';\nimport type {\n SecretProvider,\n SecretReference,\n SecretRotationResult,\n SecretValue,\n SecretWritePayload,\n} from './provider';\n\ntype SecretManagerClient = SecretManagerServiceClient;\n\ninterface GcpSecretManagerProviderOptions {\n projectId?: string;\n client?: SecretManagerClient;\n clientOptions?: ConstructorParameters<typeof SecretManagerServiceClient>[0];\n defaultReplication?: protos.google.cloud.secretmanager.v1.IReplication;\n}\n\ninterface GcpSecretLocation {\n projectId: string;\n secretId: string;\n version?: string;\n}\n\nconst DEFAULT_REPLICATION: protos.google.cloud.secretmanager.v1.IReplication = {\n automatic: {},\n};\n\nexport class GcpSecretManagerProvider implements SecretProvider {\n readonly id = 'gcp-secret-manager';\n private readonly client: SecretManagerClient;\n private readonly explicitProjectId?: string;\n private readonly replication: protos.google.cloud.secretmanager.v1.IReplication;\n\n constructor(options: GcpSecretManagerProviderOptions = {}) {\n this.client =\n options.client ??\n new SecretManagerServiceClient(options.clientOptions ?? {});\n this.explicitProjectId = options.projectId;\n this.replication = options.defaultReplication ?? DEFAULT_REPLICATION;\n }\n\n canHandle(reference: SecretReference): boolean {\n try {\n const parsed = parseSecretUri(reference);\n return parsed.provider === 'gcp';\n } catch {\n return false;\n }\n }\n\n async getSecret(\n reference: SecretReference,\n options?: { version?: string },\n callOptions?: CallOptions\n ): Promise<SecretValue> {\n const location = this.parseReference(reference);\n const secretVersionName = this.buildVersionName(location, options?.version);\n try {\n const response = await this.client.accessSecretVersion(\n {\n name: secretVersionName,\n },\n callOptions ?? {}\n );\n const [result] = response;\n const payload = result.payload;\n if (!payload?.data) {\n throw new SecretProviderError({\n message: `Secret payload empty for ${secretVersionName}`,\n provider: this.id,\n reference,\n code: 'UNKNOWN',\n });\n }\n\n const version = extractVersionFromName(result.name ?? secretVersionName);\n return {\n data: payload.data as Uint8Array,\n version,\n metadata: payload.dataCrc32c\n ? { crc32c: payload.dataCrc32c.toString() }\n : undefined,\n retrievedAt: new Date(),\n };\n } catch (error) {\n throw toSecretProviderError({\n error,\n provider: this.id,\n reference,\n operation: 'access',\n });\n }\n }\n\n async setSecret(\n reference: SecretReference,\n payload: SecretWritePayload\n ): Promise<SecretRotationResult> {\n const location = this.parseReference(reference);\n const { secretName } = this.buildNames(location);\n const data = normalizeSecretPayload(payload);\n await this.ensureSecretExists(location, payload);\n\n try {\n const response = await this.client.addSecretVersion({\n parent: secretName,\n payload: {\n data,\n },\n });\n if (!response) {\n throw new SecretProviderError({\n message: `No version returned when adding secret version for ${secretName}`,\n provider: this.id,\n reference,\n code: 'UNKNOWN',\n });\n }\n const [version] = response;\n const versionName = version?.name ?? `${secretName}/versions/latest`;\n return {\n reference: `gcp://${versionName}`,\n version: extractVersionFromName(versionName) ?? 'latest',\n };\n } catch (error) {\n throw toSecretProviderError({\n error,\n provider: this.id,\n reference,\n operation: 'addSecretVersion',\n });\n }\n }\n\n async rotateSecret(\n reference: SecretReference,\n payload: SecretWritePayload\n ): Promise<SecretRotationResult> {\n return this.setSecret(reference, payload);\n }\n\n async deleteSecret(reference: SecretReference): Promise<void> {\n const location = this.parseReference(reference);\n const { secretName } = this.buildNames(location);\n try {\n await this.client.deleteSecret({\n name: secretName,\n });\n } catch (error) {\n throw toSecretProviderError({\n error,\n provider: this.id,\n reference,\n operation: 'delete',\n });\n }\n }\n\n private parseReference(reference: SecretReference): GcpSecretLocation {\n const parsed = parseSecretUri(reference);\n if (parsed.provider !== 'gcp') {\n throw new SecretProviderError({\n message: `Unsupported secret provider: ${parsed.provider}`,\n provider: this.id,\n reference,\n code: 'INVALID',\n });\n }\n\n const segments = parsed.path.split('/').filter(Boolean);\n if (segments.length < 4 || segments[0] !== 'projects') {\n throw new SecretProviderError({\n message: `Expected secret reference format gcp://projects/{project}/secrets/{secret}[(/versions/{version})] but received \"${parsed.path}\"`,\n provider: this.id,\n reference,\n code: 'INVALID',\n });\n }\n\n const projectIdCandidate = segments[1] ?? this.explicitProjectId;\n if (!projectIdCandidate) {\n throw new SecretProviderError({\n message: `Unable to resolve project or secret from reference \"${parsed.path}\"`,\n provider: this.id,\n reference,\n code: 'INVALID',\n });\n }\n\n const indexOfSecrets = segments.indexOf('secrets');\n if (indexOfSecrets === -1 || indexOfSecrets + 1 >= segments.length) {\n throw new SecretProviderError({\n message: `Unable to resolve project or secret from reference \"${parsed.path}\"`,\n provider: this.id,\n reference,\n code: 'INVALID',\n });\n }\n\n const resolvedProjectId = projectIdCandidate;\n const secretIdCandidate = segments[indexOfSecrets + 1];\n if (!secretIdCandidate) {\n throw new SecretProviderError({\n message: `Unable to resolve secret ID from reference \"${parsed.path}\"`,\n provider: this.id,\n reference,\n code: 'INVALID',\n });\n }\n const secretId = secretIdCandidate;\n const indexOfVersions = segments.indexOf('versions');\n const version =\n parsed.extras?.version ??\n (indexOfVersions !== -1 && indexOfVersions + 1 < segments.length\n ? segments[indexOfVersions + 1]\n : undefined);\n\n return {\n projectId: resolvedProjectId,\n secretId,\n version,\n };\n }\n\n private buildNames(location: GcpSecretLocation): {\n secretName: string;\n projectParent: string;\n } {\n const projectId = location.projectId ?? this.explicitProjectId;\n if (!projectId) {\n throw new SecretProviderError({\n message:\n 'Project ID must be provided either in reference or provider configuration',\n provider: this.id,\n reference: `gcp://projects//secrets/${location.secretId}`,\n code: 'INVALID',\n });\n }\n\n const projectParent = `projects/${projectId}`;\n const secretName = `${projectParent}/secrets/${location.secretId}`;\n return {\n projectParent,\n secretName,\n };\n }\n\n private buildVersionName(\n location: GcpSecretLocation,\n explicitVersion?: string\n ): string {\n const { secretName } = this.buildNames(location);\n const version = explicitVersion ?? location.version ?? 'latest';\n return `${secretName}/versions/${version}`;\n }\n\n private async ensureSecretExists(\n location: GcpSecretLocation,\n payload: SecretWritePayload\n ): Promise<void> {\n const { secretName, projectParent } = this.buildNames(location);\n try {\n await this.client.getSecret({ name: secretName });\n } catch (error) {\n const providerError = toSecretProviderError({\n error,\n provider: this.id,\n reference: `gcp://${secretName}`,\n operation: 'getSecret',\n suppressThrow: true,\n });\n if (!providerError || providerError.code !== 'NOT_FOUND') {\n if (providerError) {\n throw providerError;\n }\n throw error;\n }\n try {\n await this.client.createSecret({\n parent: projectParent,\n secretId: location.secretId,\n secret: {\n replication: this.replication,\n labels: payload.labels,\n },\n });\n } catch (creationError) {\n const creationProviderError = toSecretProviderError({\n error: creationError,\n provider: this.id,\n reference: `gcp://${secretName}`,\n operation: 'createSecret',\n });\n throw creationProviderError;\n }\n }\n }\n}\n\nfunction extractVersionFromName(name: string): string | undefined {\n const segments = name.split('/').filter(Boolean);\n const index = segments.indexOf('versions');\n if (index === -1 || index + 1 >= segments.length) {\n return undefined;\n }\n return segments[index + 1];\n}\n\nfunction toSecretProviderError(params: {\n error: unknown;\n provider: string;\n reference: SecretReference;\n operation: string;\n suppressThrow?: boolean;\n}): SecretProviderError {\n const { error, provider, reference, operation, suppressThrow } = params;\n if (error instanceof SecretProviderError) {\n return error;\n }\n\n const code = deriveErrorCode(error);\n const message =\n error instanceof Error\n ? error.message\n : `Unknown error during ${operation}`;\n\n const providerError = new SecretProviderError({\n message,\n provider,\n reference,\n code,\n cause: error,\n });\n\n if (suppressThrow) {\n return providerError;\n }\n\n throw providerError;\n}\n\nfunction deriveErrorCode(error: unknown): SecretProviderError['code'] {\n if (typeof error !== 'object' || error === null) {\n return 'UNKNOWN';\n }\n\n const errorAny = error as { code?: number | string };\n const code = errorAny.code;\n if (code === 5 || code === 'NOT_FOUND') return 'NOT_FOUND';\n if (code === 6 || code === 'ALREADY_EXISTS') return 'INVALID';\n if (code === 7 || code === 'PERMISSION_DENIED' || code === 403) {\n return 'FORBIDDEN';\n }\n if (code === 3 || code === 'INVALID_ARGUMENT') return 'INVALID';\n return 'UNKNOWN';\n}\n"],"mappings":"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"}
@@ -44,4 +44,5 @@ declare class SecretProviderManager implements SecretProvider {
44
44
  }
45
45
  type SecretFetchOptions = Parameters<SecretProvider['getSecret']>[1];
46
46
  //#endregion
47
- export { SecretProviderManager, SecretProviderManagerOptions };
47
+ export { SecretProviderManager, SecretProviderManagerOptions };
48
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","names":[],"sources":["../../src/secrets/manager.ts"],"sourcesContent":[],"mappings":";;;UAeU,eAAA;;AATU;AAgBpB;EAmBa,QAAA,CAAA,EAAA,MAAA;;AAaQ,UAhCJ,4BAAA,CAgCI;EAAyB;;;EAuBhC,EAAA,CAAA,EAAA,MAAA;EACD;;;;EA2BA,SAAA,CAAA,EAAA;IAAR,QAAA,EA1EqB,cA0ErB;IAOU,QAAA,CAAA,EAAA,MAAA;EACF,CAAA,EAAA;;;;;;;AA2EZ;;cAnJY,qBAAA,YAAiC;;;;wBAKvB;qBAQF,0BAAyB;uBAevB;uBAOR,2BACD,qBACT,QAAQ;uBAyBE,0BACF,qBACR,QAAQ;0BAOE,0BACF,qBACR,QAAQ;0BAMmB,kBAAkB;;;;KA8E7C,kBAAA,GAAqB,WAAW"}
@@ -100,4 +100,5 @@ function safeCanHandle(provider, reference) {
100
100
  }
101
101
 
102
102
  //#endregion
103
- export { SecretProviderManager };
103
+ export { SecretProviderManager };
104
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","names":["errors: SecretProviderError[]"],"sources":["../../src/secrets/manager.ts"],"sourcesContent":["import type {\n SecretProvider,\n SecretReference,\n SecretRotationResult,\n SecretValue,\n SecretWritePayload,\n} from './provider';\nimport { SecretProviderError } from './provider';\n\ninterface ProviderRegistration {\n readonly provider: SecretProvider;\n readonly priority: number;\n readonly order: number;\n}\n\ninterface RegisterOptions {\n /**\n * Larger priority values are attempted first. Defaults to 0.\n */\n priority?: number;\n}\n\nexport interface SecretProviderManagerOptions {\n /**\n * Override manager identifier. Defaults to \"secret-provider-manager\".\n */\n id?: string;\n /**\n * Providers to pre-register. They are registered in array order with\n * descending priority (first entry wins ties).\n */\n providers?: { provider: SecretProvider; priority?: number }[];\n}\n\n/**\n * Composite secret provider that delegates to registered providers.\n * Providers are attempted in order of descending priority, respecting the\n * registration order for ties. This enables privileged overrides (e.g.\n * environment variables) while still supporting durable backends like GCP\n * Secret Manager.\n */\nexport class SecretProviderManager implements SecretProvider {\n readonly id: string;\n private readonly providers: ProviderRegistration[] = [];\n private registrationCounter = 0;\n\n constructor(options: SecretProviderManagerOptions = {}) {\n this.id = options.id ?? 'secret-provider-manager';\n const initialProviders = options.providers ?? [];\n for (const entry of initialProviders) {\n this.register(entry.provider, { priority: entry.priority });\n }\n }\n\n register(provider: SecretProvider, options: RegisterOptions = {}): this {\n this.providers.push({\n provider,\n priority: options.priority ?? 0,\n order: this.registrationCounter++,\n });\n this.providers.sort((a, b) => {\n if (a.priority !== b.priority) {\n return b.priority - a.priority;\n }\n return a.order - b.order;\n });\n return this;\n }\n\n canHandle(reference: SecretReference): boolean {\n return this.providers.some(({ provider }) =>\n safeCanHandle(provider, reference)\n );\n }\n\n async getSecret(\n reference: SecretReference,\n options?: SecretFetchOptions\n ): Promise<SecretValue> {\n const errors: SecretProviderError[] = [];\n\n for (const { provider } of this.providers) {\n if (!safeCanHandle(provider, reference)) {\n continue;\n }\n try {\n return await provider.getSecret(reference, options);\n } catch (error) {\n if (error instanceof SecretProviderError) {\n errors.push(error);\n if (error.code !== 'NOT_FOUND') {\n break;\n }\n continue;\n }\n throw error;\n }\n }\n\n throw this.composeError('getSecret', reference, errors, options?.version);\n }\n\n async setSecret(\n reference: SecretReference,\n payload: SecretWritePayload\n ): Promise<SecretRotationResult> {\n return this.delegateToFirst('setSecret', reference, (provider) =>\n provider.setSecret(reference, payload)\n );\n }\n\n async rotateSecret(\n reference: SecretReference,\n payload: SecretWritePayload\n ): Promise<SecretRotationResult> {\n return this.delegateToFirst('rotateSecret', reference, (provider) =>\n provider.rotateSecret(reference, payload)\n );\n }\n\n async deleteSecret(reference: SecretReference): Promise<void> {\n await this.delegateToFirst('deleteSecret', reference, (provider) =>\n provider.deleteSecret(reference)\n );\n }\n\n private async delegateToFirst<T>(\n operation: 'setSecret' | 'rotateSecret' | 'deleteSecret',\n reference: SecretReference,\n invoker: (provider: SecretProvider) => Promise<T>\n ): Promise<T> {\n const errors: SecretProviderError[] = [];\n\n for (const { provider } of this.providers) {\n if (!safeCanHandle(provider, reference)) {\n continue;\n }\n try {\n return await invoker(provider);\n } catch (error) {\n if (error instanceof SecretProviderError) {\n errors.push(error);\n continue;\n }\n throw error;\n }\n }\n\n throw this.composeError(operation, reference, errors);\n }\n\n private composeError(\n operation: string,\n reference: SecretReference,\n errors: SecretProviderError[],\n version?: string\n ): SecretProviderError {\n if (errors.length === 1) {\n const [singleError] = errors;\n if (singleError) {\n return singleError;\n }\n }\n\n const messageParts = [\n `No registered secret provider could ${operation}`,\n `reference \"${reference}\"`,\n ];\n if (version) {\n messageParts.push(`(version: ${version})`);\n }\n if (errors.length > 1) {\n messageParts.push(\n `Attempts: ${errors\n .map((error) => `${error.provider}:${error.code}`)\n .join(', ')}`\n );\n }\n\n return new SecretProviderError({\n message: messageParts.join(' '),\n provider: this.id,\n reference,\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n code: errors.length > 0 ? errors[errors.length - 1]!.code : 'UNKNOWN',\n cause: errors,\n });\n }\n}\n\nfunction safeCanHandle(provider: SecretProvider, reference: SecretReference) {\n try {\n return provider.canHandle(reference);\n } catch {\n return false;\n }\n}\n\ntype SecretFetchOptions = Parameters<SecretProvider['getSecret']>[1];\n"],"mappings":";;;;;;;;;;AAyCA,IAAa,wBAAb,MAA6D;CAC3D,AAAS;CACT,AAAiB,YAAoC,EAAE;CACvD,AAAQ,sBAAsB;CAE9B,YAAY,UAAwC,EAAE,EAAE;AACtD,OAAK,KAAK,QAAQ,MAAM;EACxB,MAAM,mBAAmB,QAAQ,aAAa,EAAE;AAChD,OAAK,MAAM,SAAS,iBAClB,MAAK,SAAS,MAAM,UAAU,EAAE,UAAU,MAAM,UAAU,CAAC;;CAI/D,SAAS,UAA0B,UAA2B,EAAE,EAAQ;AACtE,OAAK,UAAU,KAAK;GAClB;GACA,UAAU,QAAQ,YAAY;GAC9B,OAAO,KAAK;GACb,CAAC;AACF,OAAK,UAAU,MAAM,GAAG,MAAM;AAC5B,OAAI,EAAE,aAAa,EAAE,SACnB,QAAO,EAAE,WAAW,EAAE;AAExB,UAAO,EAAE,QAAQ,EAAE;IACnB;AACF,SAAO;;CAGT,UAAU,WAAqC;AAC7C,SAAO,KAAK,UAAU,MAAM,EAAE,eAC5B,cAAc,UAAU,UAAU,CACnC;;CAGH,MAAM,UACJ,WACA,SACsB;EACtB,MAAMA,SAAgC,EAAE;AAExC,OAAK,MAAM,EAAE,cAAc,KAAK,WAAW;AACzC,OAAI,CAAC,cAAc,UAAU,UAAU,CACrC;AAEF,OAAI;AACF,WAAO,MAAM,SAAS,UAAU,WAAW,QAAQ;YAC5C,OAAO;AACd,QAAI,iBAAiB,qBAAqB;AACxC,YAAO,KAAK,MAAM;AAClB,SAAI,MAAM,SAAS,YACjB;AAEF;;AAEF,UAAM;;;AAIV,QAAM,KAAK,aAAa,aAAa,WAAW,QAAQ,SAAS,QAAQ;;CAG3E,MAAM,UACJ,WACA,SAC+B;AAC/B,SAAO,KAAK,gBAAgB,aAAa,YAAY,aACnD,SAAS,UAAU,WAAW,QAAQ,CACvC;;CAGH,MAAM,aACJ,WACA,SAC+B;AAC/B,SAAO,KAAK,gBAAgB,gBAAgB,YAAY,aACtD,SAAS,aAAa,WAAW,QAAQ,CAC1C;;CAGH,MAAM,aAAa,WAA2C;AAC5D,QAAM,KAAK,gBAAgB,gBAAgB,YAAY,aACrD,SAAS,aAAa,UAAU,CACjC;;CAGH,MAAc,gBACZ,WACA,WACA,SACY;EACZ,MAAMA,SAAgC,EAAE;AAExC,OAAK,MAAM,EAAE,cAAc,KAAK,WAAW;AACzC,OAAI,CAAC,cAAc,UAAU,UAAU,CACrC;AAEF,OAAI;AACF,WAAO,MAAM,QAAQ,SAAS;YACvB,OAAO;AACd,QAAI,iBAAiB,qBAAqB;AACxC,YAAO,KAAK,MAAM;AAClB;;AAEF,UAAM;;;AAIV,QAAM,KAAK,aAAa,WAAW,WAAW,OAAO;;CAGvD,AAAQ,aACN,WACA,WACA,QACA,SACqB;AACrB,MAAI,OAAO,WAAW,GAAG;GACvB,MAAM,CAAC,eAAe;AACtB,OAAI,YACF,QAAO;;EAIX,MAAM,eAAe,CACnB,uCAAuC,aACvC,cAAc,UAAU,GACzB;AACD,MAAI,QACF,cAAa,KAAK,aAAa,QAAQ,GAAG;AAE5C,MAAI,OAAO,SAAS,EAClB,cAAa,KACX,aAAa,OACV,KAAK,UAAU,GAAG,MAAM,SAAS,GAAG,MAAM,OAAO,CACjD,KAAK,KAAK,GACd;AAGH,SAAO,IAAI,oBAAoB;GAC7B,SAAS,aAAa,KAAK,IAAI;GAC/B,UAAU,KAAK;GACf;GAEA,MAAM,OAAO,SAAS,IAAI,OAAO,OAAO,SAAS,GAAI,OAAO;GAC5D,OAAO;GACR,CAAC;;;AAIN,SAAS,cAAc,UAA0B,WAA4B;AAC3E,KAAI;AACF,SAAO,SAAS,UAAU,UAAU;SAC9B;AACN,SAAO"}
@@ -49,4 +49,5 @@ declare class SecretProviderError extends Error {
49
49
  declare function parseSecretUri(reference: SecretReference): ParsedSecretUri;
50
50
  declare function normalizeSecretPayload(payload: SecretWritePayload): Uint8Array;
51
51
  //#endregion
52
- export { ParsedSecretUri, SecretFetchOptions, SecretPayloadEncoding, SecretProvider, SecretProviderError, SecretReference, SecretRotationResult, SecretValue, SecretWritePayload, normalizeSecretPayload, parseSecretUri };
52
+ export { ParsedSecretUri, SecretFetchOptions, SecretPayloadEncoding, SecretProvider, SecretProviderError, SecretReference, SecretRotationResult, SecretValue, SecretWritePayload, normalizeSecretPayload, parseSecretUri };
53
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","names":[],"sources":["../../src/secrets/provider.ts"],"sourcesContent":[],"mappings":";KAEY,eAAA;AAAA,UAEK,WAAA,CAFU;EAEV,IAAA,EACT,UADoB;EACpB,OAAA,CAAA,EAAA,MAAA;EAEK,QAAA,CAAA,EAAA,MAAA,CAAA,MAAA,EAAA,MAAA,CAAA;EACE,WAAA,EAAA,IAAA;;AAGE,UAAA,kBAAA,CAAkB;EAIvB,OAAA,CAAA,EAAA,MAAA;AAEZ;AACiB,KAHL,qBAAA,GAGK,OAAA,GAAA,QAAA,GAAA,QAAA;AACJ,UAFI,kBAAA,CAEJ;EAEF,IAAA,EAAA,MAAA,GAHM,UAGN;EAAM,QAAA,CAAA,EAFJ,qBAEI;EAGA,WAAA,CAAA,EAAA,MAAA;EAKA,MAAA,CAAA,EARN,MAQM,CAAA,MAAc,EAAA,MAAA,CAAA;;AAIhB,UATE,oBAAA,CASF;EACD,SAAA,EATD,eASC;EACD,OAAA,EAAA,MAAA;;AAEE,UARE,cAAA,CAQF;EACF,SAAA,EAAA,EAAA,MAAA;EACA,SAAA,CAAA,SAAA,EARU,eAQV,CAAA,EAAA,OAAA;EAAR,SAAA,CAAA,SAAA,EANU,eAMV,EAAA,OAAA,CAAA,EALS,kBAKT,CAAA,EAJA,OAIA,CAJQ,WAIR,CAAA;EAEU,SAAA,CAAA,SAAA,EAJA,eAIA,EAAA,OAAA,EAHF,kBAGE,CAAA,EAFV,OAEU,CAFF,oBAEE,CAAA;EACF,YAAA,CAAA,SAAA,EADE,eACF,EAAA,OAAA,EAAA,kBAAA,CAAA,EACR,OADQ,CACA,oBADA,CAAA;EACA,YAAA,CAAA,SAAA,EACa,eADb,CAAA,EAC+B,OAD/B,CAAA,IAAA,CAAA;;AACa,UAGT,eAAA,CAHS;EAAkB,QAAA,EAAA,MAAA;EAAO,IAAA,EAAA,MAAA;EAGlC,MAAA,CAAA,EAGN,MAHM,CAAA,MAAe,EAAA,MAGrB,CAAA;AAGX;AAEsB,cAFT,mBAAA,SAA4B,KAAA,CAEnB;EAOP,SAAA,QAAA,EAAA,MAAA;EACJ,SAAA,SAAA,EARW,eAQX;EAV8B,SAAA,IAAA,EAAA,WAAA,GAAA,WAAA,GAAA,SAAA,GAAA,SAAA;EAAK,SAAA,KAAA,CAAA,EAAA,OAAA;EAsB9B,WAAA,CAAA,MAAc,EAAA;IAiDd,OAAA,EAAA,MAAA;;eA9DD;WACJ;;;;iBAYK,cAAA,YAA0B,kBAAkB;iBAiD5C,sBAAA,UACL,qBACR"}
@@ -55,4 +55,5 @@ function normalizeSecretPayload(payload) {
55
55
  }
56
56
 
57
57
  //#endregion
58
- export { SecretProviderError, normalizeSecretPayload, parseSecretUri };
58
+ export { SecretProviderError, normalizeSecretPayload, parseSecretUri };
59
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","names":[],"sources":["../../src/secrets/provider.ts"],"sourcesContent":["import { Buffer } from 'node:buffer';\n\nexport type SecretReference = string;\n\nexport interface SecretValue {\n data: Uint8Array;\n version?: string;\n metadata?: Record<string, string>;\n retrievedAt: Date;\n}\n\nexport interface SecretFetchOptions {\n version?: string;\n}\n\nexport type SecretPayloadEncoding = 'utf-8' | 'base64' | 'binary';\n\nexport interface SecretWritePayload {\n data: string | Uint8Array;\n encoding?: SecretPayloadEncoding;\n contentType?: string;\n labels?: Record<string, string>;\n}\n\nexport interface SecretRotationResult {\n reference: SecretReference;\n version: string;\n}\n\nexport interface SecretProvider {\n readonly id: string;\n canHandle(reference: SecretReference): boolean;\n getSecret(\n reference: SecretReference,\n options?: SecretFetchOptions\n ): Promise<SecretValue>;\n setSecret(\n reference: SecretReference,\n payload: SecretWritePayload\n ): Promise<SecretRotationResult>;\n rotateSecret(\n reference: SecretReference,\n payload: SecretWritePayload\n ): Promise<SecretRotationResult>;\n deleteSecret(reference: SecretReference): Promise<void>;\n}\n\nexport interface ParsedSecretUri {\n provider: string;\n path: string;\n extras?: Record<string, string>;\n}\n\nexport class SecretProviderError extends Error {\n readonly provider: string;\n readonly reference: SecretReference;\n readonly code: 'NOT_FOUND' | 'FORBIDDEN' | 'INVALID' | 'UNKNOWN';\n readonly cause?: unknown;\n\n constructor(params: {\n message: string;\n provider: string;\n reference: SecretReference;\n code?: SecretProviderError['code'];\n cause?: unknown;\n }) {\n super(params.message);\n this.name = 'SecretProviderError';\n this.provider = params.provider;\n this.reference = params.reference;\n this.code = params.code ?? 'UNKNOWN';\n this.cause = params.cause;\n }\n}\n\nexport function parseSecretUri(reference: SecretReference): ParsedSecretUri {\n if (!reference) {\n throw new SecretProviderError({\n message: 'Secret reference cannot be empty',\n provider: 'unknown',\n reference,\n code: 'INVALID',\n });\n }\n\n const [scheme, rest] = reference.split('://');\n if (!scheme || !rest) {\n throw new SecretProviderError({\n message: `Invalid secret reference: ${reference}`,\n provider: 'unknown',\n reference,\n code: 'INVALID',\n });\n }\n\n const queryIndex = rest.indexOf('?');\n if (queryIndex === -1) {\n return {\n provider: scheme,\n path: rest,\n };\n }\n\n const path = rest.slice(0, queryIndex);\n const query = rest.slice(queryIndex + 1);\n const extras = Object.fromEntries(\n query\n .split('&')\n .filter(Boolean)\n .map((pair) => {\n const [keyRaw, valueRaw] = pair.split('=');\n const key = keyRaw ?? '';\n const value = valueRaw ?? '';\n return [decodeURIComponent(key), decodeURIComponent(value)];\n })\n );\n\n return {\n provider: scheme,\n path,\n extras,\n };\n}\n\nexport function normalizeSecretPayload(\n payload: SecretWritePayload\n): Uint8Array {\n if (payload.data instanceof Uint8Array) {\n return payload.data;\n }\n\n if (payload.encoding === 'base64') {\n return Buffer.from(payload.data, 'base64');\n }\n\n if (payload.encoding === 'binary') {\n return Buffer.from(payload.data, 'binary');\n }\n\n return Buffer.from(payload.data, 'utf-8');\n}\n"],"mappings":";;;AAqDA,IAAa,sBAAb,cAAyC,MAAM;CAC7C,AAAS;CACT,AAAS;CACT,AAAS;CACT,AAAS;CAET,YAAY,QAMT;AACD,QAAM,OAAO,QAAQ;AACrB,OAAK,OAAO;AACZ,OAAK,WAAW,OAAO;AACvB,OAAK,YAAY,OAAO;AACxB,OAAK,OAAO,OAAO,QAAQ;AAC3B,OAAK,QAAQ,OAAO;;;AAIxB,SAAgB,eAAe,WAA6C;AAC1E,KAAI,CAAC,UACH,OAAM,IAAI,oBAAoB;EAC5B,SAAS;EACT,UAAU;EACV;EACA,MAAM;EACP,CAAC;CAGJ,MAAM,CAAC,QAAQ,QAAQ,UAAU,MAAM,MAAM;AAC7C,KAAI,CAAC,UAAU,CAAC,KACd,OAAM,IAAI,oBAAoB;EAC5B,SAAS,6BAA6B;EACtC,UAAU;EACV;EACA,MAAM;EACP,CAAC;CAGJ,MAAM,aAAa,KAAK,QAAQ,IAAI;AACpC,KAAI,eAAe,GACjB,QAAO;EACL,UAAU;EACV,MAAM;EACP;CAGH,MAAM,OAAO,KAAK,MAAM,GAAG,WAAW;CACtC,MAAM,QAAQ,KAAK,MAAM,aAAa,EAAE;AAaxC,QAAO;EACL,UAAU;EACV;EACA,QAfa,OAAO,YACpB,MACG,MAAM,IAAI,CACV,OAAO,QAAQ,CACf,KAAK,SAAS;GACb,MAAM,CAAC,QAAQ,YAAY,KAAK,MAAM,IAAI;GAC1C,MAAM,MAAM,UAAU;GACtB,MAAM,QAAQ,YAAY;AAC1B,UAAO,CAAC,mBAAmB,IAAI,EAAE,mBAAmB,MAAM,CAAC;IAC3D,CACL;EAMA;;AAGH,SAAgB,uBACd,SACY;AACZ,KAAI,QAAQ,gBAAgB,WAC1B,QAAO,QAAQ;AAGjB,KAAI,QAAQ,aAAa,SACvB,QAAO,OAAO,KAAK,QAAQ,MAAM,SAAS;AAG5C,KAAI,QAAQ,aAAa,SACvB,QAAO,OAAO,KAAK,QAAQ,MAAM,SAAS;AAG5C,QAAO,OAAO,KAAK,QAAQ,MAAM,QAAQ"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lssm/integration.runtime",
3
- "version": "0.0.0-canary-20251217083314",
3
+ "version": "0.0.0-canary-20251220002821",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -23,15 +23,15 @@
23
23
  "test": "bun test"
24
24
  },
25
25
  "dependencies": {
26
- "@lssm/lib.contracts": "0.0.0-canary-20251217083314",
27
- "@lssm/lib.logger": "0.0.0-canary-20251217083314",
26
+ "@lssm/lib.contracts": "0.0.0-canary-20251220002821",
27
+ "@lssm/lib.logger": "0.0.0-canary-20251220002821",
28
28
  "@google-cloud/secret-manager": "^6.1.1",
29
29
  "google-gax": "^5.0.0"
30
30
  },
31
31
  "devDependencies": {
32
- "@lssm/tool.tsdown": "0.0.0-canary-20251217083314",
33
- "@lssm/tool.typescript": "0.0.0-canary-20251217083314",
34
- "tsdown": "^0.17.4",
32
+ "@lssm/tool.tsdown": "0.0.0-canary-20251220002821",
33
+ "@lssm/tool.typescript": "0.0.0-canary-20251220002821",
34
+ "tsdown": "^0.18.1",
35
35
  "typescript": "^5.9.3"
36
36
  },
37
37
  "exports": {
@@ -57,6 +57,13 @@
57
57
  "./secrets/manager": "./dist/secrets/manager.js",
58
58
  "./secrets/provider": "./dist/secrets/provider.js",
59
59
  "./*": "./*"
60
- }
60
+ },
61
+ "registry": "https://registry.npmjs.org/"
62
+ },
63
+ "license": "MIT",
64
+ "repository": {
65
+ "type": "git",
66
+ "url": "https://github.com/lssm-tech/contractspec.git",
67
+ "directory": "packages/integrations/runtime"
61
68
  }
62
69
  }