@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.
@@ -0,0 +1,746 @@
1
+ // src/transports/cloudflare/binding.ts
2
+ import { createLogger } from "@parsrun/core";
3
+
4
+ // src/serialization/index.ts
5
+ var jsonSerializer = {
6
+ encode(data) {
7
+ return JSON.stringify(data);
8
+ },
9
+ decode(raw) {
10
+ if (raw instanceof ArrayBuffer) {
11
+ const decoder = new TextDecoder();
12
+ return JSON.parse(decoder.decode(raw));
13
+ }
14
+ return JSON.parse(raw);
15
+ },
16
+ contentType: "application/json"
17
+ };
18
+
19
+ // src/rpc/errors.ts
20
+ import { ParsError } from "@parsrun/core";
21
+ var RpcError = class extends ParsError {
22
+ retryable;
23
+ retryAfter;
24
+ constructor(message, code, statusCode = 500, options) {
25
+ super(message, code, statusCode, options?.details);
26
+ this.name = "RpcError";
27
+ this.retryable = options?.retryable ?? false;
28
+ if (options?.retryAfter !== void 0) {
29
+ this.retryAfter = options.retryAfter;
30
+ }
31
+ }
32
+ };
33
+ var TransportError = class extends RpcError {
34
+ constructor(message, cause) {
35
+ const options = {
36
+ retryable: true
37
+ };
38
+ if (cause) {
39
+ options.details = { cause: cause.message };
40
+ }
41
+ super(message, "TRANSPORT_ERROR", 502, options);
42
+ this.name = "TransportError";
43
+ }
44
+ };
45
+ var SerializationError = class extends RpcError {
46
+ constructor(message, cause) {
47
+ const options = {
48
+ retryable: false
49
+ };
50
+ if (cause) {
51
+ options.details = { cause: cause.message };
52
+ }
53
+ super(message, "SERIALIZATION_ERROR", 400, options);
54
+ this.name = "SerializationError";
55
+ }
56
+ };
57
+
58
+ // src/rpc/transports/http.ts
59
+ function parseTraceparent(header) {
60
+ const parts = header.split("-");
61
+ if (parts.length !== 4) {
62
+ return null;
63
+ }
64
+ const [version, traceId, spanId, flags] = parts;
65
+ if (version !== "00" || !traceId || !spanId || !flags) {
66
+ return null;
67
+ }
68
+ if (traceId.length !== 32 || spanId.length !== 16 || flags.length !== 2) {
69
+ return null;
70
+ }
71
+ return {
72
+ traceId,
73
+ spanId,
74
+ traceFlags: parseInt(flags, 16)
75
+ };
76
+ }
77
+
78
+ // src/transports/cloudflare/binding.ts
79
+ var ServiceBindingTransport = class {
80
+ name = "service-binding";
81
+ serviceName;
82
+ binding;
83
+ serializer;
84
+ logger;
85
+ constructor(options) {
86
+ this.serviceName = options.serviceName;
87
+ this.binding = options.binding;
88
+ this.serializer = options.serializer ?? jsonSerializer;
89
+ this.logger = options.logger ?? createLogger({ name: `binding:${options.serviceName}` });
90
+ }
91
+ async call(request) {
92
+ const startTime = Date.now();
93
+ try {
94
+ let body;
95
+ try {
96
+ body = this.serializer.encode(request);
97
+ } catch (error) {
98
+ throw new SerializationError(
99
+ "Failed to serialize request",
100
+ error instanceof Error ? error : void 0
101
+ );
102
+ }
103
+ const headers = {
104
+ "Content-Type": this.serializer.contentType,
105
+ Accept: this.serializer.contentType,
106
+ "X-Request-ID": request.id,
107
+ "X-Service": request.service,
108
+ "X-Method": request.method,
109
+ "X-Method-Type": request.type
110
+ };
111
+ if (request.version) {
112
+ headers["X-Service-Version"] = request.version;
113
+ }
114
+ if (request.traceContext) {
115
+ headers["traceparent"] = formatTraceparent(request.traceContext);
116
+ if (request.traceContext.traceState) {
117
+ headers["tracestate"] = request.traceContext.traceState;
118
+ }
119
+ }
120
+ if (request.metadata?.tenantId) {
121
+ headers["X-Tenant-ID"] = String(request.metadata.tenantId);
122
+ }
123
+ const response = await this.binding.fetch("http://internal/rpc", {
124
+ method: "POST",
125
+ headers,
126
+ body: typeof body === "string" ? body : body
127
+ });
128
+ let responseData;
129
+ try {
130
+ const contentType = response.headers.get("Content-Type") ?? "";
131
+ if (contentType.includes("msgpack")) {
132
+ const buffer = await response.arrayBuffer();
133
+ responseData = this.serializer.decode(buffer);
134
+ } else {
135
+ const text = await response.text();
136
+ responseData = this.serializer.decode(text);
137
+ }
138
+ } catch (error) {
139
+ throw new SerializationError(
140
+ "Failed to deserialize response",
141
+ error instanceof Error ? error : void 0
142
+ );
143
+ }
144
+ const duration = Date.now() - startTime;
145
+ this.logger.debug(`RPC call completed`, {
146
+ service: this.serviceName,
147
+ method: request.method,
148
+ durationMs: duration,
149
+ success: responseData.success
150
+ });
151
+ return responseData;
152
+ } catch (error) {
153
+ const duration = Date.now() - startTime;
154
+ if (error instanceof SerializationError) {
155
+ throw error;
156
+ }
157
+ this.logger.error(`RPC call failed`, error, {
158
+ service: this.serviceName,
159
+ method: request.method,
160
+ durationMs: duration
161
+ });
162
+ throw new TransportError(
163
+ `Service binding call failed: ${error.message}`,
164
+ error
165
+ );
166
+ }
167
+ }
168
+ async close() {
169
+ }
170
+ };
171
+ function createServiceBindingTransport(options) {
172
+ return new ServiceBindingTransport(options);
173
+ }
174
+ function createServiceBindingHandler(server, options) {
175
+ const serializer = options?.serializer ?? jsonSerializer;
176
+ const logger = options?.logger ?? createLogger({ name: "binding-handler" });
177
+ return async (request) => {
178
+ const url = new URL(request.url);
179
+ if (request.method !== "POST" || url.pathname !== "/rpc") {
180
+ return new Response("Not Found", { status: 404 });
181
+ }
182
+ try {
183
+ const contentType = request.headers.get("Content-Type") ?? "";
184
+ let body;
185
+ if (contentType.includes("msgpack")) {
186
+ const buffer = await request.arrayBuffer();
187
+ body = serializer.decode(buffer);
188
+ } else {
189
+ const text = await request.text();
190
+ body = serializer.decode(text);
191
+ }
192
+ const traceparent = request.headers.get("traceparent");
193
+ if (traceparent) {
194
+ const parsedTrace = parseTraceparent(traceparent);
195
+ if (parsedTrace) {
196
+ body.traceContext = parsedTrace;
197
+ const tracestate = request.headers.get("tracestate");
198
+ if (tracestate) {
199
+ body.traceContext.traceState = tracestate;
200
+ }
201
+ }
202
+ }
203
+ const tenantId = request.headers.get("X-Tenant-ID");
204
+ if (tenantId) {
205
+ body.metadata = { ...body.metadata, tenantId };
206
+ }
207
+ const response = await server.handle(body);
208
+ const responseBody = serializer.encode(response);
209
+ return new Response(
210
+ typeof responseBody === "string" ? responseBody : responseBody,
211
+ {
212
+ status: response.success ? 200 : getHttpStatus(response.error?.code),
213
+ headers: {
214
+ "Content-Type": serializer.contentType,
215
+ "X-Request-ID": body.id
216
+ }
217
+ }
218
+ );
219
+ } catch (error) {
220
+ logger.error("Handler error", error);
221
+ return new Response(
222
+ JSON.stringify({
223
+ success: false,
224
+ error: {
225
+ code: "INTERNAL_ERROR",
226
+ message: error.message
227
+ }
228
+ }),
229
+ {
230
+ status: 500,
231
+ headers: { "Content-Type": "application/json" }
232
+ }
233
+ );
234
+ }
235
+ };
236
+ }
237
+ function formatTraceparent(ctx) {
238
+ const flags = ctx.traceFlags.toString(16).padStart(2, "0");
239
+ return `00-${ctx.traceId}-${ctx.spanId}-${flags}`;
240
+ }
241
+ function getHttpStatus(code) {
242
+ switch (code) {
243
+ case "METHOD_NOT_FOUND":
244
+ case "SERVICE_NOT_FOUND":
245
+ return 404;
246
+ case "VERSION_MISMATCH":
247
+ case "VALIDATION_ERROR":
248
+ return 400;
249
+ case "UNAUTHORIZED":
250
+ return 401;
251
+ case "FORBIDDEN":
252
+ return 403;
253
+ case "TIMEOUT":
254
+ return 504;
255
+ case "CIRCUIT_OPEN":
256
+ case "BULKHEAD_REJECTED":
257
+ return 503;
258
+ default:
259
+ return 500;
260
+ }
261
+ }
262
+
263
+ // src/transports/cloudflare/queue.ts
264
+ import { createLogger as createLogger3 } from "@parsrun/core";
265
+
266
+ // src/events/format.ts
267
+ import { generateId } from "@parsrun/core";
268
+ function toCompactEvent(event) {
269
+ const compact = {
270
+ e: event.type,
271
+ s: event.source,
272
+ i: event.id,
273
+ t: new Date(event.time).getTime(),
274
+ d: event.data
275
+ };
276
+ if (event.parstracecontext) compact.ctx = event.parstracecontext;
277
+ if (event.parstenantid) compact.tid = event.parstenantid;
278
+ return compact;
279
+ }
280
+ function fromCompactEvent(compact, source) {
281
+ const event = {
282
+ specversion: "1.0",
283
+ type: compact.e,
284
+ source: source ?? compact.s,
285
+ id: compact.i,
286
+ time: new Date(compact.t).toISOString(),
287
+ datacontenttype: "application/json",
288
+ data: compact.d
289
+ };
290
+ if (compact.ctx) event.parstracecontext = compact.ctx;
291
+ if (compact.tid) event.parstenantid = compact.tid;
292
+ return event;
293
+ }
294
+ function matchEventType(type, pattern) {
295
+ if (pattern === "*" || pattern === "**") {
296
+ return true;
297
+ }
298
+ const typeParts = type.split(".");
299
+ const patternParts = pattern.split(".");
300
+ let ti = 0;
301
+ let pi = 0;
302
+ while (ti < typeParts.length && pi < patternParts.length) {
303
+ const pp = patternParts[pi];
304
+ if (pp === "**") {
305
+ if (pi === patternParts.length - 1) {
306
+ return true;
307
+ }
308
+ for (let i = ti; i <= typeParts.length; i++) {
309
+ const remaining = typeParts.slice(i).join(".");
310
+ const remainingPattern = patternParts.slice(pi + 1).join(".");
311
+ if (matchEventType(remaining, remainingPattern)) {
312
+ return true;
313
+ }
314
+ }
315
+ return false;
316
+ }
317
+ if (pp === "*") {
318
+ ti++;
319
+ pi++;
320
+ continue;
321
+ }
322
+ if (pp !== typeParts[ti]) {
323
+ return false;
324
+ }
325
+ ti++;
326
+ pi++;
327
+ }
328
+ return ti === typeParts.length && pi === patternParts.length;
329
+ }
330
+
331
+ // src/events/handler.ts
332
+ import { createLogger as createLogger2 } from "@parsrun/core";
333
+ var EventHandlerRegistry = class {
334
+ handlers = /* @__PURE__ */ new Map();
335
+ logger;
336
+ deadLetterQueue;
337
+ defaultOptions;
338
+ constructor(options = {}) {
339
+ this.logger = options.logger ?? createLogger2({ name: "event-handler" });
340
+ if (options.deadLetterQueue) {
341
+ this.deadLetterQueue = options.deadLetterQueue;
342
+ }
343
+ const defaultOpts = {
344
+ retries: options.defaultOptions?.retries ?? 3,
345
+ backoff: options.defaultOptions?.backoff ?? "exponential",
346
+ maxDelay: options.defaultOptions?.maxDelay ?? 3e4,
347
+ onExhausted: options.defaultOptions?.onExhausted ?? "log"
348
+ };
349
+ if (options.defaultOptions?.deadLetter) {
350
+ defaultOpts.deadLetter = options.defaultOptions.deadLetter;
351
+ }
352
+ this.defaultOptions = defaultOpts;
353
+ }
354
+ /**
355
+ * Register an event handler
356
+ */
357
+ register(pattern, handler, options) {
358
+ const registration = {
359
+ pattern,
360
+ handler,
361
+ options: {
362
+ ...this.defaultOptions,
363
+ ...options
364
+ }
365
+ };
366
+ const handlers = this.handlers.get(pattern) ?? [];
367
+ handlers.push(registration);
368
+ this.handlers.set(pattern, handlers);
369
+ this.logger.debug(`Handler registered for pattern: ${pattern}`);
370
+ return () => {
371
+ const currentHandlers = this.handlers.get(pattern);
372
+ if (currentHandlers) {
373
+ const index = currentHandlers.indexOf(registration);
374
+ if (index !== -1) {
375
+ currentHandlers.splice(index, 1);
376
+ if (currentHandlers.length === 0) {
377
+ this.handlers.delete(pattern);
378
+ }
379
+ this.logger.debug(`Handler unregistered for pattern: ${pattern}`);
380
+ }
381
+ }
382
+ };
383
+ }
384
+ /**
385
+ * Handle an event
386
+ */
387
+ async handle(event) {
388
+ const matchingHandlers = this.getMatchingHandlers(event.type);
389
+ if (matchingHandlers.length === 0) {
390
+ this.logger.debug(`No handlers for event type: ${event.type}`, {
391
+ eventId: event.id
392
+ });
393
+ return;
394
+ }
395
+ this.logger.debug(`Handling event: ${event.type}`, {
396
+ eventId: event.id,
397
+ handlerCount: matchingHandlers.length
398
+ });
399
+ const results = await Promise.allSettled(
400
+ matchingHandlers.map((reg) => this.executeHandler(event, reg))
401
+ );
402
+ for (let i = 0; i < results.length; i++) {
403
+ const result = results[i];
404
+ if (result?.status === "rejected") {
405
+ this.logger.error(
406
+ `Handler failed for ${event.type}`,
407
+ result.reason,
408
+ { eventId: event.id, pattern: matchingHandlers[i]?.pattern }
409
+ );
410
+ }
411
+ }
412
+ }
413
+ /**
414
+ * Execute a single handler with retry logic
415
+ */
416
+ async executeHandler(event, registration) {
417
+ const { handler, options } = registration;
418
+ const maxAttempts = options.retries + 1;
419
+ let lastError;
420
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
421
+ try {
422
+ const context = {
423
+ logger: this.logger.child({
424
+ eventId: event.id,
425
+ pattern: registration.pattern,
426
+ attempt
427
+ }),
428
+ attempt,
429
+ maxAttempts,
430
+ isRetry: attempt > 1
431
+ };
432
+ if (event.parstracecontext) {
433
+ const traceCtx = parseTraceContext(event.parstracecontext);
434
+ if (traceCtx) {
435
+ context.traceContext = traceCtx;
436
+ }
437
+ }
438
+ await handler(event, context);
439
+ return;
440
+ } catch (error) {
441
+ lastError = error;
442
+ if (attempt < maxAttempts) {
443
+ const delay = this.calculateBackoff(attempt, options);
444
+ this.logger.warn(
445
+ `Handler failed, retrying in ${delay}ms`,
446
+ { eventId: event.id, attempt, maxAttempts }
447
+ );
448
+ await sleep(delay);
449
+ }
450
+ }
451
+ }
452
+ await this.handleExhausted(event, registration, lastError);
453
+ }
454
+ /**
455
+ * Calculate backoff delay
456
+ */
457
+ calculateBackoff(attempt, options) {
458
+ const baseDelay = 100;
459
+ if (options.backoff === "exponential") {
460
+ return Math.min(baseDelay * Math.pow(2, attempt - 1), options.maxDelay);
461
+ }
462
+ return Math.min(baseDelay * attempt, options.maxDelay);
463
+ }
464
+ /**
465
+ * Handle exhausted retries
466
+ */
467
+ async handleExhausted(event, registration, error) {
468
+ const { options } = registration;
469
+ if (options.deadLetter && this.deadLetterQueue) {
470
+ await this.deadLetterQueue.add({
471
+ event,
472
+ error: error.message,
473
+ pattern: registration.pattern,
474
+ attempts: options.retries + 1
475
+ });
476
+ }
477
+ switch (options.onExhausted) {
478
+ case "alert":
479
+ this.logger.error(
480
+ `[ALERT] Event handler exhausted all retries`,
481
+ error,
482
+ {
483
+ eventId: event.id,
484
+ eventType: event.type,
485
+ pattern: registration.pattern
486
+ }
487
+ );
488
+ break;
489
+ case "discard":
490
+ this.logger.debug(`Event discarded after exhausted retries`, {
491
+ eventId: event.id
492
+ });
493
+ break;
494
+ case "log":
495
+ default:
496
+ this.logger.warn(`Event handler exhausted all retries`, {
497
+ eventId: event.id,
498
+ error: error.message
499
+ });
500
+ }
501
+ }
502
+ /**
503
+ * Get handlers matching an event type
504
+ */
505
+ getMatchingHandlers(eventType) {
506
+ const matching = [];
507
+ for (const [pattern, handlers] of this.handlers) {
508
+ if (matchEventType(eventType, pattern)) {
509
+ matching.push(...handlers);
510
+ }
511
+ }
512
+ return matching;
513
+ }
514
+ /**
515
+ * Get all registered patterns
516
+ */
517
+ getPatterns() {
518
+ return Array.from(this.handlers.keys());
519
+ }
520
+ /**
521
+ * Check if a pattern has handlers
522
+ */
523
+ hasHandlers(pattern) {
524
+ return this.handlers.has(pattern);
525
+ }
526
+ /**
527
+ * Clear all handlers
528
+ */
529
+ clear() {
530
+ this.handlers.clear();
531
+ }
532
+ };
533
+ function sleep(ms) {
534
+ return new Promise((resolve) => setTimeout(resolve, ms));
535
+ }
536
+ function parseTraceContext(traceparent) {
537
+ const parts = traceparent.split("-");
538
+ if (parts.length !== 4) return void 0;
539
+ const [, traceId, spanId, flags] = parts;
540
+ if (!traceId || !spanId || !flags) return void 0;
541
+ return {
542
+ traceId,
543
+ spanId,
544
+ traceFlags: parseInt(flags, 16)
545
+ };
546
+ }
547
+
548
+ // src/transports/cloudflare/queue.ts
549
+ var CloudflareQueueTransport = class {
550
+ name = "cloudflare-queue";
551
+ queue;
552
+ queueName;
553
+ compact;
554
+ logger;
555
+ batchSize;
556
+ flushInterval;
557
+ registry;
558
+ buffer = [];
559
+ flushTimer = null;
560
+ constructor(options) {
561
+ this.queue = options.queue;
562
+ this.queueName = options.queueName ?? "events";
563
+ this.compact = options.compact ?? true;
564
+ this.logger = options.logger ?? createLogger3({ name: `queue:${this.queueName}` });
565
+ this.batchSize = options.batchSize ?? 100;
566
+ this.flushInterval = options.flushInterval ?? 1e3;
567
+ this.registry = new EventHandlerRegistry({ logger: this.logger });
568
+ this.flushTimer = setInterval(() => this.flush(), this.flushInterval);
569
+ }
570
+ /**
571
+ * Emit an event to the queue
572
+ */
573
+ async emit(event) {
574
+ this.buffer.push(event);
575
+ if (this.buffer.length >= this.batchSize) {
576
+ await this.flush();
577
+ }
578
+ }
579
+ /**
580
+ * Subscribe to events (for local handler registration)
581
+ */
582
+ subscribe(eventType, handler, options) {
583
+ return this.registry.register(eventType, handler, options);
584
+ }
585
+ /**
586
+ * Flush buffered events to the queue
587
+ */
588
+ async flush() {
589
+ if (this.buffer.length === 0) return;
590
+ const events = this.buffer.splice(0, this.batchSize);
591
+ try {
592
+ if (events.length === 1) {
593
+ const body = this.compact ? toCompactEvent(events[0]) : events[0];
594
+ await this.queue.send(body);
595
+ } else {
596
+ const messages = events.map((event) => ({
597
+ body: this.compact ? toCompactEvent(event) : event
598
+ }));
599
+ await this.queue.sendBatch(messages);
600
+ }
601
+ this.logger.debug(`Sent ${events.length} events to queue`, {
602
+ queue: this.queueName
603
+ });
604
+ } catch (error) {
605
+ this.buffer.unshift(...events);
606
+ this.logger.error("Failed to send events to queue", error);
607
+ throw error;
608
+ }
609
+ }
610
+ /**
611
+ * Handle a queue message (called by queue consumer)
612
+ */
613
+ async handleMessage(message) {
614
+ try {
615
+ const event = this.parseEvent(message.body);
616
+ await this.registry.handle(event);
617
+ message.ack();
618
+ } catch (error) {
619
+ this.logger.error("Failed to handle queue message", error, {
620
+ messageId: message.id
621
+ });
622
+ message.retry();
623
+ }
624
+ }
625
+ /**
626
+ * Handle a batch of queue messages
627
+ */
628
+ async handleBatch(batch) {
629
+ const results = await Promise.allSettled(
630
+ batch.messages.map((msg) => this.handleMessage(msg))
631
+ );
632
+ const failures = results.filter((r) => r.status === "rejected");
633
+ if (failures.length > 0) {
634
+ this.logger.warn(`${failures.length}/${batch.messages.length} messages failed`);
635
+ }
636
+ }
637
+ /**
638
+ * Parse event from message body
639
+ */
640
+ parseEvent(body) {
641
+ if (this.compact && isCompactEvent(body)) {
642
+ return fromCompactEvent(body);
643
+ }
644
+ return body;
645
+ }
646
+ /**
647
+ * Close the transport
648
+ */
649
+ async close() {
650
+ if (this.flushTimer) {
651
+ clearInterval(this.flushTimer);
652
+ this.flushTimer = null;
653
+ }
654
+ await this.flush();
655
+ this.registry.clear();
656
+ }
657
+ };
658
+ function createCloudflareQueueTransport(options) {
659
+ return new CloudflareQueueTransport(options);
660
+ }
661
+ function createQueueConsumer(registry, options) {
662
+ const compact = options?.compact ?? true;
663
+ const logger = options?.logger ?? createLogger3({ name: "queue-consumer" });
664
+ return async (batch) => {
665
+ logger.info(`Processing batch of ${batch.messages.length} messages`, {
666
+ queue: batch.queue
667
+ });
668
+ for (const message of batch.messages) {
669
+ try {
670
+ let event;
671
+ if (compact && isCompactEvent(message.body)) {
672
+ event = fromCompactEvent(message.body);
673
+ } else {
674
+ event = message.body;
675
+ }
676
+ await registry.handle(event);
677
+ message.ack();
678
+ } catch (error) {
679
+ logger.error("Failed to process message", error, {
680
+ messageId: message.id
681
+ });
682
+ message.retry();
683
+ }
684
+ }
685
+ };
686
+ }
687
+ function isCompactEvent(body) {
688
+ if (!body || typeof body !== "object") return false;
689
+ const obj = body;
690
+ return typeof obj["e"] === "string" && typeof obj["s"] === "string" && typeof obj["i"] === "string" && typeof obj["t"] === "number";
691
+ }
692
+
693
+ // src/transports/cloudflare/durable-object.ts
694
+ import { createLogger as createLogger4 } from "@parsrun/core";
695
+ var DurableObjectTransport = class {
696
+ name = "durable-object";
697
+ namespace;
698
+ objectIdResolver;
699
+ serializer;
700
+ logger;
701
+ constructor(options) {
702
+ this.namespace = options.namespace;
703
+ this.objectIdResolver = typeof options.objectId === "function" ? options.objectId : () => options.objectId;
704
+ this.serializer = options.serializer ?? jsonSerializer;
705
+ this.logger = options.logger ?? createLogger4({ name: "durable-object" });
706
+ }
707
+ async call(request) {
708
+ try {
709
+ const objectIdName = this.objectIdResolver(request);
710
+ const id = this.namespace.idFromName(objectIdName);
711
+ const stub = this.namespace.get(id);
712
+ const body = this.serializer.encode(request);
713
+ const response = await stub.fetch("http://internal/rpc", {
714
+ method: "POST",
715
+ headers: {
716
+ "Content-Type": this.serializer.contentType
717
+ },
718
+ body: typeof body === "string" ? body : body
719
+ });
720
+ const text = await response.text();
721
+ return this.serializer.decode(text);
722
+ } catch (error) {
723
+ this.logger.error("Durable Object call failed", error);
724
+ throw new TransportError(
725
+ `Durable Object call failed: ${error.message}`,
726
+ error
727
+ );
728
+ }
729
+ }
730
+ async close() {
731
+ }
732
+ };
733
+ function createDurableObjectTransport(options) {
734
+ return new DurableObjectTransport(options);
735
+ }
736
+ export {
737
+ CloudflareQueueTransport,
738
+ DurableObjectTransport,
739
+ ServiceBindingTransport,
740
+ createCloudflareQueueTransport,
741
+ createDurableObjectTransport,
742
+ createQueueConsumer,
743
+ createServiceBindingHandler,
744
+ createServiceBindingTransport
745
+ };
746
+ //# sourceMappingURL=index.js.map