@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/dist/index.js ADDED
@@ -0,0 +1,3589 @@
1
+ // src/define.ts
2
+ function defineService(definition) {
3
+ validateServiceDefinition(definition);
4
+ return Object.freeze({
5
+ ...definition,
6
+ queries: definition.queries ? Object.freeze({ ...definition.queries }) : void 0,
7
+ mutations: definition.mutations ? Object.freeze({ ...definition.mutations }) : void 0,
8
+ events: definition.events ? Object.freeze({
9
+ emits: definition.events.emits ? Object.freeze({ ...definition.events.emits }) : void 0,
10
+ handles: definition.events.handles ? Object.freeze([...definition.events.handles]) : void 0
11
+ }) : void 0
12
+ });
13
+ }
14
+ function validateServiceDefinition(definition) {
15
+ if (!definition.name) {
16
+ throw new Error("Service name is required");
17
+ }
18
+ if (!definition.version) {
19
+ throw new Error("Service version is required");
20
+ }
21
+ const versionRegex = /^\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?$/;
22
+ if (!versionRegex.test(definition.version)) {
23
+ throw new Error(`Invalid version format: ${definition.version}. Expected semver (e.g., 1.0.0)`);
24
+ }
25
+ const nameRegex = /^[a-zA-Z][a-zA-Z0-9_]*$/;
26
+ if (definition.queries) {
27
+ for (const name of Object.keys(definition.queries)) {
28
+ if (!nameRegex.test(name)) {
29
+ throw new Error(
30
+ `Invalid query name: ${name}. Must start with letter and contain only alphanumeric and underscore`
31
+ );
32
+ }
33
+ }
34
+ }
35
+ if (definition.mutations) {
36
+ for (const name of Object.keys(definition.mutations)) {
37
+ if (!nameRegex.test(name)) {
38
+ throw new Error(
39
+ `Invalid mutation name: ${name}. Must start with letter and contain only alphanumeric and underscore`
40
+ );
41
+ }
42
+ }
43
+ }
44
+ const eventNameRegex = /^[a-zA-Z][a-zA-Z0-9_.]*$/;
45
+ if (definition.events?.emits) {
46
+ for (const name of Object.keys(definition.events.emits)) {
47
+ if (!eventNameRegex.test(name)) {
48
+ throw new Error(
49
+ `Invalid event name: ${name}. Must start with letter and contain only alphanumeric, underscore, and dot`
50
+ );
51
+ }
52
+ }
53
+ }
54
+ if (definition.events?.handles) {
55
+ for (const name of definition.events.handles) {
56
+ if (!eventNameRegex.test(name)) {
57
+ throw new Error(
58
+ `Invalid handled event name: ${name}. Must start with letter and contain only alphanumeric, underscore, and dot`
59
+ );
60
+ }
61
+ }
62
+ }
63
+ }
64
+ function getServiceMethods(definition) {
65
+ return {
66
+ queries: definition.queries ? Object.keys(definition.queries) : [],
67
+ mutations: definition.mutations ? Object.keys(definition.mutations) : []
68
+ };
69
+ }
70
+ function getServiceEvents(definition) {
71
+ return {
72
+ emits: definition.events?.emits ? Object.keys(definition.events.emits) : [],
73
+ handles: definition.events?.handles ?? []
74
+ };
75
+ }
76
+ function satisfiesVersion(version, requirement) {
77
+ const versionParts = version.split(".").map((p) => parseInt(p, 10));
78
+ const requirementParts = requirement.split(".");
79
+ for (let i = 0; i < requirementParts.length; i++) {
80
+ const req = requirementParts[i];
81
+ if (req === "x" || req === "*") {
82
+ continue;
83
+ }
84
+ const reqNum = parseInt(req ?? "0", 10);
85
+ const verNum = versionParts[i] ?? 0;
86
+ if (verNum !== reqNum) {
87
+ return false;
88
+ }
89
+ }
90
+ return true;
91
+ }
92
+ function isMethodDeprecated(definition, methodName, type) {
93
+ const methods = type === "query" ? definition.queries : definition.mutations;
94
+ const method = methods?.[methodName];
95
+ if (!method?.deprecated) {
96
+ return { deprecated: false };
97
+ }
98
+ const result = {
99
+ deprecated: true,
100
+ since: method.deprecated
101
+ };
102
+ if (method.replacement) {
103
+ result.replacement = method.replacement;
104
+ }
105
+ return result;
106
+ }
107
+ function getMethodTimeout(definition, methodName, type, defaultTimeout) {
108
+ const methods = type === "query" ? definition.queries : definition.mutations;
109
+ const method = methods?.[methodName];
110
+ return method?.timeout ?? defaultTimeout;
111
+ }
112
+
113
+ // src/client.ts
114
+ import { generateId as generateId3 } from "@parsrun/core";
115
+
116
+ // src/config.ts
117
+ var DEFAULT_EVENT_CONFIG = {
118
+ format: "cloudevents",
119
+ internalCompact: true
120
+ };
121
+ var DEFAULT_SERIALIZATION_CONFIG = {
122
+ format: "json"
123
+ };
124
+ var DEFAULT_TRACING_CONFIG = {
125
+ enabled: true,
126
+ sampler: { ratio: 0.1 },
127
+ exporter: "console",
128
+ endpoint: "",
129
+ serviceName: "pars-service"
130
+ };
131
+ var DEFAULT_VERSIONING_CONFIG = {
132
+ strategy: "header",
133
+ defaultVersion: "1.x"
134
+ };
135
+ var DEFAULT_RESILIENCE_CONFIG = {
136
+ circuitBreaker: {
137
+ enabled: true,
138
+ failureThreshold: 5,
139
+ resetTimeout: 3e4,
140
+ successThreshold: 2
141
+ },
142
+ bulkhead: {
143
+ maxConcurrent: 100,
144
+ maxQueue: 50
145
+ },
146
+ timeout: 5e3,
147
+ retry: {
148
+ attempts: 3,
149
+ backoff: "exponential",
150
+ initialDelay: 100,
151
+ maxDelay: 1e4
152
+ }
153
+ };
154
+ var DEFAULT_DEAD_LETTER_CONFIG = {
155
+ enabled: true,
156
+ retention: "30d",
157
+ onFail: "alert",
158
+ alertThreshold: 10
159
+ };
160
+ var DEFAULT_SERVICE_CONFIG = {
161
+ events: DEFAULT_EVENT_CONFIG,
162
+ serialization: DEFAULT_SERIALIZATION_CONFIG,
163
+ tracing: DEFAULT_TRACING_CONFIG,
164
+ versioning: DEFAULT_VERSIONING_CONFIG,
165
+ resilience: DEFAULT_RESILIENCE_CONFIG,
166
+ deadLetter: DEFAULT_DEAD_LETTER_CONFIG
167
+ };
168
+ function mergeConfig(userConfig) {
169
+ if (!userConfig) {
170
+ return { ...DEFAULT_SERVICE_CONFIG };
171
+ }
172
+ return {
173
+ events: {
174
+ ...DEFAULT_EVENT_CONFIG,
175
+ ...userConfig.events
176
+ },
177
+ serialization: {
178
+ ...DEFAULT_SERIALIZATION_CONFIG,
179
+ ...userConfig.serialization
180
+ },
181
+ tracing: {
182
+ ...DEFAULT_TRACING_CONFIG,
183
+ ...userConfig.tracing
184
+ },
185
+ versioning: {
186
+ ...DEFAULT_VERSIONING_CONFIG,
187
+ ...userConfig.versioning
188
+ },
189
+ resilience: {
190
+ ...DEFAULT_RESILIENCE_CONFIG,
191
+ ...userConfig.resilience,
192
+ circuitBreaker: {
193
+ ...DEFAULT_RESILIENCE_CONFIG.circuitBreaker,
194
+ ...userConfig.resilience?.circuitBreaker
195
+ },
196
+ bulkhead: {
197
+ ...DEFAULT_RESILIENCE_CONFIG.bulkhead,
198
+ ...userConfig.resilience?.bulkhead
199
+ },
200
+ retry: {
201
+ ...DEFAULT_RESILIENCE_CONFIG.retry,
202
+ ...userConfig.resilience?.retry
203
+ }
204
+ },
205
+ deadLetter: {
206
+ ...DEFAULT_DEAD_LETTER_CONFIG,
207
+ ...userConfig.deadLetter
208
+ }
209
+ };
210
+ }
211
+ function createDevConfig(overrides) {
212
+ return mergeConfig({
213
+ tracing: {
214
+ enabled: true,
215
+ sampler: "always",
216
+ exporter: "console"
217
+ },
218
+ resilience: {
219
+ circuitBreaker: { enabled: false },
220
+ timeout: 3e4
221
+ },
222
+ ...overrides
223
+ });
224
+ }
225
+ function createProdConfig(overrides) {
226
+ return mergeConfig({
227
+ tracing: {
228
+ enabled: true,
229
+ sampler: { ratio: 0.1 },
230
+ exporter: "otlp"
231
+ },
232
+ resilience: {
233
+ circuitBreaker: { enabled: true },
234
+ timeout: 5e3
235
+ },
236
+ ...overrides
237
+ });
238
+ }
239
+ function validateConfig(config) {
240
+ const errors = [];
241
+ if (config.tracing?.sampler && typeof config.tracing.sampler === "object") {
242
+ const ratio = config.tracing.sampler.ratio;
243
+ if (ratio < 0 || ratio > 1) {
244
+ errors.push("tracing.sampler.ratio must be between 0 and 1");
245
+ }
246
+ }
247
+ if (config.resilience?.timeout !== void 0 && config.resilience.timeout < 0) {
248
+ errors.push("resilience.timeout must be non-negative");
249
+ }
250
+ if (config.resilience?.circuitBreaker?.failureThreshold !== void 0) {
251
+ if (config.resilience.circuitBreaker.failureThreshold < 1) {
252
+ errors.push("resilience.circuitBreaker.failureThreshold must be at least 1");
253
+ }
254
+ }
255
+ if (config.resilience?.bulkhead?.maxConcurrent !== void 0) {
256
+ if (config.resilience.bulkhead.maxConcurrent < 1) {
257
+ errors.push("resilience.bulkhead.maxConcurrent must be at least 1");
258
+ }
259
+ }
260
+ if (config.resilience?.retry?.attempts !== void 0) {
261
+ if (config.resilience.retry.attempts < 0) {
262
+ errors.push("resilience.retry.attempts must be non-negative");
263
+ }
264
+ }
265
+ return {
266
+ valid: errors.length === 0,
267
+ errors
268
+ };
269
+ }
270
+
271
+ // src/rpc/client.ts
272
+ import { generateId } from "@parsrun/core";
273
+
274
+ // src/rpc/errors.ts
275
+ import { ParsError } from "@parsrun/core";
276
+ var RpcError = class extends ParsError {
277
+ retryable;
278
+ retryAfter;
279
+ constructor(message, code, statusCode = 500, options) {
280
+ super(message, code, statusCode, options?.details);
281
+ this.name = "RpcError";
282
+ this.retryable = options?.retryable ?? false;
283
+ if (options?.retryAfter !== void 0) {
284
+ this.retryAfter = options.retryAfter;
285
+ }
286
+ }
287
+ };
288
+ var ServiceNotFoundError = class extends RpcError {
289
+ constructor(serviceName) {
290
+ super(`Service not found: ${serviceName}`, "SERVICE_NOT_FOUND", 404, {
291
+ retryable: false,
292
+ details: { service: serviceName }
293
+ });
294
+ this.name = "ServiceNotFoundError";
295
+ }
296
+ };
297
+ var MethodNotFoundError = class extends RpcError {
298
+ constructor(serviceName, methodName) {
299
+ super(
300
+ `Method not found: ${serviceName}.${methodName}`,
301
+ "METHOD_NOT_FOUND",
302
+ 404,
303
+ {
304
+ retryable: false,
305
+ details: { service: serviceName, method: methodName }
306
+ }
307
+ );
308
+ this.name = "MethodNotFoundError";
309
+ }
310
+ };
311
+ var VersionMismatchError = class extends RpcError {
312
+ constructor(serviceName, requested, available) {
313
+ super(
314
+ `Version mismatch for ${serviceName}: requested ${requested}, available ${available}`,
315
+ "VERSION_MISMATCH",
316
+ 400,
317
+ {
318
+ retryable: false,
319
+ details: { service: serviceName, requested, available }
320
+ }
321
+ );
322
+ this.name = "VersionMismatchError";
323
+ }
324
+ };
325
+ var TimeoutError = class extends RpcError {
326
+ constructor(serviceName, methodName, timeoutMs) {
327
+ super(
328
+ `Request to ${serviceName}.${methodName} timed out after ${timeoutMs}ms`,
329
+ "TIMEOUT",
330
+ 504,
331
+ {
332
+ retryable: true,
333
+ details: { service: serviceName, method: methodName, timeout: timeoutMs }
334
+ }
335
+ );
336
+ this.name = "TimeoutError";
337
+ }
338
+ };
339
+ var CircuitOpenError = class extends RpcError {
340
+ constructor(serviceName, resetAfterMs) {
341
+ super(
342
+ `Circuit breaker open for ${serviceName}`,
343
+ "CIRCUIT_OPEN",
344
+ 503,
345
+ {
346
+ retryable: true,
347
+ retryAfter: Math.ceil(resetAfterMs / 1e3),
348
+ details: { service: serviceName, resetAfterMs }
349
+ }
350
+ );
351
+ this.name = "CircuitOpenError";
352
+ }
353
+ };
354
+ var BulkheadRejectedError = class extends RpcError {
355
+ constructor(serviceName) {
356
+ super(
357
+ `Request rejected by bulkhead for ${serviceName}: too many concurrent requests`,
358
+ "BULKHEAD_REJECTED",
359
+ 503,
360
+ {
361
+ retryable: true,
362
+ retryAfter: 1,
363
+ details: { service: serviceName }
364
+ }
365
+ );
366
+ this.name = "BulkheadRejectedError";
367
+ }
368
+ };
369
+ var TransportError = class extends RpcError {
370
+ constructor(message, cause) {
371
+ const options = {
372
+ retryable: true
373
+ };
374
+ if (cause) {
375
+ options.details = { cause: cause.message };
376
+ }
377
+ super(message, "TRANSPORT_ERROR", 502, options);
378
+ this.name = "TransportError";
379
+ }
380
+ };
381
+ var SerializationError = class extends RpcError {
382
+ constructor(message, cause) {
383
+ const options = {
384
+ retryable: false
385
+ };
386
+ if (cause) {
387
+ options.details = { cause: cause.message };
388
+ }
389
+ super(message, "SERIALIZATION_ERROR", 400, options);
390
+ this.name = "SerializationError";
391
+ }
392
+ };
393
+ function toRpcError(error) {
394
+ if (error instanceof RpcError) {
395
+ return error;
396
+ }
397
+ if (error instanceof Error) {
398
+ return new RpcError(error.message, "INTERNAL_ERROR", 500, {
399
+ retryable: false,
400
+ details: { originalError: error.name }
401
+ });
402
+ }
403
+ return new RpcError(String(error), "UNKNOWN_ERROR", 500, {
404
+ retryable: false
405
+ });
406
+ }
407
+
408
+ // src/resilience/circuit-breaker.ts
409
+ var CircuitBreaker = class {
410
+ _state = "closed";
411
+ failures = 0;
412
+ successes = 0;
413
+ lastFailureTime = 0;
414
+ options;
415
+ constructor(options) {
416
+ this.options = options;
417
+ }
418
+ /**
419
+ * Get current state
420
+ */
421
+ get state() {
422
+ if (this._state === "open") {
423
+ const timeSinceFailure = Date.now() - this.lastFailureTime;
424
+ if (timeSinceFailure >= this.options.resetTimeout) {
425
+ this.transitionTo("half-open");
426
+ }
427
+ }
428
+ return this._state;
429
+ }
430
+ /**
431
+ * Execute a function with circuit breaker protection
432
+ */
433
+ async execute(fn) {
434
+ const currentState = this.state;
435
+ if (currentState === "open") {
436
+ const resetAfter = this.options.resetTimeout - (Date.now() - this.lastFailureTime);
437
+ throw new CircuitOpenError("service", Math.max(0, resetAfter));
438
+ }
439
+ try {
440
+ const result = await fn();
441
+ this.onSuccess();
442
+ return result;
443
+ } catch (error) {
444
+ this.onFailure();
445
+ throw error;
446
+ }
447
+ }
448
+ /**
449
+ * Record a successful call
450
+ */
451
+ onSuccess() {
452
+ if (this._state === "half-open") {
453
+ this.successes++;
454
+ if (this.successes >= this.options.successThreshold) {
455
+ this.transitionTo("closed");
456
+ }
457
+ } else if (this._state === "closed") {
458
+ this.failures = 0;
459
+ }
460
+ }
461
+ /**
462
+ * Record a failed call
463
+ */
464
+ onFailure() {
465
+ this.lastFailureTime = Date.now();
466
+ if (this._state === "half-open") {
467
+ this.transitionTo("open");
468
+ } else if (this._state === "closed") {
469
+ this.failures++;
470
+ if (this.failures >= this.options.failureThreshold) {
471
+ this.transitionTo("open");
472
+ }
473
+ }
474
+ }
475
+ /**
476
+ * Transition to a new state
477
+ */
478
+ transitionTo(newState) {
479
+ const oldState = this._state;
480
+ this._state = newState;
481
+ if (newState === "closed") {
482
+ this.failures = 0;
483
+ this.successes = 0;
484
+ } else if (newState === "half-open") {
485
+ this.successes = 0;
486
+ }
487
+ this.options.onStateChange?.(oldState, newState);
488
+ }
489
+ /**
490
+ * Manually reset the circuit breaker
491
+ */
492
+ reset() {
493
+ this.transitionTo("closed");
494
+ }
495
+ /**
496
+ * Get circuit breaker statistics
497
+ */
498
+ getStats() {
499
+ return {
500
+ state: this.state,
501
+ failures: this.failures,
502
+ successes: this.successes,
503
+ lastFailureTime: this.lastFailureTime
504
+ };
505
+ }
506
+ };
507
+
508
+ // src/resilience/bulkhead.ts
509
+ var Bulkhead = class {
510
+ _concurrent = 0;
511
+ queue = [];
512
+ options;
513
+ constructor(options) {
514
+ this.options = options;
515
+ }
516
+ /**
517
+ * Get current concurrent count
518
+ */
519
+ get concurrent() {
520
+ return this._concurrent;
521
+ }
522
+ /**
523
+ * Get current queue size
524
+ */
525
+ get queued() {
526
+ return this.queue.length;
527
+ }
528
+ /**
529
+ * Check if bulkhead is full
530
+ */
531
+ get isFull() {
532
+ return this._concurrent >= this.options.maxConcurrent && this.queue.length >= this.options.maxQueue;
533
+ }
534
+ /**
535
+ * Execute a function with bulkhead protection
536
+ */
537
+ async execute(fn) {
538
+ if (this._concurrent < this.options.maxConcurrent) {
539
+ return this.doExecute(fn);
540
+ }
541
+ if (this.queue.length < this.options.maxQueue) {
542
+ return this.enqueue(fn);
543
+ }
544
+ this.options.onRejected?.();
545
+ throw new BulkheadRejectedError("service");
546
+ }
547
+ /**
548
+ * Execute immediately
549
+ */
550
+ async doExecute(fn) {
551
+ this._concurrent++;
552
+ try {
553
+ return await fn();
554
+ } finally {
555
+ this._concurrent--;
556
+ this.processQueue();
557
+ }
558
+ }
559
+ /**
560
+ * Add to queue
561
+ */
562
+ enqueue(fn) {
563
+ return new Promise((resolve, reject) => {
564
+ this.queue.push({
565
+ fn,
566
+ resolve,
567
+ reject
568
+ });
569
+ });
570
+ }
571
+ /**
572
+ * Process queued requests
573
+ */
574
+ processQueue() {
575
+ if (this.queue.length === 0) return;
576
+ if (this._concurrent >= this.options.maxConcurrent) return;
577
+ const queued = this.queue.shift();
578
+ if (!queued) return;
579
+ this.doExecute(queued.fn).then(queued.resolve).catch(queued.reject);
580
+ }
581
+ /**
582
+ * Get bulkhead statistics
583
+ */
584
+ getStats() {
585
+ return {
586
+ concurrent: this._concurrent,
587
+ queued: this.queue.length,
588
+ maxConcurrent: this.options.maxConcurrent,
589
+ maxQueue: this.options.maxQueue
590
+ };
591
+ }
592
+ /**
593
+ * Clear the queue (reject all pending)
594
+ */
595
+ clearQueue() {
596
+ const error = new BulkheadRejectedError("service");
597
+ while (this.queue.length > 0) {
598
+ const queued = this.queue.shift();
599
+ queued?.reject(error);
600
+ }
601
+ }
602
+ };
603
+
604
+ // src/resilience/retry.ts
605
+ var defaultShouldRetry = (error) => {
606
+ if (error && typeof error === "object" && "retryable" in error) {
607
+ return error.retryable;
608
+ }
609
+ return false;
610
+ };
611
+ function calculateDelay(attempt, options) {
612
+ let delay;
613
+ if (options.backoff === "exponential") {
614
+ delay = options.initialDelay * Math.pow(2, attempt);
615
+ } else {
616
+ delay = options.initialDelay * (attempt + 1);
617
+ }
618
+ delay = Math.min(delay, options.maxDelay);
619
+ if (options.jitter && options.jitter > 0) {
620
+ const jitterRange = delay * options.jitter;
621
+ delay = delay - jitterRange / 2 + Math.random() * jitterRange;
622
+ }
623
+ return Math.round(delay);
624
+ }
625
+ function sleep(ms) {
626
+ return new Promise((resolve) => setTimeout(resolve, ms));
627
+ }
628
+ function withRetry(fn, options) {
629
+ const shouldRetry = options.shouldRetry ?? defaultShouldRetry;
630
+ return async () => {
631
+ let lastError;
632
+ for (let attempt = 0; attempt <= options.attempts; attempt++) {
633
+ try {
634
+ return await fn();
635
+ } catch (error) {
636
+ lastError = error;
637
+ if (attempt >= options.attempts || !shouldRetry(error, attempt)) {
638
+ throw error;
639
+ }
640
+ const delay = calculateDelay(attempt, options);
641
+ options.onRetry?.(error, attempt + 1, delay);
642
+ await sleep(delay);
643
+ }
644
+ }
645
+ throw lastError;
646
+ };
647
+ }
648
+ async function executeWithRetry(fn, options) {
649
+ return withRetry(fn, options)();
650
+ }
651
+ function createRetryWrapper(defaultOptions) {
652
+ const defaults = {
653
+ attempts: defaultOptions.attempts ?? 3,
654
+ backoff: defaultOptions.backoff ?? "exponential",
655
+ initialDelay: defaultOptions.initialDelay ?? 100,
656
+ maxDelay: defaultOptions.maxDelay ?? 1e4,
657
+ jitter: defaultOptions.jitter ?? 0.1
658
+ };
659
+ if (defaultOptions.shouldRetry) {
660
+ defaults.shouldRetry = defaultOptions.shouldRetry;
661
+ }
662
+ if (defaultOptions.onRetry) {
663
+ defaults.onRetry = defaultOptions.onRetry;
664
+ }
665
+ return async (fn, options) => {
666
+ return executeWithRetry(fn, { ...defaults, ...options });
667
+ };
668
+ }
669
+
670
+ // src/resilience/timeout.ts
671
+ var TimeoutExceededError = class extends Error {
672
+ timeout;
673
+ constructor(timeout) {
674
+ super(`Operation timed out after ${timeout}ms`);
675
+ this.name = "TimeoutExceededError";
676
+ this.timeout = timeout;
677
+ }
678
+ };
679
+ function withTimeout(fn, timeoutMs, onTimeout) {
680
+ return async () => {
681
+ let timeoutId;
682
+ const timeoutPromise = new Promise((_, reject) => {
683
+ timeoutId = setTimeout(() => {
684
+ if (onTimeout) {
685
+ try {
686
+ onTimeout();
687
+ } catch (error) {
688
+ reject(error);
689
+ return;
690
+ }
691
+ }
692
+ reject(new TimeoutExceededError(timeoutMs));
693
+ }, timeoutMs);
694
+ });
695
+ try {
696
+ return await Promise.race([fn(), timeoutPromise]);
697
+ } finally {
698
+ if (timeoutId !== void 0) {
699
+ clearTimeout(timeoutId);
700
+ }
701
+ }
702
+ };
703
+ }
704
+ async function executeWithTimeout(fn, timeoutMs, onTimeout) {
705
+ return withTimeout(fn, timeoutMs, onTimeout)();
706
+ }
707
+ function createTimeoutWrapper(defaultTimeoutMs) {
708
+ return async (fn, timeoutMs) => {
709
+ return executeWithTimeout(fn, timeoutMs ?? defaultTimeoutMs);
710
+ };
711
+ }
712
+ async function raceWithTimeout(promises, timeoutMs) {
713
+ let timeoutId;
714
+ const timeoutPromise = new Promise((_, reject) => {
715
+ timeoutId = setTimeout(() => {
716
+ reject(new TimeoutExceededError(timeoutMs));
717
+ }, timeoutMs);
718
+ });
719
+ try {
720
+ return await Promise.race([...promises, timeoutPromise]);
721
+ } finally {
722
+ if (timeoutId !== void 0) {
723
+ clearTimeout(timeoutId);
724
+ }
725
+ }
726
+ }
727
+ async function executeWithDeadline(fn, deadline) {
728
+ const now = Date.now();
729
+ const deadlineMs = deadline.getTime();
730
+ const timeoutMs = Math.max(0, deadlineMs - now);
731
+ if (timeoutMs === 0) {
732
+ throw new TimeoutExceededError(0);
733
+ }
734
+ return executeWithTimeout(fn, timeoutMs);
735
+ }
736
+
737
+ // src/rpc/client.ts
738
+ var RpcClient = class {
739
+ service;
740
+ transport;
741
+ config;
742
+ defaultMetadata;
743
+ circuitBreaker;
744
+ bulkhead;
745
+ constructor(options) {
746
+ this.service = options.service;
747
+ this.transport = options.transport;
748
+ this.config = mergeConfig(options.config);
749
+ this.defaultMetadata = options.defaultMetadata ?? {};
750
+ const cbConfig = this.config.resilience?.circuitBreaker;
751
+ if (cbConfig && cbConfig.enabled && cbConfig.failureThreshold !== void 0 && cbConfig.resetTimeout !== void 0 && cbConfig.successThreshold !== void 0) {
752
+ this.circuitBreaker = new CircuitBreaker({
753
+ failureThreshold: cbConfig.failureThreshold,
754
+ resetTimeout: cbConfig.resetTimeout,
755
+ successThreshold: cbConfig.successThreshold
756
+ });
757
+ } else {
758
+ this.circuitBreaker = null;
759
+ }
760
+ const bhConfig = this.config.resilience?.bulkhead;
761
+ if (bhConfig && bhConfig.maxConcurrent !== void 0 && bhConfig.maxQueue !== void 0) {
762
+ this.bulkhead = new Bulkhead({
763
+ maxConcurrent: bhConfig.maxConcurrent,
764
+ maxQueue: bhConfig.maxQueue
765
+ });
766
+ } else {
767
+ this.bulkhead = null;
768
+ }
769
+ }
770
+ /**
771
+ * Execute a query
772
+ */
773
+ async query(method, input, options) {
774
+ return this.call("query", method, input, options);
775
+ }
776
+ /**
777
+ * Execute a mutation
778
+ */
779
+ async mutate(method, input, options) {
780
+ return this.call("mutation", method, input, options);
781
+ }
782
+ /**
783
+ * Internal call implementation
784
+ */
785
+ async call(type, method, input, options) {
786
+ const request = {
787
+ id: generateId(),
788
+ service: this.service,
789
+ method,
790
+ type,
791
+ input,
792
+ metadata: {
793
+ ...this.defaultMetadata,
794
+ ...options?.metadata
795
+ }
796
+ };
797
+ const version = options?.version ?? this.config.versioning.defaultVersion;
798
+ if (version) {
799
+ request.version = version;
800
+ }
801
+ if (options?.traceContext) {
802
+ request.traceContext = options.traceContext;
803
+ }
804
+ const timeout = options?.timeout ?? this.config.resilience.timeout ?? 3e4;
805
+ const retryConfig = options?.retry ?? this.config.resilience.retry;
806
+ let execute = async () => {
807
+ const response = await this.transport.call(request);
808
+ if (!response.success) {
809
+ const error = toRpcError(
810
+ new Error(response.error?.message ?? "Unknown error")
811
+ );
812
+ throw error;
813
+ }
814
+ return response.output;
815
+ };
816
+ execute = withTimeout(execute, timeout, () => {
817
+ throw new TimeoutError(this.service, method, timeout);
818
+ });
819
+ const attempts = retryConfig?.attempts ?? 0;
820
+ if (attempts > 0) {
821
+ execute = withRetry(execute, {
822
+ attempts,
823
+ backoff: retryConfig?.backoff ?? "exponential",
824
+ initialDelay: retryConfig?.initialDelay ?? 100,
825
+ maxDelay: retryConfig?.maxDelay ?? 5e3,
826
+ shouldRetry: (error) => {
827
+ if (error instanceof Error && "retryable" in error) {
828
+ return error.retryable;
829
+ }
830
+ return false;
831
+ }
832
+ });
833
+ }
834
+ if (this.circuitBreaker) {
835
+ const cb = this.circuitBreaker;
836
+ const originalExecute = execute;
837
+ execute = async () => {
838
+ return cb.execute(originalExecute);
839
+ };
840
+ }
841
+ if (this.bulkhead) {
842
+ const bh = this.bulkhead;
843
+ const originalExecute = execute;
844
+ execute = async () => {
845
+ return bh.execute(originalExecute);
846
+ };
847
+ }
848
+ return execute();
849
+ }
850
+ /**
851
+ * Get circuit breaker state
852
+ */
853
+ getCircuitState() {
854
+ return this.circuitBreaker?.state ?? null;
855
+ }
856
+ /**
857
+ * Get bulkhead stats
858
+ */
859
+ getBulkheadStats() {
860
+ if (!this.bulkhead) return null;
861
+ return {
862
+ concurrent: this.bulkhead.concurrent,
863
+ queued: this.bulkhead.queued
864
+ };
865
+ }
866
+ /**
867
+ * Close the client and release resources
868
+ */
869
+ async close() {
870
+ await this.transport.close?.();
871
+ }
872
+ };
873
+ function createRpcClient(options) {
874
+ return new RpcClient(options);
875
+ }
876
+
877
+ // src/rpc/transports/embedded.ts
878
+ var EmbeddedTransport = class {
879
+ name = "embedded";
880
+ server;
881
+ constructor(server) {
882
+ this.server = server;
883
+ }
884
+ async call(request) {
885
+ return this.server.handle(request);
886
+ }
887
+ async close() {
888
+ }
889
+ };
890
+ function createEmbeddedTransport(server) {
891
+ return new EmbeddedTransport(server);
892
+ }
893
+ var EmbeddedRegistry = class _EmbeddedRegistry {
894
+ static instance = null;
895
+ servers = /* @__PURE__ */ new Map();
896
+ constructor() {
897
+ }
898
+ static getInstance() {
899
+ if (!_EmbeddedRegistry.instance) {
900
+ _EmbeddedRegistry.instance = new _EmbeddedRegistry();
901
+ }
902
+ return _EmbeddedRegistry.instance;
903
+ }
904
+ /**
905
+ * Register a service
906
+ */
907
+ register(name, server) {
908
+ if (this.servers.has(name)) {
909
+ throw new Error(`Service already registered: ${name}`);
910
+ }
911
+ this.servers.set(name, server);
912
+ }
913
+ /**
914
+ * Unregister a service
915
+ */
916
+ unregister(name) {
917
+ return this.servers.delete(name);
918
+ }
919
+ /**
920
+ * Get a service by name
921
+ */
922
+ get(name) {
923
+ return this.servers.get(name);
924
+ }
925
+ /**
926
+ * Check if a service is registered
927
+ */
928
+ has(name) {
929
+ return this.servers.has(name);
930
+ }
931
+ /**
932
+ * Get all registered service names
933
+ */
934
+ getServiceNames() {
935
+ return Array.from(this.servers.keys());
936
+ }
937
+ /**
938
+ * Create a transport for a registered service
939
+ */
940
+ createTransport(name) {
941
+ const server = this.servers.get(name);
942
+ if (!server) {
943
+ throw new Error(`Service not found: ${name}`);
944
+ }
945
+ return new EmbeddedTransport(server);
946
+ }
947
+ /**
948
+ * Clear all registered services
949
+ */
950
+ clear() {
951
+ this.servers.clear();
952
+ }
953
+ /**
954
+ * Reset the singleton instance (for testing)
955
+ */
956
+ static reset() {
957
+ _EmbeddedRegistry.instance = null;
958
+ }
959
+ };
960
+ function getEmbeddedRegistry() {
961
+ return EmbeddedRegistry.getInstance();
962
+ }
963
+
964
+ // src/serialization/index.ts
965
+ var jsonSerializer = {
966
+ encode(data) {
967
+ return JSON.stringify(data);
968
+ },
969
+ decode(raw) {
970
+ if (raw instanceof ArrayBuffer) {
971
+ const decoder = new TextDecoder();
972
+ return JSON.parse(decoder.decode(raw));
973
+ }
974
+ return JSON.parse(raw);
975
+ },
976
+ contentType: "application/json"
977
+ };
978
+ function msgpackEncode(value) {
979
+ const parts = [];
980
+ function encode(val) {
981
+ if (val === null || val === void 0) {
982
+ parts.push(new Uint8Array([192]));
983
+ return;
984
+ }
985
+ if (typeof val === "boolean") {
986
+ parts.push(new Uint8Array([val ? 195 : 194]));
987
+ return;
988
+ }
989
+ if (typeof val === "number") {
990
+ if (Number.isInteger(val)) {
991
+ if (val >= 0 && val <= 127) {
992
+ parts.push(new Uint8Array([val]));
993
+ } else if (val < 0 && val >= -32) {
994
+ parts.push(new Uint8Array([val & 255]));
995
+ } else if (val >= 0 && val <= 255) {
996
+ parts.push(new Uint8Array([204, val]));
997
+ } else if (val >= 0 && val <= 65535) {
998
+ parts.push(new Uint8Array([205, val >> 8 & 255, val & 255]));
999
+ } else if (val >= 0 && val <= 4294967295) {
1000
+ parts.push(
1001
+ new Uint8Array([
1002
+ 206,
1003
+ val >> 24 & 255,
1004
+ val >> 16 & 255,
1005
+ val >> 8 & 255,
1006
+ val & 255
1007
+ ])
1008
+ );
1009
+ } else if (val >= -128 && val <= 127) {
1010
+ parts.push(new Uint8Array([208, val & 255]));
1011
+ } else if (val >= -32768 && val <= 32767) {
1012
+ parts.push(new Uint8Array([209, val >> 8 & 255, val & 255]));
1013
+ } else if (val >= -2147483648 && val <= 2147483647) {
1014
+ parts.push(
1015
+ new Uint8Array([
1016
+ 210,
1017
+ val >> 24 & 255,
1018
+ val >> 16 & 255,
1019
+ val >> 8 & 255,
1020
+ val & 255
1021
+ ])
1022
+ );
1023
+ } else {
1024
+ const buffer = new ArrayBuffer(9);
1025
+ const view = new DataView(buffer);
1026
+ view.setUint8(0, 203);
1027
+ view.setFloat64(1, val, false);
1028
+ parts.push(new Uint8Array(buffer));
1029
+ }
1030
+ } else {
1031
+ const buffer = new ArrayBuffer(9);
1032
+ const view = new DataView(buffer);
1033
+ view.setUint8(0, 203);
1034
+ view.setFloat64(1, val, false);
1035
+ parts.push(new Uint8Array(buffer));
1036
+ }
1037
+ return;
1038
+ }
1039
+ if (typeof val === "string") {
1040
+ const encoded = new TextEncoder().encode(val);
1041
+ const len = encoded.length;
1042
+ if (len <= 31) {
1043
+ parts.push(new Uint8Array([160 | len]));
1044
+ } else if (len <= 255) {
1045
+ parts.push(new Uint8Array([217, len]));
1046
+ } else if (len <= 65535) {
1047
+ parts.push(new Uint8Array([218, len >> 8 & 255, len & 255]));
1048
+ } else {
1049
+ parts.push(
1050
+ new Uint8Array([
1051
+ 219,
1052
+ len >> 24 & 255,
1053
+ len >> 16 & 255,
1054
+ len >> 8 & 255,
1055
+ len & 255
1056
+ ])
1057
+ );
1058
+ }
1059
+ parts.push(encoded);
1060
+ return;
1061
+ }
1062
+ if (Array.isArray(val)) {
1063
+ const len = val.length;
1064
+ if (len <= 15) {
1065
+ parts.push(new Uint8Array([144 | len]));
1066
+ } else if (len <= 65535) {
1067
+ parts.push(new Uint8Array([220, len >> 8 & 255, len & 255]));
1068
+ } else {
1069
+ parts.push(
1070
+ new Uint8Array([
1071
+ 221,
1072
+ len >> 24 & 255,
1073
+ len >> 16 & 255,
1074
+ len >> 8 & 255,
1075
+ len & 255
1076
+ ])
1077
+ );
1078
+ }
1079
+ for (const item of val) {
1080
+ encode(item);
1081
+ }
1082
+ return;
1083
+ }
1084
+ if (typeof val === "object") {
1085
+ const keys = Object.keys(val);
1086
+ const len = keys.length;
1087
+ if (len <= 15) {
1088
+ parts.push(new Uint8Array([128 | len]));
1089
+ } else if (len <= 65535) {
1090
+ parts.push(new Uint8Array([222, len >> 8 & 255, len & 255]));
1091
+ } else {
1092
+ parts.push(
1093
+ new Uint8Array([
1094
+ 223,
1095
+ len >> 24 & 255,
1096
+ len >> 16 & 255,
1097
+ len >> 8 & 255,
1098
+ len & 255
1099
+ ])
1100
+ );
1101
+ }
1102
+ for (const key of keys) {
1103
+ encode(key);
1104
+ encode(val[key]);
1105
+ }
1106
+ return;
1107
+ }
1108
+ parts.push(new Uint8Array([192]));
1109
+ }
1110
+ encode(value);
1111
+ const totalLength = parts.reduce((sum, p) => sum + p.length, 0);
1112
+ const result = new Uint8Array(totalLength);
1113
+ let offset = 0;
1114
+ for (const part of parts) {
1115
+ result.set(part, offset);
1116
+ offset += part.length;
1117
+ }
1118
+ return result;
1119
+ }
1120
+ function msgpackDecode(buffer) {
1121
+ let offset = 0;
1122
+ function decode() {
1123
+ if (offset >= buffer.length) {
1124
+ throw new Error("Unexpected end of buffer");
1125
+ }
1126
+ const byte = buffer[offset++];
1127
+ if (byte <= 127) {
1128
+ return byte;
1129
+ }
1130
+ if (byte >= 224) {
1131
+ return byte - 256;
1132
+ }
1133
+ if (byte >= 128 && byte <= 143) {
1134
+ const len = byte - 128;
1135
+ const result = {};
1136
+ for (let i = 0; i < len; i++) {
1137
+ const key = decode();
1138
+ result[key] = decode();
1139
+ }
1140
+ return result;
1141
+ }
1142
+ if (byte >= 144 && byte <= 159) {
1143
+ const len = byte - 144;
1144
+ const result = [];
1145
+ for (let i = 0; i < len; i++) {
1146
+ result.push(decode());
1147
+ }
1148
+ return result;
1149
+ }
1150
+ if (byte >= 160 && byte <= 191) {
1151
+ const len = byte - 160;
1152
+ const str = new TextDecoder().decode(buffer.subarray(offset, offset + len));
1153
+ offset += len;
1154
+ return str;
1155
+ }
1156
+ switch (byte) {
1157
+ case 192:
1158
+ return null;
1159
+ case 194:
1160
+ return false;
1161
+ case 195:
1162
+ return true;
1163
+ case 204:
1164
+ return buffer[offset++];
1165
+ case 205:
1166
+ return buffer[offset++] << 8 | buffer[offset++];
1167
+ case 206:
1168
+ return (buffer[offset++] << 24 >>> 0) + (buffer[offset++] << 16) + (buffer[offset++] << 8) + buffer[offset++];
1169
+ case 208: {
1170
+ const val = buffer[offset++];
1171
+ return val > 127 ? val - 256 : val;
1172
+ }
1173
+ case 209: {
1174
+ const val = buffer[offset++] << 8 | buffer[offset++];
1175
+ return val > 32767 ? val - 65536 : val;
1176
+ }
1177
+ case 210: {
1178
+ const val = buffer[offset++] << 24 | buffer[offset++] << 16 | buffer[offset++] << 8 | buffer[offset++];
1179
+ return val;
1180
+ }
1181
+ case 203: {
1182
+ const view = new DataView(buffer.buffer, buffer.byteOffset + offset, 8);
1183
+ offset += 8;
1184
+ return view.getFloat64(0, false);
1185
+ }
1186
+ case 217: {
1187
+ const len = buffer[offset++];
1188
+ const str = new TextDecoder().decode(buffer.subarray(offset, offset + len));
1189
+ offset += len;
1190
+ return str;
1191
+ }
1192
+ case 218: {
1193
+ const len = buffer[offset++] << 8 | buffer[offset++];
1194
+ const str = new TextDecoder().decode(buffer.subarray(offset, offset + len));
1195
+ offset += len;
1196
+ return str;
1197
+ }
1198
+ case 219: {
1199
+ const len = buffer[offset++] << 24 | buffer[offset++] << 16 | buffer[offset++] << 8 | buffer[offset++];
1200
+ const str = new TextDecoder().decode(buffer.subarray(offset, offset + len));
1201
+ offset += len;
1202
+ return str;
1203
+ }
1204
+ case 220: {
1205
+ const len = buffer[offset++] << 8 | buffer[offset++];
1206
+ const result = [];
1207
+ for (let i = 0; i < len; i++) {
1208
+ result.push(decode());
1209
+ }
1210
+ return result;
1211
+ }
1212
+ case 221: {
1213
+ const len = buffer[offset++] << 24 | buffer[offset++] << 16 | buffer[offset++] << 8 | buffer[offset++];
1214
+ const result = [];
1215
+ for (let i = 0; i < len; i++) {
1216
+ result.push(decode());
1217
+ }
1218
+ return result;
1219
+ }
1220
+ case 222: {
1221
+ const len = buffer[offset++] << 8 | buffer[offset++];
1222
+ const result = {};
1223
+ for (let i = 0; i < len; i++) {
1224
+ const key = decode();
1225
+ result[key] = decode();
1226
+ }
1227
+ return result;
1228
+ }
1229
+ case 223: {
1230
+ const len = buffer[offset++] << 24 | buffer[offset++] << 16 | buffer[offset++] << 8 | buffer[offset++];
1231
+ const result = {};
1232
+ for (let i = 0; i < len; i++) {
1233
+ const key = decode();
1234
+ result[key] = decode();
1235
+ }
1236
+ return result;
1237
+ }
1238
+ default:
1239
+ throw new Error(`Unknown MessagePack type: 0x${byte.toString(16)}`);
1240
+ }
1241
+ }
1242
+ return decode();
1243
+ }
1244
+ var msgpackSerializer = {
1245
+ encode(data) {
1246
+ const encoded = msgpackEncode(data);
1247
+ const buffer = new ArrayBuffer(encoded.byteLength);
1248
+ new Uint8Array(buffer).set(encoded);
1249
+ return buffer;
1250
+ },
1251
+ decode(raw) {
1252
+ if (typeof raw === "string") {
1253
+ const binary = atob(raw);
1254
+ const bytes = new Uint8Array(binary.length);
1255
+ for (let i = 0; i < binary.length; i++) {
1256
+ bytes[i] = binary.charCodeAt(i);
1257
+ }
1258
+ return msgpackDecode(bytes);
1259
+ }
1260
+ return msgpackDecode(new Uint8Array(raw));
1261
+ },
1262
+ contentType: "application/msgpack"
1263
+ };
1264
+ function getSerializer(format) {
1265
+ switch (format) {
1266
+ case "json":
1267
+ return jsonSerializer;
1268
+ case "msgpack":
1269
+ return msgpackSerializer;
1270
+ default:
1271
+ return jsonSerializer;
1272
+ }
1273
+ }
1274
+ function createSerializer(options) {
1275
+ return options;
1276
+ }
1277
+
1278
+ // src/rpc/transports/http.ts
1279
+ var HttpTransport = class {
1280
+ name = "http";
1281
+ baseUrl;
1282
+ serializer;
1283
+ headers;
1284
+ fetchFn;
1285
+ timeout;
1286
+ constructor(options) {
1287
+ this.baseUrl = options.baseUrl.replace(/\/$/, "");
1288
+ this.serializer = options.serializer ?? jsonSerializer;
1289
+ this.headers = options.headers ?? {};
1290
+ this.fetchFn = options.fetch ?? globalThis.fetch.bind(globalThis);
1291
+ this.timeout = options.timeout ?? 3e4;
1292
+ }
1293
+ async call(request) {
1294
+ const url = `${this.baseUrl}/rpc`;
1295
+ const controller = new AbortController();
1296
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
1297
+ try {
1298
+ let body;
1299
+ try {
1300
+ body = this.serializer.encode(request);
1301
+ } catch (error) {
1302
+ throw new SerializationError(
1303
+ "Failed to serialize request",
1304
+ error instanceof Error ? error : void 0
1305
+ );
1306
+ }
1307
+ const response = await this.fetchFn(url, {
1308
+ method: "POST",
1309
+ headers: {
1310
+ "Content-Type": this.serializer.contentType,
1311
+ Accept: this.serializer.contentType,
1312
+ "X-Request-ID": request.id,
1313
+ "X-Service": request.service,
1314
+ "X-Method": request.method,
1315
+ "X-Method-Type": request.type,
1316
+ ...request.version ? { "X-Service-Version": request.version } : {},
1317
+ ...request.traceContext ? {
1318
+ traceparent: formatTraceparent(request.traceContext),
1319
+ ...request.traceContext.traceState ? { tracestate: request.traceContext.traceState } : {}
1320
+ } : {},
1321
+ ...this.headers
1322
+ },
1323
+ body: body instanceof ArrayBuffer ? body : body,
1324
+ signal: controller.signal
1325
+ });
1326
+ let responseData;
1327
+ try {
1328
+ const contentType = response.headers.get("Content-Type") ?? "";
1329
+ if (contentType.includes("msgpack")) {
1330
+ const buffer = await response.arrayBuffer();
1331
+ responseData = this.serializer.decode(buffer);
1332
+ } else {
1333
+ const text = await response.text();
1334
+ responseData = this.serializer.decode(text);
1335
+ }
1336
+ } catch (error) {
1337
+ throw new SerializationError(
1338
+ "Failed to deserialize response",
1339
+ error instanceof Error ? error : void 0
1340
+ );
1341
+ }
1342
+ return responseData;
1343
+ } catch (error) {
1344
+ if (error instanceof SerializationError) {
1345
+ throw error;
1346
+ }
1347
+ if (error instanceof Error) {
1348
+ if (error.name === "AbortError") {
1349
+ throw new TransportError(`Request timeout after ${this.timeout}ms`);
1350
+ }
1351
+ throw new TransportError(`HTTP request failed: ${error.message}`, error);
1352
+ }
1353
+ throw new TransportError("Unknown transport error");
1354
+ } finally {
1355
+ clearTimeout(timeoutId);
1356
+ }
1357
+ }
1358
+ async close() {
1359
+ }
1360
+ };
1361
+ function createHttpTransport(options) {
1362
+ return new HttpTransport(options);
1363
+ }
1364
+ function formatTraceparent(ctx) {
1365
+ const flags = ctx.traceFlags.toString(16).padStart(2, "0");
1366
+ return `00-${ctx.traceId}-${ctx.spanId}-${flags}`;
1367
+ }
1368
+ function parseTraceparent(header) {
1369
+ const parts = header.split("-");
1370
+ if (parts.length !== 4) {
1371
+ return null;
1372
+ }
1373
+ const [version, traceId, spanId, flags] = parts;
1374
+ if (version !== "00" || !traceId || !spanId || !flags) {
1375
+ return null;
1376
+ }
1377
+ if (traceId.length !== 32 || spanId.length !== 16 || flags.length !== 2) {
1378
+ return null;
1379
+ }
1380
+ return {
1381
+ traceId,
1382
+ spanId,
1383
+ traceFlags: parseInt(flags, 16)
1384
+ };
1385
+ }
1386
+ function createHttpHandler(server) {
1387
+ return async (request) => {
1388
+ try {
1389
+ const contentType = request.headers.get("Content-Type") ?? "application/json";
1390
+ let body;
1391
+ if (contentType.includes("msgpack")) {
1392
+ const buffer = await request.arrayBuffer();
1393
+ body = JSON.parse(new TextDecoder().decode(buffer));
1394
+ } else {
1395
+ body = await request.json();
1396
+ }
1397
+ const rpcRequest = body;
1398
+ const traceparent = request.headers.get("traceparent");
1399
+ if (traceparent) {
1400
+ const traceContext = parseTraceparent(traceparent);
1401
+ if (traceContext) {
1402
+ const tracestate = request.headers.get("tracestate");
1403
+ if (tracestate) {
1404
+ traceContext.traceState = tracestate;
1405
+ }
1406
+ rpcRequest.traceContext = traceContext;
1407
+ }
1408
+ }
1409
+ const response = await server.handle(rpcRequest);
1410
+ return new Response(JSON.stringify(response), {
1411
+ status: response.success ? 200 : getHttpStatus(response.error?.code),
1412
+ headers: {
1413
+ "Content-Type": "application/json",
1414
+ "X-Request-ID": rpcRequest.id
1415
+ }
1416
+ });
1417
+ } catch (error) {
1418
+ const message = error instanceof Error ? error.message : "Unknown error";
1419
+ return new Response(
1420
+ JSON.stringify({
1421
+ success: false,
1422
+ error: {
1423
+ code: "INTERNAL_ERROR",
1424
+ message
1425
+ }
1426
+ }),
1427
+ {
1428
+ status: 500,
1429
+ headers: { "Content-Type": "application/json" }
1430
+ }
1431
+ );
1432
+ }
1433
+ };
1434
+ }
1435
+ function getHttpStatus(code) {
1436
+ switch (code) {
1437
+ case "METHOD_NOT_FOUND":
1438
+ case "SERVICE_NOT_FOUND":
1439
+ return 404;
1440
+ case "VERSION_MISMATCH":
1441
+ case "VALIDATION_ERROR":
1442
+ case "SERIALIZATION_ERROR":
1443
+ return 400;
1444
+ case "UNAUTHORIZED":
1445
+ return 401;
1446
+ case "FORBIDDEN":
1447
+ return 403;
1448
+ case "TIMEOUT":
1449
+ return 504;
1450
+ case "CIRCUIT_OPEN":
1451
+ case "BULKHEAD_REJECTED":
1452
+ return 503;
1453
+ default:
1454
+ return 500;
1455
+ }
1456
+ }
1457
+
1458
+ // src/events/transports/memory.ts
1459
+ import { createLogger as createLogger2 } from "@parsrun/core";
1460
+
1461
+ // src/events/handler.ts
1462
+ import { createLogger } from "@parsrun/core";
1463
+
1464
+ // src/events/format.ts
1465
+ import { generateId as generateId2 } from "@parsrun/core";
1466
+ function createEvent(options) {
1467
+ const event = {
1468
+ specversion: "1.0",
1469
+ type: options.type,
1470
+ source: options.source,
1471
+ id: options.id ?? generateId2(),
1472
+ time: (/* @__PURE__ */ new Date()).toISOString(),
1473
+ datacontenttype: "application/json",
1474
+ data: options.data
1475
+ };
1476
+ if (options.subject) event.subject = options.subject;
1477
+ if (options.tenantId) event.parstenantid = options.tenantId;
1478
+ if (options.requestId) event.parsrequestid = options.requestId;
1479
+ if (options.traceContext) event.parstracecontext = formatTraceContext(options.traceContext);
1480
+ if (options.delivery) event.parsdelivery = options.delivery;
1481
+ return event;
1482
+ }
1483
+ function toCloudEvent(event) {
1484
+ return { ...event };
1485
+ }
1486
+ function toCompactEvent(event) {
1487
+ const compact = {
1488
+ e: event.type,
1489
+ s: event.source,
1490
+ i: event.id,
1491
+ t: new Date(event.time).getTime(),
1492
+ d: event.data
1493
+ };
1494
+ if (event.parstracecontext) compact.ctx = event.parstracecontext;
1495
+ if (event.parstenantid) compact.tid = event.parstenantid;
1496
+ return compact;
1497
+ }
1498
+ function fromCompactEvent(compact, source) {
1499
+ const event = {
1500
+ specversion: "1.0",
1501
+ type: compact.e,
1502
+ source: source ?? compact.s,
1503
+ id: compact.i,
1504
+ time: new Date(compact.t).toISOString(),
1505
+ datacontenttype: "application/json",
1506
+ data: compact.d
1507
+ };
1508
+ if (compact.ctx) event.parstracecontext = compact.ctx;
1509
+ if (compact.tid) event.parstenantid = compact.tid;
1510
+ return event;
1511
+ }
1512
+ function formatEventType(source, type) {
1513
+ return `com.pars.${source}.${type}`;
1514
+ }
1515
+ function parseEventType(fullType) {
1516
+ const prefix = "com.pars.";
1517
+ if (!fullType.startsWith(prefix)) {
1518
+ const parts = fullType.split(".");
1519
+ if (parts.length >= 2) {
1520
+ const [source, ...rest] = parts;
1521
+ return { source, type: rest.join(".") };
1522
+ }
1523
+ return null;
1524
+ }
1525
+ const withoutPrefix = fullType.slice(prefix.length);
1526
+ const dotIndex = withoutPrefix.indexOf(".");
1527
+ if (dotIndex === -1) {
1528
+ return null;
1529
+ }
1530
+ return {
1531
+ source: withoutPrefix.slice(0, dotIndex),
1532
+ type: withoutPrefix.slice(dotIndex + 1)
1533
+ };
1534
+ }
1535
+ function matchEventType(type, pattern) {
1536
+ if (pattern === "*" || pattern === "**") {
1537
+ return true;
1538
+ }
1539
+ const typeParts = type.split(".");
1540
+ const patternParts = pattern.split(".");
1541
+ let ti = 0;
1542
+ let pi = 0;
1543
+ while (ti < typeParts.length && pi < patternParts.length) {
1544
+ const pp = patternParts[pi];
1545
+ if (pp === "**") {
1546
+ if (pi === patternParts.length - 1) {
1547
+ return true;
1548
+ }
1549
+ for (let i = ti; i <= typeParts.length; i++) {
1550
+ const remaining = typeParts.slice(i).join(".");
1551
+ const remainingPattern = patternParts.slice(pi + 1).join(".");
1552
+ if (matchEventType(remaining, remainingPattern)) {
1553
+ return true;
1554
+ }
1555
+ }
1556
+ return false;
1557
+ }
1558
+ if (pp === "*") {
1559
+ ti++;
1560
+ pi++;
1561
+ continue;
1562
+ }
1563
+ if (pp !== typeParts[ti]) {
1564
+ return false;
1565
+ }
1566
+ ti++;
1567
+ pi++;
1568
+ }
1569
+ return ti === typeParts.length && pi === patternParts.length;
1570
+ }
1571
+ function formatTraceContext(ctx) {
1572
+ const flags = ctx.traceFlags.toString(16).padStart(2, "0");
1573
+ return `00-${ctx.traceId}-${ctx.spanId}-${flags}`;
1574
+ }
1575
+ function validateEvent(event) {
1576
+ if (!event || typeof event !== "object") {
1577
+ return false;
1578
+ }
1579
+ const e = event;
1580
+ if (e["specversion"] !== "1.0") return false;
1581
+ if (typeof e["type"] !== "string" || e["type"].length === 0) return false;
1582
+ if (typeof e["source"] !== "string" || e["source"].length === 0) return false;
1583
+ if (typeof e["id"] !== "string" || e["id"].length === 0) return false;
1584
+ if (typeof e["time"] !== "string") return false;
1585
+ return true;
1586
+ }
1587
+ function validateCompactEvent(event) {
1588
+ if (!event || typeof event !== "object") {
1589
+ return false;
1590
+ }
1591
+ const e = event;
1592
+ if (typeof e["e"] !== "string" || e["e"].length === 0) return false;
1593
+ if (typeof e["s"] !== "string" || e["s"].length === 0) return false;
1594
+ if (typeof e["i"] !== "string" || e["i"].length === 0) return false;
1595
+ if (typeof e["t"] !== "number") return false;
1596
+ return true;
1597
+ }
1598
+
1599
+ // src/events/handler.ts
1600
+ var EventHandlerRegistry = class {
1601
+ handlers = /* @__PURE__ */ new Map();
1602
+ logger;
1603
+ deadLetterQueue;
1604
+ defaultOptions;
1605
+ constructor(options = {}) {
1606
+ this.logger = options.logger ?? createLogger({ name: "event-handler" });
1607
+ if (options.deadLetterQueue) {
1608
+ this.deadLetterQueue = options.deadLetterQueue;
1609
+ }
1610
+ const defaultOpts = {
1611
+ retries: options.defaultOptions?.retries ?? 3,
1612
+ backoff: options.defaultOptions?.backoff ?? "exponential",
1613
+ maxDelay: options.defaultOptions?.maxDelay ?? 3e4,
1614
+ onExhausted: options.defaultOptions?.onExhausted ?? "log"
1615
+ };
1616
+ if (options.defaultOptions?.deadLetter) {
1617
+ defaultOpts.deadLetter = options.defaultOptions.deadLetter;
1618
+ }
1619
+ this.defaultOptions = defaultOpts;
1620
+ }
1621
+ /**
1622
+ * Register an event handler
1623
+ */
1624
+ register(pattern, handler, options) {
1625
+ const registration = {
1626
+ pattern,
1627
+ handler,
1628
+ options: {
1629
+ ...this.defaultOptions,
1630
+ ...options
1631
+ }
1632
+ };
1633
+ const handlers = this.handlers.get(pattern) ?? [];
1634
+ handlers.push(registration);
1635
+ this.handlers.set(pattern, handlers);
1636
+ this.logger.debug(`Handler registered for pattern: ${pattern}`);
1637
+ return () => {
1638
+ const currentHandlers = this.handlers.get(pattern);
1639
+ if (currentHandlers) {
1640
+ const index = currentHandlers.indexOf(registration);
1641
+ if (index !== -1) {
1642
+ currentHandlers.splice(index, 1);
1643
+ if (currentHandlers.length === 0) {
1644
+ this.handlers.delete(pattern);
1645
+ }
1646
+ this.logger.debug(`Handler unregistered for pattern: ${pattern}`);
1647
+ }
1648
+ }
1649
+ };
1650
+ }
1651
+ /**
1652
+ * Handle an event
1653
+ */
1654
+ async handle(event) {
1655
+ const matchingHandlers = this.getMatchingHandlers(event.type);
1656
+ if (matchingHandlers.length === 0) {
1657
+ this.logger.debug(`No handlers for event type: ${event.type}`, {
1658
+ eventId: event.id
1659
+ });
1660
+ return;
1661
+ }
1662
+ this.logger.debug(`Handling event: ${event.type}`, {
1663
+ eventId: event.id,
1664
+ handlerCount: matchingHandlers.length
1665
+ });
1666
+ const results = await Promise.allSettled(
1667
+ matchingHandlers.map((reg) => this.executeHandler(event, reg))
1668
+ );
1669
+ for (let i = 0; i < results.length; i++) {
1670
+ const result = results[i];
1671
+ if (result?.status === "rejected") {
1672
+ this.logger.error(
1673
+ `Handler failed for ${event.type}`,
1674
+ result.reason,
1675
+ { eventId: event.id, pattern: matchingHandlers[i]?.pattern }
1676
+ );
1677
+ }
1678
+ }
1679
+ }
1680
+ /**
1681
+ * Execute a single handler with retry logic
1682
+ */
1683
+ async executeHandler(event, registration) {
1684
+ const { handler, options } = registration;
1685
+ const maxAttempts = options.retries + 1;
1686
+ let lastError;
1687
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
1688
+ try {
1689
+ const context = {
1690
+ logger: this.logger.child({
1691
+ eventId: event.id,
1692
+ pattern: registration.pattern,
1693
+ attempt
1694
+ }),
1695
+ attempt,
1696
+ maxAttempts,
1697
+ isRetry: attempt > 1
1698
+ };
1699
+ if (event.parstracecontext) {
1700
+ const traceCtx = parseTraceContext(event.parstracecontext);
1701
+ if (traceCtx) {
1702
+ context.traceContext = traceCtx;
1703
+ }
1704
+ }
1705
+ await handler(event, context);
1706
+ return;
1707
+ } catch (error) {
1708
+ lastError = error;
1709
+ if (attempt < maxAttempts) {
1710
+ const delay = this.calculateBackoff(attempt, options);
1711
+ this.logger.warn(
1712
+ `Handler failed, retrying in ${delay}ms`,
1713
+ { eventId: event.id, attempt, maxAttempts }
1714
+ );
1715
+ await sleep2(delay);
1716
+ }
1717
+ }
1718
+ }
1719
+ await this.handleExhausted(event, registration, lastError);
1720
+ }
1721
+ /**
1722
+ * Calculate backoff delay
1723
+ */
1724
+ calculateBackoff(attempt, options) {
1725
+ const baseDelay = 100;
1726
+ if (options.backoff === "exponential") {
1727
+ return Math.min(baseDelay * Math.pow(2, attempt - 1), options.maxDelay);
1728
+ }
1729
+ return Math.min(baseDelay * attempt, options.maxDelay);
1730
+ }
1731
+ /**
1732
+ * Handle exhausted retries
1733
+ */
1734
+ async handleExhausted(event, registration, error) {
1735
+ const { options } = registration;
1736
+ if (options.deadLetter && this.deadLetterQueue) {
1737
+ await this.deadLetterQueue.add({
1738
+ event,
1739
+ error: error.message,
1740
+ pattern: registration.pattern,
1741
+ attempts: options.retries + 1
1742
+ });
1743
+ }
1744
+ switch (options.onExhausted) {
1745
+ case "alert":
1746
+ this.logger.error(
1747
+ `[ALERT] Event handler exhausted all retries`,
1748
+ error,
1749
+ {
1750
+ eventId: event.id,
1751
+ eventType: event.type,
1752
+ pattern: registration.pattern
1753
+ }
1754
+ );
1755
+ break;
1756
+ case "discard":
1757
+ this.logger.debug(`Event discarded after exhausted retries`, {
1758
+ eventId: event.id
1759
+ });
1760
+ break;
1761
+ case "log":
1762
+ default:
1763
+ this.logger.warn(`Event handler exhausted all retries`, {
1764
+ eventId: event.id,
1765
+ error: error.message
1766
+ });
1767
+ }
1768
+ }
1769
+ /**
1770
+ * Get handlers matching an event type
1771
+ */
1772
+ getMatchingHandlers(eventType) {
1773
+ const matching = [];
1774
+ for (const [pattern, handlers] of this.handlers) {
1775
+ if (matchEventType(eventType, pattern)) {
1776
+ matching.push(...handlers);
1777
+ }
1778
+ }
1779
+ return matching;
1780
+ }
1781
+ /**
1782
+ * Get all registered patterns
1783
+ */
1784
+ getPatterns() {
1785
+ return Array.from(this.handlers.keys());
1786
+ }
1787
+ /**
1788
+ * Check if a pattern has handlers
1789
+ */
1790
+ hasHandlers(pattern) {
1791
+ return this.handlers.has(pattern);
1792
+ }
1793
+ /**
1794
+ * Clear all handlers
1795
+ */
1796
+ clear() {
1797
+ this.handlers.clear();
1798
+ }
1799
+ };
1800
+ function createEventHandlerRegistry(options) {
1801
+ return new EventHandlerRegistry(options);
1802
+ }
1803
+ function sleep2(ms) {
1804
+ return new Promise((resolve) => setTimeout(resolve, ms));
1805
+ }
1806
+ function parseTraceContext(traceparent) {
1807
+ const parts = traceparent.split("-");
1808
+ if (parts.length !== 4) return void 0;
1809
+ const [, traceId, spanId, flags] = parts;
1810
+ if (!traceId || !spanId || !flags) return void 0;
1811
+ return {
1812
+ traceId,
1813
+ spanId,
1814
+ traceFlags: parseInt(flags, 16)
1815
+ };
1816
+ }
1817
+
1818
+ // src/events/transports/memory.ts
1819
+ var MemoryEventTransport = class {
1820
+ name = "memory";
1821
+ registry;
1822
+ logger;
1823
+ sync;
1824
+ pendingEvents = [];
1825
+ processing = false;
1826
+ constructor(options = {}) {
1827
+ this.logger = options.logger ?? createLogger2({ name: "memory-transport" });
1828
+ this.sync = options.sync ?? false;
1829
+ const registryOptions = {
1830
+ logger: this.logger
1831
+ };
1832
+ if (options.defaultHandlerOptions) {
1833
+ registryOptions.defaultOptions = options.defaultHandlerOptions;
1834
+ }
1835
+ this.registry = new EventHandlerRegistry(registryOptions);
1836
+ }
1837
+ /**
1838
+ * Emit an event
1839
+ */
1840
+ async emit(event) {
1841
+ this.logger.debug(`Event emitted: ${event.type}`, {
1842
+ eventId: event.id,
1843
+ tenantId: event.parstenantid
1844
+ });
1845
+ if (this.sync) {
1846
+ await this.registry.handle(event);
1847
+ } else {
1848
+ this.pendingEvents.push(event);
1849
+ this.processQueue();
1850
+ }
1851
+ }
1852
+ /**
1853
+ * Subscribe to events
1854
+ */
1855
+ subscribe(eventType, handler, options) {
1856
+ return this.registry.register(eventType, handler, options);
1857
+ }
1858
+ /**
1859
+ * Process pending events asynchronously
1860
+ */
1861
+ async processQueue() {
1862
+ if (this.processing) return;
1863
+ this.processing = true;
1864
+ try {
1865
+ while (this.pendingEvents.length > 0) {
1866
+ const event = this.pendingEvents.shift();
1867
+ if (event) {
1868
+ await this.registry.handle(event);
1869
+ }
1870
+ }
1871
+ } finally {
1872
+ this.processing = false;
1873
+ }
1874
+ }
1875
+ /**
1876
+ * Wait for all pending events to be processed
1877
+ */
1878
+ async flush() {
1879
+ while (this.pendingEvents.length > 0 || this.processing) {
1880
+ await new Promise((resolve) => setTimeout(resolve, 10));
1881
+ }
1882
+ }
1883
+ /**
1884
+ * Get pending event count
1885
+ */
1886
+ get pendingCount() {
1887
+ return this.pendingEvents.length;
1888
+ }
1889
+ /**
1890
+ * Get registered patterns
1891
+ */
1892
+ getPatterns() {
1893
+ return this.registry.getPatterns();
1894
+ }
1895
+ /**
1896
+ * Clear all subscriptions
1897
+ */
1898
+ clear() {
1899
+ this.registry.clear();
1900
+ this.pendingEvents.length = 0;
1901
+ }
1902
+ /**
1903
+ * Close the transport
1904
+ */
1905
+ async close() {
1906
+ await this.flush();
1907
+ this.clear();
1908
+ }
1909
+ };
1910
+ function createMemoryEventTransport(options) {
1911
+ return new MemoryEventTransport(options);
1912
+ }
1913
+ var GlobalEventBus = class _GlobalEventBus {
1914
+ static instance = null;
1915
+ transports = /* @__PURE__ */ new Map();
1916
+ logger;
1917
+ constructor() {
1918
+ this.logger = createLogger2({ name: "global-event-bus" });
1919
+ }
1920
+ static getInstance() {
1921
+ if (!_GlobalEventBus.instance) {
1922
+ _GlobalEventBus.instance = new _GlobalEventBus();
1923
+ }
1924
+ return _GlobalEventBus.instance;
1925
+ }
1926
+ /**
1927
+ * Register a service's event transport
1928
+ */
1929
+ register(serviceName, transport) {
1930
+ if (this.transports.has(serviceName)) {
1931
+ throw new Error(`Service already registered: ${serviceName}`);
1932
+ }
1933
+ this.transports.set(serviceName, transport);
1934
+ this.logger.debug(`Service registered: ${serviceName}`);
1935
+ }
1936
+ /**
1937
+ * Unregister a service
1938
+ */
1939
+ unregister(serviceName) {
1940
+ const deleted = this.transports.delete(serviceName);
1941
+ if (deleted) {
1942
+ this.logger.debug(`Service unregistered: ${serviceName}`);
1943
+ }
1944
+ return deleted;
1945
+ }
1946
+ /**
1947
+ * Broadcast an event to all services (except source)
1948
+ */
1949
+ async broadcast(event, excludeSource) {
1950
+ const promises = [];
1951
+ for (const [name, transport] of this.transports) {
1952
+ if (name !== excludeSource) {
1953
+ promises.push(transport.emit(event));
1954
+ }
1955
+ }
1956
+ await Promise.allSettled(promises);
1957
+ }
1958
+ /**
1959
+ * Send an event to a specific service
1960
+ */
1961
+ async send(serviceName, event) {
1962
+ const transport = this.transports.get(serviceName);
1963
+ if (!transport) {
1964
+ this.logger.warn(`Target service not found: ${serviceName}`, {
1965
+ eventId: event.id
1966
+ });
1967
+ return;
1968
+ }
1969
+ await transport.emit(event);
1970
+ }
1971
+ /**
1972
+ * Get all registered service names
1973
+ */
1974
+ getServices() {
1975
+ return Array.from(this.transports.keys());
1976
+ }
1977
+ /**
1978
+ * Clear all registrations
1979
+ */
1980
+ clear() {
1981
+ this.transports.clear();
1982
+ }
1983
+ /**
1984
+ * Reset singleton (for testing)
1985
+ */
1986
+ static reset() {
1987
+ _GlobalEventBus.instance = null;
1988
+ }
1989
+ };
1990
+ function getGlobalEventBus() {
1991
+ return GlobalEventBus.getInstance();
1992
+ }
1993
+
1994
+ // src/tracing/tracer.ts
1995
+ import { createLogger as createLogger4 } from "@parsrun/core";
1996
+
1997
+ // src/tracing/context.ts
1998
+ function generateTraceId() {
1999
+ const bytes = new Uint8Array(16);
2000
+ crypto.getRandomValues(bytes);
2001
+ return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
2002
+ }
2003
+ function generateSpanId() {
2004
+ const bytes = new Uint8Array(8);
2005
+ crypto.getRandomValues(bytes);
2006
+ return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
2007
+ }
2008
+ function createTraceContext(options) {
2009
+ const ctx = {
2010
+ traceId: options?.traceId ?? generateTraceId(),
2011
+ spanId: options?.spanId ?? generateSpanId(),
2012
+ traceFlags: options?.traceFlags ?? 1
2013
+ // Default: sampled
2014
+ };
2015
+ if (options?.traceState) {
2016
+ ctx.traceState = options.traceState;
2017
+ }
2018
+ return ctx;
2019
+ }
2020
+ function createChildContext(parent) {
2021
+ const ctx = {
2022
+ traceId: parent.traceId,
2023
+ spanId: generateSpanId(),
2024
+ traceFlags: parent.traceFlags
2025
+ };
2026
+ if (parent.traceState) {
2027
+ ctx.traceState = parent.traceState;
2028
+ }
2029
+ return ctx;
2030
+ }
2031
+ function formatTraceparent2(ctx) {
2032
+ const version = "00";
2033
+ const flags = ctx.traceFlags.toString(16).padStart(2, "0");
2034
+ return `${version}-${ctx.traceId}-${ctx.spanId}-${flags}`;
2035
+ }
2036
+ function parseTraceparent2(header) {
2037
+ const parts = header.trim().split("-");
2038
+ if (parts.length !== 4) {
2039
+ return null;
2040
+ }
2041
+ const [version, traceId, spanId, flags] = parts;
2042
+ if (version !== "00") {
2043
+ return null;
2044
+ }
2045
+ if (!traceId || traceId.length !== 32 || !/^[0-9a-f]+$/i.test(traceId)) {
2046
+ return null;
2047
+ }
2048
+ if (!spanId || spanId.length !== 16 || !/^[0-9a-f]+$/i.test(spanId)) {
2049
+ return null;
2050
+ }
2051
+ if (!flags || flags.length !== 2 || !/^[0-9a-f]+$/i.test(flags)) {
2052
+ return null;
2053
+ }
2054
+ return {
2055
+ traceId: traceId.toLowerCase(),
2056
+ spanId: spanId.toLowerCase(),
2057
+ traceFlags: parseInt(flags, 16)
2058
+ };
2059
+ }
2060
+ function formatTracestate(state) {
2061
+ return Object.entries(state).map(([key, value]) => `${key}=${value}`).join(",");
2062
+ }
2063
+ function parseTracestate(header) {
2064
+ const state = {};
2065
+ for (const pair of header.split(",")) {
2066
+ const [key, value] = pair.trim().split("=");
2067
+ if (key && value) {
2068
+ state[key] = value;
2069
+ }
2070
+ }
2071
+ return state;
2072
+ }
2073
+ var TraceContextManager = class {
2074
+ stack = [];
2075
+ /**
2076
+ * Get current trace context
2077
+ */
2078
+ current() {
2079
+ return this.stack[this.stack.length - 1];
2080
+ }
2081
+ /**
2082
+ * Run a function with a trace context
2083
+ */
2084
+ async run(ctx, fn) {
2085
+ this.stack.push(ctx);
2086
+ try {
2087
+ return await fn();
2088
+ } finally {
2089
+ this.stack.pop();
2090
+ }
2091
+ }
2092
+ /**
2093
+ * Run a function with a new child context
2094
+ */
2095
+ async runChild(fn) {
2096
+ const parent = this.current();
2097
+ const child = parent ? createChildContext(parent) : createTraceContext();
2098
+ return this.run(child, fn);
2099
+ }
2100
+ /**
2101
+ * Create context from incoming request headers
2102
+ */
2103
+ fromHeaders(headers) {
2104
+ const traceparent = headers instanceof Headers ? headers.get("traceparent") : headers["traceparent"];
2105
+ if (!traceparent) {
2106
+ return void 0;
2107
+ }
2108
+ const ctx = parseTraceparent2(traceparent);
2109
+ if (!ctx) {
2110
+ return void 0;
2111
+ }
2112
+ const tracestate = headers instanceof Headers ? headers.get("tracestate") : headers["tracestate"];
2113
+ if (tracestate) {
2114
+ ctx.traceState = tracestate;
2115
+ }
2116
+ return ctx;
2117
+ }
2118
+ /**
2119
+ * Add trace context to outgoing request headers
2120
+ */
2121
+ toHeaders(ctx) {
2122
+ const headers = {
2123
+ traceparent: formatTraceparent2(ctx)
2124
+ };
2125
+ if (ctx.traceState) {
2126
+ headers["tracestate"] = ctx.traceState;
2127
+ }
2128
+ return headers;
2129
+ }
2130
+ /**
2131
+ * Check if current context is sampled
2132
+ */
2133
+ isSampled() {
2134
+ const ctx = this.current();
2135
+ return ctx ? (ctx.traceFlags & 1) === 1 : false;
2136
+ }
2137
+ /**
2138
+ * Clear all contexts (for testing)
2139
+ */
2140
+ clear() {
2141
+ this.stack.length = 0;
2142
+ }
2143
+ };
2144
+ function shouldSample(sampler, traceId) {
2145
+ if (sampler === "always") {
2146
+ return true;
2147
+ }
2148
+ if (sampler === "never") {
2149
+ return false;
2150
+ }
2151
+ if (traceId) {
2152
+ const hash = parseInt(traceId.slice(-8), 16);
2153
+ const threshold = Math.floor(sampler.ratio * 4294967295);
2154
+ return hash < threshold;
2155
+ }
2156
+ return Math.random() < sampler.ratio;
2157
+ }
2158
+
2159
+ // src/tracing/spans.ts
2160
+ function createSpan(options) {
2161
+ let traceContext;
2162
+ if (options.parent) {
2163
+ traceContext = {
2164
+ traceId: options.parent.traceId,
2165
+ spanId: generateSpanId(),
2166
+ traceFlags: options.parent.traceFlags
2167
+ };
2168
+ if (options.parent.traceState) {
2169
+ traceContext.traceState = options.parent.traceState;
2170
+ }
2171
+ } else {
2172
+ traceContext = createTraceContext();
2173
+ }
2174
+ const span = {
2175
+ name: options.name,
2176
+ kind: options.kind ?? "internal",
2177
+ traceContext,
2178
+ startTime: options.startTime ?? Date.now(),
2179
+ status: "unset",
2180
+ attributes: options.attributes ?? {},
2181
+ events: []
2182
+ };
2183
+ if (options.parent?.spanId) {
2184
+ span.parentSpanId = options.parent.spanId;
2185
+ }
2186
+ return span;
2187
+ }
2188
+ var SpanManager = class {
2189
+ spans = /* @__PURE__ */ new Map();
2190
+ /**
2191
+ * Start a new span
2192
+ */
2193
+ startSpan(options) {
2194
+ const span = createSpan(options);
2195
+ this.spans.set(span.traceContext.spanId, span);
2196
+ return span;
2197
+ }
2198
+ /**
2199
+ * End a span
2200
+ */
2201
+ endSpan(span, status) {
2202
+ span.endTime = Date.now();
2203
+ if (status) {
2204
+ span.status = status;
2205
+ } else if (span.status === "unset") {
2206
+ span.status = "ok";
2207
+ }
2208
+ return span;
2209
+ }
2210
+ /**
2211
+ * Set span attribute
2212
+ */
2213
+ setAttribute(span, key, value) {
2214
+ span.attributes[key] = value;
2215
+ }
2216
+ /**
2217
+ * Set multiple span attributes
2218
+ */
2219
+ setAttributes(span, attributes) {
2220
+ Object.assign(span.attributes, attributes);
2221
+ }
2222
+ /**
2223
+ * Add span event
2224
+ */
2225
+ addEvent(span, name, attributes) {
2226
+ const event = {
2227
+ name,
2228
+ time: Date.now()
2229
+ };
2230
+ if (attributes) {
2231
+ event.attributes = attributes;
2232
+ }
2233
+ span.events.push(event);
2234
+ }
2235
+ /**
2236
+ * Set span status
2237
+ */
2238
+ setStatus(span, status) {
2239
+ span.status = status;
2240
+ }
2241
+ /**
2242
+ * Record exception on span
2243
+ */
2244
+ recordException(span, error) {
2245
+ span.status = "error";
2246
+ this.addEvent(span, "exception", {
2247
+ "exception.type": error.name,
2248
+ "exception.message": error.message,
2249
+ "exception.stacktrace": error.stack ?? ""
2250
+ });
2251
+ }
2252
+ /**
2253
+ * Get span by ID
2254
+ */
2255
+ getSpan(spanId) {
2256
+ return this.spans.get(spanId);
2257
+ }
2258
+ /**
2259
+ * Get all completed spans and clear
2260
+ */
2261
+ flush() {
2262
+ const completed = Array.from(this.spans.values()).filter((s) => s.endTime);
2263
+ for (const span of completed) {
2264
+ this.spans.delete(span.traceContext.spanId);
2265
+ }
2266
+ return completed;
2267
+ }
2268
+ /**
2269
+ * Clear all spans
2270
+ */
2271
+ clear() {
2272
+ this.spans.clear();
2273
+ }
2274
+ };
2275
+ function getSpanDuration(span) {
2276
+ if (!span.endTime) return void 0;
2277
+ return span.endTime - span.startTime;
2278
+ }
2279
+ function isSpanCompleted(span) {
2280
+ return span.endTime !== void 0;
2281
+ }
2282
+ function spanToLogObject(span) {
2283
+ return {
2284
+ traceId: span.traceContext.traceId,
2285
+ spanId: span.traceContext.spanId,
2286
+ parentSpanId: span.parentSpanId,
2287
+ name: span.name,
2288
+ kind: span.kind,
2289
+ status: span.status,
2290
+ startTime: new Date(span.startTime).toISOString(),
2291
+ endTime: span.endTime ? new Date(span.endTime).toISOString() : void 0,
2292
+ durationMs: getSpanDuration(span),
2293
+ attributes: span.attributes,
2294
+ events: span.events.map((e) => ({
2295
+ name: e.name,
2296
+ time: new Date(e.time).toISOString(),
2297
+ attributes: e.attributes
2298
+ }))
2299
+ };
2300
+ }
2301
+ var SpanAttributes = {
2302
+ // HTTP
2303
+ HTTP_METHOD: "http.method",
2304
+ HTTP_URL: "http.url",
2305
+ HTTP_STATUS_CODE: "http.status_code",
2306
+ HTTP_REQUEST_CONTENT_LENGTH: "http.request_content_length",
2307
+ HTTP_RESPONSE_CONTENT_LENGTH: "http.response_content_length",
2308
+ // RPC
2309
+ RPC_SYSTEM: "rpc.system",
2310
+ RPC_SERVICE: "rpc.service",
2311
+ RPC_METHOD: "rpc.method",
2312
+ // Database
2313
+ DB_SYSTEM: "db.system",
2314
+ DB_NAME: "db.name",
2315
+ DB_OPERATION: "db.operation",
2316
+ DB_STATEMENT: "db.statement",
2317
+ // Messaging
2318
+ MESSAGING_SYSTEM: "messaging.system",
2319
+ MESSAGING_DESTINATION: "messaging.destination",
2320
+ MESSAGING_MESSAGE_ID: "messaging.message_id",
2321
+ // Service
2322
+ SERVICE_NAME: "service.name",
2323
+ SERVICE_VERSION: "service.version",
2324
+ // Error
2325
+ EXCEPTION_TYPE: "exception.type",
2326
+ EXCEPTION_MESSAGE: "exception.message",
2327
+ EXCEPTION_STACKTRACE: "exception.stacktrace",
2328
+ // Custom Pars attributes
2329
+ PARS_TENANT_ID: "pars.tenant_id",
2330
+ PARS_USER_ID: "pars.user_id",
2331
+ PARS_REQUEST_ID: "pars.request_id"
2332
+ };
2333
+
2334
+ // src/tracing/exporters.ts
2335
+ import { createLogger as createLogger3 } from "@parsrun/core";
2336
+ var ConsoleExporter = class {
2337
+ name = "console";
2338
+ logger;
2339
+ pretty;
2340
+ includeAttributes;
2341
+ includeEvents;
2342
+ constructor(options = {}) {
2343
+ this.logger = options.logger ?? createLogger3({ name: "trace-exporter" });
2344
+ this.pretty = options.pretty ?? true;
2345
+ this.includeAttributes = options.includeAttributes ?? true;
2346
+ this.includeEvents = options.includeEvents ?? true;
2347
+ }
2348
+ async export(spans) {
2349
+ for (const span of spans) {
2350
+ const duration = getSpanDuration(span);
2351
+ const status = span.status === "error" ? "ERROR" : span.status === "ok" ? "OK" : "UNSET";
2352
+ if (this.pretty) {
2353
+ const indent = span.parentSpanId ? " \u2514\u2500" : "\u2500\u2500";
2354
+ const statusIcon = span.status === "error" ? "\u2717" : span.status === "ok" ? "\u2713" : "\u25CB";
2355
+ const durationStr = duration !== void 0 ? `${duration}ms` : "?ms";
2356
+ console.log(
2357
+ `${indent} ${statusIcon} [${span.kind}] ${span.name} (${durationStr}) trace=${span.traceContext.traceId.slice(0, 8)}`
2358
+ );
2359
+ if (this.includeAttributes && Object.keys(span.attributes).length > 0) {
2360
+ console.log(` attributes:`, span.attributes);
2361
+ }
2362
+ if (this.includeEvents && span.events.length > 0) {
2363
+ for (const event of span.events) {
2364
+ console.log(` event: ${event.name}`, event.attributes ?? "");
2365
+ }
2366
+ }
2367
+ } else {
2368
+ const logObj = spanToLogObject(span);
2369
+ this.logger.info(`Span: ${span.name}`, {
2370
+ ...logObj,
2371
+ status,
2372
+ durationMs: duration
2373
+ });
2374
+ }
2375
+ }
2376
+ }
2377
+ async shutdown() {
2378
+ }
2379
+ };
2380
+ function createConsoleExporter(options) {
2381
+ return new ConsoleExporter(options);
2382
+ }
2383
+ var OtlpExporter = class {
2384
+ name = "otlp";
2385
+ endpoint;
2386
+ serviceName;
2387
+ serviceVersion;
2388
+ headers;
2389
+ timeout;
2390
+ batchSize;
2391
+ flushInterval;
2392
+ logger;
2393
+ buffer = [];
2394
+ flushTimer = null;
2395
+ constructor(options) {
2396
+ this.endpoint = options.endpoint.replace(/\/$/, "");
2397
+ this.serviceName = options.serviceName;
2398
+ this.serviceVersion = options.serviceVersion ?? "1.0.0";
2399
+ this.headers = options.headers ?? {};
2400
+ this.timeout = options.timeout ?? 1e4;
2401
+ this.batchSize = options.batchSize ?? 100;
2402
+ this.flushInterval = options.flushInterval ?? 5e3;
2403
+ this.logger = options.logger ?? createLogger3({ name: "otlp-exporter" });
2404
+ this.flushTimer = setInterval(() => this.flush(), this.flushInterval);
2405
+ }
2406
+ async export(spans) {
2407
+ this.buffer.push(...spans);
2408
+ if (this.buffer.length >= this.batchSize) {
2409
+ await this.flush();
2410
+ }
2411
+ }
2412
+ async flush() {
2413
+ if (this.buffer.length === 0) return;
2414
+ const spansToExport = this.buffer.splice(0, this.batchSize);
2415
+ try {
2416
+ const payload = this.buildOtlpPayload(spansToExport);
2417
+ const controller = new AbortController();
2418
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
2419
+ try {
2420
+ const response = await fetch(`${this.endpoint}/v1/traces`, {
2421
+ method: "POST",
2422
+ headers: {
2423
+ "Content-Type": "application/json",
2424
+ ...this.headers
2425
+ },
2426
+ body: JSON.stringify(payload),
2427
+ signal: controller.signal
2428
+ });
2429
+ if (!response.ok) {
2430
+ throw new Error(`OTLP export failed: ${response.status} ${response.statusText}`);
2431
+ }
2432
+ this.logger.debug(`Exported ${spansToExport.length} spans to OTLP`);
2433
+ } finally {
2434
+ clearTimeout(timeoutId);
2435
+ }
2436
+ } catch (error) {
2437
+ this.logger.error(`Failed to export spans to OTLP`, error);
2438
+ this.buffer.unshift(...spansToExport);
2439
+ }
2440
+ }
2441
+ buildOtlpPayload(spans) {
2442
+ return {
2443
+ resourceSpans: [
2444
+ {
2445
+ resource: {
2446
+ attributes: [
2447
+ { key: "service.name", value: { stringValue: this.serviceName } },
2448
+ { key: "service.version", value: { stringValue: this.serviceVersion } }
2449
+ ]
2450
+ },
2451
+ scopeSpans: [
2452
+ {
2453
+ scope: {
2454
+ name: "@parsrun/service",
2455
+ version: "0.1.0"
2456
+ },
2457
+ spans: spans.map((span) => this.convertSpan(span))
2458
+ }
2459
+ ]
2460
+ }
2461
+ ]
2462
+ };
2463
+ }
2464
+ convertSpan(span) {
2465
+ const otlpSpan = {
2466
+ traceId: span.traceContext.traceId,
2467
+ spanId: span.traceContext.spanId,
2468
+ name: span.name,
2469
+ kind: this.convertSpanKind(span.kind),
2470
+ startTimeUnixNano: String(span.startTime * 1e6),
2471
+ attributes: Object.entries(span.attributes).map(([key, value]) => ({
2472
+ key,
2473
+ value: this.convertAttributeValue(value)
2474
+ })),
2475
+ events: span.events.map((event) => ({
2476
+ name: event.name,
2477
+ timeUnixNano: String(event.time * 1e6),
2478
+ attributes: event.attributes ? Object.entries(event.attributes).map(([key, value]) => ({
2479
+ key,
2480
+ value: this.convertAttributeValue(value)
2481
+ })) : []
2482
+ })),
2483
+ status: {
2484
+ code: span.status === "error" ? 2 : span.status === "ok" ? 1 : 0
2485
+ }
2486
+ };
2487
+ if (span.parentSpanId) {
2488
+ otlpSpan.parentSpanId = span.parentSpanId;
2489
+ }
2490
+ if (span.endTime) {
2491
+ otlpSpan.endTimeUnixNano = String(span.endTime * 1e6);
2492
+ }
2493
+ return otlpSpan;
2494
+ }
2495
+ convertSpanKind(kind) {
2496
+ switch (kind) {
2497
+ case "internal":
2498
+ return 1;
2499
+ case "server":
2500
+ return 2;
2501
+ case "client":
2502
+ return 3;
2503
+ case "producer":
2504
+ return 4;
2505
+ case "consumer":
2506
+ return 5;
2507
+ default:
2508
+ return 0;
2509
+ }
2510
+ }
2511
+ convertAttributeValue(value) {
2512
+ if (typeof value === "string") {
2513
+ return { stringValue: value };
2514
+ }
2515
+ if (typeof value === "number") {
2516
+ if (Number.isInteger(value)) {
2517
+ return { intValue: String(value) };
2518
+ }
2519
+ return { doubleValue: value };
2520
+ }
2521
+ if (typeof value === "boolean") {
2522
+ return { boolValue: value };
2523
+ }
2524
+ if (Array.isArray(value)) {
2525
+ return {
2526
+ arrayValue: {
2527
+ values: value.map((v) => this.convertAttributeValue(v))
2528
+ }
2529
+ };
2530
+ }
2531
+ return { stringValue: String(value) };
2532
+ }
2533
+ async shutdown() {
2534
+ if (this.flushTimer) {
2535
+ clearInterval(this.flushTimer);
2536
+ this.flushTimer = null;
2537
+ }
2538
+ await this.flush();
2539
+ }
2540
+ };
2541
+ function createOtlpExporter(options) {
2542
+ return new OtlpExporter(options);
2543
+ }
2544
+
2545
+ // src/tracing/tracer.ts
2546
+ var Tracer = class {
2547
+ serviceName;
2548
+ serviceVersion;
2549
+ sampler;
2550
+ exporter;
2551
+ logger;
2552
+ contextManager;
2553
+ spanManager;
2554
+ enabled;
2555
+ flushTimer = null;
2556
+ constructor(options) {
2557
+ this.serviceName = options.serviceName;
2558
+ this.serviceVersion = options.serviceVersion ?? "1.0.0";
2559
+ this.enabled = options.config?.enabled ?? true;
2560
+ this.sampler = options.config?.sampler ?? { ratio: 0.1 };
2561
+ this.exporter = options.exporter ?? new ConsoleExporter();
2562
+ this.logger = options.logger ?? createLogger4({ name: `tracer:${options.serviceName}` });
2563
+ this.contextManager = new TraceContextManager();
2564
+ this.spanManager = new SpanManager();
2565
+ if (this.enabled) {
2566
+ this.flushTimer = setInterval(() => this.flush(), 5e3);
2567
+ }
2568
+ }
2569
+ /**
2570
+ * Start a new span
2571
+ */
2572
+ startSpan(name, options) {
2573
+ if (!this.enabled) return null;
2574
+ const parent = options?.parent ?? this.contextManager.current();
2575
+ if (!parent && !shouldSample(this.sampler)) {
2576
+ return null;
2577
+ }
2578
+ const spanOptions = {
2579
+ name,
2580
+ kind: options?.kind ?? "internal",
2581
+ attributes: {
2582
+ [SpanAttributes.SERVICE_NAME]: this.serviceName,
2583
+ [SpanAttributes.SERVICE_VERSION]: this.serviceVersion,
2584
+ ...options?.attributes
2585
+ }
2586
+ };
2587
+ if (parent) {
2588
+ spanOptions.parent = parent;
2589
+ }
2590
+ const span = this.spanManager.startSpan(spanOptions);
2591
+ return span;
2592
+ }
2593
+ /**
2594
+ * End a span
2595
+ */
2596
+ endSpan(span, error) {
2597
+ if (!span) return;
2598
+ if (error) {
2599
+ this.spanManager.recordException(span, error);
2600
+ }
2601
+ this.spanManager.endSpan(span, error ? "error" : "ok");
2602
+ }
2603
+ /**
2604
+ * Run a function with automatic span creation
2605
+ */
2606
+ async trace(name, fn, options) {
2607
+ const span = this.startSpan(name, options);
2608
+ if (!span) {
2609
+ return fn(null);
2610
+ }
2611
+ try {
2612
+ const result = await this.contextManager.run(span.traceContext, () => fn(span));
2613
+ this.endSpan(span);
2614
+ return result;
2615
+ } catch (error) {
2616
+ this.endSpan(span, error);
2617
+ throw error;
2618
+ }
2619
+ }
2620
+ /**
2621
+ * Add attribute to current span
2622
+ */
2623
+ setAttribute(key, value) {
2624
+ const ctx = this.contextManager.current();
2625
+ if (!ctx) return;
2626
+ const span = this.spanManager.getSpan(ctx.spanId);
2627
+ if (span) {
2628
+ this.spanManager.setAttribute(span, key, value);
2629
+ }
2630
+ }
2631
+ /**
2632
+ * Add event to current span
2633
+ */
2634
+ addEvent(name, attributes) {
2635
+ const ctx = this.contextManager.current();
2636
+ if (!ctx) return;
2637
+ const span = this.spanManager.getSpan(ctx.spanId);
2638
+ if (span) {
2639
+ this.spanManager.addEvent(span, name, attributes);
2640
+ }
2641
+ }
2642
+ /**
2643
+ * Get current trace context
2644
+ */
2645
+ currentContext() {
2646
+ return this.contextManager.current();
2647
+ }
2648
+ /**
2649
+ * Get context manager for advanced use
2650
+ */
2651
+ getContextManager() {
2652
+ return this.contextManager;
2653
+ }
2654
+ /**
2655
+ * Extract trace context from incoming request
2656
+ */
2657
+ extract(headers) {
2658
+ return this.contextManager.fromHeaders(headers);
2659
+ }
2660
+ /**
2661
+ * Inject trace context into outgoing request headers
2662
+ */
2663
+ inject(ctx) {
2664
+ const context = ctx ?? this.contextManager.current();
2665
+ if (!context) return {};
2666
+ return this.contextManager.toHeaders(context);
2667
+ }
2668
+ /**
2669
+ * Flush completed spans to exporter
2670
+ */
2671
+ async flush() {
2672
+ const spans = this.spanManager.flush();
2673
+ if (spans.length > 0) {
2674
+ try {
2675
+ await this.exporter.export(spans);
2676
+ } catch (error) {
2677
+ this.logger.error("Failed to export spans", error);
2678
+ }
2679
+ }
2680
+ }
2681
+ /**
2682
+ * Shutdown tracer
2683
+ */
2684
+ async shutdown() {
2685
+ if (this.flushTimer) {
2686
+ clearInterval(this.flushTimer);
2687
+ this.flushTimer = null;
2688
+ }
2689
+ await this.flush();
2690
+ await this.exporter.shutdown();
2691
+ this.spanManager.clear();
2692
+ this.contextManager.clear();
2693
+ }
2694
+ };
2695
+ function createTracer(options) {
2696
+ return new Tracer(options);
2697
+ }
2698
+ var globalTracer = null;
2699
+ function getGlobalTracer() {
2700
+ return globalTracer;
2701
+ }
2702
+ function setGlobalTracer(tracer) {
2703
+ globalTracer = tracer;
2704
+ }
2705
+ function resetGlobalTracer() {
2706
+ globalTracer = null;
2707
+ }
2708
+ function createTracingMiddleware(tracer) {
2709
+ return async (request, next) => {
2710
+ const parentCtx = tracer.extract(request.headers);
2711
+ const url = new URL(request.url);
2712
+ const spanOpts = {
2713
+ kind: "server",
2714
+ attributes: {
2715
+ [SpanAttributes.HTTP_METHOD]: request.method,
2716
+ [SpanAttributes.HTTP_URL]: request.url
2717
+ }
2718
+ };
2719
+ if (parentCtx) {
2720
+ spanOpts.parent = parentCtx;
2721
+ }
2722
+ const span = tracer.startSpan(`${request.method} ${url.pathname}`, spanOpts);
2723
+ if (!span) {
2724
+ return next();
2725
+ }
2726
+ try {
2727
+ const response = await tracer.getContextManager().run(span.traceContext, next);
2728
+ tracer.endSpan(span);
2729
+ span.attributes[SpanAttributes.HTTP_STATUS_CODE] = response.status;
2730
+ return response;
2731
+ } catch (error) {
2732
+ tracer.endSpan(span, error);
2733
+ throw error;
2734
+ }
2735
+ };
2736
+ }
2737
+ function createRpcTracing(tracer) {
2738
+ return {
2739
+ /**
2740
+ * Trace an outgoing RPC call
2741
+ */
2742
+ async traceCall(service, method, fn) {
2743
+ return tracer.trace(
2744
+ `rpc.${service}.${method}`,
2745
+ fn,
2746
+ {
2747
+ kind: "client",
2748
+ attributes: {
2749
+ [SpanAttributes.RPC_SYSTEM]: "pars",
2750
+ [SpanAttributes.RPC_SERVICE]: service,
2751
+ [SpanAttributes.RPC_METHOD]: method
2752
+ }
2753
+ }
2754
+ );
2755
+ },
2756
+ /**
2757
+ * Trace an incoming RPC request
2758
+ */
2759
+ async traceHandler(service, method, fn, parentCtx) {
2760
+ const handlerOpts = {
2761
+ kind: "server",
2762
+ attributes: {
2763
+ [SpanAttributes.RPC_SYSTEM]: "pars",
2764
+ [SpanAttributes.RPC_SERVICE]: service,
2765
+ [SpanAttributes.RPC_METHOD]: method
2766
+ }
2767
+ };
2768
+ if (parentCtx) {
2769
+ handlerOpts.parent = parentCtx;
2770
+ }
2771
+ const span = tracer.startSpan(`rpc.${service}.${method}`, handlerOpts);
2772
+ if (!span) {
2773
+ return fn();
2774
+ }
2775
+ try {
2776
+ const result = await tracer.getContextManager().run(span.traceContext, fn);
2777
+ tracer.endSpan(span);
2778
+ return result;
2779
+ } catch (error) {
2780
+ tracer.endSpan(span, error);
2781
+ throw error;
2782
+ }
2783
+ }
2784
+ };
2785
+ }
2786
+
2787
+ // src/client.ts
2788
+ var ServiceClientImpl = class {
2789
+ name;
2790
+ rpcClient;
2791
+ eventTransport;
2792
+ config;
2793
+ tracer;
2794
+ constructor(definition, rpcTransport, eventTransport, config, _logger) {
2795
+ this.name = definition.name;
2796
+ this.config = mergeConfig(config);
2797
+ this.tracer = getGlobalTracer();
2798
+ this.rpcClient = new RpcClient({
2799
+ service: definition.name,
2800
+ transport: rpcTransport,
2801
+ config: this.config
2802
+ });
2803
+ this.eventTransport = eventTransport;
2804
+ }
2805
+ /**
2806
+ * Execute a query
2807
+ */
2808
+ async query(method, input) {
2809
+ const methodName = String(method);
2810
+ const traceContext = this.tracer?.currentContext();
2811
+ if (this.tracer && traceContext) {
2812
+ return this.tracer.trace(
2813
+ `rpc.${this.name}.${methodName}`,
2814
+ async () => {
2815
+ return this.rpcClient.query(methodName, input, {
2816
+ traceContext
2817
+ });
2818
+ },
2819
+ { kind: "client" }
2820
+ );
2821
+ }
2822
+ return this.rpcClient.query(methodName, input);
2823
+ }
2824
+ /**
2825
+ * Execute a mutation
2826
+ */
2827
+ async mutate(method, input) {
2828
+ const methodName = String(method);
2829
+ const traceContext = this.tracer?.currentContext();
2830
+ if (this.tracer && traceContext) {
2831
+ return this.tracer.trace(
2832
+ `rpc.${this.name}.${methodName}`,
2833
+ async () => {
2834
+ return this.rpcClient.mutate(methodName, input, {
2835
+ traceContext
2836
+ });
2837
+ },
2838
+ { kind: "client" }
2839
+ );
2840
+ }
2841
+ return this.rpcClient.mutate(methodName, input);
2842
+ }
2843
+ /**
2844
+ * Emit an event
2845
+ */
2846
+ async emit(eventType, data) {
2847
+ const type = String(eventType);
2848
+ const traceContext = this.tracer?.currentContext();
2849
+ const event = {
2850
+ specversion: "1.0",
2851
+ type,
2852
+ source: this.name,
2853
+ id: generateId3(),
2854
+ time: (/* @__PURE__ */ new Date()).toISOString(),
2855
+ data
2856
+ };
2857
+ if (traceContext) {
2858
+ event.parstracecontext = `00-${traceContext.traceId}-${traceContext.spanId}-01`;
2859
+ }
2860
+ await this.eventTransport.emit(event);
2861
+ }
2862
+ /**
2863
+ * Subscribe to events
2864
+ */
2865
+ on(eventType, handler, options) {
2866
+ return this.eventTransport.subscribe(eventType, handler, options);
2867
+ }
2868
+ /**
2869
+ * Get circuit breaker state
2870
+ */
2871
+ getCircuitState() {
2872
+ return this.rpcClient.getCircuitState();
2873
+ }
2874
+ /**
2875
+ * Close the client
2876
+ */
2877
+ async close() {
2878
+ await this.rpcClient.close();
2879
+ await this.eventTransport.close?.();
2880
+ }
2881
+ };
2882
+ function useService(serviceName, options = {}) {
2883
+ const mode = options.mode ?? "embedded";
2884
+ const config = options.config ?? {};
2885
+ let rpcTransport;
2886
+ let eventTransport;
2887
+ switch (mode) {
2888
+ case "embedded": {
2889
+ const registry = getEmbeddedRegistry();
2890
+ if (!registry.has(serviceName)) {
2891
+ throw new Error(
2892
+ `Service not found in embedded registry: ${serviceName}. Make sure the service is registered before using it.`
2893
+ );
2894
+ }
2895
+ rpcTransport = registry.createTransport(serviceName);
2896
+ const eventBus = getGlobalEventBus();
2897
+ const services = eventBus.getServices();
2898
+ if (services.includes(serviceName)) {
2899
+ eventTransport = createMemoryEventTransport();
2900
+ } else {
2901
+ eventTransport = createMemoryEventTransport();
2902
+ }
2903
+ break;
2904
+ }
2905
+ case "http": {
2906
+ if (!options.baseUrl) {
2907
+ throw new Error("baseUrl is required for HTTP mode");
2908
+ }
2909
+ rpcTransport = createHttpTransport({
2910
+ baseUrl: options.baseUrl
2911
+ });
2912
+ eventTransport = createMemoryEventTransport();
2913
+ break;
2914
+ }
2915
+ case "binding": {
2916
+ if (!options.binding) {
2917
+ throw new Error("binding is required for binding mode");
2918
+ }
2919
+ rpcTransport = createBindingTransport(serviceName, options.binding);
2920
+ eventTransport = createMemoryEventTransport();
2921
+ break;
2922
+ }
2923
+ default:
2924
+ throw new Error(`Unknown service client mode: ${mode}`);
2925
+ }
2926
+ if (options.rpcTransport) {
2927
+ rpcTransport = options.rpcTransport;
2928
+ }
2929
+ if (options.eventTransport) {
2930
+ eventTransport = options.eventTransport;
2931
+ }
2932
+ const definition = {
2933
+ name: serviceName,
2934
+ version: "1.x"
2935
+ };
2936
+ return new ServiceClientImpl(
2937
+ definition,
2938
+ rpcTransport,
2939
+ eventTransport,
2940
+ config
2941
+ );
2942
+ }
2943
+ function useTypedService(definition, options = {}) {
2944
+ return useService(definition.name, options);
2945
+ }
2946
+ function createBindingTransport(_serviceName, binding) {
2947
+ return {
2948
+ name: "binding",
2949
+ async call(request) {
2950
+ const response = await binding.fetch("http://internal/rpc", {
2951
+ method: "POST",
2952
+ headers: {
2953
+ "Content-Type": "application/json",
2954
+ "X-Request-ID": request.id,
2955
+ "X-Service": request.service,
2956
+ "X-Method": request.method
2957
+ },
2958
+ body: JSON.stringify(request)
2959
+ });
2960
+ return response.json();
2961
+ },
2962
+ async close() {
2963
+ }
2964
+ };
2965
+ }
2966
+ var ServiceRegistry = class {
2967
+ clients = /* @__PURE__ */ new Map();
2968
+ config;
2969
+ constructor(config) {
2970
+ this.config = config ?? {};
2971
+ }
2972
+ /**
2973
+ * Get or create a service client
2974
+ */
2975
+ get(serviceName, options) {
2976
+ let client = this.clients.get(serviceName);
2977
+ if (!client) {
2978
+ client = useService(serviceName, {
2979
+ ...options,
2980
+ config: { ...this.config, ...options?.config }
2981
+ });
2982
+ this.clients.set(serviceName, client);
2983
+ }
2984
+ return client;
2985
+ }
2986
+ /**
2987
+ * Close all clients
2988
+ */
2989
+ async closeAll() {
2990
+ const closePromises = Array.from(this.clients.values()).map((client) => {
2991
+ if ("close" in client && typeof client.close === "function") {
2992
+ return client.close();
2993
+ }
2994
+ return Promise.resolve();
2995
+ });
2996
+ await Promise.all(closePromises);
2997
+ this.clients.clear();
2998
+ }
2999
+ };
3000
+ function createServiceRegistry(config) {
3001
+ return new ServiceRegistry(config);
3002
+ }
3003
+
3004
+ // src/rpc/server.ts
3005
+ import { createLogger as createLogger5 } from "@parsrun/core";
3006
+ var RpcServer = class {
3007
+ definition;
3008
+ handlers;
3009
+ logger;
3010
+ defaultTimeout;
3011
+ middleware;
3012
+ constructor(options) {
3013
+ this.definition = options.definition;
3014
+ this.handlers = options.handlers;
3015
+ this.logger = options.logger ?? createLogger5({ name: `rpc:${options.definition.name}` });
3016
+ this.defaultTimeout = options.defaultTimeout ?? 3e4;
3017
+ this.middleware = options.middleware ?? [];
3018
+ }
3019
+ /**
3020
+ * Handle an RPC request
3021
+ */
3022
+ async handle(request) {
3023
+ const startTime = Date.now();
3024
+ const context = {
3025
+ requestId: request.id,
3026
+ service: request.service,
3027
+ method: request.method,
3028
+ type: request.type,
3029
+ metadata: request.metadata ?? {},
3030
+ logger: this.logger.child({ requestId: request.id, method: request.method })
3031
+ };
3032
+ if (request.traceContext) {
3033
+ context.traceContext = request.traceContext;
3034
+ }
3035
+ try {
3036
+ if (request.version && !satisfiesVersion(this.definition.version, request.version)) {
3037
+ throw new VersionMismatchError(
3038
+ this.definition.name,
3039
+ request.version,
3040
+ this.definition.version
3041
+ );
3042
+ }
3043
+ const handler = this.getHandler(request.method, request.type);
3044
+ if (!handler) {
3045
+ throw new MethodNotFoundError(this.definition.name, request.method);
3046
+ }
3047
+ const deprecation = isMethodDeprecated(this.definition, request.method, request.type);
3048
+ if (deprecation.deprecated) {
3049
+ context.logger.warn(`Method ${request.method} is deprecated`, {
3050
+ since: deprecation.since,
3051
+ replacement: deprecation.replacement
3052
+ });
3053
+ }
3054
+ const chain = this.buildMiddlewareChain(request, context, handler);
3055
+ const timeout = getMethodTimeout(
3056
+ this.definition,
3057
+ request.method,
3058
+ request.type,
3059
+ this.defaultTimeout
3060
+ );
3061
+ const output = await Promise.race([
3062
+ chain(),
3063
+ new Promise(
3064
+ (_, reject) => setTimeout(() => reject(new Error("Handler timeout")), timeout)
3065
+ )
3066
+ ]);
3067
+ const duration = Date.now() - startTime;
3068
+ context.logger.info(`${request.type} ${request.method} completed`, { durationMs: duration });
3069
+ const successResponse = {
3070
+ id: request.id,
3071
+ success: true,
3072
+ version: this.definition.version,
3073
+ output
3074
+ };
3075
+ if (request.traceContext) {
3076
+ successResponse.traceContext = request.traceContext;
3077
+ }
3078
+ return successResponse;
3079
+ } catch (error) {
3080
+ const duration = Date.now() - startTime;
3081
+ const rpcError = toRpcError(error);
3082
+ context.logger.error(`${request.type} ${request.method} failed`, error, {
3083
+ durationMs: duration,
3084
+ errorCode: rpcError.code
3085
+ });
3086
+ const errorData = {
3087
+ code: rpcError.code,
3088
+ message: rpcError.message,
3089
+ retryable: rpcError.retryable
3090
+ };
3091
+ if (rpcError.details) {
3092
+ errorData.details = rpcError.details;
3093
+ }
3094
+ if (rpcError.retryAfter !== void 0) {
3095
+ errorData.retryAfter = rpcError.retryAfter;
3096
+ }
3097
+ const errorResponse = {
3098
+ id: request.id,
3099
+ success: false,
3100
+ version: this.definition.version,
3101
+ error: errorData
3102
+ };
3103
+ if (request.traceContext) {
3104
+ errorResponse.traceContext = request.traceContext;
3105
+ }
3106
+ return errorResponse;
3107
+ }
3108
+ }
3109
+ /**
3110
+ * Get handler for a method
3111
+ */
3112
+ getHandler(method, type) {
3113
+ const handlers = type === "query" ? this.handlers.queries : this.handlers.mutations;
3114
+ return handlers?.[method];
3115
+ }
3116
+ /**
3117
+ * Build middleware chain
3118
+ */
3119
+ buildMiddlewareChain(request, context, handler) {
3120
+ let index = -1;
3121
+ const dispatch = async (i) => {
3122
+ if (i <= index) {
3123
+ throw new Error("next() called multiple times");
3124
+ }
3125
+ index = i;
3126
+ if (i < this.middleware.length) {
3127
+ const mw = this.middleware[i];
3128
+ return mw(request, context, () => dispatch(i + 1));
3129
+ }
3130
+ return handler(request.input, context);
3131
+ };
3132
+ return () => dispatch(0);
3133
+ }
3134
+ /**
3135
+ * Get service definition
3136
+ */
3137
+ getDefinition() {
3138
+ return this.definition;
3139
+ }
3140
+ /**
3141
+ * Get registered methods
3142
+ */
3143
+ getMethods() {
3144
+ return {
3145
+ queries: Object.keys(this.handlers.queries ?? {}),
3146
+ mutations: Object.keys(this.handlers.mutations ?? {})
3147
+ };
3148
+ }
3149
+ };
3150
+ function createRpcServer(options) {
3151
+ return new RpcServer(options);
3152
+ }
3153
+ function loggingMiddleware() {
3154
+ return async (request, context, next) => {
3155
+ context.logger.debug(`Handling ${request.type} ${request.method}`, {
3156
+ inputKeys: Object.keys(request.input)
3157
+ });
3158
+ const result = await next();
3159
+ context.logger.debug(`Completed ${request.type} ${request.method}`);
3160
+ return result;
3161
+ };
3162
+ }
3163
+ function validationMiddleware(validators) {
3164
+ return async (request, _context, next) => {
3165
+ const validator = validators[request.method];
3166
+ if (validator) {
3167
+ request.input = validator(request.input);
3168
+ }
3169
+ return next();
3170
+ };
3171
+ }
3172
+ function tenantMiddleware() {
3173
+ return async (_request, context, next) => {
3174
+ const tenantId = context.metadata["tenantId"];
3175
+ if (tenantId) {
3176
+ context.logger = context.logger.child({ tenantId });
3177
+ }
3178
+ return next();
3179
+ };
3180
+ }
3181
+
3182
+ // src/events/emitter.ts
3183
+ import { createLogger as createLogger6 } from "@parsrun/core";
3184
+ var EventEmitter = class {
3185
+ service;
3186
+ definition;
3187
+ transport;
3188
+ logger;
3189
+ defaultTenantId;
3190
+ validateEvents;
3191
+ constructor(options) {
3192
+ this.service = options.service;
3193
+ if (options.definition) {
3194
+ this.definition = options.definition;
3195
+ }
3196
+ this.transport = options.transport;
3197
+ this.logger = options.logger ?? createLogger6({ name: `events:${options.service}` });
3198
+ if (options.defaultTenantId) {
3199
+ this.defaultTenantId = options.defaultTenantId;
3200
+ }
3201
+ this.validateEvents = options.validateEvents ?? true;
3202
+ }
3203
+ /**
3204
+ * Emit an event
3205
+ */
3206
+ async emit(type, data, options) {
3207
+ if (this.validateEvents && this.definition?.events?.emits) {
3208
+ const emits = this.definition.events.emits;
3209
+ if (!(type in emits)) {
3210
+ this.logger.warn(`Event type not declared in service definition: ${type}`);
3211
+ }
3212
+ }
3213
+ let delivery;
3214
+ if (this.definition?.events?.emits?.[type]) {
3215
+ delivery = this.definition.events.emits[type].delivery;
3216
+ }
3217
+ const eventOptions = {
3218
+ type,
3219
+ source: this.service,
3220
+ data
3221
+ };
3222
+ if (options?.eventId) eventOptions.id = options.eventId;
3223
+ if (options?.subject) eventOptions.subject = options.subject;
3224
+ const tenantId = options?.tenantId ?? this.defaultTenantId;
3225
+ if (tenantId) eventOptions.tenantId = tenantId;
3226
+ if (options?.requestId) eventOptions.requestId = options.requestId;
3227
+ if (options?.traceContext) eventOptions.traceContext = options.traceContext;
3228
+ const eventDelivery = options?.delivery ?? delivery;
3229
+ if (eventDelivery) eventOptions.delivery = eventDelivery;
3230
+ const event = createEvent(eventOptions);
3231
+ try {
3232
+ await this.transport.emit(event);
3233
+ this.logger.debug(`Event emitted: ${type}`, {
3234
+ eventId: event.id,
3235
+ tenantId: event.parstenantid
3236
+ });
3237
+ return event.id;
3238
+ } catch (error) {
3239
+ this.logger.error(`Failed to emit event: ${type}`, error, {
3240
+ eventId: event.id
3241
+ });
3242
+ throw error;
3243
+ }
3244
+ }
3245
+ /**
3246
+ * Emit multiple events
3247
+ */
3248
+ async emitBatch(events) {
3249
+ const results = [];
3250
+ for (const { type, data, options } of events) {
3251
+ const eventId = await this.emit(type, data, options);
3252
+ results.push(eventId);
3253
+ }
3254
+ return results;
3255
+ }
3256
+ /**
3257
+ * Create a scoped emitter with preset options
3258
+ */
3259
+ scoped(options) {
3260
+ return new ScopedEmitter(this, options);
3261
+ }
3262
+ /**
3263
+ * Get service name
3264
+ */
3265
+ get serviceName() {
3266
+ return this.service;
3267
+ }
3268
+ };
3269
+ var ScopedEmitter = class {
3270
+ emitter;
3271
+ defaultOptions;
3272
+ constructor(emitter, defaultOptions) {
3273
+ this.emitter = emitter;
3274
+ this.defaultOptions = defaultOptions;
3275
+ }
3276
+ async emit(type, data, options) {
3277
+ return this.emitter.emit(type, data, {
3278
+ ...this.defaultOptions,
3279
+ ...options
3280
+ });
3281
+ }
3282
+ };
3283
+ function createEventEmitter(options) {
3284
+ return new EventEmitter(options);
3285
+ }
3286
+ function createTypedEmitter(definition, options) {
3287
+ const emitter = new EventEmitter({
3288
+ ...options,
3289
+ service: definition.name,
3290
+ definition
3291
+ });
3292
+ return emitter;
3293
+ }
3294
+
3295
+ // src/events/dead-letter.ts
3296
+ import { createLogger as createLogger7, generateId as generateId4 } from "@parsrun/core";
3297
+ var DeadLetterQueue = class {
3298
+ entries = /* @__PURE__ */ new Map();
3299
+ resolvedOptions;
3300
+ logger;
3301
+ cleanupTimer = null;
3302
+ constructor(options = {}) {
3303
+ this.resolvedOptions = {
3304
+ maxSize: options.maxSize ?? 1e3,
3305
+ retentionMs: options.retentionMs ?? 30 * 24 * 60 * 60 * 1e3,
3306
+ // 30 days
3307
+ alertThreshold: options.alertThreshold ?? 10
3308
+ };
3309
+ if (options.onAdd) this.resolvedOptions.onAdd = options.onAdd;
3310
+ if (options.onThreshold) this.resolvedOptions.onThreshold = options.onThreshold;
3311
+ if (options.logger) this.resolvedOptions.logger = options.logger;
3312
+ this.logger = options.logger ?? createLogger7({ name: "dlq" });
3313
+ this.cleanupTimer = setInterval(() => this.cleanup(), 60 * 60 * 1e3);
3314
+ }
3315
+ /**
3316
+ * Add an entry to the DLQ
3317
+ */
3318
+ async add(options) {
3319
+ const entry = {
3320
+ id: generateId4(),
3321
+ event: options.event,
3322
+ error: options.error,
3323
+ pattern: options.pattern,
3324
+ attempts: options.attempts,
3325
+ addedAt: /* @__PURE__ */ new Date()
3326
+ };
3327
+ if (options.metadata) {
3328
+ entry.metadata = options.metadata;
3329
+ }
3330
+ if (this.entries.size >= this.resolvedOptions.maxSize) {
3331
+ const oldest = this.getOldest();
3332
+ if (oldest) {
3333
+ this.entries.delete(oldest.id);
3334
+ this.logger.debug(`DLQ: Removed oldest entry to make room`, {
3335
+ removedId: oldest.id
3336
+ });
3337
+ }
3338
+ }
3339
+ this.entries.set(entry.id, entry);
3340
+ this.logger.warn(`DLQ: Entry added`, {
3341
+ id: entry.id,
3342
+ eventId: entry.event.id,
3343
+ eventType: entry.event.type,
3344
+ error: entry.error
3345
+ });
3346
+ this.resolvedOptions.onAdd?.(entry);
3347
+ if (this.entries.size >= this.resolvedOptions.alertThreshold) {
3348
+ this.resolvedOptions.onThreshold?.(this.entries.size);
3349
+ }
3350
+ return entry.id;
3351
+ }
3352
+ /**
3353
+ * Get an entry by ID
3354
+ */
3355
+ get(id) {
3356
+ return this.entries.get(id);
3357
+ }
3358
+ /**
3359
+ * Get all entries
3360
+ */
3361
+ getAll() {
3362
+ return Array.from(this.entries.values());
3363
+ }
3364
+ /**
3365
+ * Get entries by event type
3366
+ */
3367
+ getByEventType(eventType) {
3368
+ return Array.from(this.entries.values()).filter(
3369
+ (e) => e.event.type === eventType
3370
+ );
3371
+ }
3372
+ /**
3373
+ * Get entries by pattern
3374
+ */
3375
+ getByPattern(pattern) {
3376
+ return Array.from(this.entries.values()).filter(
3377
+ (e) => e.pattern === pattern
3378
+ );
3379
+ }
3380
+ /**
3381
+ * Remove an entry
3382
+ */
3383
+ remove(id) {
3384
+ const deleted = this.entries.delete(id);
3385
+ if (deleted) {
3386
+ this.logger.debug(`DLQ: Entry removed`, { id });
3387
+ }
3388
+ return deleted;
3389
+ }
3390
+ /**
3391
+ * Retry an entry (remove from DLQ and return event)
3392
+ */
3393
+ retry(id) {
3394
+ const entry = this.entries.get(id);
3395
+ if (!entry) return void 0;
3396
+ this.entries.delete(id);
3397
+ this.logger.info(`DLQ: Entry removed for retry`, {
3398
+ id,
3399
+ eventId: entry.event.id
3400
+ });
3401
+ return entry.event;
3402
+ }
3403
+ /**
3404
+ * Get count
3405
+ */
3406
+ get size() {
3407
+ return this.entries.size;
3408
+ }
3409
+ /**
3410
+ * Clear all entries
3411
+ */
3412
+ clear() {
3413
+ this.entries.clear();
3414
+ this.logger.info(`DLQ: Cleared all entries`);
3415
+ }
3416
+ /**
3417
+ * Cleanup expired entries
3418
+ */
3419
+ cleanup() {
3420
+ const now = Date.now();
3421
+ let removed = 0;
3422
+ for (const [id, entry] of this.entries) {
3423
+ const age = now - entry.addedAt.getTime();
3424
+ if (age > this.resolvedOptions.retentionMs) {
3425
+ this.entries.delete(id);
3426
+ removed++;
3427
+ }
3428
+ }
3429
+ if (removed > 0) {
3430
+ this.logger.debug(`DLQ: Cleaned up ${removed} expired entries`);
3431
+ }
3432
+ }
3433
+ /**
3434
+ * Get oldest entry
3435
+ */
3436
+ getOldest() {
3437
+ let oldest;
3438
+ for (const entry of this.entries.values()) {
3439
+ if (!oldest || entry.addedAt < oldest.addedAt) {
3440
+ oldest = entry;
3441
+ }
3442
+ }
3443
+ return oldest;
3444
+ }
3445
+ /**
3446
+ * Stop cleanup timer
3447
+ */
3448
+ close() {
3449
+ if (this.cleanupTimer) {
3450
+ clearInterval(this.cleanupTimer);
3451
+ this.cleanupTimer = null;
3452
+ }
3453
+ }
3454
+ /**
3455
+ * Export entries for persistence
3456
+ */
3457
+ export() {
3458
+ return Array.from(this.entries.values()).map((e) => ({
3459
+ ...e,
3460
+ addedAt: e.addedAt
3461
+ }));
3462
+ }
3463
+ /**
3464
+ * Import entries from persistence
3465
+ */
3466
+ import(entries) {
3467
+ for (const entry of entries) {
3468
+ this.entries.set(entry.id, {
3469
+ ...entry,
3470
+ addedAt: new Date(entry.addedAt)
3471
+ });
3472
+ }
3473
+ this.logger.info(`DLQ: Imported ${entries.length} entries`);
3474
+ }
3475
+ };
3476
+ function createDeadLetterQueue(options) {
3477
+ return new DeadLetterQueue(options);
3478
+ }
3479
+ export {
3480
+ Bulkhead,
3481
+ BulkheadRejectedError,
3482
+ CircuitBreaker,
3483
+ CircuitOpenError,
3484
+ ConsoleExporter,
3485
+ DEFAULT_DEAD_LETTER_CONFIG,
3486
+ DEFAULT_EVENT_CONFIG,
3487
+ DEFAULT_RESILIENCE_CONFIG,
3488
+ DEFAULT_SERIALIZATION_CONFIG,
3489
+ DEFAULT_SERVICE_CONFIG,
3490
+ DEFAULT_TRACING_CONFIG,
3491
+ DEFAULT_VERSIONING_CONFIG,
3492
+ DeadLetterQueue,
3493
+ EmbeddedRegistry,
3494
+ EmbeddedTransport,
3495
+ EventEmitter,
3496
+ EventHandlerRegistry,
3497
+ GlobalEventBus,
3498
+ HttpTransport,
3499
+ MemoryEventTransport,
3500
+ MethodNotFoundError,
3501
+ OtlpExporter,
3502
+ RpcClient,
3503
+ RpcError,
3504
+ RpcServer,
3505
+ ScopedEmitter,
3506
+ SerializationError,
3507
+ ServiceNotFoundError,
3508
+ ServiceRegistry,
3509
+ SpanAttributes,
3510
+ SpanManager,
3511
+ TimeoutError,
3512
+ TimeoutExceededError,
3513
+ TraceContextManager,
3514
+ Tracer,
3515
+ TransportError,
3516
+ VersionMismatchError,
3517
+ createChildContext,
3518
+ createConsoleExporter,
3519
+ createDeadLetterQueue,
3520
+ createDevConfig,
3521
+ createEmbeddedTransport,
3522
+ createEvent,
3523
+ createEventEmitter,
3524
+ createEventHandlerRegistry,
3525
+ createHttpHandler,
3526
+ createHttpTransport,
3527
+ createMemoryEventTransport,
3528
+ createOtlpExporter,
3529
+ createProdConfig,
3530
+ createRetryWrapper,
3531
+ createRpcClient,
3532
+ createRpcServer,
3533
+ createRpcTracing,
3534
+ createSerializer,
3535
+ createServiceRegistry,
3536
+ createSpan,
3537
+ createTimeoutWrapper,
3538
+ createTraceContext,
3539
+ createTracer,
3540
+ createTracingMiddleware,
3541
+ createTypedEmitter,
3542
+ defineService,
3543
+ executeWithDeadline,
3544
+ executeWithRetry,
3545
+ executeWithTimeout,
3546
+ formatEventType,
3547
+ formatTraceparent2 as formatTraceparent,
3548
+ formatTracestate,
3549
+ fromCompactEvent,
3550
+ generateSpanId,
3551
+ generateTraceId,
3552
+ getEmbeddedRegistry,
3553
+ getGlobalEventBus,
3554
+ getGlobalTracer,
3555
+ getMethodTimeout,
3556
+ getSerializer,
3557
+ getServiceEvents,
3558
+ getServiceMethods,
3559
+ getSpanDuration,
3560
+ isMethodDeprecated,
3561
+ isSpanCompleted,
3562
+ jsonSerializer,
3563
+ loggingMiddleware,
3564
+ matchEventType,
3565
+ mergeConfig,
3566
+ msgpackSerializer,
3567
+ parseEventType,
3568
+ parseTraceparent,
3569
+ parseTracestate,
3570
+ raceWithTimeout,
3571
+ resetGlobalTracer,
3572
+ satisfiesVersion,
3573
+ setGlobalTracer,
3574
+ shouldSample,
3575
+ spanToLogObject,
3576
+ tenantMiddleware,
3577
+ toCloudEvent,
3578
+ toCompactEvent,
3579
+ toRpcError,
3580
+ useService,
3581
+ useTypedService,
3582
+ validateCompactEvent,
3583
+ validateConfig,
3584
+ validateEvent,
3585
+ validationMiddleware,
3586
+ withRetry,
3587
+ withTimeout
3588
+ };
3589
+ //# sourceMappingURL=index.js.map