@burdenoff/be-sdk 2026.703.2 → 2026.703.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.
- package/dist/auth/index.d.ts +2 -2
- package/dist/auth/index.js +2 -2
- package/dist/{chunk-OWUVYM2S.js → chunk-5ITGIBF4.js} +14 -6
- package/dist/chunk-5ITGIBF4.js.map +1 -0
- package/dist/{chunk-4OQRBSHM.js → chunk-A6DGEZJ4.js} +3 -3
- package/dist/{chunk-4OQRBSHM.js.map → chunk-A6DGEZJ4.js.map} +1 -1
- package/dist/{chunk-F5BPKP75.js → chunk-BMK6ZIP6.js} +3 -3
- package/dist/{chunk-F5BPKP75.js.map → chunk-BMK6ZIP6.js.map} +1 -1
- package/dist/{chunk-YEA4BZOL.js → chunk-MNKU7I2G.js} +3 -3
- package/dist/{chunk-YEA4BZOL.js.map → chunk-MNKU7I2G.js.map} +1 -1
- package/dist/{chunk-EZ4PKRUK.js → chunk-QGBXVNRM.js} +2 -2
- package/dist/chunk-QGBXVNRM.js.map +1 -0
- package/dist/{chunk-NRSIT4VI.js → chunk-RNR45JQH.js} +2 -2
- package/dist/{chunk-NRSIT4VI.js.map → chunk-RNR45JQH.js.map} +1 -1
- package/dist/{chunk-SS4XWRYR.js → chunk-RXMOV3YE.js} +3 -3
- package/dist/{chunk-SS4XWRYR.js.map → chunk-RXMOV3YE.js.map} +1 -1
- package/dist/{chunk-DXX6C6X6.js → chunk-RZOFS2BQ.js} +26 -11
- package/dist/chunk-RZOFS2BQ.js.map +1 -0
- package/dist/{chunk-6NB7P6SR.js → chunk-S32JOMMW.js} +3 -3
- package/dist/{chunk-6NB7P6SR.js.map → chunk-S32JOMMW.js.map} +1 -1
- package/dist/{chunk-P7SUUFEX.js → chunk-STLDHYPB.js} +3 -3
- package/dist/{chunk-P7SUUFEX.js.map → chunk-STLDHYPB.js.map} +1 -1
- package/dist/{chunk-UJI2S556.js → chunk-WUXITWC2.js} +3 -3
- package/dist/{chunk-UJI2S556.js.map → chunk-WUXITWC2.js.map} +1 -1
- package/dist/{chunk-TYXGWVRL.js → chunk-XN3DNXXV.js} +5 -5
- package/dist/{chunk-TYXGWVRL.js.map → chunk-XN3DNXXV.js.map} +1 -1
- package/dist/{chunk-IUL5TEKE.js → chunk-ZMCD5XAK.js} +3 -3
- package/dist/{chunk-IUL5TEKE.js.map → chunk-ZMCD5XAK.js.map} +1 -1
- package/dist/database/index.js +2 -2
- package/dist/event-queue/index.d.ts +3 -3
- package/dist/export/index.js +3 -3
- package/dist/feature-flags/index.js +2 -2
- package/dist/gateway/index.js +2 -2
- package/dist/graph/index.d.ts +3 -3
- package/dist/graph/index.js +2 -2
- package/dist/{graphql-BRj5KPOL.d.ts → graphql-Dxxpbzr3.d.ts} +1 -1
- package/dist/{index-B3ECnOLp.d.ts → index-5QTY_V54.d.ts} +2 -2
- package/dist/{index-DDCOGyYh.d.ts → index-B8viwwDM.d.ts} +1 -0
- package/dist/{index-DvDoMbXM.d.ts → index-Bui1kclE.d.ts} +2 -2
- package/dist/{index-CNy4MwKc.d.ts → index-C0qWSC_Q.d.ts} +1 -1
- package/dist/{index-DsBZRR82.d.ts → index-CDPSJW0O.d.ts} +3 -3
- package/dist/{index-BIhZJ1w7.d.ts → index-CXPvdXhS.d.ts} +1 -1
- package/dist/{index-1qCbBvKE.d.ts → index-Cpr38QiE.d.ts} +2 -2
- package/dist/index.d.ts +15 -14
- package/dist/index.js +27 -23
- package/dist/index.js.map +1 -1
- package/dist/init/index.js +3 -3
- package/dist/instrumentation/index.d.ts +3 -3
- package/dist/logger/index.d.ts +2 -2
- package/dist/notifications/index.d.ts +3 -3
- package/dist/notifications/index.js +2 -2
- package/dist/pino-logger-XF275Y5C.js +5 -0
- package/dist/{pino-logger-TSRWXWIU.js.map → pino-logger-XF275Y5C.js.map} +1 -1
- package/dist/rbac/index.d.ts +2 -2
- package/dist/rbac/index.js +2 -2
- package/dist/resource-caps/index.d.ts +2 -2
- package/dist/server/index.js +2 -2
- package/dist/server/index.js.map +1 -1
- package/dist/telemetry/index.d.ts +4 -4
- package/dist/telemetry/index.js +2 -2
- package/dist/tracker/index.d.ts +4 -4
- package/dist/tracker/index.js +4 -4
- package/package.json +1 -1
- package/dist/chunk-DXX6C6X6.js.map +0 -1
- package/dist/chunk-EZ4PKRUK.js.map +0 -1
- package/dist/chunk-OWUVYM2S.js.map +0 -1
- package/dist/pino-logger-TSRWXWIU.js +0 -5
package/dist/tracker/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import '../graphql-
|
|
2
|
-
import '../index-
|
|
3
|
-
export { a as ActivityTrackingOptions, P as ProductTracker, R as RbacCheckOptions, b as TrackOptions, c as TrackResult, T as TrackerModule, d as TrackingEvent, e as UNIFIED_TRACKER_CONSTANTS, f as UnifiedTrackerStub, g as UnifiedTrackingOptions, h as UsageMetricType, i as UsageTrackingOptions, j as createProductTracker, t as trackOperation, k as trackerStub } from '../index-
|
|
4
|
-
import '../index-
|
|
1
|
+
import '../graphql-Dxxpbzr3.js';
|
|
2
|
+
import '../index-B8viwwDM.js';
|
|
3
|
+
export { a as ActivityTrackingOptions, P as ProductTracker, R as RbacCheckOptions, b as TrackOptions, c as TrackResult, T as TrackerModule, d as TrackingEvent, e as UNIFIED_TRACKER_CONSTANTS, f as UnifiedTrackerStub, g as UnifiedTrackingOptions, h as UsageMetricType, i as UsageTrackingOptions, j as createProductTracker, t as trackOperation, k as trackerStub } from '../index-CDPSJW0O.js';
|
|
4
|
+
import '../index-Cpr38QiE.js';
|
|
5
5
|
import 'graphql-request';
|
|
6
6
|
import '../layer-GNAVXBMf.js';
|
package/dist/tracker/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { TrackerModule, UNIFIED_TRACKER_CONSTANTS, UnifiedTrackerStub, UsageMetricType, createProductTracker, trackOperation, trackerStub } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
3
|
-
import '../chunk-
|
|
4
|
-
import '../chunk-
|
|
1
|
+
export { TrackerModule, UNIFIED_TRACKER_CONSTANTS, UnifiedTrackerStub, UsageMetricType, createProductTracker, trackOperation, trackerStub } from '../chunk-XN3DNXXV.js';
|
|
2
|
+
import '../chunk-S32JOMMW.js';
|
|
3
|
+
import '../chunk-ZMCD5XAK.js';
|
|
4
|
+
import '../chunk-QGBXVNRM.js';
|
|
5
5
|
import '../chunk-YFOHAHZE.js';
|
|
6
6
|
import '../chunk-CBZNP6RF.js';
|
|
7
7
|
import '../chunk-XE4OXN2W.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@burdenoff/be-sdk",
|
|
3
|
-
"version": "2026.703.
|
|
3
|
+
"version": "2026.703.4",
|
|
4
4
|
"description": "Backend SDK for Burdenoff products providing unified access to notifications, RBAC, activity tracking, usage monitoring, and more",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/context/index.ts"],"names":["asyncLocalStorage","AsyncLocalStorage","cfAccessFallback","ContextManager","getContext","getStore","setContext","context","currentContext","enterWith","cfAccessClientId","cfAccessClientSecret","setCfAccessContext","clientId","clientSecret","withContext","fn","run","withContextSync","clearContext","disable","undefined","getActorId","actorId","getUser","userId","getWorkspace","workspaceId","getTenant","tenantId","getOrganization","organizationId","getProject","projectId","getApp","appId","getToken","token","getProduct","productId","getCfAccessClientId","getCfAccessClientSecret","getCfAccessHeaders","updateContext","updates","current","hasContext","getCustomField","key","setCustomField","value"],"mappings":"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","file":"chunk-DXX6C6X6.js","sourcesContent":["/**\n * Context Module\n * Manages request-scoped context using AsyncLocalStorage\n * Thread-safe context propagation for async operations\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport type { SDKContext } from '../types/index.js';\n\nconst asyncLocalStorage = new AsyncLocalStorage<SDKContext>();\n\n/**\n * Module-level fallback for the Cloudflare Access service token.\n *\n * WHY THIS EXISTS — read before \"simplifying\" it away:\n * `asyncLocalStorage.enterWith()` (used by `setContext`) does NOT reliably\n * propagate across every async boundary under Bun + GraphQL Yoga — the same\n * limitation documented for the Prisma workspace context store\n * (see `src/prisma/workspace-extension.ts`). On top of that, the `createServer`\n * request path (`src/server/context.ts` `buildContext`) populates the *Prisma*\n * workspace store, not this `ContextManager` ALS at all. So a resolver-initiated\n * cross-layer call would otherwise read an empty context and attach no CF creds,\n * making the propagation a silent no-op on alpha.\n *\n * Unlike workspaceId/actorId (which differ per request and would race in a\n * module-level singleton), the CF Access service token is effectively\n * CONSTANT per environment — it's a single service-token pair fronting the\n * gateway. So caching it module-side is race-safe: concurrent requests all\n * carry the same value. It is only ever set when a request actually presents\n * the headers (gated upstream on `cf-ray`), and stays unset in dev/prod where\n * no CF Access sits in front of the gateways.\n */\nlet cfAccessFallback: { clientId: string; clientSecret: string } | undefined;\n\n/**\n * Context Manager for handling request-scoped context\n */\nexport class ContextManager {\n /**\n * Get current context from async local storage\n */\n public static getContext(): SDKContext | undefined {\n return asyncLocalStorage.getStore();\n }\n\n /**\n * Set context for current async scope\n * Merges with existing context if present\n */\n public static setContext(context: SDKContext): void {\n const currentContext = this.getContext() || {};\n asyncLocalStorage.enterWith({ ...currentContext, ...context });\n // Mirror CF creds to the module-level fallback so cross-layer calls can\n // recover them even when enterWith() doesn't reach the resolver chain.\n if (context.cfAccessClientId && context.cfAccessClientSecret) {\n this.setCfAccessContext(context.cfAccessClientId, context.cfAccessClientSecret);\n }\n }\n\n /**\n * Record the Cloudflare Access service token for the current process.\n *\n * Call this from every request-context builder that may receive CF headers\n * (the SDK `createServer` `buildContext` and the bootstrap HTTP middleware\n * both do). Stored in a module-level fallback because `enterWith()` is not a\n * reliable carrier under Bun + Yoga — see the `cfAccessFallback` note above.\n *\n * Deliberately a NO-OP when either cred is absent: `buildContext` runs on\n * every request, so clearing here on a tokenless request could wipe the value\n * a concurrent CF request just stored. The token is constant per environment,\n * so \"remember, never clear on absence\" is both safe and correct. Use\n * `clearContext()` to reset (shutdown / tests).\n */\n public static setCfAccessContext(clientId?: string, clientSecret?: string): void {\n if (clientId && clientSecret) {\n cfAccessFallback = { clientId, clientSecret };\n }\n }\n\n /**\n * Run function with specific context\n * Context is isolated to this execution and its children\n */\n public static async withContext<T>(context: SDKContext, fn: () => Promise<T>): Promise<T> {\n return asyncLocalStorage.run(context, fn);\n }\n\n /**\n * Run synchronous function with specific context\n */\n public static withContextSync<T>(context: SDKContext, fn: () => T): T {\n return asyncLocalStorage.run(context, fn);\n }\n\n /**\n * Clear current context (including the module-level CF Access fallback).\n */\n public static clearContext(): void {\n asyncLocalStorage.disable();\n cfAccessFallback = undefined;\n }\n\n /**\n * Get actor ID from context\n */\n public static getActorId(): string | undefined {\n return this.getContext()?.actorId;\n }\n\n /**\n * Get legacy user ID from context.\n */\n public static getUser(): string | undefined {\n const context = this.getContext();\n const userId = context?.['userId'];\n return typeof userId === 'string' ? userId : context?.actorId;\n }\n\n /**\n * Get workspace ID from context\n */\n public static getWorkspace(): string | undefined {\n return this.getContext()?.workspaceId;\n }\n\n /**\n * Get tenant ID from context\n */\n public static getTenant(): string | undefined {\n return this.getContext()?.tenantId;\n }\n\n /**\n * Get legacy organization ID from context.\n */\n public static getOrganization(): string | undefined {\n const organizationId = this.getContext()?.['organizationId'];\n return typeof organizationId === 'string' ? organizationId : undefined;\n }\n\n /**\n * Get project ID from context\n */\n public static getProject(): string | undefined {\n return this.getContext()?.projectId;\n }\n\n /**\n * Get app ID from context\n */\n public static getApp(): string | undefined {\n return this.getContext()?.appId;\n }\n\n /**\n * Get JWT token from context\n */\n public static getToken(): string | undefined {\n return this.getContext()?.token;\n }\n\n /**\n * Get product ID from context\n */\n public static getProduct(): string | undefined {\n return this.getContext()?.productId;\n }\n\n /**\n * Get the Cloudflare Access service-token client id (ALS first, then the\n * module-level fallback — see `cfAccessFallback`).\n */\n public static getCfAccessClientId(): string | undefined {\n return this.getContext()?.cfAccessClientId ?? cfAccessFallback?.clientId;\n }\n\n /**\n * Get the Cloudflare Access service-token client secret (ALS first, then the\n * module-level fallback — see `cfAccessFallback`).\n */\n public static getCfAccessClientSecret(): string | undefined {\n return this.getContext()?.cfAccessClientSecret ?? cfAccessFallback?.clientSecret;\n }\n\n /**\n * Build the Cloudflare Access service-token header pair to re-present on a\n * cross-layer outbound call.\n *\n * Cross-layer calls (wspace ↔ global) traverse the peer layer's PUBLIC\n * gateway, which on alpha sits behind Cloudflare Access. Without the CF\n * service token the request is rejected at the CF edge before reaching the\n * gateway. We reuse the *inbound* request's CF creds (propagated by the\n * public gateway into request-scoped context) so the cross-layer leg passes.\n *\n * Inbound-only: sourced from the request context (AsyncLocalStorage first,\n * module-level fallback second — see `cfAccessFallback`). Returns `{}` unless\n * BOTH creds are present — so it is a no-op in environments without CF in\n * front of the gateways (local dev, and production, which is not\n * CF-Access-gated and has no CF service token).\n */\n public static getCfAccessHeaders(): Record<string, string> {\n const clientId = this.getCfAccessClientId();\n const clientSecret = this.getCfAccessClientSecret();\n if (clientId && clientSecret) {\n return {\n 'cf-access-client-id': clientId,\n 'cf-access-client-secret': clientSecret,\n };\n }\n return {};\n }\n\n /**\n * Update specific context fields\n */\n public static updateContext(updates: Partial<SDKContext>): void {\n const current = this.getContext();\n if (current) {\n this.setContext({ ...current, ...updates });\n } else {\n this.setContext(updates);\n }\n }\n\n /**\n * Check if context exists\n */\n public static hasContext(): boolean {\n return this.getContext() !== undefined;\n }\n\n /**\n * Get custom field from context\n */\n public static getCustomField(key: string): unknown {\n return this.getContext()?.[key];\n }\n\n /**\n * Set custom field in context\n */\n public static setCustomField(key: string, value: unknown): void {\n const current = this.getContext() || {};\n this.setContext({ ...current, [key]: value });\n }\n}\n\n/**\n * Default export for convenience\n */\nexport const contextManager = ContextManager;\n\n/**\n * Helper function to extract context from HTTP request\n */\nexport function extractContextFromRequest(req: {\n headers: Record<string, string | string[] | undefined>;\n user?: { user_id?: string; workspace_id?: string; tenant_endpoint?: string };\n}): SDKContext {\n const context: SDKContext = {};\n\n // Extract from user object (if JWT already verified)\n if (req.user) {\n context.actorId = req.user.user_id;\n context.workspaceId = req.user.workspace_id;\n context.tenantId = req.user.tenant_endpoint;\n }\n\n // Extract from headers\n const getHeader = (key: string): string | undefined => {\n const value = req.headers[key.toLowerCase()];\n return Array.isArray(value) ? value[0] : value;\n };\n\n const authHeader = getHeader('authorization');\n if (authHeader) {\n context.token = authHeader.replace('Bearer ', '');\n }\n\n const workspaceId = getHeader('x-workspace-id');\n if (workspaceId && !context.workspaceId) {\n context.workspaceId = workspaceId;\n }\n\n const productId = getHeader('x-product-id');\n if (productId) {\n context.productId = productId;\n }\n\n const projectId = getHeader('x-project-id');\n if (projectId) {\n context.projectId = projectId;\n }\n\n const appId = getHeader('x-app-id');\n if (appId) {\n context.appId = appId;\n }\n\n // Cloudflare Access service token. Forwarded to subgraphs by the public\n // gateways only when the request actually transited CF (cf-ray present), so\n // we can capture whatever arrives here. Re-presented on cross-layer outbound\n // calls — see ContextManager.getCfAccessHeaders.\n const cfAccessClientId = getHeader('cf-access-client-id');\n if (cfAccessClientId) {\n context.cfAccessClientId = cfAccessClientId;\n }\n\n const cfAccessClientSecret = getHeader('cf-access-client-secret');\n if (cfAccessClientSecret) {\n context.cfAccessClientSecret = cfAccessClientSecret;\n }\n\n return context;\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types/index.ts"],"names":["SDKError","Error","message","code","details","name","Object","setPrototypeOf","prototype","PermissionDeniedError","AuthenticationError","APIError","ValidationError","QuotaExceededError","NetworkError","TimeoutError"],"mappings":"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","file":"chunk-EZ4PKRUK.js","sourcesContent":["/**\n * Core type definitions for Burdenoff Backend SDK\n */\n\nimport type { ServiceLayer } from './layer.js';\n\n/**\n * SDK Configuration\n */\nexport interface SDKConfig {\n /** Workspaces API GraphQL endpoint (should point to wspace-int-gateway for M2M calls) */\n workspacesApiUrl: string;\n /**\n * Tenant API GraphQL endpoint for cross-layer (wspace → global) M2M calls.\n * Cross-layer traffic must go through the **public** global gateway\n * (`GLOBAL_PUBLIC_GATEWAY_URL`), not the internal gateway — ACA internal\n * ingress is environment-scoped and does not route across the wspace/global\n * environment boundary.\n */\n tenantApiUrl?: string;\n /**\n * Calling service's layer (`wspace` | `global`). Used to construct the\n * cross-layer GatewayClient. Defaults to the `SERVICE_LAYER` env var, then\n * `wspace`.\n */\n serviceLayer?: ServiceLayer;\n /**\n * Calling service name. Used as the cross-layer GatewayClient service identity\n * and the `sub` of the minted service JWT. Defaults to the `SERVICE_NAME` env\n * var, then `burdenoff-be-sdk`.\n */\n serviceName?: string;\n /** Default timeout for API requests in milliseconds */\n timeout?: number;\n /** Retry configuration */\n retry?: RetryConfig;\n /** Logger configuration */\n logger?: LoggerConfig;\n /** Event queue configuration (Redis Streams). Reads `REDIS_URL` when present. */\n eventQueue?: EventQueueSDKConfig;\n /** Temporal module type (workspace or tenant) */\n temporalModuleType?: 'workspace' | 'tenant';\n /** Temporal server address */\n temporalAddress?: string;\n /** Temporal namespace */\n temporalNamespace?: string;\n /** Temporal task queue */\n temporalTaskQueue?: string;\n /** Auto-connect to Temporal (default: true) */\n temporalAutoConnect?: boolean;\n}\n\n/**\n * Retry configuration for API requests\n */\nexport interface RetryConfig {\n /** Maximum number of retry attempts */\n maxAttempts: number;\n /** Initial retry delay in milliseconds */\n initialDelay: number;\n /** Maximum retry delay in milliseconds */\n maxDelay: number;\n /** Backoff multiplier */\n backoffMultiplier: number;\n}\n\n/**\n * Logger configuration\n */\nexport interface LoggerConfig {\n /** Log level */\n level: 'debug' | 'info' | 'warn' | 'error';\n /** Enable console output */\n console: boolean;\n /** Custom logger transport */\n transport?: LoggerTransport;\n}\n\n/**\n * Custom logger transport interface\n */\nexport interface LoggerTransport {\n log(level: string, message: string, meta?: Record<string, unknown>): void;\n}\n\n/**\n * Actor type for RBAC authorization\n * - user: Direct user request (via frontend)\n * - app: OAuth app acting on behalf of user\n * - service: M2M service-to-service communication\n * - super_admin: Platform administration (bypasses all checks)\n */\nexport type ActorType = 'user' | 'app' | 'service' | 'super_admin';\n\n/**\n * Request context passed with every SDK operation\n */\nexport interface SDKContext {\n /** Actor ID - identifies the entity making the request */\n actorId?: string;\n /** Actor type - determines authorization behavior */\n actorType?: ActorType;\n /** Workspace ID */\n workspaceId?: string;\n /** Tenant ID */\n tenantId?: string;\n /** Project ID */\n projectId?: string;\n /** App ID */\n appId?: string;\n /** JWT token for authentication */\n token?: string;\n /** Product ID */\n productId?: string;\n /**\n * Cloudflare Access service-token client id, captured from the inbound\n * `cf-access-client-id` header. Re-presented on cross-layer outbound calls so\n * the peer layer's CF-Access-gated public gateway admits the request.\n */\n cfAccessClientId?: string;\n /**\n * Cloudflare Access service-token client secret, from `cf-access-client-secret`.\n * Sensitive — redacted by the SDK logger's secret pattern; never log directly.\n */\n cfAccessClientSecret?: string;\n /** Additional custom context */\n [key: string]: unknown;\n}\n\n/**\n * SDK Error base class\n */\nexport class SDKError extends Error {\n constructor(\n message: string,\n public code: string,\n public details?: Record<string, unknown>\n ) {\n super(message);\n this.name = 'SDKError';\n Object.setPrototypeOf(this, SDKError.prototype);\n }\n}\n\n/**\n * Permission denied error\n */\nexport class PermissionDeniedError extends SDKError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, 'PERMISSION_DENIED', details);\n this.name = 'PermissionDeniedError';\n Object.setPrototypeOf(this, PermissionDeniedError.prototype);\n }\n}\n\n/**\n * Authentication error\n */\nexport class AuthenticationError extends SDKError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, 'AUTHENTICATION_ERROR', details);\n this.name = 'AuthenticationError';\n Object.setPrototypeOf(this, AuthenticationError.prototype);\n }\n}\n\n/**\n * API error from backend\n */\nexport class APIError extends SDKError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, 'API_ERROR', details);\n this.name = 'APIError';\n Object.setPrototypeOf(this, APIError.prototype);\n }\n}\n\n/**\n * Validation error\n */\nexport class ValidationError extends SDKError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, 'VALIDATION_ERROR', details);\n this.name = 'ValidationError';\n Object.setPrototypeOf(this, ValidationError.prototype);\n }\n}\n\n/**\n * Quota exceeded error\n */\nexport class QuotaExceededError extends SDKError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, 'QUOTA_EXCEEDED', details);\n this.name = 'QuotaExceededError';\n Object.setPrototypeOf(this, QuotaExceededError.prototype);\n }\n}\n\n/**\n * Network error\n */\nexport class NetworkError extends SDKError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, 'NETWORK_ERROR', details);\n this.name = 'NetworkError';\n Object.setPrototypeOf(this, NetworkError.prototype);\n }\n}\n\n/**\n * Timeout error\n */\nexport class TimeoutError extends SDKError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, 'TIMEOUT_ERROR', details);\n this.name = 'TimeoutError';\n Object.setPrototypeOf(this, TimeoutError.prototype);\n }\n}\n\n/**\n * Event queue SDK configuration (Redis Streams backend).\n *\n * The publisher is created via `createPublisher()` from\n * `@burdenoff/be-sdk/event-queue` and reads `REDIS_URL` from the env.\n * The fields here are for client-name + reconnect tuning only.\n */\nexport interface EventQueueSDKConfig {\n /** Redis Streams server URL. Overrides `REDIS_URL` env if set. */\n url?: string;\n /** Optional password for TLS/auth */\n password?: string;\n /** Maximum reconnect attempts (default: -1 = infinite) */\n maxReconnectAttempts?: number;\n /** Reconnect time wait in milliseconds (default: 2000) */\n reconnectTimeWait?: number;\n /** Client name for logging (default: service name) */\n name?: string;\n /** Auto-connect on SDK initialization (default: true) */\n autoConnect?: boolean;\n}\n\n/**\n * Event queue health status\n */\nexport interface EventQueueHealthStatus {\n status: 'healthy' | 'unhealthy' | 'not_configured';\n connected: boolean;\n url?: string;\n details?: Record<string, unknown>;\n}\n\n/**\n * Temporal health status\n */\nexport interface TemporalHealthStatus {\n status: 'healthy' | 'unhealthy' | 'not_configured';\n connected: boolean;\n address?: string;\n namespace?: string;\n details?: Record<string, unknown>;\n}\n\n/**\n * Overall SDK health status\n */\nexport interface SDKHealthStatus {\n eventQueue: EventQueueHealthStatus;\n temporal: TemporalHealthStatus;\n}\n\n/**\n * SDK shutdown options\n */\nexport interface SDKShutdownOptions {\n /** Shutdown timeout in milliseconds (default: 5000) */\n timeout?: number;\n /** Force shutdown even if timeout is exceeded (default: true) */\n force?: boolean;\n}\n\n// ============================================================================\n// Layer Types Export\n// ============================================================================\n\n/**\n * Re-export all layer-related types for convenience\n */\nexport type {\n ServiceLayer,\n LayerConfig,\n LayerGatewayConfig,\n LayerResourceUrls,\n LayerFullConfig,\n GatewayRoutingConfig,\n CircuitBreakerConfig,\n GatewayRetryConfig,\n GatewayRequestHeaders,\n} from './layer.js';\n\nexport {\n DEFAULT_GATEWAY_ROUTING,\n DEFAULT_LAYER_RESOURCES,\n DEFAULT_LAYER_STREAMS,\n DEFAULT_CIRCUIT_BREAKER_CONFIG,\n DEFAULT_GATEWAY_RETRY_CONFIG,\n} from './layer.js';\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/gateway/index.ts","../src/gateway/types.ts","../src/gateway/client.ts"],"names":["CircuitState","GatewayErrorType","GatewayError","Error","type","gatewayUrl","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","layer","serviceName","serviceIdentity","internalGatewayUrl","crossLayerGatewayUrl","cbConfig","DEFAULT_CIRCUIT_BREAKER_CONFIG","circuitBreaker","DEFAULT_GATEWAY_RETRY_CONFIG","retry","getServiceIdentity","debug","internalUrl","getInternalUrl","crossLayerUrl","getCrossLayerUrl","getInternalGatewayUrl","getCrossLayerGatewayUrl","internalQuery","context","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","assign","ContextManager","getCfAccessHeaders","value","entries","undefined","toString","handleGraphQLErrors","duration","errors","errorMessages","map","e","join","handleFetchError","TIMEOUT_ERROR","NETWORK_ERROR","serviceActorId","serviceJwt","signServiceJwt","body","JSON","stringify","variables","operationName","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-OWUVYM2S.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 * 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 {\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 service\n // token so the call passes the CF edge. Added before default/request headers\n // so a caller may still override it explicitly. No-op when the inbound\n // request carried no CF creds (local dev, production) — returns {}.\n if (context.callType === 'cross-layer') {\n Object.assign(headers, ContextManager.getCfAccessHeaders());\n }\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 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 if (this.config.enableLogging) {\n // Subtle failure mode: without the JWT the public gateway strips\n // actor headers and the subgraph rejects with `authenticationRequired`.\n // Surface the root cause so operators rolling out a new caller don't\n // spend time debugging the downstream error.\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 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"]}
|