@burdenoff/be-sdk 2026.825.2 → 2026.825.4

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.
@@ -1,5 +1,6 @@
1
- export { CacheFactory, CacheProviderType, MemoryCacheProvider, ValkeyGlideProvider, assertCacheEndpointConfigured, closeAllCaches, createCache, getCache, getValkeyClient, warnOnLayerDefaultEndpoint } from '../chunk-7UF4Q5HK.js';
1
+ export { CacheFactory, CacheProviderType, MemoryCacheProvider, ValkeyGlideProvider, assertCacheEndpointConfigured, closeAllCaches, createCache, getCache, getValkeyClient, warnOnLayerDefaultEndpoint } from '../chunk-AW6JUXCU.js';
2
2
  import '../chunk-VBXPFYZ5.js';
3
+ import '../chunk-A5F6Z5UE.js';
3
4
  import '../chunk-YFOHAHZE.js';
4
5
  import '../chunk-CBZNP6RF.js';
5
6
  import '../chunk-XE4OXN2W.js';
@@ -1,7 +1,8 @@
1
- import { security_exports } from './chunk-AW6A5K6S.js';
1
+ import { security_exports } from './chunk-NVVWSOY7.js';
2
2
  import { LayerManager } from './chunk-7UJXIX4I.js';
3
3
  import { signServiceJwt } from './chunk-VFCMR5GX.js';
4
4
  import { ContextManager } from './chunk-RZOFS2BQ.js';
5
+ import { currentEnvironment, isDeployedEnvironment } from './chunk-A5F6Z5UE.js';
5
6
  import { DEFAULT_CIRCUIT_BREAKER_CONFIG, DEFAULT_GATEWAY_RETRY_CONFIG } from './chunk-YFOHAHZE.js';
6
7
  import { logger } from './chunk-CBZNP6RF.js';
7
8
  import { __export, __name } from './chunk-XE4OXN2W.js';
@@ -19,6 +20,22 @@ __export(gateway_exports, {
19
20
  signServiceJwt: () => signServiceJwt
20
21
  });
21
22
 
23
+ // src/gateway/service-jwt-guard.ts
24
+ var SERVICE_JWT_SECRET_ENV = "SERVICE_JWT_SECRET";
25
+ function serviceJwtMisconfigurationMessage(context) {
26
+ const environment = currentEnvironment() || "unset";
27
+ const layer = context.layer ?? "{layer}";
28
+ const operation = context.operationName ? ` (operation ${context.operationName})` : "";
29
+ const identity = context.serviceIdentity ? ` as '${context.serviceIdentity}'` : "";
30
+ return `[GatewayClient] Cross-layer call to ${context.gatewayUrl}${operation} cannot be authenticated${identity}: ${SERVICE_JWT_SECRET_ENV} is not set, so no service JWT can be minted. The peer layer's public gateway will strip actor headers and the subgraph will reject the request, so this call cannot succeed. Refusing to send it with DEPLOY_ENV=${environment}. Set ${SERVICE_JWT_SECRET_ENV} in boff/${environment}/${layer}/{module} \u2014 it must match the value the peer layer's gateway verifies with, which is per-environment and must never be copied across environments.`;
31
+ }
32
+ __name(serviceJwtMisconfigurationMessage, "serviceJwtMisconfigurationMessage");
33
+ function assertServiceJwtConfigured(context) {
34
+ if (!isDeployedEnvironment()) return;
35
+ throw new Error(serviceJwtMisconfigurationMessage(context));
36
+ }
37
+ __name(assertServiceJwtConfigured, "assertServiceJwtConfigured");
38
+
22
39
  // src/gateway/types.ts
23
40
  var CircuitState = /* @__PURE__ */ (function(CircuitState2) {
24
41
  CircuitState2["CLOSED"] = "CLOSED";
@@ -443,11 +460,19 @@ var GatewayClient = class {
443
460
  const serviceJwt = await signServiceJwt(serviceActorId);
444
461
  if (serviceJwt) {
445
462
  headers["Authorization"] = `Bearer ${serviceJwt}`;
446
- } else if (this.config.enableLogging) {
447
- logger.debug("[GatewayClient] SERVICE_JWT_SECRET not configured \u2014 cross-layer call will proceed without service JWT", {
448
- requestId: context.requestId,
449
- gatewayUrl
463
+ } else {
464
+ assertServiceJwtConfigured({
465
+ gatewayUrl,
466
+ operationName: options.operationName,
467
+ layer: this.layerManager.getLayer(),
468
+ serviceIdentity: serviceActorId
450
469
  });
470
+ if (this.config.enableLogging) {
471
+ logger.debug("[GatewayClient] SERVICE_JWT_SECRET not configured \u2014 cross-layer call will proceed without service JWT", {
472
+ requestId: context.requestId,
473
+ gatewayUrl
474
+ });
475
+ }
451
476
  }
452
477
  }
453
478
  const body = JSON.stringify({
@@ -522,5 +547,5 @@ function createGatewayClientFromEnv() {
522
547
  __name(createGatewayClientFromEnv, "createGatewayClientFromEnv");
523
548
 
524
549
  export { CircuitState, GatewayClient, GatewayError, GatewayErrorType, createGatewayClient, createGatewayClientFromEnv, gateway_exports };
525
- //# sourceMappingURL=chunk-D67OENCT.js.map
526
- //# sourceMappingURL=chunk-D67OENCT.js.map
550
+ //# sourceMappingURL=chunk-4X5WL6I3.js.map
551
+ //# sourceMappingURL=chunk-4X5WL6I3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/gateway/index.ts","../src/gateway/service-jwt-guard.ts","../src/gateway/types.ts","../src/gateway/client.ts"],"names":["SERVICE_JWT_SECRET_ENV","serviceJwtMisconfigurationMessage","context","environment","currentEnvironment","layer","operation","operationName","identity","serviceIdentity","gatewayUrl","assertServiceJwtConfigured","isDeployedEnvironment","Error","CircuitState","GatewayErrorType","GatewayError","type","statusCode","graphqlErrors","cause","message","options","name","Object","setPrototypeOf","prototype","uuidv4","crypto","randomUUID","hasAuthorizationHeader","headers","key","keys","toLowerCase","resolveBypassPermissionValue","token","process","env","normalizedToken","trim","CircuitBreaker","state","CLOSED","failures","successes","consecutiveFailures","lastFailureTime","lastSuccessTime","openedAt","failureTimestamps","config","getState","checkStateTransition","recordSuccess","Date","now","HALF_OPEN","logger","info","recordFailure","push","windowStart","failureWindow","filter","t","length","failureThreshold","OPEN","warn","threshold","allowRequest","forceOpen","forceClose","getStats","elapsed","resetTimeout","GatewayClient","layerManager","internalCircuitBreaker","crossLayerCircuitBreaker","retryConfig","defaultHeaders","timeout","enableLogging","LayerManager","serviceName","internalGatewayUrl","crossLayerGatewayUrl","cbConfig","DEFAULT_CIRCUIT_BREAKER_CONFIG","circuitBreaker","DEFAULT_GATEWAY_RETRY_CONFIG","retry","getServiceIdentity","debug","internalUrl","getInternalUrl","crossLayerUrl","getCrossLayerUrl","getInternalGatewayUrl","getCrossLayerGatewayUrl","internalQuery","createRequestContext","executeWithRetry","bypassPermission","crossLayerQuery","query","getInternalCircuitBreaker","getCrossLayerCircuitBreaker","getHealthStatus","internal","url","circuitState","stats","crossLayer","updateDefaultHeaders","callType","requestId","actorId","workspaceId","startTime","shouldRetryError","error","GRAPHQL_ERROR","CIRCUIT_OPEN","calculateRetryDelay","attempt","Math","min","initialDelay","pow","backoffMultiplier","maxDelay","logRetryAttempt","maxAttempts","delay","settings","skipCircuitBreaker","skipRetry","lastError","result","executeRequest","String","sleep","UNKNOWN_ERROR","buildRequestHeaders","cfHeaders","ContextManager","getCfAccessHeaders","assign","value","entries","undefined","toString","cfCookie","existing","split","some","c","handleGraphQLErrors","duration","errors","errorMessages","map","e","join","handleFetchError","TIMEOUT_ERROR","NETWORK_ERROR","serviceActorId","serviceJwt","signServiceJwt","getLayer","body","JSON","stringify","variables","controller","AbortController","timeoutId","setTimeout","abort","response","fetch","method","signal","clearTimeout","ok","status","statusText","json","hasData","data","ms","Promise","resolve","createGatewayClient","createGatewayClientFromEnv"],"mappings":"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","file":"chunk-4X5WL6I3.js","sourcesContent":["/**\n * Gateway Module\n *\n * Provides unified gateway client for layer-aware M2M communication\n * with circuit breaker and retry logic.\n *\n * @module gateway\n * @category Gateway\n *\n * @example\n * ```typescript\n * import { GatewayClient, createGatewayClientFromEnv } from '@burdenoff/be-sdk/gateway';\n *\n * // Create from environment variables\n * const client = createGatewayClientFromEnv();\n *\n * // Or create manually\n * const client = new GatewayClient({\n * layer: 'wspace',\n * serviceName: 'wspace-tags-svc',\n * });\n *\n * // Internal call (same layer, uses int-gateway with bypass)\n * const internalResult = await client.internalQuery({\n * query: `query { getTag(id: \"123\") { id name } }`,\n * });\n *\n * // Cross-layer call (via public gateway)\n * const crossLayerResult = await client.crossLayerQuery({\n * query: `query { getCurrentUser { id email } }`,\n * });\n * ```\n */\n\n// Client exports\nexport { GatewayClient, createGatewayClient, createGatewayClientFromEnv } from './client.js';\n\n// Service-JWT minting for cross-layer M2M auth. Exposed so non-GatewayClient\n// callers (e.g. bespoke graphql-request clients) can authenticate identically.\nexport { signServiceJwt } from './service-jwt.js';\n\n// Type exports\nexport {\n CircuitState,\n GatewayErrorType,\n GatewayError,\n type GatewayClientConfig,\n type GraphQLRequestOptions,\n type GraphQLResponse,\n type GraphQLError,\n type IGatewayClient,\n type ICircuitBreaker,\n type CircuitBreakerStats,\n type GatewayClientHealth,\n type RequestContext,\n} from './types.js';\n\n// Gateway-side security plugin stack (for public gateways).\n// Imported by consumers as `@burdenoff/be-sdk/gateway/security` — this\n// re-export lets `@burdenoff/be-sdk/gateway` also resolve the namespace.\nexport * as Security from './security/index.js';\n","/**\n * Cross-layer service-JWT configuration guard.\n *\n * A cross-layer call transits the peer layer's PUBLIC gateway, which propagates\n * `x-actor-*` context to subgraphs only when the request carries a valid JWT.\n * Without one the gateway strips those headers as potential client spoofing and\n * the subgraph rejects the call. So on a cross-layer request with no\n * Authorization header and no mintable service JWT, the outcome is already\n * decided before the request leaves the process: it will fail, downstream, with\n * an authentication error that names the callee rather than the missing secret.\n *\n * That is a bad trade in a deployed environment. It converts a one-line config\n * problem into an opaque failure attributed to the wrong service, and — because\n * several cross-layer callers treat these calls as best-effort and swallow the\n * error — into no visible failure at all. Alpha ran exactly that way: 414 calls\n * in 24h on `AddWorkspaceMemberFromWspace` and `WorkspaceOrganization`, every\n * one rejected, workspace-member mirroring silently not happening, and nothing\n * in the caller's logs above debug level.\n *\n * So in alpha, staging and production this throws before the request is sent,\n * naming the secret and the bundle to fix. Locally it stays a log: a laptop\n * calling across layers without a service JWT is a normal state while a\n * developer is mid-setup, and failing their `bun run dev` would be hostile.\n *\n * Verified inert before shipping, the same way the cache guard was: of the\n * alpha and prod service bundles in Secrets Manager, every be-sdk service that\n * makes cross-layer calls already carries `SERVICE_JWT_SECRET` (166 bundles).\n * The bundles without it are Temporal, OPA, the OTel collectors, NATS, Gatus,\n * the vibetunnels pair, the ai-assistant trio, the dormant `*-community`\n * deployments and the retired `state-archive-*` configs — none of which\n * constructs a GatewayClient or makes a cross-layer call. Nothing changes\n * today; this only catches the next caller rolled out without the secret.\n */\nimport { isDeployedEnvironment, currentEnvironment } from '../runtime/deployed-environment.js';\n\n/** Env var that must hold the signing key for service-actor JWTs. */\nexport const SERVICE_JWT_SECRET_ENV = 'SERVICE_JWT_SECRET';\n\nexport interface ServiceJwtGuardContext {\n /** Absolute URL of the peer gateway the call was about to be sent to. */\n gatewayUrl: string;\n /** GraphQL operation name, when the caller supplied one. */\n operationName?: string;\n /** Layer boundary of the CALLER, used to name the bundle to fix. */\n layer?: string;\n /** Service identity the JWT would have been minted for. */\n serviceIdentity?: string;\n}\n\n/**\n * Build the operator-facing explanation. Exported so the message itself is\n * covered by tests — a guard whose text does not say what to change just moves\n * the debugging, it does not remove it.\n */\nexport function serviceJwtMisconfigurationMessage(context: ServiceJwtGuardContext): string {\n const environment = currentEnvironment() || 'unset';\n const layer = context.layer ?? '{layer}';\n const operation = context.operationName ? ` (operation ${context.operationName})` : '';\n const identity = context.serviceIdentity ? ` as '${context.serviceIdentity}'` : '';\n return (\n `[GatewayClient] Cross-layer call to ${context.gatewayUrl}${operation} cannot be authenticated${identity}: ` +\n `${SERVICE_JWT_SECRET_ENV} is not set, so no service JWT can be minted. The peer layer's public ` +\n `gateway will strip actor headers and the subgraph will reject the request, so this call cannot ` +\n `succeed. Refusing to send it with DEPLOY_ENV=${environment}. Set ${SERVICE_JWT_SECRET_ENV} in ` +\n `boff/${environment}/${layer}/{module} — it must match the value the peer layer's gateway ` +\n `verifies with, which is per-environment and must never be copied across environments.`\n );\n}\n\n/**\n * Throw in a deployed environment when a cross-layer call is about to be sent\n * with no way to authenticate it. Returns normally everywhere else, and\n * whenever a JWT was available — so this costs nothing on the happy path.\n */\nexport function assertServiceJwtConfigured(context: ServiceJwtGuardContext): void {\n if (!isDeployedEnvironment()) return;\n throw new Error(serviceJwtMisconfigurationMessage(context));\n}\n","/**\n * Gateway Client Types\n *\n * Type definitions for the unified gateway client with\n * circuit breaker and retry logic.\n *\n * @module gateway/types\n * @category Gateway\n */\n\nimport type { ServiceLayer, CircuitBreakerConfig, GatewayRetryConfig, GatewayRequestHeaders } from '../types/layer.js';\n\n/**\n * Gateway client configuration\n */\nexport interface GatewayClientConfig {\n /**\n * Layer this client belongs to\n */\n layer: ServiceLayer;\n\n /**\n * Service name (for logging and headers)\n */\n serviceName: string;\n\n /**\n * Service identity for bypass headers\n * @default serviceName\n */\n serviceIdentity?: string;\n\n /**\n * Internal gateway URL (same layer M2M)\n * @default Resolved from layer defaults or environment\n */\n internalGatewayUrl?: string;\n\n /**\n * Cross-layer gateway URL (cross layer via public gateway)\n * @default Resolved from layer defaults or environment\n */\n crossLayerGatewayUrl?: string;\n\n /**\n * Request timeout in milliseconds\n * @default 30000 (30 seconds)\n */\n timeout?: number;\n\n /**\n * Circuit breaker configuration\n */\n circuitBreaker?: Partial<CircuitBreakerConfig>;\n\n /**\n * Retry configuration\n */\n retry?: Partial<GatewayRetryConfig>;\n\n /**\n * Enable request logging\n * @default true\n */\n enableLogging?: boolean;\n\n /**\n * Default headers to include in all requests\n */\n defaultHeaders?: GatewayRequestHeaders;\n}\n\n/**\n * Circuit breaker states\n */\nexport enum CircuitState {\n CLOSED = 'CLOSED',\n OPEN = 'OPEN',\n HALF_OPEN = 'HALF_OPEN',\n}\n\n/**\n * Circuit breaker instance interface\n */\nexport interface ICircuitBreaker {\n /**\n * Get current circuit state\n */\n getState(): CircuitState;\n\n /**\n * Record a successful call\n */\n recordSuccess(): void;\n\n /**\n * Record a failed call\n */\n recordFailure(): void;\n\n /**\n * Check if circuit allows calls\n */\n allowRequest(): boolean;\n\n /**\n * Force open the circuit\n */\n forceOpen(): void;\n\n /**\n * Force close the circuit\n */\n forceClose(): void;\n\n /**\n * Get circuit statistics\n */\n getStats(): CircuitBreakerStats;\n}\n\n/**\n * Circuit breaker statistics\n */\nexport interface CircuitBreakerStats {\n state: CircuitState;\n failures: number;\n successes: number;\n consecutiveFailures: number;\n lastFailureTime: number | null;\n lastSuccessTime: number | null;\n openedAt: number | null;\n}\n\n/**\n * GraphQL request options\n */\nexport interface GraphQLRequestOptions {\n /**\n * GraphQL query or mutation string\n */\n query: string;\n\n /**\n * GraphQL variables\n */\n variables?: Record<string, unknown>;\n\n /**\n * Operation name (for multi-operation documents)\n */\n operationName?: string;\n\n /**\n * Additional headers for this request\n */\n headers?: GatewayRequestHeaders;\n\n /**\n * Override timeout for this request\n */\n timeout?: number;\n\n /**\n * Skip circuit breaker for this request\n * @default false\n */\n skipCircuitBreaker?: boolean;\n\n /**\n * Skip retry logic for this request\n * @default false\n */\n skipRetry?: boolean;\n}\n\n/**\n * GraphQL response\n */\nexport interface GraphQLResponse<T = unknown> {\n /**\n * Response data\n */\n data?: T;\n\n /**\n * GraphQL errors\n */\n errors?: GraphQLError[];\n}\n\n/**\n * GraphQL error structure\n */\nexport interface GraphQLError {\n message: string;\n locations?: Array<{ line: number; column: number }>;\n path?: Array<string | number>;\n extensions?: Record<string, unknown>;\n}\n\n/**\n * Gateway client interface\n */\nexport interface IGatewayClient {\n /**\n * Execute internal (same layer) GraphQL query/mutation\n *\n * Uses internal gateway with bypass headers for M2M communication.\n *\n * @param options - Request options\n * @returns GraphQL response\n */\n internalQuery<T = unknown>(options: GraphQLRequestOptions): Promise<GraphQLResponse<T>>;\n\n /**\n * Execute cross-layer GraphQL query/mutation\n *\n * Uses public gateway for cross-layer communication.\n *\n * @param options - Request options\n * @returns GraphQL response\n */\n crossLayerQuery<T = unknown>(options: GraphQLRequestOptions): Promise<GraphQLResponse<T>>;\n\n /**\n * Execute GraphQL query/mutation with explicit gateway URL\n *\n * @param gatewayUrl - Gateway URL to use\n * @param options - Request options\n * @returns GraphQL response\n */\n query<T = unknown>(gatewayUrl: string, options: GraphQLRequestOptions): Promise<GraphQLResponse<T>>;\n\n /**\n * Get internal gateway circuit breaker\n */\n getInternalCircuitBreaker(): ICircuitBreaker;\n\n /**\n * Get cross-layer gateway circuit breaker\n */\n getCrossLayerCircuitBreaker(): ICircuitBreaker;\n\n /**\n * Get client health status\n */\n getHealthStatus(): GatewayClientHealth;\n\n /**\n * Update default headers\n */\n updateDefaultHeaders(headers: Partial<GatewayRequestHeaders>): void;\n}\n\n/**\n * Gateway client health status\n */\nexport interface GatewayClientHealth {\n /**\n * Internal gateway status\n */\n internal: {\n url: string;\n circuitState: CircuitState;\n stats: CircuitBreakerStats;\n };\n\n /**\n * Cross-layer gateway status\n */\n crossLayer: {\n url: string;\n circuitState: CircuitState;\n stats: CircuitBreakerStats;\n };\n}\n\n/**\n * Gateway error types\n */\nexport enum GatewayErrorType {\n NETWORK_ERROR = 'NETWORK_ERROR',\n TIMEOUT_ERROR = 'TIMEOUT_ERROR',\n CIRCUIT_OPEN = 'CIRCUIT_OPEN',\n GRAPHQL_ERROR = 'GRAPHQL_ERROR',\n UNKNOWN_ERROR = 'UNKNOWN_ERROR',\n}\n\n/**\n * Gateway error class\n */\nexport class GatewayError extends Error {\n type: GatewayErrorType;\n gatewayUrl: string;\n statusCode?: number;\n graphqlErrors?: GraphQLError[];\n override cause?: Error;\n\n constructor(\n message: string,\n type: GatewayErrorType,\n gatewayUrl: string,\n options?: {\n statusCode?: number;\n graphqlErrors?: GraphQLError[];\n cause?: Error;\n }\n ) {\n super(message);\n this.name = 'GatewayError';\n this.type = type;\n this.gatewayUrl = gatewayUrl;\n this.statusCode = options?.statusCode;\n this.graphqlErrors = options?.graphqlErrors;\n this.cause = options?.cause;\n Object.setPrototypeOf(this, GatewayError.prototype);\n }\n}\n\n/**\n * Request context for logging and tracing\n */\nexport interface RequestContext {\n /**\n * Request ID for tracing\n */\n requestId: string;\n\n /**\n * Actor ID making the request\n */\n actorId?: string;\n\n /**\n * Workspace ID context\n */\n workspaceId?: string;\n\n /**\n * Timestamp when request started\n */\n startTime: number;\n\n /**\n * Call type\n */\n callType: 'internal' | 'cross-layer' | 'direct';\n}\n","/**\n * Unified Gateway Client\n *\n * Provides a layer-aware GraphQL client with circuit breaker,\n * retry logic, and automatic header management for M2M communication.\n *\n * @module gateway/client\n * @category Gateway\n *\n * @example\n * ```typescript\n * import { GatewayClient } from '@burdenoff/be-sdk/gateway';\n *\n * const client = new GatewayClient({\n * layer: 'wspace',\n * serviceName: 'wspace-tags-svc',\n * });\n *\n * // Internal call (same layer)\n * const result = await client.internalQuery({\n * query: `query { getTag(id: \"123\") { id name } }`,\n * });\n *\n * // Cross-layer call\n * const authResult = await client.crossLayerQuery({\n * query: `query { getCurrentUser { id email } }`,\n * });\n * ```\n */\n\nimport { ContextManager } from '../context/index.js';\nimport { LayerManager } from '../layer/index.js';\nimport { logger } from '../logger/index.js';\nimport { signServiceJwt } from './service-jwt.js';\nimport { assertServiceJwtConfigured } from './service-jwt-guard.js';\nimport {\n DEFAULT_CIRCUIT_BREAKER_CONFIG,\n DEFAULT_GATEWAY_RETRY_CONFIG,\n type CircuitBreakerConfig,\n type GatewayRequestHeaders,\n type GatewayRetryConfig,\n type ServiceLayer,\n} from '../types/layer.js';\nimport {\n CircuitState,\n GatewayError,\n GatewayErrorType,\n type CircuitBreakerStats,\n type GatewayClientConfig,\n type GatewayClientHealth,\n type GraphQLError,\n type GraphQLRequestOptions,\n type GraphQLResponse,\n type ICircuitBreaker,\n type IGatewayClient,\n type RequestContext,\n} from './types.js';\n\nconst uuidv4 = (): string => crypto.randomUUID();\n\n/**\n * Case-insensitive presence check for the `Authorization` header. HTTP header\n * names are case-insensitive (RFC 7230), and while the outbound `fetch` will\n * preserve whatever casing the caller supplies, callers may legitimately set\n * `authorization` / `Authorization` / even `AUTHORIZATION` via defaultHeaders\n * or options.headers. We must not overwrite an already-supplied token.\n */\nfunction hasAuthorizationHeader(headers: Record<string, string>): boolean {\n for (const key of Object.keys(headers)) {\n if (key.toLowerCase() === 'authorization') return true;\n }\n return false;\n}\n\nexport function resolveBypassPermissionValue(\n token: string | undefined = process.env['INTERNAL_SERVICE_TOKEN']\n): string {\n const normalizedToken = token?.trim();\n\n if (!normalizedToken) {\n throw new Error('INTERNAL_SERVICE_TOKEN must be configured for bypass-enabled gateway calls');\n }\n\n return normalizedToken;\n}\n\n/**\n * Circuit Breaker Implementation\n */\nclass CircuitBreaker implements ICircuitBreaker {\n private state: CircuitState = CircuitState.CLOSED;\n private failures = 0;\n private successes = 0;\n private consecutiveFailures = 0;\n private lastFailureTime: number | null = null;\n private lastSuccessTime: number | null = null;\n private openedAt: number | null = null;\n private failureTimestamps: number[] = [];\n private config: CircuitBreakerConfig;\n\n constructor(config: CircuitBreakerConfig) {\n this.config = config;\n }\n\n getState(): CircuitState {\n this.checkStateTransition();\n return this.state;\n }\n\n recordSuccess(): void {\n this.successes++;\n this.consecutiveFailures = 0;\n this.lastSuccessTime = Date.now();\n\n if (this.state === CircuitState.HALF_OPEN) {\n this.state = CircuitState.CLOSED;\n this.failures = 0;\n this.failureTimestamps = [];\n this.openedAt = null;\n logger.info('[CircuitBreaker] Circuit closed after successful test');\n }\n }\n\n recordFailure(): void {\n this.failures++;\n this.consecutiveFailures++;\n this.lastFailureTime = Date.now();\n this.failureTimestamps.push(Date.now());\n\n // Clean up old timestamps\n const windowStart = Date.now() - this.config.failureWindow;\n this.failureTimestamps = this.failureTimestamps.filter((t) => t > windowStart);\n\n // Check if we should open the circuit\n if (this.state === CircuitState.CLOSED && this.failureTimestamps.length >= this.config.failureThreshold) {\n this.state = CircuitState.OPEN;\n this.openedAt = Date.now();\n logger.warn('[CircuitBreaker] Circuit opened due to failures', {\n failures: this.failureTimestamps.length,\n threshold: this.config.failureThreshold,\n });\n }\n\n // If we're half-open and fail, go back to open\n if (this.state === CircuitState.HALF_OPEN) {\n this.state = CircuitState.OPEN;\n this.openedAt = Date.now();\n logger.warn('[CircuitBreaker] Circuit re-opened after failed test');\n }\n }\n\n allowRequest(): boolean {\n this.checkStateTransition();\n\n switch (this.state) {\n case CircuitState.CLOSED:\n return true;\n case CircuitState.OPEN:\n return false;\n case CircuitState.HALF_OPEN:\n // Allow one test request\n return true;\n default:\n return true;\n }\n }\n\n forceOpen(): void {\n this.state = CircuitState.OPEN;\n this.openedAt = Date.now();\n logger.info('[CircuitBreaker] Circuit force-opened');\n }\n\n forceClose(): void {\n this.state = CircuitState.CLOSED;\n this.failures = 0;\n this.consecutiveFailures = 0;\n this.failureTimestamps = [];\n this.openedAt = null;\n logger.info('[CircuitBreaker] Circuit force-closed');\n }\n\n getStats(): CircuitBreakerStats {\n return {\n state: this.state,\n failures: this.failures,\n successes: this.successes,\n consecutiveFailures: this.consecutiveFailures,\n lastFailureTime: this.lastFailureTime,\n lastSuccessTime: this.lastSuccessTime,\n openedAt: this.openedAt,\n };\n }\n\n private checkStateTransition(): void {\n if (this.state === CircuitState.OPEN && this.openedAt) {\n const elapsed = Date.now() - this.openedAt;\n if (elapsed >= this.config.resetTimeout) {\n this.state = CircuitState.HALF_OPEN;\n logger.info('[CircuitBreaker] Circuit transitioning to half-open');\n }\n }\n }\n}\n\n/**\n * Unified Gateway Client\n */\nexport class GatewayClient implements IGatewayClient {\n private config: GatewayClientConfig;\n private layerManager: LayerManager;\n private internalCircuitBreaker: CircuitBreaker;\n private crossLayerCircuitBreaker: CircuitBreaker;\n private retryConfig: GatewayRetryConfig;\n private defaultHeaders: GatewayRequestHeaders;\n\n constructor(config: GatewayClientConfig) {\n this.config = {\n timeout: 30000,\n enableLogging: true,\n ...config,\n };\n\n // Initialize layer manager\n this.layerManager = new LayerManager({\n layer: config.layer,\n serviceName: config.serviceName,\n serviceIdentity: config.serviceIdentity,\n });\n\n // Override URLs if provided\n if (config.internalGatewayUrl) {\n // Use getter internally, but we'll store the override\n }\n if (config.crossLayerGatewayUrl) {\n // Use getter internally, but we'll store the override\n }\n\n // Initialize circuit breakers\n const cbConfig: CircuitBreakerConfig = {\n ...DEFAULT_CIRCUIT_BREAKER_CONFIG,\n ...config.circuitBreaker,\n };\n this.internalCircuitBreaker = new CircuitBreaker(cbConfig);\n this.crossLayerCircuitBreaker = new CircuitBreaker(cbConfig);\n\n // Initialize retry config\n this.retryConfig = {\n ...DEFAULT_GATEWAY_RETRY_CONFIG,\n ...config.retry,\n };\n\n // Initialize default headers\n this.defaultHeaders = {\n 'x-service-identity': this.layerManager.getServiceIdentity(),\n 'x-actor-type': 'service',\n ...config.defaultHeaders,\n };\n\n logger.debug('[GatewayClient] Initialized', {\n layer: config.layer,\n serviceName: config.serviceName,\n internalUrl: this.getInternalUrl(),\n crossLayerUrl: this.getCrossLayerUrl(),\n });\n }\n\n private getInternalUrl(): string {\n return this.config.internalGatewayUrl || this.layerManager.getInternalGatewayUrl();\n }\n\n private getCrossLayerUrl(): string {\n return this.config.crossLayerGatewayUrl || this.layerManager.getCrossLayerGatewayUrl();\n }\n\n /**\n * Execute internal (same layer) GraphQL query/mutation\n */\n async internalQuery<T = unknown>(options: GraphQLRequestOptions): Promise<GraphQLResponse<T>> {\n const context = this.createRequestContext('internal', options);\n\n return this.executeWithRetry(this.getInternalUrl(), options, this.internalCircuitBreaker, context, {\n bypassPermission: true,\n });\n }\n\n /**\n * Execute cross-layer GraphQL query/mutation\n */\n async crossLayerQuery<T = unknown>(options: GraphQLRequestOptions): Promise<GraphQLResponse<T>> {\n const context = this.createRequestContext('cross-layer', options);\n\n return this.executeWithRetry(\n this.getCrossLayerUrl(),\n options,\n this.crossLayerCircuitBreaker,\n context,\n { bypassPermission: false } // Cross-layer calls go through public gateway\n );\n }\n\n /**\n * Execute GraphQL query/mutation with explicit gateway URL\n */\n async query<T = unknown>(gatewayUrl: string, options: GraphQLRequestOptions): Promise<GraphQLResponse<T>> {\n const context = this.createRequestContext('direct', options);\n\n // Use internal circuit breaker for direct calls\n return this.executeWithRetry(gatewayUrl, options, this.internalCircuitBreaker, context, {\n bypassPermission: false,\n });\n }\n\n getInternalCircuitBreaker(): ICircuitBreaker {\n return this.internalCircuitBreaker;\n }\n\n getCrossLayerCircuitBreaker(): ICircuitBreaker {\n return this.crossLayerCircuitBreaker;\n }\n\n getHealthStatus(): GatewayClientHealth {\n return {\n internal: {\n url: this.getInternalUrl(),\n circuitState: this.internalCircuitBreaker.getState(),\n stats: this.internalCircuitBreaker.getStats(),\n },\n crossLayer: {\n url: this.getCrossLayerUrl(),\n circuitState: this.crossLayerCircuitBreaker.getState(),\n stats: this.crossLayerCircuitBreaker.getStats(),\n },\n };\n }\n\n updateDefaultHeaders(headers: Partial<GatewayRequestHeaders>): void {\n this.defaultHeaders = { ...this.defaultHeaders, ...headers };\n }\n\n private createRequestContext(\n callType: 'internal' | 'cross-layer' | 'direct',\n options: GraphQLRequestOptions\n ): RequestContext {\n return {\n requestId: uuidv4(),\n actorId: options.headers?.['x-actor-id'] || this.defaultHeaders['x-actor-id'],\n workspaceId: options.headers?.['x-workspace-id'] || this.defaultHeaders['x-workspace-id'],\n startTime: Date.now(),\n callType,\n };\n }\n\n /**\n * Check if an error should be retried\n */\n private shouldRetryError(error: unknown): boolean {\n if (!(error instanceof GatewayError)) {\n return true;\n }\n // Don't retry GraphQL errors or circuit open errors\n return error.type !== GatewayErrorType.GRAPHQL_ERROR && error.type !== GatewayErrorType.CIRCUIT_OPEN;\n }\n\n /**\n * Calculate retry delay with exponential backoff\n */\n private calculateRetryDelay(attempt: number): number {\n return Math.min(\n this.retryConfig.initialDelay * Math.pow(this.retryConfig.backoffMultiplier, attempt - 1),\n this.retryConfig.maxDelay\n );\n }\n\n /**\n * Log retry attempt if logging is enabled\n */\n private logRetryAttempt(\n context: RequestContext,\n attempt: number,\n maxAttempts: number,\n delay: number,\n error: Error\n ): void {\n if (this.config.enableLogging) {\n logger.warn('[GatewayClient] Request failed, retrying', {\n requestId: context.requestId,\n attempt,\n maxAttempts,\n delay,\n error: error.message,\n });\n }\n }\n\n private async executeWithRetry<T>(\n gatewayUrl: string,\n options: GraphQLRequestOptions,\n circuitBreaker: CircuitBreaker,\n context: RequestContext,\n settings: { bypassPermission: boolean }\n ): Promise<GraphQLResponse<T>> {\n // Check circuit breaker\n if (!options.skipCircuitBreaker && !circuitBreaker.allowRequest()) {\n throw new GatewayError(`Circuit breaker is open for ${gatewayUrl}`, GatewayErrorType.CIRCUIT_OPEN, gatewayUrl);\n }\n\n const maxAttempts = options.skipRetry ? 1 : this.retryConfig.maxAttempts;\n let lastError: Error | null = null;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const result = await this.executeRequest<T>(gatewayUrl, options, context, settings.bypassPermission);\n if (!options.skipCircuitBreaker) {\n circuitBreaker.recordSuccess();\n }\n return result;\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n if (!options.skipCircuitBreaker) {\n circuitBreaker.recordFailure();\n }\n\n if (!this.shouldRetryError(error)) {\n throw error;\n }\n\n if (attempt < maxAttempts) {\n const delay = this.calculateRetryDelay(attempt);\n this.logRetryAttempt(context, attempt, maxAttempts, delay, lastError);\n await this.sleep(delay);\n }\n }\n }\n\n throw lastError || new GatewayError('Request failed after retries', GatewayErrorType.UNKNOWN_ERROR, gatewayUrl);\n }\n\n /**\n * Build headers for a request\n */\n private buildRequestHeaders(\n context: RequestContext,\n options: GraphQLRequestOptions,\n bypassPermission: boolean\n ): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'x-request-id': context.requestId,\n 'x-call-type': context.callType,\n };\n\n // Cross-layer calls transit the peer layer's PUBLIC gateway, which on alpha\n // sits behind Cloudflare Access. Re-present the inbound request's CF creds\n // (service token and/or the CF_Authorization cookie) so the call passes the\n // CF edge. Added before default/request headers so a caller may still\n // override the non-cookie CF headers explicitly; the CF cookie is reconciled\n // after the merges below so it is never silently clobbered. No-op when the\n // inbound request carried no CF creds (local dev, production) — returns {}.\n const cfHeaders = context.callType === 'cross-layer' ? ContextManager.getCfAccessHeaders() : {};\n Object.assign(headers, cfHeaders);\n\n // Add default headers\n for (const [key, value] of Object.entries(this.defaultHeaders)) {\n if (value !== undefined) {\n headers[key] = String(value);\n }\n }\n\n // Add request-specific headers\n if (options.headers) {\n for (const [key, value] of Object.entries(options.headers)) {\n if (value !== undefined) {\n headers[key] = String(value);\n }\n }\n }\n\n // Add bypass headers for internal calls\n if (bypassPermission) {\n headers['x-bypass-permission'] = resolveBypassPermissionValue();\n headers['x-bypass-source'] = this.layerManager.getServiceIdentity();\n headers['x-bypass-timestamp'] = Date.now().toString();\n }\n\n // Reconcile the CF_Authorization cookie: the default/request-header merges\n // above may set their own `cookie`, which would otherwise clobber the CF\n // cookie applied earlier (or vice versa). Merge so both survive, without\n // duplicating if it's already present.\n const cfCookie = cfHeaders['cookie'];\n if (cfCookie) {\n const existing = headers['cookie'];\n if (!existing) {\n headers['cookie'] = cfCookie;\n } else if (!existing.split(';').some((c) => c.trim() === cfCookie)) {\n headers['cookie'] = `${existing}; ${cfCookie}`;\n }\n }\n\n return headers;\n }\n\n /**\n * Handle GraphQL errors in response\n */\n private handleGraphQLErrors<T>(\n result: GraphQLResponse<T>,\n context: RequestContext,\n gatewayUrl: string,\n duration: number\n ): void {\n if (!result.errors || result.errors.length === 0) {\n return;\n }\n\n const errorMessages = result.errors.map((e: GraphQLError) => e.message).join(', ');\n\n if (this.config.enableLogging) {\n logger.warn('[GatewayClient] GraphQL errors', {\n requestId: context.requestId,\n errors: result.errors,\n duration,\n });\n }\n\n throw new GatewayError(`GraphQL error: ${errorMessages}`, GatewayErrorType.GRAPHQL_ERROR, gatewayUrl, {\n graphqlErrors: result.errors,\n });\n }\n\n /**\n * Handle fetch errors\n */\n private handleFetchError(\n error: unknown,\n context: RequestContext,\n gatewayUrl: string,\n timeout: number,\n duration: number\n ): never {\n if (error instanceof GatewayError) {\n throw error;\n }\n\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new GatewayError(`Request timed out after ${timeout}ms`, GatewayErrorType.TIMEOUT_ERROR, gatewayUrl, {\n cause: error,\n });\n }\n\n if (this.config.enableLogging) {\n logger.error('[GatewayClient] Request failed', {\n requestId: context.requestId,\n error: error.message,\n duration,\n });\n }\n\n throw new GatewayError(error.message, GatewayErrorType.NETWORK_ERROR, gatewayUrl, {\n cause: error,\n });\n }\n\n throw new GatewayError(String(error), GatewayErrorType.UNKNOWN_ERROR, gatewayUrl);\n }\n\n private async executeRequest<T>(\n gatewayUrl: string,\n options: GraphQLRequestOptions,\n context: RequestContext,\n bypassPermission: boolean\n ): Promise<GraphQLResponse<T>> {\n const timeout = options.timeout || this.config.timeout || 30000;\n const headers = this.buildRequestHeaders(context, options, bypassPermission);\n\n // Cross-layer calls transit the peer layer's PUBLIC gateway, which\n // requires JWT auth to propagate actor context. Mint a short-lived\n // service-actor JWT so the gateway admits the call and preserves\n // `x-actor-type: service` downstream. Skipped when the caller has\n // already supplied an Authorization header (e.g., user-originated\n // cross-layer flows) or when SERVICE_JWT_SECRET is unset.\n if (context.callType === 'cross-layer' && !hasAuthorizationHeader(headers)) {\n const serviceActorId = this.layerManager.getServiceIdentity();\n const serviceJwt = await signServiceJwt(serviceActorId);\n if (serviceJwt) {\n headers['Authorization'] = `Bearer ${serviceJwt}`;\n } else {\n // Without the JWT this call is already decided: the peer layer's public\n // gateway strips actor headers and the subgraph rejects it. Continuing\n // only converts a missing secret into an authentication error that names\n // the callee — and several cross-layer callers swallow that as\n // best-effort, so it surfaces as nothing at all. In a deployed\n // environment, refuse instead. See ./service-jwt-guard.ts.\n assertServiceJwtConfigured({\n gatewayUrl,\n operationName: options.operationName,\n layer: this.layerManager.getLayer(),\n serviceIdentity: serviceActorId,\n });\n if (this.config.enableLogging) {\n logger.debug(\n '[GatewayClient] SERVICE_JWT_SECRET not configured — cross-layer call will proceed without service JWT',\n { requestId: context.requestId, gatewayUrl }\n );\n }\n }\n }\n\n const body = JSON.stringify({\n query: options.query,\n variables: options.variables || {},\n operationName: options.operationName,\n });\n\n if (this.config.enableLogging) {\n logger.debug('[GatewayClient] Executing request', {\n requestId: context.requestId,\n gatewayUrl,\n operationName: options.operationName,\n callType: context.callType,\n bypassPermission,\n });\n }\n\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n const response = await fetch(gatewayUrl, {\n method: 'POST',\n headers,\n body,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n const duration = Date.now() - context.startTime;\n\n if (!response.ok) {\n throw new GatewayError(\n `HTTP ${response.status}: ${response.statusText}`,\n GatewayErrorType.NETWORK_ERROR,\n gatewayUrl,\n { statusCode: response.status }\n );\n }\n\n const result = (await response.json()) as GraphQLResponse<T>;\n this.handleGraphQLErrors(result, context, gatewayUrl, duration);\n\n if (this.config.enableLogging) {\n logger.debug('[GatewayClient] Request completed', {\n requestId: context.requestId,\n duration,\n hasData: !!result.data,\n });\n }\n\n return result;\n } catch (error) {\n const duration = Date.now() - context.startTime;\n this.handleFetchError(error, context, gatewayUrl, timeout, duration);\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n\n/**\n * Create a gateway client for a specific layer\n */\nexport function createGatewayClient(config: GatewayClientConfig): GatewayClient {\n return new GatewayClient(config);\n}\n\n/**\n * Create a gateway client from environment variables\n *\n * Required environment variables:\n * - SERVICE_LAYER: 'wspace' | 'global'\n * - SERVICE_NAME: Service name\n *\n * Optional:\n * - SERVICE_IDENTITY: Service identity (defaults to SERVICE_NAME)\n * - {LAYER}_INT_GATEWAY_URL: Internal gateway URL\n * - {OPPOSITE_LAYER}_PUBLIC_GATEWAY_URL: Cross-layer gateway URL\n */\nexport function createGatewayClientFromEnv(): GatewayClient {\n const layer = process.env['SERVICE_LAYER'] as ServiceLayer;\n\n if (!layer || (layer !== 'wspace' && layer !== 'global')) {\n throw new Error(`[GatewayClient] Invalid or missing SERVICE_LAYER. Expected 'wspace' or 'global', got '${layer}'`);\n }\n\n const serviceName = process.env['SERVICE_NAME'];\n if (!serviceName) {\n throw new Error('[GatewayClient] SERVICE_NAME environment variable is required');\n }\n\n const serviceIdentity = process.env['SERVICE_IDENTITY'] || serviceName;\n\n return new GatewayClient({\n layer,\n serviceName,\n serviceIdentity,\n });\n}\n"]}
@@ -0,0 +1,21 @@
1
+ import { __name } from './chunk-XE4OXN2W.js';
2
+
3
+ // src/runtime/deployed-environment.ts
4
+ var DEPLOYED_ENVIRONMENTS = /* @__PURE__ */ new Set([
5
+ "alpha",
6
+ "staging",
7
+ "prod",
8
+ "production"
9
+ ]);
10
+ function currentEnvironment() {
11
+ return (process.env["DEPLOY_ENV"] ?? process.env["NODE_ENV"] ?? "").trim().toLowerCase();
12
+ }
13
+ __name(currentEnvironment, "currentEnvironment");
14
+ function isDeployedEnvironment() {
15
+ return DEPLOYED_ENVIRONMENTS.has(currentEnvironment());
16
+ }
17
+ __name(isDeployedEnvironment, "isDeployedEnvironment");
18
+
19
+ export { DEPLOYED_ENVIRONMENTS, currentEnvironment, isDeployedEnvironment };
20
+ //# sourceMappingURL=chunk-A5F6Z5UE.js.map
21
+ //# sourceMappingURL=chunk-A5F6Z5UE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime/deployed-environment.ts"],"names":["DEPLOYED_ENVIRONMENTS","Set","currentEnvironment","process","env","trim","toLowerCase","isDeployedEnvironment","has"],"mappings":";;;AAeO,IAAMA,qBAAAA,uBAAiDC,GAAAA,CAAI;AAAC,EAAA,OAAA;AAAS,EAAA,SAAA;AAAW,EAAA,MAAA;AAAQ,EAAA;AAAa,CAAA;AASrG,SAASC,kBAAAA,GAAAA;AACd,EAAA,OAAA,CAAQC,OAAAA,CAAQC,GAAAA,CAAI,YAAA,CAAA,IAAiBD,OAAAA,CAAQC,GAAAA,CAAI,UAAA,CAAA,IAAe,EAAA,EAAIC,IAAAA,EAAI,CAAGC,WAAAA,EAAW;AACxF;AAFgBJ,MAAAA,CAAAA,kBAAAA,EAAAA,oBAAAA,CAAAA;AAKT,SAASK,qBAAAA,GAAAA;AACd,EAAA,OAAOP,qBAAAA,CAAsBQ,GAAAA,CAAIN,kBAAAA,EAAAA,CAAAA;AACnC;AAFgBK,MAAAA,CAAAA,qBAAAA,EAAAA,uBAAAA,CAAAA","file":"chunk-A5F6Z5UE.js","sourcesContent":["/**\n * One definition of \"is this a deployed environment?\" for the whole SDK.\n *\n * Several guards in this package need to distinguish a laptop from a cluster: a\n * fallback that is a legitimate convenience in local development is, in a\n * deployed environment, a silent misconfiguration that only surfaces later as a\n * 500. Each such guard needs the same answer to the same question.\n *\n * It lives here rather than being copied into each guard because the set below\n * is security-relevant: a guard whose copy of the list drifts stops firing in\n * exactly the environment it was written to protect, and nothing fails until\n * production does.\n */\n\n/** Environments where a local-development fallback is never the right answer. */\nexport const DEPLOYED_ENVIRONMENTS: ReadonlySet<string> = new Set(['alpha', 'staging', 'prod', 'production']);\n\n/**\n * The current deployment environment, lowercased and trimmed.\n *\n * `DEPLOY_ENV` wins over `NODE_ENV`: pods set `DEPLOY_ENV` to the estate name\n * while `NODE_ENV` is frequently just `production` for build semantics, so\n * reading `NODE_ENV` alone would misclassify a local production build.\n */\nexport function currentEnvironment(): string {\n return (process.env['DEPLOY_ENV'] ?? process.env['NODE_ENV'] ?? '').trim().toLowerCase();\n}\n\n/** True when running in alpha, staging or production. */\nexport function isDeployedEnvironment(): boolean {\n return DEPLOYED_ENVIRONMENTS.has(currentEnvironment());\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import { registerDisposable, unregisterDisposable } from './chunk-VBXPFYZ5.js';
2
+ import { currentEnvironment, DEPLOYED_ENVIRONMENTS } from './chunk-A5F6Z5UE.js';
2
3
  import { DEFAULT_LAYER_RESOURCES } from './chunk-YFOHAHZE.js';
3
4
  import { logger } from './chunk-CBZNP6RF.js';
4
5
  import { __export, __name } from './chunk-XE4OXN2W.js';
@@ -19,21 +20,11 @@ __export(cache_exports, {
19
20
  });
20
21
 
21
22
  // src/cache/endpoint.ts
22
- var DEPLOYED_ENVIRONMENTS = /* @__PURE__ */ new Set([
23
- "alpha",
24
- "staging",
25
- "prod",
26
- "production"
27
- ]);
28
23
  var LOOPBACK_HOSTS = /* @__PURE__ */ new Set([
29
24
  "localhost",
30
25
  "127.0.0.1",
31
26
  "::1"
32
27
  ]);
33
- function currentEnvironment() {
34
- return (process.env["DEPLOY_ENV"] ?? process.env["NODE_ENV"] ?? "").trim().toLowerCase();
35
- }
36
- __name(currentEnvironment, "currentEnvironment");
37
28
  function assertCacheEndpointConfigured(check) {
38
29
  const url = check.url?.trim();
39
30
  if (url) return;
@@ -1784,5 +1775,5 @@ async function closeAllCaches() {
1784
1775
  __name(closeAllCaches, "closeAllCaches");
1785
1776
 
1786
1777
  export { CacheFactory, CacheProviderType, MemoryCacheProvider, ValkeyGlideProvider, assertCacheEndpointConfigured, cache_exports, closeAllCaches, createCache, getCache, getValkeyClient, warnOnLayerDefaultEndpoint };
1787
- //# sourceMappingURL=chunk-7UF4Q5HK.js.map
1788
- //# sourceMappingURL=chunk-7UF4Q5HK.js.map
1778
+ //# sourceMappingURL=chunk-AW6JUXCU.js.map
1779
+ //# sourceMappingURL=chunk-AW6JUXCU.js.map