dspx 0.1.1-alpha.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.
Files changed (172) hide show
  1. package/.github/workflows/ci.yml +185 -0
  2. package/.vscode/c_cpp_properties.json +17 -0
  3. package/.vscode/settings.json +68 -0
  4. package/.vscode/tasks.json +28 -0
  5. package/DISCLAIMER.md +32 -0
  6. package/LICENSE +21 -0
  7. package/README.md +1803 -0
  8. package/ROADMAP.md +192 -0
  9. package/TECHNICAL_DEBT.md +165 -0
  10. package/binding.gyp +65 -0
  11. package/docs/ADVANCED_LOGGER_FEATURES.md +598 -0
  12. package/docs/AUTHENTICATION_SECURITY.md +396 -0
  13. package/docs/BACKEND_IMPROVEMENTS.md +399 -0
  14. package/docs/CHEBYSHEV_BIQUAD_EQ_IMPLEMENTATION.md +405 -0
  15. package/docs/FFT_IMPLEMENTATION.md +490 -0
  16. package/docs/FFT_IMPROVEMENTS_SUMMARY.md +387 -0
  17. package/docs/FFT_USER_GUIDE.md +494 -0
  18. package/docs/FILTERS_IMPLEMENTATION.md +260 -0
  19. package/docs/FILTER_API_GUIDE.md +418 -0
  20. package/docs/FIR_SIMD_OPTIMIZATION.md +175 -0
  21. package/docs/LOGGER_API_REFERENCE.md +350 -0
  22. package/docs/NOTCH_FILTER_QUICK_REF.md +121 -0
  23. package/docs/PHASE2_TESTS_AND_NOTCH_FILTER.md +341 -0
  24. package/docs/PHASES_5_7_SUMMARY.md +403 -0
  25. package/docs/PIPELINE_FILTER_INTEGRATION.md +446 -0
  26. package/docs/SIMD_OPTIMIZATIONS.md +211 -0
  27. package/docs/TEST_MIGRATION_SUMMARY.md +173 -0
  28. package/docs/TIMESERIES_IMPLEMENTATION_SUMMARY.md +322 -0
  29. package/docs/TIMESERIES_QUICK_REF.md +85 -0
  30. package/docs/advanced.md +559 -0
  31. package/docs/time-series-guide.md +617 -0
  32. package/docs/time-series-migration.md +376 -0
  33. package/jest.config.js +37 -0
  34. package/package.json +42 -0
  35. package/prebuilds/linux-x64/dsp-ts-redis.node +0 -0
  36. package/prebuilds/win32-x64/dsp-ts-redis.node +0 -0
  37. package/scripts/test.js +24 -0
  38. package/src/build/dsp-ts-redis.node +0 -0
  39. package/src/native/DspPipeline.cc +675 -0
  40. package/src/native/DspPipeline.h +44 -0
  41. package/src/native/FftBindings.cc +817 -0
  42. package/src/native/FilterBindings.cc +1001 -0
  43. package/src/native/IDspStage.h +53 -0
  44. package/src/native/adapters/InterpolatorStage.h +201 -0
  45. package/src/native/adapters/MeanAbsoluteValueStage.h +289 -0
  46. package/src/native/adapters/MovingAverageStage.h +306 -0
  47. package/src/native/adapters/RectifyStage.h +88 -0
  48. package/src/native/adapters/ResamplerStage.h +238 -0
  49. package/src/native/adapters/RmsStage.h +299 -0
  50. package/src/native/adapters/SscStage.h +121 -0
  51. package/src/native/adapters/VarianceStage.h +307 -0
  52. package/src/native/adapters/WampStage.h +114 -0
  53. package/src/native/adapters/WaveformLengthStage.h +115 -0
  54. package/src/native/adapters/ZScoreNormalizeStage.h +326 -0
  55. package/src/native/core/FftEngine.cc +441 -0
  56. package/src/native/core/FftEngine.h +224 -0
  57. package/src/native/core/FirFilter.cc +324 -0
  58. package/src/native/core/FirFilter.h +149 -0
  59. package/src/native/core/IirFilter.cc +576 -0
  60. package/src/native/core/IirFilter.h +210 -0
  61. package/src/native/core/MovingAbsoluteValueFilter.cc +17 -0
  62. package/src/native/core/MovingAbsoluteValueFilter.h +135 -0
  63. package/src/native/core/MovingAverageFilter.cc +18 -0
  64. package/src/native/core/MovingAverageFilter.h +135 -0
  65. package/src/native/core/MovingFftFilter.cc +291 -0
  66. package/src/native/core/MovingFftFilter.h +203 -0
  67. package/src/native/core/MovingVarianceFilter.cc +194 -0
  68. package/src/native/core/MovingVarianceFilter.h +114 -0
  69. package/src/native/core/MovingZScoreFilter.cc +215 -0
  70. package/src/native/core/MovingZScoreFilter.h +113 -0
  71. package/src/native/core/Policies.h +352 -0
  72. package/src/native/core/RmsFilter.cc +18 -0
  73. package/src/native/core/RmsFilter.h +131 -0
  74. package/src/native/core/SscFilter.cc +16 -0
  75. package/src/native/core/SscFilter.h +137 -0
  76. package/src/native/core/WampFilter.cc +16 -0
  77. package/src/native/core/WampFilter.h +101 -0
  78. package/src/native/core/WaveformLengthFilter.cc +17 -0
  79. package/src/native/core/WaveformLengthFilter.h +98 -0
  80. package/src/native/utils/CircularBufferArray.cc +336 -0
  81. package/src/native/utils/CircularBufferArray.h +62 -0
  82. package/src/native/utils/CircularBufferVector.cc +145 -0
  83. package/src/native/utils/CircularBufferVector.h +45 -0
  84. package/src/native/utils/NapiUtils.cc +53 -0
  85. package/src/native/utils/NapiUtils.h +21 -0
  86. package/src/native/utils/SimdOps.h +870 -0
  87. package/src/native/utils/SlidingWindowFilter.cc +239 -0
  88. package/src/native/utils/SlidingWindowFilter.h +159 -0
  89. package/src/native/utils/TimeSeriesBuffer.cc +205 -0
  90. package/src/native/utils/TimeSeriesBuffer.h +140 -0
  91. package/src/ts/CircularLogBuffer.ts +87 -0
  92. package/src/ts/DriftDetector.ts +331 -0
  93. package/src/ts/TopicRouter.ts +428 -0
  94. package/src/ts/__tests__/AdvancedDsp.test.ts +585 -0
  95. package/src/ts/__tests__/AuthAndEdgeCases.test.ts +241 -0
  96. package/src/ts/__tests__/Chaining.test.ts +387 -0
  97. package/src/ts/__tests__/ChebyshevBiquad.test.ts +229 -0
  98. package/src/ts/__tests__/CircularLogBuffer.test.ts +158 -0
  99. package/src/ts/__tests__/DriftDetector.test.ts +389 -0
  100. package/src/ts/__tests__/Fft.test.ts +484 -0
  101. package/src/ts/__tests__/ListState.test.ts +153 -0
  102. package/src/ts/__tests__/Logger.test.ts +208 -0
  103. package/src/ts/__tests__/LoggerAdvanced.test.ts +319 -0
  104. package/src/ts/__tests__/LoggerMinor.test.ts +247 -0
  105. package/src/ts/__tests__/MeanAbsoluteValue.test.ts +398 -0
  106. package/src/ts/__tests__/MovingAverage.test.ts +322 -0
  107. package/src/ts/__tests__/RMS.test.ts +315 -0
  108. package/src/ts/__tests__/Rectify.test.ts +272 -0
  109. package/src/ts/__tests__/Redis.test.ts +456 -0
  110. package/src/ts/__tests__/SlopeSignChange.test.ts +166 -0
  111. package/src/ts/__tests__/Tap.test.ts +164 -0
  112. package/src/ts/__tests__/TimeBasedExpiration.test.ts +124 -0
  113. package/src/ts/__tests__/TimeBasedRmsAndMav.test.ts +231 -0
  114. package/src/ts/__tests__/TimeBasedVarianceAndZScore.test.ts +284 -0
  115. package/src/ts/__tests__/TimeSeries.test.ts +254 -0
  116. package/src/ts/__tests__/TopicRouter.test.ts +332 -0
  117. package/src/ts/__tests__/TopicRouterAdvanced.test.ts +483 -0
  118. package/src/ts/__tests__/TopicRouterPriority.test.ts +487 -0
  119. package/src/ts/__tests__/Variance.test.ts +509 -0
  120. package/src/ts/__tests__/WaveformLength.test.ts +147 -0
  121. package/src/ts/__tests__/WillisonAmplitude.test.ts +197 -0
  122. package/src/ts/__tests__/ZScoreNormalize.test.ts +459 -0
  123. package/src/ts/advanced-dsp.ts +566 -0
  124. package/src/ts/backends.ts +1137 -0
  125. package/src/ts/bindings.ts +1225 -0
  126. package/src/ts/easter-egg.ts +42 -0
  127. package/src/ts/examples/MeanAbsoluteValue/test-state.ts +99 -0
  128. package/src/ts/examples/MeanAbsoluteValue/test-streaming.ts +269 -0
  129. package/src/ts/examples/MovingAverage/test-state.ts +85 -0
  130. package/src/ts/examples/MovingAverage/test-streaming.ts +188 -0
  131. package/src/ts/examples/RMS/test-state.ts +97 -0
  132. package/src/ts/examples/RMS/test-streaming.ts +253 -0
  133. package/src/ts/examples/Rectify/test-state.ts +107 -0
  134. package/src/ts/examples/Rectify/test-streaming.ts +242 -0
  135. package/src/ts/examples/Variance/test-state.ts +195 -0
  136. package/src/ts/examples/Variance/test-streaming.ts +260 -0
  137. package/src/ts/examples/ZScoreNormalize/test-state.ts +277 -0
  138. package/src/ts/examples/ZScoreNormalize/test-streaming.ts +306 -0
  139. package/src/ts/examples/advanced-dsp-examples.ts +397 -0
  140. package/src/ts/examples/callbacks/advanced-router-features.ts +326 -0
  141. package/src/ts/examples/callbacks/benchmark-circular-buffer.ts +109 -0
  142. package/src/ts/examples/callbacks/monitoring-example.ts +265 -0
  143. package/src/ts/examples/callbacks/pipeline-callbacks-example.ts +137 -0
  144. package/src/ts/examples/callbacks/pooled-callbacks-example.ts +274 -0
  145. package/src/ts/examples/callbacks/priority-routing-example.ts +277 -0
  146. package/src/ts/examples/callbacks/production-topic-router.ts +214 -0
  147. package/src/ts/examples/callbacks/topic-based-logging.ts +161 -0
  148. package/src/ts/examples/chaining/test-chaining-redis.ts +113 -0
  149. package/src/ts/examples/chaining/test-chaining.ts +52 -0
  150. package/src/ts/examples/emg-features-example.ts +284 -0
  151. package/src/ts/examples/fft-example.ts +309 -0
  152. package/src/ts/examples/fft-examples.ts +349 -0
  153. package/src/ts/examples/filter-examples.ts +320 -0
  154. package/src/ts/examples/list-state-example.ts +131 -0
  155. package/src/ts/examples/logger-example.ts +91 -0
  156. package/src/ts/examples/notch-filter-examples.ts +243 -0
  157. package/src/ts/examples/phase5/drift-detection-example.ts +290 -0
  158. package/src/ts/examples/phase6-7/production-observability.ts +476 -0
  159. package/src/ts/examples/phase6-7/redis-timeseries-integration.ts +446 -0
  160. package/src/ts/examples/redis/redis-example.ts +202 -0
  161. package/src/ts/examples/redis-example.ts +202 -0
  162. package/src/ts/examples/simd-benchmark.ts +126 -0
  163. package/src/ts/examples/tap-debugging.ts +230 -0
  164. package/src/ts/examples/timeseries/comparison-example.ts +290 -0
  165. package/src/ts/examples/timeseries/iot-sensor-example.ts +143 -0
  166. package/src/ts/examples/timeseries/redis-streaming-example.ts +233 -0
  167. package/src/ts/examples/waveform-length-example.ts +139 -0
  168. package/src/ts/fft.ts +722 -0
  169. package/src/ts/filters.ts +1078 -0
  170. package/src/ts/index.ts +120 -0
  171. package/src/ts/types.ts +589 -0
  172. package/tsconfig.json +15 -0
@@ -0,0 +1,428 @@
1
+ /**
2
+ * Topic-based log router for fan-out to multiple observability backends
3
+ *
4
+ * Implements production-grade routing pattern used by:
5
+ * - Grafana Loki
6
+ * - OpenTelemetry Collector
7
+ * - FluentBit
8
+ * - Vector.dev
9
+ */
10
+
11
+ import type { LogEntry, LogPriority } from "./types.js";
12
+
13
+ /**
14
+ * Route handler function for processing log entries
15
+ */
16
+ export type RouteHandler = (log: LogEntry) => Promise<void> | void;
17
+
18
+ /**
19
+ * Custom pattern matcher function
20
+ */
21
+ export type PatternMatcher = (topic: string) => boolean;
22
+
23
+ /**
24
+ * Route configuration options
25
+ */
26
+ export interface RouteOptions {
27
+ /** Maximum number of concurrent executions for this route (default: unlimited) */
28
+ concurrency?: number;
29
+ /** Enable latency tracking for this route (default: false) */
30
+ trackMetrics?: boolean;
31
+ /** Minimum priority level for logs to be routed (1-10, default: 1 = all logs) */
32
+ minPriority?: LogPriority;
33
+ /** Maximum priority level for logs to be routed (1-10, default: 10 = all logs) */
34
+ maxPriority?: LogPriority;
35
+ }
36
+
37
+ /**
38
+ * Route metrics for observability
39
+ */
40
+ export interface RouteMetrics {
41
+ name: string;
42
+ pattern: string;
43
+ executionCount: number;
44
+ totalDuration: number;
45
+ averageDuration: number;
46
+ minDuration: number;
47
+ maxDuration: number;
48
+ errorCount: number;
49
+ lastExecuted?: number;
50
+ }
51
+
52
+ /**
53
+ * Route definition with pattern matching
54
+ */
55
+ export interface Route {
56
+ pattern: RegExp;
57
+ handler: RouteHandler;
58
+ name?: string;
59
+ options: RouteOptions;
60
+ metrics: {
61
+ count: number;
62
+ totalDuration: number;
63
+ minDuration: number;
64
+ maxDuration: number;
65
+ errorCount: number;
66
+ lastExecuted?: number;
67
+ };
68
+ semaphore?: {
69
+ running: number;
70
+ queue: Array<() => void>;
71
+ };
72
+ }
73
+
74
+ /**
75
+ * TopicRouter - Fan-out logs to multiple backends based on topic patterns
76
+ *
77
+ * @example
78
+ * ```ts
79
+ * const router = new TopicRouter();
80
+ *
81
+ * // Add routes
82
+ * router.addRoute(/^pipeline\.error/, async (log) => {
83
+ * await pagerDuty.alert(log);
84
+ * });
85
+ *
86
+ * router.addRoute(/^pipeline\.performance/, async (log) => {
87
+ * await prometheus.record(log.topic, log.context);
88
+ * });
89
+ *
90
+ * router.addRoute(/./, async (log) => {
91
+ * await loki.send(log);
92
+ * });
93
+ *
94
+ * // Use with pipeline
95
+ * pipeline.pipeline({
96
+ * onLogBatch: (logs) => router.routeBatch(logs)
97
+ * });
98
+ * ```
99
+ */
100
+ export class TopicRouter {
101
+ private routes: Route[] = [];
102
+
103
+ /**
104
+ * Add a route with pattern matching
105
+ * @param pattern - Regex or string pattern to match against log.topic
106
+ * @param handler - Handler function to process matching logs
107
+ * @param nameOrOptions - Optional name or route options
108
+ */
109
+ addRoute(
110
+ pattern: RegExp | string,
111
+ handler: RouteHandler,
112
+ nameOrOptions?: string | RouteOptions
113
+ ): this {
114
+ const name = typeof nameOrOptions === "string" ? nameOrOptions : undefined;
115
+ const options: RouteOptions =
116
+ typeof nameOrOptions === "object" ? nameOrOptions : {};
117
+
118
+ this.routes.push({
119
+ pattern: typeof pattern === "string" ? new RegExp(pattern) : pattern,
120
+ handler,
121
+ name,
122
+ options,
123
+ metrics: {
124
+ count: 0,
125
+ totalDuration: 0,
126
+ minDuration: Infinity,
127
+ maxDuration: 0,
128
+ errorCount: 0,
129
+ },
130
+ semaphore: options.concurrency ? { running: 0, queue: [] } : undefined,
131
+ });
132
+ return this;
133
+ }
134
+
135
+ /**
136
+ * Execute a handler with concurrency control and metrics tracking
137
+ */
138
+ private async executeHandler(route: Route, log: LogEntry): Promise<void> {
139
+ // Concurrency control via semaphore
140
+ if (route.semaphore && route.options.concurrency) {
141
+ if (route.semaphore.running >= route.options.concurrency) {
142
+ // Wait for slot to become available
143
+ await new Promise<void>((resolve) => {
144
+ route.semaphore!.queue.push(resolve);
145
+ });
146
+ }
147
+ route.semaphore.running++;
148
+ }
149
+
150
+ const startTime = route.options.trackMetrics ? performance.now() : 0;
151
+
152
+ try {
153
+ const result = route.handler(log);
154
+ if (result instanceof Promise) {
155
+ await result;
156
+ }
157
+
158
+ // Update metrics on success
159
+ if (route.options.trackMetrics) {
160
+ const duration = performance.now() - startTime;
161
+ route.metrics.count++;
162
+ route.metrics.totalDuration += duration;
163
+ route.metrics.minDuration = Math.min(
164
+ route.metrics.minDuration,
165
+ duration
166
+ );
167
+ route.metrics.maxDuration = Math.max(
168
+ route.metrics.maxDuration,
169
+ duration
170
+ );
171
+ route.metrics.lastExecuted = Date.now();
172
+ }
173
+ } catch (error) {
174
+ // Track execution even on error
175
+ if (route.options.trackMetrics) {
176
+ const duration = performance.now() - startTime;
177
+ route.metrics.count++;
178
+ route.metrics.totalDuration += duration;
179
+ route.metrics.minDuration = Math.min(
180
+ route.metrics.minDuration,
181
+ duration
182
+ );
183
+ route.metrics.maxDuration = Math.max(
184
+ route.metrics.maxDuration,
185
+ duration
186
+ );
187
+ route.metrics.lastExecuted = Date.now();
188
+ }
189
+
190
+ // Update error count
191
+ route.metrics.errorCount++;
192
+
193
+ console.error(
194
+ `Topic router error in route ${route.name || route.pattern}:`,
195
+ error
196
+ );
197
+ } finally {
198
+ // Release semaphore slot
199
+ if (route.semaphore) {
200
+ route.semaphore.running--;
201
+ const nextInQueue = route.semaphore.queue.shift();
202
+ if (nextInQueue) {
203
+ nextInQueue();
204
+ }
205
+ }
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Route a single log entry to matching handlers
211
+ * @param log - Log entry to route
212
+ */
213
+ async route(log: LogEntry): Promise<void> {
214
+ if (!log.topic) {
215
+ // Skip logs without topics (backwards compatibility)
216
+ return;
217
+ }
218
+
219
+ // Default priority to 1 if not specified
220
+ const logPriority = log.priority ?? 1;
221
+
222
+ const promises: Promise<void>[] = [];
223
+
224
+ for (const route of this.routes) {
225
+ // Check topic pattern match
226
+ if (!route.pattern.test(log.topic)) {
227
+ continue;
228
+ }
229
+
230
+ // Check priority range if specified
231
+ const minPriority = route.options.minPriority ?? 1;
232
+ const maxPriority = route.options.maxPriority ?? 10;
233
+
234
+ if (logPriority < minPriority || logPriority > maxPriority) {
235
+ continue; // Skip this route - priority out of range
236
+ }
237
+
238
+ promises.push(this.executeHandler(route, log));
239
+ }
240
+
241
+ // Wait for all handlers to complete
242
+ if (promises.length > 0) {
243
+ await Promise.all(promises);
244
+ }
245
+ }
246
+
247
+ /**
248
+ * Route a batch of log entries in parallel
249
+ * @param logs - Array of log entries to route
250
+ */
251
+ async routeBatch(logs: LogEntry[]): Promise<void> {
252
+ await Promise.all(logs.map((log) => this.route(log)));
253
+ }
254
+
255
+ /**
256
+ * Clear all routes
257
+ */
258
+ clearRoutes(): void {
259
+ this.routes = [];
260
+ }
261
+
262
+ /**
263
+ * Get all registered routes
264
+ */
265
+ getRoutes(): Route[] {
266
+ return [...this.routes];
267
+ }
268
+
269
+ /**
270
+ * Get metrics for all routes
271
+ */
272
+ getMetrics(): RouteMetrics[] {
273
+ return this.routes
274
+ .filter((route) => route.options.trackMetrics)
275
+ .map((route) => ({
276
+ name: route.name || "unnamed",
277
+ pattern: route.pattern.source,
278
+ executionCount: route.metrics.count,
279
+ totalDuration: route.metrics.totalDuration,
280
+ averageDuration:
281
+ route.metrics.count > 0
282
+ ? route.metrics.totalDuration / route.metrics.count
283
+ : 0,
284
+ minDuration:
285
+ route.metrics.minDuration === Infinity
286
+ ? 0
287
+ : route.metrics.minDuration,
288
+ maxDuration: route.metrics.maxDuration,
289
+ errorCount: route.metrics.errorCount,
290
+ lastExecuted: route.metrics.lastExecuted,
291
+ }));
292
+ }
293
+
294
+ /**
295
+ * Reset all metrics
296
+ */
297
+ resetMetrics(): void {
298
+ for (const route of this.routes) {
299
+ route.metrics.count = 0;
300
+ route.metrics.totalDuration = 0;
301
+ route.metrics.minDuration = Infinity;
302
+ route.metrics.maxDuration = 0;
303
+ route.metrics.errorCount = 0;
304
+ route.metrics.lastExecuted = undefined;
305
+ }
306
+ }
307
+ }
308
+
309
+ /**
310
+ * Convenience builder for common routing patterns
311
+ */
312
+ export class TopicRouterBuilder {
313
+ private router = new TopicRouter();
314
+
315
+ /**
316
+ * Route errors to alerting system (PagerDuty, Slack, etc.)
317
+ * @param handler - Handler function
318
+ * @param options - Route options (concurrency, metrics tracking)
319
+ */
320
+ errors(handler: RouteHandler, options?: RouteOptions): this {
321
+ this.router.addRoute(
322
+ /^pipeline\..*\.error$|^pipeline\.error$/,
323
+ handler,
324
+ options ? { ...options } : "errors"
325
+ );
326
+ return this;
327
+ }
328
+
329
+ /**
330
+ * Route performance metrics to monitoring system (Prometheus, Datadog, etc.)
331
+ * @param handler - Handler function
332
+ * @param options - Route options (concurrency, metrics tracking)
333
+ */
334
+ performance(handler: RouteHandler, options?: RouteOptions): this {
335
+ this.router.addRoute(
336
+ /^pipeline\..*\.performance$/,
337
+ handler,
338
+ options ? { ...options } : "performance"
339
+ );
340
+ return this;
341
+ }
342
+
343
+ /**
344
+ * Route stage-specific logs
345
+ * @param stageName - Name of the stage
346
+ * @param handler - Handler function
347
+ * @param options - Route options (concurrency, metrics tracking)
348
+ */
349
+ stage(
350
+ stageName: string,
351
+ handler: RouteHandler,
352
+ options?: RouteOptions
353
+ ): this {
354
+ this.router.addRoute(
355
+ new RegExp("^pipeline\\.stage\\." + stageName + "\\."),
356
+ handler,
357
+ options ? { ...options } : `stage-${stageName}`
358
+ );
359
+ return this;
360
+ }
361
+
362
+ /**
363
+ * Route alerts (threshold crossings, anomalies)
364
+ * @param handler - Handler function
365
+ * @param options - Route options (concurrency, metrics tracking)
366
+ */
367
+ alerts(handler: RouteHandler, options?: RouteOptions): this {
368
+ this.router.addRoute(
369
+ /^pipeline\.alert/,
370
+ handler,
371
+ options ? { ...options } : "alerts"
372
+ );
373
+ return this;
374
+ }
375
+
376
+ /**
377
+ * Route debug logs to centralized logging (Loki, Elasticsearch, etc.)
378
+ * @param handler - Handler function
379
+ * @param options - Route options (concurrency, metrics tracking)
380
+ */
381
+ debug(handler: RouteHandler, options?: RouteOptions): this {
382
+ this.router.addRoute(
383
+ /^pipeline\.debug/,
384
+ handler,
385
+ options ? { ...options } : "debug"
386
+ );
387
+ return this;
388
+ }
389
+
390
+ /**
391
+ * Catch-all route (should be added last)
392
+ * @param handler - Handler function
393
+ * @param options - Route options (concurrency, metrics tracking)
394
+ */
395
+ default(handler: RouteHandler, options?: RouteOptions): this {
396
+ this.router.addRoute(/.*/, handler, options ? { ...options } : "default");
397
+ return this;
398
+ }
399
+
400
+ /**
401
+ * Custom route with pattern
402
+ * @param pattern - Regex or string pattern
403
+ * @param handler - Handler function
404
+ * @param nameOrOptions - Optional name or route options
405
+ */
406
+ custom(
407
+ pattern: RegExp | string,
408
+ handler: RouteHandler,
409
+ nameOrOptions?: string | RouteOptions
410
+ ): this {
411
+ this.router.addRoute(pattern, handler, nameOrOptions);
412
+ return this;
413
+ }
414
+
415
+ /**
416
+ * Build and return the configured router
417
+ */
418
+ build(): TopicRouter {
419
+ return this.router;
420
+ }
421
+ }
422
+
423
+ /**
424
+ * Create a new topic router builder
425
+ */
426
+ export function createTopicRouter(): TopicRouterBuilder {
427
+ return new TopicRouterBuilder();
428
+ }