@parsrun/service 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +375 -0
- package/dist/client.d.ts +55 -0
- package/dist/client.js +1474 -0
- package/dist/client.js.map +1 -0
- package/dist/define.d.ts +82 -0
- package/dist/define.js +120 -0
- package/dist/define.js.map +1 -0
- package/dist/events/index.d.ts +285 -0
- package/dist/events/index.js +853 -0
- package/dist/events/index.js.map +1 -0
- package/dist/handler-CmiDUWZv.d.ts +204 -0
- package/dist/index-CVOAoJjZ.d.ts +268 -0
- package/dist/index.d.ts +46 -0
- package/dist/index.js +3589 -0
- package/dist/index.js.map +1 -0
- package/dist/resilience/index.d.ts +197 -0
- package/dist/resilience/index.js +387 -0
- package/dist/resilience/index.js.map +1 -0
- package/dist/rpc/index.d.ts +5 -0
- package/dist/rpc/index.js +1175 -0
- package/dist/rpc/index.js.map +1 -0
- package/dist/serialization/index.d.ts +37 -0
- package/dist/serialization/index.js +320 -0
- package/dist/serialization/index.js.map +1 -0
- package/dist/server-DFE8n2Sx.d.ts +106 -0
- package/dist/tracing/index.d.ts +406 -0
- package/dist/tracing/index.js +820 -0
- package/dist/tracing/index.js.map +1 -0
- package/dist/transports/cloudflare/index.d.ts +237 -0
- package/dist/transports/cloudflare/index.js +746 -0
- package/dist/transports/cloudflare/index.js.map +1 -0
- package/dist/types-n4LLSPQU.d.ts +473 -0
- package/package.json +91 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/transports/cloudflare/binding.ts","../../../src/serialization/index.ts","../../../src/rpc/errors.ts","../../../src/rpc/transports/http.ts","../../../src/transports/cloudflare/queue.ts","../../../src/events/format.ts","../../../src/events/handler.ts","../../../src/transports/cloudflare/durable-object.ts"],"sourcesContent":["/**\n * @parsrun/service - Cloudflare Service Binding Transport\n * RPC transport using Cloudflare Workers Service Bindings\n */\n\nimport type { Logger } from \"@parsrun/core\";\nimport { createLogger } from \"@parsrun/core\";\nimport type {\n RpcRequest,\n RpcResponse,\n RpcTransport,\n Fetcher,\n} from \"../../types.js\";\nimport { type Serializer, jsonSerializer } from \"../../serialization/index.js\";\nimport { TransportError, SerializationError } from \"../../rpc/errors.js\";\n\n// ============================================================================\n// SERVICE BINDING TRANSPORT\n// ============================================================================\n\nexport interface ServiceBindingTransportOptions {\n /** Service name */\n serviceName: string;\n /** Cloudflare service binding */\n binding: Fetcher;\n /** Serializer (default: JSON) */\n serializer?: Serializer;\n /** Logger */\n logger?: Logger;\n /** Timeout in ms */\n timeout?: number;\n}\n\n/**\n * RPC transport using Cloudflare Service Bindings\n *\n * Service bindings provide zero-latency, in-network communication\n * between Cloudflare Workers.\n */\nexport class ServiceBindingTransport implements RpcTransport {\n readonly name = \"service-binding\";\n private readonly serviceName: string;\n private readonly binding: Fetcher;\n private readonly serializer: Serializer;\n private readonly logger: Logger;\n\n constructor(options: ServiceBindingTransportOptions) {\n this.serviceName = options.serviceName;\n this.binding = options.binding;\n this.serializer = options.serializer ?? jsonSerializer;\n this.logger = options.logger ?? createLogger({ name: `binding:${options.serviceName}` });\n // Note: timeout option reserved for future AbortController support\n }\n\n async call<TInput, TOutput>(request: RpcRequest<TInput>): Promise<RpcResponse<TOutput>> {\n const startTime = Date.now();\n\n try {\n // Serialize request\n let body: string | ArrayBuffer;\n try {\n body = this.serializer.encode(request);\n } catch (error) {\n throw new SerializationError(\n \"Failed to serialize request\",\n error instanceof Error ? error : undefined\n );\n }\n\n // Build headers\n const headers: Record<string, string> = {\n \"Content-Type\": this.serializer.contentType,\n Accept: this.serializer.contentType,\n \"X-Request-ID\": request.id,\n \"X-Service\": request.service,\n \"X-Method\": request.method,\n \"X-Method-Type\": request.type,\n };\n\n if (request.version) {\n headers[\"X-Service-Version\"] = request.version;\n }\n\n if (request.traceContext) {\n headers[\"traceparent\"] = formatTraceparent(request.traceContext);\n if (request.traceContext.traceState) {\n headers[\"tracestate\"] = request.traceContext.traceState;\n }\n }\n\n if (request.metadata?.tenantId) {\n headers[\"X-Tenant-ID\"] = String(request.metadata.tenantId);\n }\n\n // Make request via service binding\n const response = await this.binding.fetch(\"http://internal/rpc\", {\n method: \"POST\",\n headers,\n body: typeof body === \"string\" ? body : body,\n });\n\n // Parse response\n let responseData: RpcResponse<TOutput>;\n try {\n const contentType = response.headers.get(\"Content-Type\") ?? \"\";\n if (contentType.includes(\"msgpack\")) {\n const buffer = await response.arrayBuffer();\n responseData = this.serializer.decode(buffer) as RpcResponse<TOutput>;\n } else {\n const text = await response.text();\n responseData = this.serializer.decode(text) as RpcResponse<TOutput>;\n }\n } catch (error) {\n throw new SerializationError(\n \"Failed to deserialize response\",\n error instanceof Error ? error : undefined\n );\n }\n\n const duration = Date.now() - startTime;\n this.logger.debug(`RPC call completed`, {\n service: this.serviceName,\n method: request.method,\n durationMs: duration,\n success: responseData.success,\n });\n\n return responseData;\n } catch (error) {\n const duration = Date.now() - startTime;\n\n if (error instanceof SerializationError) {\n throw error;\n }\n\n this.logger.error(`RPC call failed`, error as Error, {\n service: this.serviceName,\n method: request.method,\n durationMs: duration,\n });\n\n throw new TransportError(\n `Service binding call failed: ${(error as Error).message}`,\n error as Error\n );\n }\n }\n\n async close(): Promise<void> {\n // Service bindings don't need cleanup\n }\n}\n\n/**\n * Create a service binding transport\n */\nexport function createServiceBindingTransport(\n options: ServiceBindingTransportOptions\n): ServiceBindingTransport {\n return new ServiceBindingTransport(options);\n}\n\n// ============================================================================\n// SERVICE BINDING HANDLER\n// ============================================================================\n\nimport type { RpcServer } from \"../../rpc/server.js\";\nimport { parseTraceparent } from \"../../rpc/transports/http.js\";\n\n/**\n * Create a request handler for service binding requests\n *\n * @example\n * ```typescript\n * // In your worker\n * export default {\n * fetch: createServiceBindingHandler(rpcServer),\n * };\n * ```\n */\nexport function createServiceBindingHandler(\n server: RpcServer,\n options?: {\n serializer?: Serializer;\n logger?: Logger;\n }\n): (request: Request) => Promise<Response> {\n const serializer = options?.serializer ?? jsonSerializer;\n const logger = options?.logger ?? createLogger({ name: \"binding-handler\" });\n\n return async (request: Request): Promise<Response> => {\n // Only handle POST to /rpc\n const url = new URL(request.url);\n if (request.method !== \"POST\" || url.pathname !== \"/rpc\") {\n return new Response(\"Not Found\", { status: 404 });\n }\n\n try {\n // Parse request body\n const contentType = request.headers.get(\"Content-Type\") ?? \"\";\n let body: RpcRequest;\n\n if (contentType.includes(\"msgpack\")) {\n const buffer = await request.arrayBuffer();\n body = serializer.decode(buffer) as RpcRequest;\n } else {\n const text = await request.text();\n body = serializer.decode(text) as RpcRequest;\n }\n\n // Extract trace context\n const traceparent = request.headers.get(\"traceparent\");\n if (traceparent) {\n const parsedTrace = parseTraceparent(traceparent);\n if (parsedTrace) {\n body.traceContext = parsedTrace;\n const tracestate = request.headers.get(\"tracestate\");\n if (tracestate) {\n body.traceContext.traceState = tracestate;\n }\n }\n }\n\n // Extract tenant from header\n const tenantId = request.headers.get(\"X-Tenant-ID\");\n if (tenantId) {\n body.metadata = { ...body.metadata, tenantId };\n }\n\n // Handle request\n const response = await server.handle(body);\n\n // Serialize response\n const responseBody = serializer.encode(response);\n\n return new Response(\n typeof responseBody === \"string\" ? responseBody : responseBody,\n {\n status: response.success ? 200 : getHttpStatus(response.error?.code),\n headers: {\n \"Content-Type\": serializer.contentType,\n \"X-Request-ID\": body.id,\n },\n }\n );\n } catch (error) {\n logger.error(\"Handler error\", error as Error);\n\n return new Response(\n JSON.stringify({\n success: false,\n error: {\n code: \"INTERNAL_ERROR\",\n message: (error as Error).message,\n },\n }),\n {\n status: 500,\n headers: { \"Content-Type\": \"application/json\" },\n }\n );\n }\n };\n}\n\n// ============================================================================\n// HELPERS\n// ============================================================================\n\nimport type { TraceContext } from \"../../types.js\";\n\nfunction formatTraceparent(ctx: TraceContext): string {\n const flags = ctx.traceFlags.toString(16).padStart(2, \"0\");\n return `00-${ctx.traceId}-${ctx.spanId}-${flags}`;\n}\n\nfunction getHttpStatus(code?: string): number {\n switch (code) {\n case \"METHOD_NOT_FOUND\":\n case \"SERVICE_NOT_FOUND\":\n return 404;\n case \"VERSION_MISMATCH\":\n case \"VALIDATION_ERROR\":\n return 400;\n case \"UNAUTHORIZED\":\n return 401;\n case \"FORBIDDEN\":\n return 403;\n case \"TIMEOUT\":\n return 504;\n case \"CIRCUIT_OPEN\":\n case \"BULKHEAD_REJECTED\":\n return 503;\n default:\n return 500;\n }\n}\n","/**\n * @parsrun/service - Serialization\n * JSON and MessagePack serializers\n */\n\n// ============================================================================\n// SERIALIZER INTERFACE\n// ============================================================================\n\n/**\n * Serializer interface for encoding/decoding data\n */\nexport interface Serializer {\n /** Encode data to string or buffer */\n encode(data: unknown): string | ArrayBuffer;\n /** Decode string or buffer to data */\n decode(raw: string | ArrayBuffer): unknown;\n /** Content type for HTTP headers */\n contentType: string;\n}\n\n// ============================================================================\n// JSON SERIALIZER\n// ============================================================================\n\n/**\n * JSON serializer (default)\n */\nexport const jsonSerializer: Serializer = {\n encode(data: unknown): string {\n return JSON.stringify(data);\n },\n\n decode(raw: string | ArrayBuffer): unknown {\n if (raw instanceof ArrayBuffer) {\n const decoder = new TextDecoder();\n return JSON.parse(decoder.decode(raw));\n }\n return JSON.parse(raw);\n },\n\n contentType: \"application/json\",\n};\n\n// ============================================================================\n// MESSAGEPACK SERIALIZER (Lightweight implementation)\n// ============================================================================\n\n/**\n * Lightweight MessagePack encoder\n * Supports: null, boolean, number, string, array, object\n */\nfunction msgpackEncode(value: unknown): Uint8Array {\n const parts: Uint8Array[] = [];\n\n function encode(val: unknown): void {\n if (val === null || val === undefined) {\n parts.push(new Uint8Array([0xc0])); // nil\n return;\n }\n\n if (typeof val === \"boolean\") {\n parts.push(new Uint8Array([val ? 0xc3 : 0xc2]));\n return;\n }\n\n if (typeof val === \"number\") {\n if (Number.isInteger(val)) {\n if (val >= 0 && val <= 127) {\n // positive fixint\n parts.push(new Uint8Array([val]));\n } else if (val < 0 && val >= -32) {\n // negative fixint\n parts.push(new Uint8Array([val & 0xff]));\n } else if (val >= 0 && val <= 0xff) {\n // uint8\n parts.push(new Uint8Array([0xcc, val]));\n } else if (val >= 0 && val <= 0xffff) {\n // uint16\n parts.push(new Uint8Array([0xcd, (val >> 8) & 0xff, val & 0xff]));\n } else if (val >= 0 && val <= 0xffffffff) {\n // uint32\n parts.push(\n new Uint8Array([\n 0xce,\n (val >> 24) & 0xff,\n (val >> 16) & 0xff,\n (val >> 8) & 0xff,\n val & 0xff,\n ])\n );\n } else if (val >= -128 && val <= 127) {\n // int8\n parts.push(new Uint8Array([0xd0, val & 0xff]));\n } else if (val >= -32768 && val <= 32767) {\n // int16\n parts.push(new Uint8Array([0xd1, (val >> 8) & 0xff, val & 0xff]));\n } else if (val >= -2147483648 && val <= 2147483647) {\n // int32\n parts.push(\n new Uint8Array([\n 0xd2,\n (val >> 24) & 0xff,\n (val >> 16) & 0xff,\n (val >> 8) & 0xff,\n val & 0xff,\n ])\n );\n } else {\n // Fall back to float64 for large integers\n const buffer = new ArrayBuffer(9);\n const view = new DataView(buffer);\n view.setUint8(0, 0xcb);\n view.setFloat64(1, val, false);\n parts.push(new Uint8Array(buffer));\n }\n } else {\n // float64\n const buffer = new ArrayBuffer(9);\n const view = new DataView(buffer);\n view.setUint8(0, 0xcb);\n view.setFloat64(1, val, false);\n parts.push(new Uint8Array(buffer));\n }\n return;\n }\n\n if (typeof val === \"string\") {\n const encoded = new TextEncoder().encode(val);\n const len = encoded.length;\n\n if (len <= 31) {\n // fixstr\n parts.push(new Uint8Array([0xa0 | len]));\n } else if (len <= 0xff) {\n // str8\n parts.push(new Uint8Array([0xd9, len]));\n } else if (len <= 0xffff) {\n // str16\n parts.push(new Uint8Array([0xda, (len >> 8) & 0xff, len & 0xff]));\n } else {\n // str32\n parts.push(\n new Uint8Array([\n 0xdb,\n (len >> 24) & 0xff,\n (len >> 16) & 0xff,\n (len >> 8) & 0xff,\n len & 0xff,\n ])\n );\n }\n parts.push(encoded);\n return;\n }\n\n if (Array.isArray(val)) {\n const len = val.length;\n\n if (len <= 15) {\n // fixarray\n parts.push(new Uint8Array([0x90 | len]));\n } else if (len <= 0xffff) {\n // array16\n parts.push(new Uint8Array([0xdc, (len >> 8) & 0xff, len & 0xff]));\n } else {\n // array32\n parts.push(\n new Uint8Array([\n 0xdd,\n (len >> 24) & 0xff,\n (len >> 16) & 0xff,\n (len >> 8) & 0xff,\n len & 0xff,\n ])\n );\n }\n\n for (const item of val) {\n encode(item);\n }\n return;\n }\n\n if (typeof val === \"object\") {\n const keys = Object.keys(val as object);\n const len = keys.length;\n\n if (len <= 15) {\n // fixmap\n parts.push(new Uint8Array([0x80 | len]));\n } else if (len <= 0xffff) {\n // map16\n parts.push(new Uint8Array([0xde, (len >> 8) & 0xff, len & 0xff]));\n } else {\n // map32\n parts.push(\n new Uint8Array([\n 0xdf,\n (len >> 24) & 0xff,\n (len >> 16) & 0xff,\n (len >> 8) & 0xff,\n len & 0xff,\n ])\n );\n }\n\n for (const key of keys) {\n encode(key);\n encode((val as Record<string, unknown>)[key]);\n }\n return;\n }\n\n // Unsupported type - encode as null\n parts.push(new Uint8Array([0xc0]));\n }\n\n encode(value);\n\n // Merge all parts\n const totalLength = parts.reduce((sum, p) => sum + p.length, 0);\n const result = new Uint8Array(totalLength);\n let offset = 0;\n for (const part of parts) {\n result.set(part, offset);\n offset += part.length;\n }\n\n return result;\n}\n\n/**\n * Lightweight MessagePack decoder\n */\nfunction msgpackDecode(buffer: Uint8Array): unknown {\n let offset = 0;\n\n function decode(): unknown {\n if (offset >= buffer.length) {\n throw new Error(\"Unexpected end of buffer\");\n }\n\n const byte = buffer[offset++]!;\n\n // Positive fixint (0x00 - 0x7f)\n if (byte <= 0x7f) {\n return byte;\n }\n\n // Negative fixint (0xe0 - 0xff)\n if (byte >= 0xe0) {\n return byte - 256;\n }\n\n // Fixmap (0x80 - 0x8f)\n if (byte >= 0x80 && byte <= 0x8f) {\n const len = byte - 0x80;\n const result: Record<string, unknown> = {};\n for (let i = 0; i < len; i++) {\n const key = decode() as string;\n result[key] = decode();\n }\n return result;\n }\n\n // Fixarray (0x90 - 0x9f)\n if (byte >= 0x90 && byte <= 0x9f) {\n const len = byte - 0x90;\n const result: unknown[] = [];\n for (let i = 0; i < len; i++) {\n result.push(decode());\n }\n return result;\n }\n\n // Fixstr (0xa0 - 0xbf)\n if (byte >= 0xa0 && byte <= 0xbf) {\n const len = byte - 0xa0;\n const str = new TextDecoder().decode(buffer.subarray(offset, offset + len));\n offset += len;\n return str;\n }\n\n switch (byte) {\n case 0xc0: // nil\n return null;\n case 0xc2: // false\n return false;\n case 0xc3: // true\n return true;\n\n case 0xcc: // uint8\n return buffer[offset++];\n case 0xcd: // uint16\n return (buffer[offset++]! << 8) | buffer[offset++]!;\n case 0xce: // uint32\n return (\n ((buffer[offset++]! << 24) >>> 0) +\n (buffer[offset++]! << 16) +\n (buffer[offset++]! << 8) +\n buffer[offset++]!\n );\n\n case 0xd0: // int8\n {\n const val = buffer[offset++]!;\n return val > 127 ? val - 256 : val;\n }\n case 0xd1: // int16\n {\n const val = (buffer[offset++]! << 8) | buffer[offset++]!;\n return val > 32767 ? val - 65536 : val;\n }\n case 0xd2: // int32\n {\n const val =\n (buffer[offset++]! << 24) |\n (buffer[offset++]! << 16) |\n (buffer[offset++]! << 8) |\n buffer[offset++]!;\n return val;\n }\n\n case 0xcb: // float64\n {\n const view = new DataView(buffer.buffer, buffer.byteOffset + offset, 8);\n offset += 8;\n return view.getFloat64(0, false);\n }\n\n case 0xd9: // str8\n {\n const len = buffer[offset++]!;\n const str = new TextDecoder().decode(buffer.subarray(offset, offset + len));\n offset += len;\n return str;\n }\n case 0xda: // str16\n {\n const len = (buffer[offset++]! << 8) | buffer[offset++]!;\n const str = new TextDecoder().decode(buffer.subarray(offset, offset + len));\n offset += len;\n return str;\n }\n case 0xdb: // str32\n {\n const len =\n (buffer[offset++]! << 24) |\n (buffer[offset++]! << 16) |\n (buffer[offset++]! << 8) |\n buffer[offset++]!;\n const str = new TextDecoder().decode(buffer.subarray(offset, offset + len));\n offset += len;\n return str;\n }\n\n case 0xdc: // array16\n {\n const len = (buffer[offset++]! << 8) | buffer[offset++]!;\n const result: unknown[] = [];\n for (let i = 0; i < len; i++) {\n result.push(decode());\n }\n return result;\n }\n case 0xdd: // array32\n {\n const len =\n (buffer[offset++]! << 24) |\n (buffer[offset++]! << 16) |\n (buffer[offset++]! << 8) |\n buffer[offset++]!;\n const result: unknown[] = [];\n for (let i = 0; i < len; i++) {\n result.push(decode());\n }\n return result;\n }\n\n case 0xde: // map16\n {\n const len = (buffer[offset++]! << 8) | buffer[offset++]!;\n const result: Record<string, unknown> = {};\n for (let i = 0; i < len; i++) {\n const key = decode() as string;\n result[key] = decode();\n }\n return result;\n }\n case 0xdf: // map32\n {\n const len =\n (buffer[offset++]! << 24) |\n (buffer[offset++]! << 16) |\n (buffer[offset++]! << 8) |\n buffer[offset++]!;\n const result: Record<string, unknown> = {};\n for (let i = 0; i < len; i++) {\n const key = decode() as string;\n result[key] = decode();\n }\n return result;\n }\n\n default:\n throw new Error(`Unknown MessagePack type: 0x${byte.toString(16)}`);\n }\n }\n\n return decode();\n}\n\n/**\n * MessagePack serializer\n */\nexport const msgpackSerializer: Serializer = {\n encode(data: unknown): ArrayBuffer {\n const encoded = msgpackEncode(data);\n // Create a new ArrayBuffer with the exact bytes from the Uint8Array\n const buffer = new ArrayBuffer(encoded.byteLength);\n new Uint8Array(buffer).set(encoded);\n return buffer;\n },\n\n decode(raw: string | ArrayBuffer): unknown {\n if (typeof raw === \"string\") {\n // If string is passed, assume it's base64 encoded\n const binary = atob(raw);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return msgpackDecode(bytes);\n }\n return msgpackDecode(new Uint8Array(raw));\n },\n\n contentType: \"application/msgpack\",\n};\n\n// ============================================================================\n// SERIALIZER FACTORY\n// ============================================================================\n\n/**\n * Get serializer by format name\n */\nexport function getSerializer(format: \"json\" | \"msgpack\"): Serializer {\n switch (format) {\n case \"json\":\n return jsonSerializer;\n case \"msgpack\":\n return msgpackSerializer;\n default:\n return jsonSerializer;\n }\n}\n\n/**\n * Create a custom serializer\n */\nexport function createSerializer(options: {\n encode: (data: unknown) => string | ArrayBuffer;\n decode: (raw: string | ArrayBuffer) => unknown;\n contentType: string;\n}): Serializer {\n return options;\n}\n","/**\n * @parsrun/service - RPC Errors\n */\n\nimport { ParsError } from \"@parsrun/core\";\n\n/**\n * Base RPC error\n */\nexport class RpcError extends ParsError {\n public readonly retryable: boolean;\n public readonly retryAfter?: number;\n\n constructor(\n message: string,\n code: string,\n statusCode: number = 500,\n options?: {\n retryable?: boolean;\n retryAfter?: number;\n details?: Record<string, unknown>;\n }\n ) {\n super(message, code, statusCode, options?.details);\n this.name = \"RpcError\";\n this.retryable = options?.retryable ?? false;\n if (options?.retryAfter !== undefined) {\n this.retryAfter = options.retryAfter;\n }\n }\n}\n\n/**\n * Service not found error\n */\nexport class ServiceNotFoundError extends RpcError {\n constructor(serviceName: string) {\n super(`Service not found: ${serviceName}`, \"SERVICE_NOT_FOUND\", 404, {\n retryable: false,\n details: { service: serviceName },\n });\n this.name = \"ServiceNotFoundError\";\n }\n}\n\n/**\n * Method not found error\n */\nexport class MethodNotFoundError extends RpcError {\n constructor(serviceName: string, methodName: string) {\n super(\n `Method not found: ${serviceName}.${methodName}`,\n \"METHOD_NOT_FOUND\",\n 404,\n {\n retryable: false,\n details: { service: serviceName, method: methodName },\n }\n );\n this.name = \"MethodNotFoundError\";\n }\n}\n\n/**\n * Version mismatch error\n */\nexport class VersionMismatchError extends RpcError {\n constructor(serviceName: string, requested: string, available: string) {\n super(\n `Version mismatch for ${serviceName}: requested ${requested}, available ${available}`,\n \"VERSION_MISMATCH\",\n 400,\n {\n retryable: false,\n details: { service: serviceName, requested, available },\n }\n );\n this.name = \"VersionMismatchError\";\n }\n}\n\n/**\n * Timeout error\n */\nexport class TimeoutError extends RpcError {\n constructor(serviceName: string, methodName: string, timeoutMs: number) {\n super(\n `Request to ${serviceName}.${methodName} timed out after ${timeoutMs}ms`,\n \"TIMEOUT\",\n 504,\n {\n retryable: true,\n details: { service: serviceName, method: methodName, timeout: timeoutMs },\n }\n );\n this.name = \"TimeoutError\";\n }\n}\n\n/**\n * Circuit breaker open error\n */\nexport class CircuitOpenError extends RpcError {\n constructor(serviceName: string, resetAfterMs: number) {\n super(\n `Circuit breaker open for ${serviceName}`,\n \"CIRCUIT_OPEN\",\n 503,\n {\n retryable: true,\n retryAfter: Math.ceil(resetAfterMs / 1000),\n details: { service: serviceName, resetAfterMs },\n }\n );\n this.name = \"CircuitOpenError\";\n }\n}\n\n/**\n * Bulkhead rejected error\n */\nexport class BulkheadRejectedError extends RpcError {\n constructor(serviceName: string) {\n super(\n `Request rejected by bulkhead for ${serviceName}: too many concurrent requests`,\n \"BULKHEAD_REJECTED\",\n 503,\n {\n retryable: true,\n retryAfter: 1,\n details: { service: serviceName },\n }\n );\n this.name = \"BulkheadRejectedError\";\n }\n}\n\n/**\n * Transport error\n */\nexport class TransportError extends RpcError {\n constructor(message: string, cause?: Error) {\n const options: { retryable: boolean; details?: Record<string, unknown> } = {\n retryable: true,\n };\n if (cause) {\n options.details = { cause: cause.message };\n }\n super(message, \"TRANSPORT_ERROR\", 502, options);\n this.name = \"TransportError\";\n }\n}\n\n/**\n * Serialization error\n */\nexport class SerializationError extends RpcError {\n constructor(message: string, cause?: Error) {\n const options: { retryable: boolean; details?: Record<string, unknown> } = {\n retryable: false,\n };\n if (cause) {\n options.details = { cause: cause.message };\n }\n super(message, \"SERIALIZATION_ERROR\", 400, options);\n this.name = \"SerializationError\";\n }\n}\n\n/**\n * Convert unknown error to RpcError\n */\nexport function toRpcError(error: unknown): RpcError {\n if (error instanceof RpcError) {\n return error;\n }\n\n if (error instanceof Error) {\n return new RpcError(error.message, \"INTERNAL_ERROR\", 500, {\n retryable: false,\n details: { originalError: error.name },\n });\n }\n\n return new RpcError(String(error), \"UNKNOWN_ERROR\", 500, {\n retryable: false,\n });\n}\n","/**\n * @parsrun/service - HTTP RPC Transport\n * HTTP-based transport for distributed services\n */\n\nimport type { RpcRequest, RpcResponse, RpcTransport } from \"../../types.js\";\nimport { type Serializer, jsonSerializer } from \"../../serialization/index.js\";\nimport { TransportError, SerializationError } from \"../errors.js\";\n\n// ============================================================================\n// HTTP TRANSPORT\n// ============================================================================\n\nexport interface HttpTransportOptions {\n /** Base URL of the service */\n baseUrl: string;\n /** Custom serializer (default: JSON) */\n serializer?: Serializer;\n /** Custom headers */\n headers?: Record<string, string>;\n /** Fetch function (for testing or custom implementations) */\n fetch?: typeof globalThis.fetch;\n /** Request timeout in ms */\n timeout?: number;\n}\n\n/**\n * HTTP transport for RPC calls\n */\nexport class HttpTransport implements RpcTransport {\n readonly name = \"http\";\n private readonly baseUrl: string;\n private readonly serializer: Serializer;\n private readonly headers: Record<string, string>;\n private readonly fetchFn: typeof globalThis.fetch;\n private readonly timeout: number;\n\n constructor(options: HttpTransportOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, \"\"); // Remove trailing slash\n this.serializer = options.serializer ?? jsonSerializer;\n this.headers = options.headers ?? {};\n this.fetchFn = options.fetch ?? globalThis.fetch.bind(globalThis);\n this.timeout = options.timeout ?? 30_000;\n }\n\n async call<TInput, TOutput>(request: RpcRequest<TInput>): Promise<RpcResponse<TOutput>> {\n const url = `${this.baseUrl}/rpc`;\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n // Serialize request\n let body: string | ArrayBuffer;\n try {\n body = this.serializer.encode(request);\n } catch (error) {\n throw new SerializationError(\n \"Failed to serialize request\",\n error instanceof Error ? error : undefined\n );\n }\n\n // Make HTTP request\n const response = await this.fetchFn(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": this.serializer.contentType,\n Accept: this.serializer.contentType,\n \"X-Request-ID\": request.id,\n \"X-Service\": request.service,\n \"X-Method\": request.method,\n \"X-Method-Type\": request.type,\n ...(request.version ? { \"X-Service-Version\": request.version } : {}),\n ...(request.traceContext\n ? {\n traceparent: formatTraceparent(request.traceContext),\n ...(request.traceContext.traceState\n ? { tracestate: request.traceContext.traceState }\n : {}),\n }\n : {}),\n ...this.headers,\n },\n body: body instanceof ArrayBuffer ? body : body,\n signal: controller.signal,\n });\n\n // Parse response\n let responseData: RpcResponse<TOutput>;\n try {\n const contentType = response.headers.get(\"Content-Type\") ?? \"\";\n if (contentType.includes(\"msgpack\")) {\n const buffer = await response.arrayBuffer();\n responseData = this.serializer.decode(buffer) as RpcResponse<TOutput>;\n } else {\n const text = await response.text();\n responseData = this.serializer.decode(text) as RpcResponse<TOutput>;\n }\n } catch (error) {\n throw new SerializationError(\n \"Failed to deserialize response\",\n error instanceof Error ? error : undefined\n );\n }\n\n return responseData;\n } catch (error) {\n if (error instanceof SerializationError) {\n throw error;\n }\n\n if (error instanceof Error) {\n if (error.name === \"AbortError\") {\n throw new TransportError(`Request timeout after ${this.timeout}ms`);\n }\n throw new TransportError(`HTTP request failed: ${error.message}`, error);\n }\n\n throw new TransportError(\"Unknown transport error\");\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async close(): Promise<void> {\n // No persistent connection to close\n }\n}\n\n/**\n * Create an HTTP transport\n */\nexport function createHttpTransport(options: HttpTransportOptions): HttpTransport {\n return new HttpTransport(options);\n}\n\n// ============================================================================\n// TRACE CONTEXT HELPERS\n// ============================================================================\n\nimport type { TraceContext } from \"../../types.js\";\n\n/**\n * Format trace context as W3C traceparent header\n */\nfunction formatTraceparent(ctx: TraceContext): string {\n const flags = ctx.traceFlags.toString(16).padStart(2, \"0\");\n return `00-${ctx.traceId}-${ctx.spanId}-${flags}`;\n}\n\n/**\n * Parse W3C traceparent header\n */\nexport function parseTraceparent(header: string): TraceContext | null {\n const parts = header.split(\"-\");\n if (parts.length !== 4) {\n return null;\n }\n\n const [version, traceId, spanId, flags] = parts;\n if (version !== \"00\" || !traceId || !spanId || !flags) {\n return null;\n }\n\n if (traceId.length !== 32 || spanId.length !== 16 || flags.length !== 2) {\n return null;\n }\n\n return {\n traceId,\n spanId,\n traceFlags: parseInt(flags, 16),\n };\n}\n\n// ============================================================================\n// HTTP SERVER ADAPTER\n// ============================================================================\n\nimport type { RpcServer } from \"../server.js\";\n\n/**\n * Create HTTP request handler for RPC server\n * Can be used with Hono, Express, or any HTTP framework\n */\nexport function createHttpHandler(server: RpcServer) {\n return async (request: Request): Promise<Response> => {\n try {\n // Parse request body\n const contentType = request.headers.get(\"Content-Type\") ?? \"application/json\";\n let body: unknown;\n\n if (contentType.includes(\"msgpack\")) {\n const buffer = await request.arrayBuffer();\n // For msgpack, we'd need to decode - using JSON for now\n body = JSON.parse(new TextDecoder().decode(buffer));\n } else {\n body = await request.json();\n }\n\n const rpcRequest = body as RpcRequest;\n\n // Parse trace context\n const traceparent = request.headers.get(\"traceparent\");\n if (traceparent) {\n const traceContext = parseTraceparent(traceparent);\n if (traceContext) {\n const tracestate = request.headers.get(\"tracestate\");\n if (tracestate) {\n traceContext.traceState = tracestate;\n }\n rpcRequest.traceContext = traceContext;\n }\n }\n\n // Handle request\n const response = await server.handle(rpcRequest);\n\n // Return response\n return new Response(JSON.stringify(response), {\n status: response.success ? 200 : getHttpStatus(response.error?.code),\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Request-ID\": rpcRequest.id,\n },\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Unknown error\";\n return new Response(\n JSON.stringify({\n success: false,\n error: {\n code: \"INTERNAL_ERROR\",\n message,\n },\n }),\n {\n status: 500,\n headers: { \"Content-Type\": \"application/json\" },\n }\n );\n }\n };\n}\n\n/**\n * Map error code to HTTP status\n */\nfunction getHttpStatus(code?: string): number {\n switch (code) {\n case \"METHOD_NOT_FOUND\":\n case \"SERVICE_NOT_FOUND\":\n return 404;\n case \"VERSION_MISMATCH\":\n case \"VALIDATION_ERROR\":\n case \"SERIALIZATION_ERROR\":\n return 400;\n case \"UNAUTHORIZED\":\n return 401;\n case \"FORBIDDEN\":\n return 403;\n case \"TIMEOUT\":\n return 504;\n case \"CIRCUIT_OPEN\":\n case \"BULKHEAD_REJECTED\":\n return 503;\n default:\n return 500;\n }\n}\n","/**\n * @parsrun/service - Cloudflare Queue Transport\n * Event transport using Cloudflare Queues\n */\n\nimport type { Logger } from \"@parsrun/core\";\nimport { createLogger } from \"@parsrun/core\";\nimport type {\n ParsEvent,\n EventTransport,\n EventHandler,\n EventHandlerOptions,\n Unsubscribe,\n CompactEvent,\n} from \"../../types.js\";\nimport { toCompactEvent, fromCompactEvent } from \"../../events/format.js\";\nimport { EventHandlerRegistry } from \"../../events/handler.js\";\n\n// ============================================================================\n// CLOUDFLARE QUEUE TYPES\n// ============================================================================\n\n/**\n * Cloudflare Queue interface\n */\nexport interface CloudflareQueue {\n send(message: unknown, options?: { contentType?: string }): Promise<void>;\n sendBatch(\n messages: Array<{ body: unknown; contentType?: string }>\n ): Promise<void>;\n}\n\n/**\n * Queue message from Cloudflare\n */\nexport interface QueueMessage<T = unknown> {\n id: string;\n timestamp: Date;\n body: T;\n ack(): void;\n retry(): void;\n}\n\n/**\n * Queue batch from Cloudflare\n */\nexport interface QueueBatch<T = unknown> {\n queue: string;\n messages: QueueMessage<T>[];\n ackAll(): void;\n retryAll(): void;\n}\n\n// ============================================================================\n// CLOUDFLARE QUEUE TRANSPORT\n// ============================================================================\n\nexport interface CloudflareQueueTransportOptions {\n /** Cloudflare Queue binding */\n queue: CloudflareQueue;\n /** Queue name (for logging) */\n queueName?: string;\n /** Use compact event format */\n compact?: boolean;\n /** Logger */\n logger?: Logger;\n /** Batch size for sending */\n batchSize?: number;\n /** Flush interval in ms */\n flushInterval?: number;\n}\n\n/**\n * Event transport using Cloudflare Queues\n *\n * Events are sent to a Cloudflare Queue for async processing.\n * Handlers are registered to process events from the queue.\n */\nexport class CloudflareQueueTransport implements EventTransport {\n readonly name = \"cloudflare-queue\";\n private readonly queue: CloudflareQueue;\n private readonly queueName: string;\n private readonly compact: boolean;\n private readonly logger: Logger;\n private readonly batchSize: number;\n private readonly flushInterval: number;\n private readonly registry: EventHandlerRegistry;\n private readonly buffer: ParsEvent[] = [];\n private flushTimer: ReturnType<typeof setInterval> | null = null;\n\n constructor(options: CloudflareQueueTransportOptions) {\n this.queue = options.queue;\n this.queueName = options.queueName ?? \"events\";\n this.compact = options.compact ?? true;\n this.logger = options.logger ?? createLogger({ name: `queue:${this.queueName}` });\n this.batchSize = options.batchSize ?? 100;\n this.flushInterval = options.flushInterval ?? 1000;\n this.registry = new EventHandlerRegistry({ logger: this.logger });\n\n // Start flush timer\n this.flushTimer = setInterval(() => this.flush(), this.flushInterval);\n }\n\n /**\n * Emit an event to the queue\n */\n async emit<T>(event: ParsEvent<T>): Promise<void> {\n this.buffer.push(event);\n\n if (this.buffer.length >= this.batchSize) {\n await this.flush();\n }\n }\n\n /**\n * Subscribe to events (for local handler registration)\n */\n subscribe(\n eventType: string,\n handler: EventHandler,\n options?: EventHandlerOptions\n ): Unsubscribe {\n return this.registry.register(eventType, handler, options);\n }\n\n /**\n * Flush buffered events to the queue\n */\n async flush(): Promise<void> {\n if (this.buffer.length === 0) return;\n\n const events = this.buffer.splice(0, this.batchSize);\n\n try {\n if (events.length === 1) {\n // Single event\n const body = this.compact\n ? toCompactEvent(events[0]!)\n : events[0];\n await this.queue.send(body);\n } else {\n // Batch send\n const messages = events.map((event) => ({\n body: this.compact ? toCompactEvent(event) : event,\n }));\n await this.queue.sendBatch(messages);\n }\n\n this.logger.debug(`Sent ${events.length} events to queue`, {\n queue: this.queueName,\n });\n } catch (error) {\n // Put events back in buffer for retry\n this.buffer.unshift(...events);\n this.logger.error(\"Failed to send events to queue\", error as Error);\n throw error;\n }\n }\n\n /**\n * Handle a queue message (called by queue consumer)\n */\n async handleMessage<T>(message: QueueMessage<T>): Promise<void> {\n try {\n const event = this.parseEvent(message.body);\n await this.registry.handle(event);\n message.ack();\n } catch (error) {\n this.logger.error(\"Failed to handle queue message\", error as Error, {\n messageId: message.id,\n });\n message.retry();\n }\n }\n\n /**\n * Handle a batch of queue messages\n */\n async handleBatch<T>(batch: QueueBatch<T>): Promise<void> {\n const results = await Promise.allSettled(\n batch.messages.map((msg) => this.handleMessage(msg))\n );\n\n const failures = results.filter((r) => r.status === \"rejected\");\n if (failures.length > 0) {\n this.logger.warn(`${failures.length}/${batch.messages.length} messages failed`);\n }\n }\n\n /**\n * Parse event from message body\n */\n private parseEvent(body: unknown): ParsEvent {\n if (this.compact && isCompactEvent(body)) {\n return fromCompactEvent(body as CompactEvent);\n }\n return body as ParsEvent;\n }\n\n /**\n * Close the transport\n */\n async close(): Promise<void> {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n await this.flush();\n this.registry.clear();\n }\n}\n\n/**\n * Create a Cloudflare Queue transport\n */\nexport function createCloudflareQueueTransport(\n options: CloudflareQueueTransportOptions\n): CloudflareQueueTransport {\n return new CloudflareQueueTransport(options);\n}\n\n// ============================================================================\n// QUEUE CONSUMER\n// ============================================================================\n\n/**\n * Create a queue consumer handler\n *\n * @example\n * ```typescript\n * // In your worker\n * const consumer = createQueueConsumer(registry);\n *\n * export default {\n * queue: consumer,\n * };\n * ```\n */\nexport function createQueueConsumer(\n registry: EventHandlerRegistry,\n options?: {\n compact?: boolean;\n logger?: Logger;\n }\n): (batch: QueueBatch) => Promise<void> {\n const compact = options?.compact ?? true;\n const logger = options?.logger ?? createLogger({ name: \"queue-consumer\" });\n\n return async (batch: QueueBatch): Promise<void> => {\n logger.info(`Processing batch of ${batch.messages.length} messages`, {\n queue: batch.queue,\n });\n\n for (const message of batch.messages) {\n try {\n let event: ParsEvent;\n\n if (compact && isCompactEvent(message.body)) {\n event = fromCompactEvent(message.body as CompactEvent);\n } else {\n event = message.body as ParsEvent;\n }\n\n await registry.handle(event);\n message.ack();\n } catch (error) {\n logger.error(\"Failed to process message\", error as Error, {\n messageId: message.id,\n });\n message.retry();\n }\n }\n };\n}\n\n// ============================================================================\n// HELPERS\n// ============================================================================\n\nfunction isCompactEvent(body: unknown): boolean {\n if (!body || typeof body !== \"object\") return false;\n const obj = body as Record<string, unknown>;\n return (\n typeof obj[\"e\"] === \"string\" &&\n typeof obj[\"s\"] === \"string\" &&\n typeof obj[\"i\"] === \"string\" &&\n typeof obj[\"t\"] === \"number\"\n );\n}\n","/**\n * @parsrun/service - Event Format\n * CloudEvents and compact event format utilities\n */\n\nimport { generateId } from \"@parsrun/core\";\nimport type { ParsEvent, CompactEvent, TraceContext } from \"../types.js\";\n\n// ============================================================================\n// EVENT CREATION\n// ============================================================================\n\nexport interface CreateEventOptions<T = unknown> {\n /** Event type (e.g., \"subscription.created\") */\n type: string;\n /** Source service */\n source: string;\n /** Event data */\n data: T;\n /** Optional event ID (auto-generated if not provided) */\n id?: string;\n /** Optional subject */\n subject?: string;\n /** Tenant ID */\n tenantId?: string;\n /** Request ID for correlation */\n requestId?: string;\n /** Trace context */\n traceContext?: TraceContext;\n /** Delivery guarantee */\n delivery?: \"at-most-once\" | \"at-least-once\";\n}\n\n/**\n * Create a CloudEvents-compatible event\n */\nexport function createEvent<T = unknown>(options: CreateEventOptions<T>): ParsEvent<T> {\n const event: ParsEvent<T> = {\n specversion: \"1.0\",\n type: options.type,\n source: options.source,\n id: options.id ?? generateId(),\n time: new Date().toISOString(),\n datacontenttype: \"application/json\",\n data: options.data,\n };\n\n if (options.subject) event.subject = options.subject;\n if (options.tenantId) event.parstenantid = options.tenantId;\n if (options.requestId) event.parsrequestid = options.requestId;\n if (options.traceContext) event.parstracecontext = formatTraceContext(options.traceContext);\n if (options.delivery) event.parsdelivery = options.delivery;\n\n return event;\n}\n\n// ============================================================================\n// FORMAT CONVERSION\n// ============================================================================\n\n/**\n * Convert to full CloudEvents format\n */\nexport function toCloudEvent<T>(event: ParsEvent<T>): ParsEvent<T> {\n return { ...event };\n}\n\n/**\n * Convert to compact internal format\n */\nexport function toCompactEvent<T>(event: ParsEvent<T>): CompactEvent<T> {\n const compact: CompactEvent<T> = {\n e: event.type,\n s: event.source,\n i: event.id,\n t: new Date(event.time).getTime(),\n d: event.data,\n };\n\n if (event.parstracecontext) compact.ctx = event.parstracecontext;\n if (event.parstenantid) compact.tid = event.parstenantid;\n\n return compact;\n}\n\n/**\n * Convert from compact format to CloudEvents\n */\nexport function fromCompactEvent<T>(compact: CompactEvent<T>, source?: string): ParsEvent<T> {\n const event: ParsEvent<T> = {\n specversion: \"1.0\",\n type: compact.e,\n source: source ?? compact.s,\n id: compact.i,\n time: new Date(compact.t).toISOString(),\n datacontenttype: \"application/json\",\n data: compact.d,\n };\n\n if (compact.ctx) event.parstracecontext = compact.ctx;\n if (compact.tid) event.parstenantid = compact.tid;\n\n return event;\n}\n\n// ============================================================================\n// EVENT TYPE UTILITIES\n// ============================================================================\n\n/**\n * Format full event type with source prefix\n *\n * @example\n * formatEventType('payments', 'subscription.created')\n * // Returns: 'com.pars.payments.subscription.created'\n */\nexport function formatEventType(source: string, type: string): string {\n return `com.pars.${source}.${type}`;\n}\n\n/**\n * Parse event type to extract source and type\n *\n * @example\n * parseEventType('com.pars.payments.subscription.created')\n * // Returns: { source: 'payments', type: 'subscription.created' }\n */\nexport function parseEventType(fullType: string): { source: string; type: string } | null {\n const prefix = \"com.pars.\";\n if (!fullType.startsWith(prefix)) {\n // Try to parse as simple type (source.type)\n const parts = fullType.split(\".\");\n if (parts.length >= 2) {\n const [source, ...rest] = parts;\n return { source: source!, type: rest.join(\".\") };\n }\n return null;\n }\n\n const withoutPrefix = fullType.slice(prefix.length);\n const dotIndex = withoutPrefix.indexOf(\".\");\n if (dotIndex === -1) {\n return null;\n }\n\n return {\n source: withoutPrefix.slice(0, dotIndex),\n type: withoutPrefix.slice(dotIndex + 1),\n };\n}\n\n/**\n * Check if event type matches a pattern\n * Supports wildcards: * matches one segment, ** matches multiple segments\n *\n * @example\n * matchEventType('subscription.created', 'subscription.*') // true\n * matchEventType('payment.invoice.paid', 'payment.**') // true\n * matchEventType('subscription.created', 'payment.*') // false\n */\nexport function matchEventType(type: string, pattern: string): boolean {\n if (pattern === \"*\" || pattern === \"**\") {\n return true;\n }\n\n const typeParts = type.split(\".\");\n const patternParts = pattern.split(\".\");\n\n let ti = 0;\n let pi = 0;\n\n while (ti < typeParts.length && pi < patternParts.length) {\n const pp = patternParts[pi];\n\n if (pp === \"**\") {\n // ** matches rest of type\n if (pi === patternParts.length - 1) {\n return true;\n }\n // Try to match remaining pattern\n for (let i = ti; i <= typeParts.length; i++) {\n const remaining = typeParts.slice(i).join(\".\");\n const remainingPattern = patternParts.slice(pi + 1).join(\".\");\n if (matchEventType(remaining, remainingPattern)) {\n return true;\n }\n }\n return false;\n }\n\n if (pp === \"*\") {\n // * matches single segment\n ti++;\n pi++;\n continue;\n }\n\n if (pp !== typeParts[ti]) {\n return false;\n }\n\n ti++;\n pi++;\n }\n\n return ti === typeParts.length && pi === patternParts.length;\n}\n\n// ============================================================================\n// TRACE CONTEXT HELPERS\n// ============================================================================\n\n/**\n * Format trace context to W3C traceparent string\n */\nfunction formatTraceContext(ctx: TraceContext): string {\n const flags = ctx.traceFlags.toString(16).padStart(2, \"0\");\n return `00-${ctx.traceId}-${ctx.spanId}-${flags}`;\n}\n\n/**\n * Parse W3C traceparent string to trace context\n */\nexport function parseTraceContext(traceparent: string): TraceContext | null {\n const parts = traceparent.split(\"-\");\n if (parts.length !== 4) {\n return null;\n }\n\n const [version, traceId, spanId, flags] = parts;\n if (version !== \"00\" || !traceId || !spanId || !flags) {\n return null;\n }\n\n return {\n traceId,\n spanId,\n traceFlags: parseInt(flags, 16),\n };\n}\n\n// ============================================================================\n// VALIDATION\n// ============================================================================\n\n/**\n * Validate CloudEvents structure\n */\nexport function validateEvent(event: unknown): event is ParsEvent {\n if (!event || typeof event !== \"object\") {\n return false;\n }\n\n const e = event as Record<string, unknown>;\n\n // Required fields\n if (e[\"specversion\"] !== \"1.0\") return false;\n if (typeof e[\"type\"] !== \"string\" || (e[\"type\"] as string).length === 0) return false;\n if (typeof e[\"source\"] !== \"string\" || (e[\"source\"] as string).length === 0) return false;\n if (typeof e[\"id\"] !== \"string\" || (e[\"id\"] as string).length === 0) return false;\n if (typeof e[\"time\"] !== \"string\") return false;\n\n return true;\n}\n\n/**\n * Validate compact event structure\n */\nexport function validateCompactEvent(event: unknown): event is CompactEvent {\n if (!event || typeof event !== \"object\") {\n return false;\n }\n\n const e = event as Record<string, unknown>;\n\n if (typeof e[\"e\"] !== \"string\" || (e[\"e\"] as string).length === 0) return false;\n if (typeof e[\"s\"] !== \"string\" || (e[\"s\"] as string).length === 0) return false;\n if (typeof e[\"i\"] !== \"string\" || (e[\"i\"] as string).length === 0) return false;\n if (typeof e[\"t\"] !== \"number\") return false;\n\n return true;\n}\n","/**\n * @parsrun/service - Event Handler\n * Event handler registration and execution\n */\n\nimport type { Logger } from \"@parsrun/core\";\nimport { createLogger } from \"@parsrun/core\";\nimport type {\n ParsEvent,\n EventHandler,\n EventHandlerContext,\n EventHandlerOptions,\n Unsubscribe,\n} from \"../types.js\";\nimport { matchEventType } from \"./format.js\";\nimport type { DeadLetterQueue } from \"./dead-letter.js\";\n\n// ============================================================================\n// EVENT HANDLER REGISTRY\n// ============================================================================\n\n/**\n * Resolved handler options with required fields\n */\nexport interface ResolvedHandlerOptions {\n retries: number;\n backoff: \"linear\" | \"exponential\";\n maxDelay: number;\n onExhausted: \"alert\" | \"log\" | \"discard\";\n deadLetter?: string;\n}\n\nexport interface HandlerRegistration {\n /** Event type pattern (supports wildcards) */\n pattern: string;\n /** Handler function */\n handler: EventHandler;\n /** Handler options */\n options: ResolvedHandlerOptions;\n}\n\nexport interface EventHandlerRegistryOptions {\n /** Logger */\n logger?: Logger;\n /** Dead letter queue */\n deadLetterQueue?: DeadLetterQueue;\n /** Default handler options */\n defaultOptions?: Partial<EventHandlerOptions>;\n}\n\n/**\n * Registry for event handlers\n */\nexport class EventHandlerRegistry {\n private readonly handlers: Map<string, HandlerRegistration[]> = new Map();\n private readonly logger: Logger;\n private readonly deadLetterQueue?: DeadLetterQueue;\n private readonly defaultOptions: ResolvedHandlerOptions;\n\n constructor(options: EventHandlerRegistryOptions = {}) {\n this.logger = options.logger ?? createLogger({ name: \"event-handler\" });\n if (options.deadLetterQueue) {\n this.deadLetterQueue = options.deadLetterQueue;\n }\n const defaultOpts: ResolvedHandlerOptions = {\n retries: options.defaultOptions?.retries ?? 3,\n backoff: options.defaultOptions?.backoff ?? \"exponential\",\n maxDelay: options.defaultOptions?.maxDelay ?? 30_000,\n onExhausted: options.defaultOptions?.onExhausted ?? \"log\",\n };\n if (options.defaultOptions?.deadLetter) {\n defaultOpts.deadLetter = options.defaultOptions.deadLetter;\n }\n this.defaultOptions = defaultOpts;\n }\n\n /**\n * Register an event handler\n */\n register(\n pattern: string,\n handler: EventHandler,\n options?: EventHandlerOptions\n ): Unsubscribe {\n const registration: HandlerRegistration = {\n pattern,\n handler,\n options: {\n ...this.defaultOptions,\n ...options,\n },\n };\n\n const handlers = this.handlers.get(pattern) ?? [];\n handlers.push(registration);\n this.handlers.set(pattern, handlers);\n\n this.logger.debug(`Handler registered for pattern: ${pattern}`);\n\n // Return unsubscribe function\n return () => {\n const currentHandlers = this.handlers.get(pattern);\n if (currentHandlers) {\n const index = currentHandlers.indexOf(registration);\n if (index !== -1) {\n currentHandlers.splice(index, 1);\n if (currentHandlers.length === 0) {\n this.handlers.delete(pattern);\n }\n this.logger.debug(`Handler unregistered for pattern: ${pattern}`);\n }\n }\n };\n }\n\n /**\n * Handle an event\n */\n async handle(event: ParsEvent): Promise<void> {\n const matchingHandlers = this.getMatchingHandlers(event.type);\n\n if (matchingHandlers.length === 0) {\n this.logger.debug(`No handlers for event type: ${event.type}`, {\n eventId: event.id,\n });\n return;\n }\n\n this.logger.debug(`Handling event: ${event.type}`, {\n eventId: event.id,\n handlerCount: matchingHandlers.length,\n });\n\n // Execute handlers in parallel\n const results = await Promise.allSettled(\n matchingHandlers.map((reg) => this.executeHandler(event, reg))\n );\n\n // Log failures\n for (let i = 0; i < results.length; i++) {\n const result = results[i];\n if (result?.status === \"rejected\") {\n this.logger.error(\n `Handler failed for ${event.type}`,\n result.reason as Error,\n { eventId: event.id, pattern: matchingHandlers[i]?.pattern }\n );\n }\n }\n }\n\n /**\n * Execute a single handler with retry logic\n */\n private async executeHandler(\n event: ParsEvent,\n registration: HandlerRegistration\n ): Promise<void> {\n const { handler, options } = registration;\n const maxAttempts = options.retries + 1;\n let lastError: Error | undefined;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const context: EventHandlerContext = {\n logger: this.logger.child({\n eventId: event.id,\n pattern: registration.pattern,\n attempt,\n }),\n attempt,\n maxAttempts,\n isRetry: attempt > 1,\n };\n\n // Add trace context if available\n if (event.parstracecontext) {\n const traceCtx = parseTraceContext(event.parstracecontext);\n if (traceCtx) {\n context.traceContext = traceCtx;\n }\n }\n\n await handler(event, context);\n return; // Success\n } catch (error) {\n lastError = error as Error;\n\n if (attempt < maxAttempts) {\n const delay = this.calculateBackoff(attempt, options);\n this.logger.warn(\n `Handler failed, retrying in ${delay}ms`,\n { eventId: event.id, attempt, maxAttempts }\n );\n await sleep(delay);\n }\n }\n }\n\n // All retries exhausted\n await this.handleExhausted(event, registration, lastError!);\n }\n\n /**\n * Calculate backoff delay\n */\n private calculateBackoff(\n attempt: number,\n options: ResolvedHandlerOptions\n ): number {\n const baseDelay = 100;\n\n if (options.backoff === \"exponential\") {\n return Math.min(baseDelay * Math.pow(2, attempt - 1), options.maxDelay);\n }\n\n // Linear\n return Math.min(baseDelay * attempt, options.maxDelay);\n }\n\n /**\n * Handle exhausted retries\n */\n private async handleExhausted(\n event: ParsEvent,\n registration: HandlerRegistration,\n error: Error\n ): Promise<void> {\n const { options } = registration;\n\n // Send to dead letter queue\n if (options.deadLetter && this.deadLetterQueue) {\n await this.deadLetterQueue.add({\n event,\n error: error.message,\n pattern: registration.pattern,\n attempts: options.retries + 1,\n });\n }\n\n // Handle based on onExhausted option\n switch (options.onExhausted) {\n case \"alert\":\n this.logger.error(\n `[ALERT] Event handler exhausted all retries`,\n error,\n {\n eventId: event.id,\n eventType: event.type,\n pattern: registration.pattern,\n }\n );\n break;\n case \"discard\":\n this.logger.debug(`Event discarded after exhausted retries`, {\n eventId: event.id,\n });\n break;\n case \"log\":\n default:\n this.logger.warn(`Event handler exhausted all retries`, {\n eventId: event.id,\n error: error.message,\n });\n }\n }\n\n /**\n * Get handlers matching an event type\n */\n private getMatchingHandlers(eventType: string): HandlerRegistration[] {\n const matching: HandlerRegistration[] = [];\n\n for (const [pattern, handlers] of this.handlers) {\n if (matchEventType(eventType, pattern)) {\n matching.push(...handlers);\n }\n }\n\n return matching;\n }\n\n /**\n * Get all registered patterns\n */\n getPatterns(): string[] {\n return Array.from(this.handlers.keys());\n }\n\n /**\n * Check if a pattern has handlers\n */\n hasHandlers(pattern: string): boolean {\n return this.handlers.has(pattern);\n }\n\n /**\n * Clear all handlers\n */\n clear(): void {\n this.handlers.clear();\n }\n}\n\n/**\n * Create an event handler registry\n */\nexport function createEventHandlerRegistry(\n options?: EventHandlerRegistryOptions\n): EventHandlerRegistry {\n return new EventHandlerRegistry(options);\n}\n\n// ============================================================================\n// HELPERS\n// ============================================================================\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction parseTraceContext(traceparent: string): {\n traceId: string;\n spanId: string;\n traceFlags: number;\n} | undefined {\n const parts = traceparent.split(\"-\");\n if (parts.length !== 4) return undefined;\n\n const [, traceId, spanId, flags] = parts;\n if (!traceId || !spanId || !flags) return undefined;\n\n return {\n traceId,\n spanId,\n traceFlags: parseInt(flags, 16),\n };\n}\n","/**\n * @parsrun/service - Durable Object Transport\n * RPC/Event transport using Cloudflare Durable Objects\n */\n\nimport type { Logger } from \"@parsrun/core\";\nimport { createLogger } from \"@parsrun/core\";\nimport type {\n RpcRequest,\n RpcResponse,\n RpcTransport,\n ParsEvent,\n EventTransport,\n EventHandler,\n EventHandlerOptions,\n Unsubscribe,\n} from \"../../types.js\";\nimport { type Serializer, jsonSerializer } from \"../../serialization/index.js\";\nimport { TransportError } from \"../../rpc/errors.js\";\nimport { EventHandlerRegistry } from \"../../events/handler.js\";\n\n// ============================================================================\n// DURABLE OBJECT TYPES\n// ============================================================================\n\n/**\n * Durable Object namespace binding\n */\nexport interface DurableObjectNamespace {\n idFromName(name: string): DurableObjectId;\n idFromString(id: string): DurableObjectId;\n newUniqueId(): DurableObjectId;\n get(id: DurableObjectId): DurableObjectStub;\n}\n\n/**\n * Durable Object ID\n */\nexport interface DurableObjectId {\n toString(): string;\n}\n\n/**\n * Durable Object stub for making requests\n */\nexport interface DurableObjectStub {\n fetch(input: string | Request | URL, init?: RequestInit): Promise<Response>;\n}\n\n// ============================================================================\n// DURABLE OBJECT TRANSPORT\n// ============================================================================\n\nexport interface DurableObjectTransportOptions {\n /** Durable Object namespace */\n namespace: DurableObjectNamespace;\n /** Object ID or name resolver */\n objectId: string | ((request: RpcRequest) => string);\n /** Serializer (default: JSON) */\n serializer?: Serializer;\n /** Logger */\n logger?: Logger;\n}\n\n/**\n * RPC transport using Durable Objects\n *\n * Routes requests to specific Durable Object instances,\n * enabling stateful, single-threaded execution.\n */\nexport class DurableObjectTransport implements RpcTransport {\n readonly name = \"durable-object\";\n private readonly namespace: DurableObjectNamespace;\n private readonly objectIdResolver: (request: RpcRequest) => string;\n private readonly serializer: Serializer;\n private readonly logger: Logger;\n\n constructor(options: DurableObjectTransportOptions) {\n this.namespace = options.namespace;\n this.objectIdResolver =\n typeof options.objectId === \"function\"\n ? options.objectId\n : () => options.objectId as string;\n this.serializer = options.serializer ?? jsonSerializer;\n this.logger = options.logger ?? createLogger({ name: \"durable-object\" });\n }\n\n async call<TInput, TOutput>(request: RpcRequest<TInput>): Promise<RpcResponse<TOutput>> {\n try {\n // Resolve object ID\n const objectIdName = this.objectIdResolver(request);\n const id = this.namespace.idFromName(objectIdName);\n const stub = this.namespace.get(id);\n\n // Make request to Durable Object\n const body = this.serializer.encode(request);\n const response = await stub.fetch(\"http://internal/rpc\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": this.serializer.contentType,\n },\n body: typeof body === \"string\" ? body : body,\n });\n\n // Parse response\n const text = await response.text();\n return this.serializer.decode(text) as RpcResponse<TOutput>;\n } catch (error) {\n this.logger.error(\"Durable Object call failed\", error as Error);\n throw new TransportError(\n `Durable Object call failed: ${(error as Error).message}`,\n error as Error\n );\n }\n }\n\n async close(): Promise<void> {\n // No cleanup needed\n }\n}\n\n/**\n * Create a Durable Object transport\n */\nexport function createDurableObjectTransport(\n options: DurableObjectTransportOptions\n): DurableObjectTransport {\n return new DurableObjectTransport(options);\n}\n\n// ============================================================================\n// DURABLE OBJECT EVENT TRANSPORT\n// ============================================================================\n\nexport interface DurableObjectEventTransportOptions {\n /** Durable Object namespace */\n namespace: DurableObjectNamespace;\n /** Object ID resolver (e.g., by tenant ID) */\n objectIdResolver: (event: ParsEvent) => string;\n /** Logger */\n logger?: Logger;\n}\n\n/**\n * Event transport using Durable Objects\n *\n * Routes events to specific Durable Object instances,\n * useful for tenant-specific event processing.\n */\nexport class DurableObjectEventTransport implements EventTransport {\n readonly name = \"durable-object-events\";\n private readonly namespace: DurableObjectNamespace;\n private readonly objectIdResolver: (event: ParsEvent) => string;\n private readonly logger: Logger;\n private readonly registry: EventHandlerRegistry;\n\n constructor(options: DurableObjectEventTransportOptions) {\n this.namespace = options.namespace;\n this.objectIdResolver = options.objectIdResolver;\n this.logger = options.logger ?? createLogger({ name: \"do-events\" });\n this.registry = new EventHandlerRegistry({ logger: this.logger });\n }\n\n async emit<T>(event: ParsEvent<T>): Promise<void> {\n try {\n const objectIdName = this.objectIdResolver(event);\n const id = this.namespace.idFromName(objectIdName);\n const stub = this.namespace.get(id);\n\n await stub.fetch(\"http://internal/event\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(event),\n });\n } catch (error) {\n this.logger.error(\"Failed to emit event to Durable Object\", error as Error);\n throw error;\n }\n }\n\n subscribe(\n eventType: string,\n handler: EventHandler,\n options?: EventHandlerOptions\n ): Unsubscribe {\n return this.registry.register(eventType, handler, options);\n }\n\n async close(): Promise<void> {\n this.registry.clear();\n }\n}\n\n// ============================================================================\n// DURABLE OBJECT BASE CLASS\n// ============================================================================\n\nimport type { RpcServer } from \"../../rpc/server.js\";\n\n/**\n * Base class for service Durable Objects\n *\n * @example\n * ```typescript\n * export class PaymentsDO extends ServiceDurableObject {\n * constructor(state: DurableObjectState, env: Env) {\n * super(state, env, createPaymentsServer());\n * }\n * }\n * ```\n */\nexport abstract class ServiceDurableObject {\n protected readonly state: DurableObjectState;\n protected readonly rpcServer: RpcServer;\n protected readonly eventRegistry: EventHandlerRegistry;\n protected readonly logger: Logger;\n\n constructor(\n state: DurableObjectState,\n _env: unknown,\n rpcServer: RpcServer\n ) {\n this.state = state;\n this.rpcServer = rpcServer;\n this.eventRegistry = new EventHandlerRegistry();\n this.logger = createLogger({ name: `do:${rpcServer.getDefinition().name}` });\n }\n\n async fetch(request: Request): Promise<Response> {\n const url = new URL(request.url);\n\n if (request.method === \"POST\" && url.pathname === \"/rpc\") {\n return this.handleRpc(request);\n }\n\n if (request.method === \"POST\" && url.pathname === \"/event\") {\n return this.handleEvent(request);\n }\n\n return new Response(\"Not Found\", { status: 404 });\n }\n\n private async handleRpc(request: Request): Promise<Response> {\n try {\n const body = await request.json() as RpcRequest;\n const response = await this.rpcServer.handle(body);\n\n return new Response(JSON.stringify(response), {\n status: response.success ? 200 : 500,\n headers: { \"Content-Type\": \"application/json\" },\n });\n } catch (error) {\n this.logger.error(\"RPC handler error\", error as Error);\n return new Response(\n JSON.stringify({\n success: false,\n error: { code: \"INTERNAL_ERROR\", message: (error as Error).message },\n }),\n { status: 500, headers: { \"Content-Type\": \"application/json\" } }\n );\n }\n }\n\n private async handleEvent(request: Request): Promise<Response> {\n try {\n const event = await request.json() as ParsEvent;\n await this.eventRegistry.handle(event);\n return new Response(\"OK\", { status: 200 });\n } catch (error) {\n this.logger.error(\"Event handler error\", error as Error);\n return new Response(\"Error\", { status: 500 });\n }\n }\n\n /**\n * Register an event handler\n */\n protected on(\n eventType: string,\n handler: EventHandler,\n options?: EventHandlerOptions\n ): Unsubscribe {\n return this.eventRegistry.register(eventType, handler, options);\n }\n}\n\n/**\n * Durable Object state interface\n */\ninterface DurableObjectState {\n id: DurableObjectId;\n storage: DurableObjectStorage;\n blockConcurrencyWhile<T>(callback: () => Promise<T>): Promise<T>;\n}\n\ninterface DurableObjectStorage {\n get<T>(key: string): Promise<T | undefined>;\n get<T>(keys: string[]): Promise<Map<string, T>>;\n put<T>(key: string, value: T): Promise<void>;\n put<T>(entries: Record<string, T>): Promise<void>;\n delete(key: string): Promise<boolean>;\n delete(keys: string[]): Promise<number>;\n list<T>(options?: { prefix?: string; limit?: number }): Promise<Map<string, T>>;\n}\n"],"mappings":"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","names":["createLogger","createLogger","createLogger","createLogger","createLogger","createLogger"]}
|