@synkro/core 0.13.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +109 -6
- package/dist/handlers/decorators.d.ts +2 -2
- package/dist/handlers/decorators.d.ts.map +1 -1
- package/dist/handlers/decorators.js +0 -2
- package/dist/handlers/decorators.js.map +1 -1
- package/dist/handlers/handler-registry.d.ts +10 -3
- package/dist/handlers/handler-registry.d.ts.map +1 -1
- package/dist/handlers/handler-registry.js +60 -11
- package/dist/handlers/handler-registry.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +7 -0
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +17 -0
- package/dist/logger.js.map +1 -1
- package/dist/synkro.d.ts +8 -2
- package/dist/synkro.d.ts.map +1 -1
- package/dist/synkro.js +43 -9
- package/dist/synkro.js.map +1 -1
- package/dist/transport/in-memory.d.ts +4 -0
- package/dist/transport/in-memory.d.ts.map +1 -1
- package/dist/transport/in-memory.js +10 -2
- package/dist/transport/in-memory.js.map +1 -1
- package/dist/transport/redis.d.ts +1 -0
- package/dist/transport/redis.d.ts.map +1 -1
- package/dist/transport/redis.js +6 -0
- package/dist/transport/redis.js.map +1 -1
- package/dist/transport/transport.d.ts +1 -0
- package/dist/transport/transport.d.ts.map +1 -1
- package/dist/types.d.ts +13 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/workflows/index.d.ts +1 -0
- package/dist/workflows/index.d.ts.map +1 -1
- package/dist/workflows/workflow-registry.d.ts +16 -1
- package/dist/workflows/workflow-registry.d.ts.map +1 -1
- package/dist/workflows/workflow-registry.js +83 -18
- package/dist/workflows/workflow-registry.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,6 +10,13 @@ Lightweight workflow and state machine orchestrator. Define event-driven workflo
|
|
|
10
10
|
- **Workflow Chaining** — Trigger follow-up workflows on completion, success, or failure
|
|
11
11
|
- **Retry Support** — Configurable retry logic per step
|
|
12
12
|
- **Transport Options** — Redis for production or in-memory for simple projects and local development
|
|
13
|
+
- **Schema Validation** — Optional payload validation at publish and handler dispatch time
|
|
14
|
+
- **Workflow Timeout** — Configurable timeouts per step or per workflow
|
|
15
|
+
- **Graceful Shutdown** — Drains active handlers before disconnecting
|
|
16
|
+
- **Workflow State Query** — Inspect running workflow state at any time
|
|
17
|
+
- **Workflow Cancellation** — Cancel running workflows programmatically
|
|
18
|
+
- **Handler Unsubscribe** — Remove event handlers at runtime with `off()`
|
|
19
|
+
- **Typed Payloads** — Generic `HandlerCtx<T>` for compile-time payload safety
|
|
13
20
|
- **Simple API** — Single `Synkro` class with minimal configuration
|
|
14
21
|
- **TypeScript** — Full type support out of the box
|
|
15
22
|
|
|
@@ -218,6 +225,55 @@ Configure retries per step. The handler will be retried up to `maxRetries` times
|
|
|
218
225
|
}
|
|
219
226
|
```
|
|
220
227
|
|
|
228
|
+
### Schema Validation
|
|
229
|
+
|
|
230
|
+
Validate event payloads at publish time and handler dispatch. The `SchemaValidator` type is `(payload: unknown) => void` — just throw on invalid input. This works with **any validation library** (Zod, Joi, Valibot, etc.) or plain manual checks.
|
|
231
|
+
|
|
232
|
+
**Global schemas** — validated at publish time (rejects before the message is sent):
|
|
233
|
+
|
|
234
|
+
```ts
|
|
235
|
+
import { z } from "zod";
|
|
236
|
+
|
|
237
|
+
const synkro = await Synkro.start({
|
|
238
|
+
transport: "redis",
|
|
239
|
+
connectionUrl: "redis://localhost:6379",
|
|
240
|
+
schemas: {
|
|
241
|
+
"UserSignedUp": (payload) => z.object({ email: z.string().email() }).parse(payload),
|
|
242
|
+
"OrderPlaced": (payload) => z.object({ orderId: z.string(), amount: z.number() }).parse(payload),
|
|
243
|
+
},
|
|
244
|
+
// ...
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
await synkro.publish("UserSignedUp", { email: "invalid" }); // throws ZodError
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
**Per-event schemas** — validated at both publish time and handler dispatch:
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
const synkro = await Synkro.start({
|
|
254
|
+
events: [
|
|
255
|
+
{
|
|
256
|
+
type: "AuditLog",
|
|
257
|
+
schema: (payload) => z.object({ action: z.string(), userId: z.string() }).parse(payload),
|
|
258
|
+
handler: async (ctx) => {
|
|
259
|
+
// payload is guaranteed valid here
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
],
|
|
263
|
+
});
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
**Manual validation** (no dependencies):
|
|
267
|
+
|
|
268
|
+
```ts
|
|
269
|
+
schemas: {
|
|
270
|
+
"UserSignedUp": (payload) => {
|
|
271
|
+
if (!payload || typeof payload !== "object" || !("email" in payload))
|
|
272
|
+
throw new Error("email is required");
|
|
273
|
+
},
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
221
277
|
## API
|
|
222
278
|
|
|
223
279
|
### `Synkro.start(options): Promise<Synkro>`
|
|
@@ -231,6 +287,10 @@ type SynkroOptions = {
|
|
|
231
287
|
debug?: boolean;
|
|
232
288
|
events?: SynkroEvent[];
|
|
233
289
|
workflows?: SynkroWorkflow[];
|
|
290
|
+
handlers?: object[];
|
|
291
|
+
retention?: RetentionConfig;
|
|
292
|
+
schemas?: Record<string, SchemaValidator>; // global payload validators per event type
|
|
293
|
+
drainTimeout?: number; // ms to wait for in-flight handlers on stop() (default: 5000)
|
|
234
294
|
};
|
|
235
295
|
```
|
|
236
296
|
|
|
@@ -279,9 +339,41 @@ synkro.on("ValidateStock", async (ctx) => {
|
|
|
279
339
|
});
|
|
280
340
|
```
|
|
281
341
|
|
|
342
|
+
### `synkro.off(eventType, handler?): void`
|
|
343
|
+
|
|
344
|
+
Removes an event handler at runtime. If `handler` is provided, only that specific handler is removed (by reference). If omitted, all handlers for the event type are removed.
|
|
345
|
+
|
|
346
|
+
```ts
|
|
347
|
+
const handler = (ctx) => console.log(ctx.payload);
|
|
348
|
+
synkro.on("StockUpdate", handler);
|
|
349
|
+
|
|
350
|
+
// Later: remove this specific handler
|
|
351
|
+
synkro.off("StockUpdate", handler);
|
|
352
|
+
|
|
353
|
+
// Or remove all handlers for the event type
|
|
354
|
+
synkro.off("StockUpdate");
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### `synkro.getWorkflowState(requestId, workflowName): Promise<WorkflowState | null>`
|
|
358
|
+
|
|
359
|
+
Returns the current state of a workflow instance, or `null` if no state exists.
|
|
360
|
+
|
|
361
|
+
```ts
|
|
362
|
+
const state = await synkro.getWorkflowState(requestId, "ProcessOrder");
|
|
363
|
+
// { workflowName: "ProcessOrder", currentStep: 2, status: "running" }
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### `synkro.cancelWorkflow(requestId, workflowName): Promise<boolean>`
|
|
367
|
+
|
|
368
|
+
Cancels a running workflow. Returns `true` if the workflow was cancelled, `false` if it was not in a cancellable state. Cancelled workflows will not advance to subsequent steps.
|
|
369
|
+
|
|
370
|
+
```ts
|
|
371
|
+
const cancelled = await synkro.cancelWorkflow(requestId, "ProcessOrder");
|
|
372
|
+
```
|
|
373
|
+
|
|
282
374
|
### `synkro.stop(): Promise<void>`
|
|
283
375
|
|
|
284
|
-
|
|
376
|
+
Gracefully shuts down. Waits for in-flight handlers to complete (up to `drainTimeout`), then disconnects the transport.
|
|
285
377
|
|
|
286
378
|
## Types
|
|
287
379
|
|
|
@@ -294,10 +386,13 @@ type RetryConfig = {
|
|
|
294
386
|
retryable?: (error: unknown) => boolean; // skip retries for non-retryable errors
|
|
295
387
|
};
|
|
296
388
|
|
|
297
|
-
type
|
|
389
|
+
type SchemaValidator = (payload: unknown) => void; // throws on invalid
|
|
390
|
+
|
|
391
|
+
type SynkroEvent<T = unknown> = {
|
|
298
392
|
type: string;
|
|
299
|
-
handler: HandlerFunction
|
|
393
|
+
handler: HandlerFunction<T>;
|
|
300
394
|
retry?: RetryConfig;
|
|
395
|
+
schema?: SchemaValidator;
|
|
301
396
|
};
|
|
302
397
|
|
|
303
398
|
type SynkroWorkflow = {
|
|
@@ -306,6 +401,7 @@ type SynkroWorkflow = {
|
|
|
306
401
|
onComplete?: string;
|
|
307
402
|
onSuccess?: string;
|
|
308
403
|
onFailure?: string;
|
|
404
|
+
timeoutMs?: number; // default timeout for all steps
|
|
309
405
|
};
|
|
310
406
|
|
|
311
407
|
type SynkroWorkflowStep = {
|
|
@@ -314,11 +410,12 @@ type SynkroWorkflowStep = {
|
|
|
314
410
|
retry?: RetryConfig;
|
|
315
411
|
onSuccess?: string;
|
|
316
412
|
onFailure?: string;
|
|
413
|
+
timeoutMs?: number; // overrides workflow-level timeout
|
|
317
414
|
};
|
|
318
415
|
|
|
319
|
-
type HandlerCtx = {
|
|
416
|
+
type HandlerCtx<T = unknown> = {
|
|
320
417
|
requestId: string;
|
|
321
|
-
payload:
|
|
418
|
+
payload: T;
|
|
322
419
|
publish: PublishFunction;
|
|
323
420
|
setPayload: (data: Record<string, unknown>) => void;
|
|
324
421
|
};
|
|
@@ -329,7 +426,13 @@ type PublishFunction = (
|
|
|
329
426
|
requestId?: string,
|
|
330
427
|
) => Promise<string>;
|
|
331
428
|
|
|
332
|
-
type HandlerFunction = (ctx: HandlerCtx) => void | Promise<void>;
|
|
429
|
+
type HandlerFunction<T = unknown> = (ctx: HandlerCtx<T>) => void | Promise<void>;
|
|
430
|
+
|
|
431
|
+
type WorkflowState = {
|
|
432
|
+
workflowName: string;
|
|
433
|
+
currentStep: number;
|
|
434
|
+
status: "running" | "completed" | "failed" | "cancelled";
|
|
435
|
+
};
|
|
333
436
|
```
|
|
334
437
|
|
|
335
438
|
## License
|
|
@@ -9,6 +9,6 @@ export type OnWorkflowStepMetadata = {
|
|
|
9
9
|
workflowName: string;
|
|
10
10
|
stepType: string;
|
|
11
11
|
};
|
|
12
|
-
export declare function OnEvent(eventType: string, retry?: RetryConfig): <T extends
|
|
13
|
-
export declare function OnWorkflowStep(workflowName: string, stepType: string): <T extends
|
|
12
|
+
export declare function OnEvent(eventType: string, retry?: RetryConfig): <T extends (...args: any[]) => any>(target: T, _context: ClassMethodDecoratorContext) => T;
|
|
13
|
+
export declare function OnWorkflowStep(workflowName: string, stepType: string): <T extends (...args: any[]) => any>(target: T, _context: ClassMethodDecoratorContext) => T;
|
|
14
14
|
//# sourceMappingURL=decorators.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/handlers/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,eAAO,MAAM,aAAa,eAAgC,CAAC;AAC3D,eAAO,MAAM,qBAAqB,eAAwC,CAAC;AAE3E,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/handlers/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,eAAO,MAAM,aAAa,eAAgC,CAAC;AAC3D,eAAO,MAAM,qBAAqB,eAAwC,CAAC;AAE3E,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,IAC3C,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EAChD,QAAQ,CAAC,EACT,UAAU,2BAA2B,KACpC,CAAC,CAYL;AAED,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAClD,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EAChD,QAAQ,CAAC,EACT,UAAU,2BAA2B,KACpC,CAAC,CAQL"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export const ON_EVENT_META = Symbol.for("synkro:on-event");
|
|
2
2
|
export const ON_WORKFLOW_STEP_META = Symbol.for("synkro:on-workflow-step");
|
|
3
3
|
export function OnEvent(eventType, retry) {
|
|
4
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
5
4
|
return function (target, _context) {
|
|
6
5
|
const metadata = { eventType };
|
|
7
6
|
if (retry !== undefined) {
|
|
@@ -16,7 +15,6 @@ export function OnEvent(eventType, retry) {
|
|
|
16
15
|
};
|
|
17
16
|
}
|
|
18
17
|
export function OnWorkflowStep(workflowName, stepType) {
|
|
19
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
20
18
|
return function (target, _context) {
|
|
21
19
|
Object.defineProperty(target, ON_WORKFLOW_STEP_META, {
|
|
22
20
|
value: { workflowName, stepType },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../src/handlers/decorators.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;AAC3D,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;AAY3E,MAAM,UAAU,OAAO,CAAC,SAAiB,EAAE,KAAmB;IAC5D,
|
|
1
|
+
{"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../src/handlers/decorators.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;AAC3D,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;AAY3E,MAAM,UAAU,OAAO,CAAC,SAAiB,EAAE,KAAmB;IAC5D,OAAO,UACL,MAAS,EACT,QAAqC;QAErC,MAAM,QAAQ,GAAoB,EAAE,SAAS,EAAE,CAAC;QAChD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,QAAQ,CAAC,KAAK,GAAG,KAAK,CAAC;QACzB,CAAC;QACD,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,aAAa,EAAE;YAC3C,KAAK,EAAE,QAAQ;YACf,UAAU,EAAE,KAAK;YACjB,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,YAAoB,EAAE,QAAgB;IACnE,OAAO,UACL,MAAS,EACT,QAAqC;QAErC,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,qBAAqB,EAAE;YACnD,KAAK,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAmC;YAClE,UAAU,EAAE,KAAK;YACjB,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -1,19 +1,26 @@
|
|
|
1
|
+
import { Logger } from "../logger.js";
|
|
1
2
|
import type { TransportManager } from "../transport/transport.js";
|
|
2
|
-
import type { EventInfo, EventMetrics, HandlerFunction, PublishFunction, RetentionConfig, RetryConfig } from "../types.js";
|
|
3
|
+
import type { EventInfo, EventMetrics, HandlerFunction, PublishFunction, RetentionConfig, RetryConfig, SchemaValidator } from "../types.js";
|
|
3
4
|
export declare class HandlerRegistry {
|
|
4
5
|
private redis;
|
|
6
|
+
private readonly logger;
|
|
5
7
|
private handlers;
|
|
6
8
|
private processingLocks;
|
|
7
9
|
private subscribedChannels;
|
|
10
|
+
private schemas;
|
|
8
11
|
private publishFn;
|
|
9
12
|
private readonly lockTtl;
|
|
10
13
|
private readonly dedupTtl;
|
|
11
14
|
private readonly metricsTtl;
|
|
12
|
-
constructor(redis: TransportManager, retention?: RetentionConfig);
|
|
15
|
+
constructor(redis: TransportManager, retention?: RetentionConfig, logger?: Logger);
|
|
16
|
+
get activeCount(): number;
|
|
13
17
|
setPublishFn(fn: PublishFunction): void;
|
|
18
|
+
registerSchema(eventType: string, schema: SchemaValidator): void;
|
|
19
|
+
getSchema(eventType: string): SchemaValidator | undefined;
|
|
14
20
|
getEventMetrics(eventType: string): Promise<EventMetrics>;
|
|
15
21
|
getRegisteredEvents(): EventInfo[];
|
|
16
|
-
register(eventType: string, handlerFn: HandlerFunction, retry?: RetryConfig): void;
|
|
22
|
+
register(eventType: string, handlerFn: HandlerFunction, retry?: RetryConfig, schema?: SchemaValidator): void;
|
|
23
|
+
unregister(eventType: string, handlerFn?: HandlerFunction): void;
|
|
17
24
|
private handleMessage;
|
|
18
25
|
private distributedLockKey;
|
|
19
26
|
private dedupeKey;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler-registry.d.ts","sourceRoot":"","sources":["../../src/handlers/handler-registry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"handler-registry.d.ts","sourceRoot":"","sources":["../../src/handlers/handler-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,KAAK,EACV,SAAS,EACT,YAAY,EAEZ,eAAe,EACf,eAAe,EACf,eAAe,EAEf,WAAW,EACX,eAAe,EAChB,MAAM,aAAa,CAAC;AAwCrB,qBAAa,eAAe;IAYxB,OAAO,CAAC,KAAK;IAEb,OAAO,CAAC,QAAQ,CAAC,MAAM;IAbzB,OAAO,CAAC,QAAQ,CAAwC;IACxD,OAAO,CAAC,eAAe,CAAqB;IAC5C,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,OAAO,CAAsC;IAErD,OAAO,CAAC,SAAS,CAAgC;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAqB;gBAGtC,KAAK,EAAE,gBAAgB,EAC/B,SAAS,CAAC,EAAE,eAAe,EACV,MAAM,GAAE,MAAqB;IAOhD,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,YAAY,CAAC,EAAE,EAAE,eAAe,GAAG,IAAI;IAIvC,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI;IAIhE,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAInD,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAc/D,mBAAmB,IAAI,SAAS,EAAE;IAWlC,QAAQ,CACN,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,eAAe,EAC1B,KAAK,CAAC,EAAE,WAAW,EACnB,MAAM,CAAC,EAAE,eAAe,GACvB,IAAI;IAkBP,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,eAAe,GAAG,IAAI;YAwBlD,aAAa;IA+H3B,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,SAAS;YAIH,cAAc;CAoD7B"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Logger } from "../logger.js";
|
|
2
2
|
const DEFAULT_RETRY_DELAY_MS = 1000;
|
|
3
3
|
function computeRetryDelay(attempt, backoff = "fixed", baseDelayMs = DEFAULT_RETRY_DELAY_MS, jitter = false) {
|
|
4
4
|
const delay = backoff === "exponential"
|
|
@@ -21,22 +21,34 @@ const DEFAULT_LOCK_TTL = 300;
|
|
|
21
21
|
const DEFAULT_DEDUPE_TTL = 86400;
|
|
22
22
|
export class HandlerRegistry {
|
|
23
23
|
redis;
|
|
24
|
+
logger;
|
|
24
25
|
handlers = new Map();
|
|
25
26
|
processingLocks = new Set();
|
|
26
27
|
subscribedChannels = new Set();
|
|
28
|
+
schemas = new Map();
|
|
27
29
|
publishFn = null;
|
|
28
30
|
lockTtl;
|
|
29
31
|
dedupTtl;
|
|
30
32
|
metricsTtl;
|
|
31
|
-
constructor(redis, retention) {
|
|
33
|
+
constructor(redis, retention, logger = new Logger()) {
|
|
32
34
|
this.redis = redis;
|
|
35
|
+
this.logger = logger;
|
|
33
36
|
this.lockTtl = retention?.lockTtl ?? DEFAULT_LOCK_TTL;
|
|
34
37
|
this.dedupTtl = retention?.dedupTtl ?? DEFAULT_DEDUPE_TTL;
|
|
35
38
|
this.metricsTtl = retention?.metricsTtl;
|
|
36
39
|
}
|
|
40
|
+
get activeCount() {
|
|
41
|
+
return this.processingLocks.size;
|
|
42
|
+
}
|
|
37
43
|
setPublishFn(fn) {
|
|
38
44
|
this.publishFn = fn;
|
|
39
45
|
}
|
|
46
|
+
registerSchema(eventType, schema) {
|
|
47
|
+
this.schemas.set(eventType, schema);
|
|
48
|
+
}
|
|
49
|
+
getSchema(eventType) {
|
|
50
|
+
return this.schemas.get(eventType);
|
|
51
|
+
}
|
|
40
52
|
async getEventMetrics(eventType) {
|
|
41
53
|
const [received, completed, failed] = await Promise.all([
|
|
42
54
|
this.redis.getCache(`synkro:metrics:${eventType}:received`),
|
|
@@ -58,13 +70,14 @@ export class HandlerRegistry {
|
|
|
58
70
|
...(entry.retry && { retry: entry.retry }),
|
|
59
71
|
})));
|
|
60
72
|
}
|
|
61
|
-
register(eventType, handlerFn, retry) {
|
|
73
|
+
register(eventType, handlerFn, retry, schema) {
|
|
62
74
|
if (!this.handlers.has(eventType)) {
|
|
63
75
|
this.handlers.set(eventType, new Set());
|
|
64
76
|
}
|
|
65
77
|
this.handlers.get(eventType).add({
|
|
66
78
|
handler: handlerFn,
|
|
67
79
|
...(retry && { retry }),
|
|
80
|
+
...(schema && { schema }),
|
|
68
81
|
});
|
|
69
82
|
if (!this.subscribedChannels.has(eventType)) {
|
|
70
83
|
this.subscribedChannels.add(eventType);
|
|
@@ -73,6 +86,29 @@ export class HandlerRegistry {
|
|
|
73
86
|
});
|
|
74
87
|
}
|
|
75
88
|
}
|
|
89
|
+
unregister(eventType, handlerFn) {
|
|
90
|
+
const entries = this.handlers.get(eventType);
|
|
91
|
+
if (!entries)
|
|
92
|
+
return;
|
|
93
|
+
if (handlerFn) {
|
|
94
|
+
for (const entry of entries) {
|
|
95
|
+
if (entry.handler === handlerFn) {
|
|
96
|
+
entries.delete(entry);
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
entries.clear();
|
|
103
|
+
}
|
|
104
|
+
if (entries.size === 0) {
|
|
105
|
+
this.handlers.delete(eventType);
|
|
106
|
+
if (this.subscribedChannels.has(eventType)) {
|
|
107
|
+
this.subscribedChannels.delete(eventType);
|
|
108
|
+
this.redis.unsubscribeFromChannel(eventType);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
76
112
|
async handleMessage(eventType, message) {
|
|
77
113
|
const entries = this.handlers.get(eventType);
|
|
78
114
|
if (!entries || entries.size === 0) {
|
|
@@ -83,13 +119,23 @@ export class HandlerRegistry {
|
|
|
83
119
|
event = JSON.parse(message);
|
|
84
120
|
}
|
|
85
121
|
catch {
|
|
86
|
-
logger.error(`[HandlerRegistry] - Malformed message on "${eventType}", dropping: ${message}`);
|
|
122
|
+
this.logger.error(`[HandlerRegistry] - Malformed message on "${eventType}", dropping: ${message}`);
|
|
87
123
|
return;
|
|
88
124
|
}
|
|
89
125
|
if (!event.requestId || typeof event.requestId !== "string") {
|
|
90
|
-
logger.error(`[HandlerRegistry] - Missing or invalid requestId on "${eventType}", dropping message`);
|
|
126
|
+
this.logger.error(`[HandlerRegistry] - Missing or invalid requestId on "${eventType}", dropping message`);
|
|
91
127
|
return;
|
|
92
128
|
}
|
|
129
|
+
const globalSchema = this.schemas.get(eventType);
|
|
130
|
+
if (globalSchema) {
|
|
131
|
+
try {
|
|
132
|
+
globalSchema(event.payload);
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
this.logger.error(`[HandlerRegistry] - Schema validation failed for "${eventType}" (requestId: ${event.requestId}): ${err}`);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
93
139
|
const localLockKey = `${event.requestId}:${eventType}`;
|
|
94
140
|
if (this.processingLocks.has(localLockKey)) {
|
|
95
141
|
return;
|
|
@@ -97,12 +143,12 @@ export class HandlerRegistry {
|
|
|
97
143
|
const dedupeKey = this.dedupeKey(localLockKey);
|
|
98
144
|
const alreadyProcessed = await this.redis.getCache(dedupeKey);
|
|
99
145
|
if (alreadyProcessed === "1") {
|
|
100
|
-
logger.debug(`[HandlerRegistry] duplicate message ignored for "${eventType}" (requestId: ${event.requestId})`);
|
|
146
|
+
this.logger.debug(`[HandlerRegistry] duplicate message ignored for "${eventType}" (requestId: ${event.requestId})`);
|
|
101
147
|
return;
|
|
102
148
|
}
|
|
103
149
|
this.processingLocks.add(localLockKey);
|
|
104
150
|
if (this.processingLocks.size > 1000) {
|
|
105
|
-
logger.warn(`[HandlerRegistry] - processingLocks size exceeded 1000 (current: ${this.processingLocks.size})`);
|
|
151
|
+
this.logger.warn(`[HandlerRegistry] - processingLocks size exceeded 1000 (current: ${this.processingLocks.size})`);
|
|
106
152
|
}
|
|
107
153
|
const distributedLockKey = this.distributedLockKey(localLockKey);
|
|
108
154
|
let distributedLockAcquired = false;
|
|
@@ -110,10 +156,10 @@ export class HandlerRegistry {
|
|
|
110
156
|
try {
|
|
111
157
|
distributedLockAcquired = await this.redis.setCacheIfNotExists(distributedLockKey, "1", this.lockTtl);
|
|
112
158
|
if (!distributedLockAcquired) {
|
|
113
|
-
logger.debug(`[HandlerRegistry] in-flight message ignored for "${eventType}" (requestId: ${event.requestId})`);
|
|
159
|
+
this.logger.debug(`[HandlerRegistry] in-flight message ignored for "${eventType}" (requestId: ${event.requestId})`);
|
|
114
160
|
return;
|
|
115
161
|
}
|
|
116
|
-
logger.debug(`[HandlerRegistry] handleMessage("${eventType}") entries=${entries.size}`);
|
|
162
|
+
this.logger.debug(`[HandlerRegistry] handleMessage("${eventType}") entries=${entries.size}`);
|
|
117
163
|
if (trackMetrics) {
|
|
118
164
|
await this.redis.incrementCache(`synkro:metrics:${eventType}:received`, this.metricsTtl);
|
|
119
165
|
}
|
|
@@ -165,6 +211,9 @@ export class HandlerRegistry {
|
|
|
165
211
|
: data;
|
|
166
212
|
},
|
|
167
213
|
};
|
|
214
|
+
if (entry.schema) {
|
|
215
|
+
entry.schema(event.payload);
|
|
216
|
+
}
|
|
168
217
|
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
169
218
|
try {
|
|
170
219
|
await entry.handler(ctx);
|
|
@@ -176,11 +225,11 @@ export class HandlerRegistry {
|
|
|
176
225
|
: true;
|
|
177
226
|
if (attempt < maxRetries && isRetryable) {
|
|
178
227
|
const delay = computeRetryDelay(attempt, entry.retry?.backoff, entry.retry?.delayMs, entry.retry?.jitter);
|
|
179
|
-
logger.warn(`[HandlerRegistry] - Handler "${eventType}" failed (attempt ${attempt + 1}/${maxRetries + 1}), retrying in ${delay}ms...`);
|
|
228
|
+
this.logger.warn(`[HandlerRegistry] - Handler "${eventType}" failed (attempt ${attempt + 1}/${maxRetries + 1}), retrying in ${delay}ms...`);
|
|
180
229
|
await sleep(delay);
|
|
181
230
|
}
|
|
182
231
|
else {
|
|
183
|
-
logger.error(`[HandlerRegistry] - Handler "${eventType}" failed after ${attempt + 1} attempt(s): ${error}`);
|
|
232
|
+
this.logger.error(`[HandlerRegistry] - Handler "${eventType}" failed after ${attempt + 1} attempt(s): ${error}`);
|
|
184
233
|
throw error;
|
|
185
234
|
}
|
|
186
235
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler-registry.js","sourceRoot":"","sources":["../../src/handlers/handler-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"handler-registry.js","sourceRoot":"","sources":["../../src/handlers/handler-registry.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { Synkro } from "./synkro.js";
|
|
2
|
+
export { Logger } from "./logger.js";
|
|
2
3
|
export { OnEvent, OnWorkflowStep } from "./handlers/index.js";
|
|
3
4
|
export type { TransportManager } from "./transport/index.js";
|
|
4
|
-
export type { EventInfo, EventMetrics, HandlerCtx, HandlerFunction, PublishFunction, RetentionConfig, RetryBackoffStrategy, RetryConfig, SynkroEvent, SynkroIntrospection, SynkroOptions, SynkroWorkflow, SynkroWorkflowStep, WorkflowInfo, WorkflowStepInfo, } from "./types.js";
|
|
5
|
+
export type { EventInfo, EventMetrics, HandlerCtx, HandlerFunction, PublishFunction, RetentionConfig, RetryBackoffStrategy, RetryConfig, SchemaValidator, SynkroEvent, SynkroIntrospection, SynkroOptions, SynkroWorkflow, SynkroWorkflowStep, WorkflowInfo, WorkflowStepInfo, } from "./types.js";
|
|
6
|
+
export type { WorkflowState } from "./workflows/index.js";
|
|
5
7
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC9D,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,YAAY,EACV,SAAS,EACT,YAAY,EACZ,UAAU,EACV,eAAe,EACf,eAAe,EACf,eAAe,EACf,oBAAoB,EACpB,WAAW,EACX,WAAW,EACX,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,GACjB,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC9D,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,YAAY,EACV,SAAS,EACT,YAAY,EACZ,UAAU,EACV,eAAe,EACf,eAAe,EACf,eAAe,EACf,oBAAoB,EACpB,WAAW,EACX,eAAe,EACf,WAAW,EACX,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,GACjB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/logger.d.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
export declare class Logger {
|
|
2
|
+
private debugEnabled;
|
|
3
|
+
constructor(debugEnabled?: boolean);
|
|
4
|
+
debug(...args: unknown[]): void;
|
|
5
|
+
warn(...args: unknown[]): void;
|
|
6
|
+
error(...args: unknown[]): void;
|
|
7
|
+
}
|
|
1
8
|
export declare function setDebug(enabled: boolean): void;
|
|
2
9
|
export declare const logger: {
|
|
3
10
|
debug(...args: unknown[]): void;
|
package/dist/logger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,qBAAa,MAAM;IACL,OAAO,CAAC,YAAY;gBAAZ,YAAY,GAAE,OAAe;IAEjD,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAM/B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAI9B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;CAGhC;AAID,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAE/C;AAED,eAAO,MAAM,MAAM;mBACF,OAAO,EAAE,GAAG,IAAI;kBAKjB,OAAO,EAAE,GAAG,IAAI;mBAGf,OAAO,EAAE,GAAG,IAAI;CAGhC,CAAC"}
|
package/dist/logger.js
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
export class Logger {
|
|
2
|
+
debugEnabled;
|
|
3
|
+
constructor(debugEnabled = false) {
|
|
4
|
+
this.debugEnabled = debugEnabled;
|
|
5
|
+
}
|
|
6
|
+
debug(...args) {
|
|
7
|
+
if (this.debugEnabled) {
|
|
8
|
+
console.log(...args);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
warn(...args) {
|
|
12
|
+
console.warn(...args);
|
|
13
|
+
}
|
|
14
|
+
error(...args) {
|
|
15
|
+
console.error(...args);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
1
18
|
let debugEnabled = false;
|
|
2
19
|
export function setDebug(enabled) {
|
|
3
20
|
debugEnabled = enabled;
|
package/dist/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,IAAI,YAAY,GAAG,KAAK,CAAC;AAEzB,MAAM,UAAU,QAAQ,CAAC,OAAgB;IACvC,YAAY,GAAG,OAAO,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,KAAK,CAAC,GAAG,IAAe;QACtB,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IACD,IAAI,CAAC,GAAG,IAAe;QACrB,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IACxB,CAAC;IACD,KAAK,CAAC,GAAG,IAAe;QACtB,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IACzB,CAAC;CACF,CAAC"}
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,MAAM;IACG;IAApB,YAAoB,eAAwB,KAAK;QAA7B,iBAAY,GAAZ,YAAY,CAAiB;IAAG,CAAC;IAErD,KAAK,CAAC,GAAG,IAAe;QACtB,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,IAAI,CAAC,GAAG,IAAe;QACrB,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,GAAG,IAAe;QACtB,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IACzB,CAAC;CACF;AAED,IAAI,YAAY,GAAG,KAAK,CAAC;AAEzB,MAAM,UAAU,QAAQ,CAAC,OAAgB;IACvC,YAAY,GAAG,OAAO,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,KAAK,CAAC,GAAG,IAAe;QACtB,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IACD,IAAI,CAAC,GAAG,IAAe;QACrB,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IACxB,CAAC;IACD,KAAK,CAAC,GAAG,IAAe;QACtB,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IACzB,CAAC;CACF,CAAC"}
|
package/dist/synkro.d.ts
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
|
-
import type { EventMetrics, HandlerFunction, RetryConfig, SynkroIntrospection, SynkroOptions } from "./types.js";
|
|
1
|
+
import type { EventMetrics, HandlerFunction, RetryConfig, SchemaValidator, SynkroIntrospection, SynkroOptions } from "./types.js";
|
|
2
|
+
import type { WorkflowState } from "./workflows/workflow-registry.js";
|
|
2
3
|
export declare class Synkro {
|
|
3
4
|
private transport;
|
|
4
5
|
private handlerRegistry;
|
|
5
6
|
private workflowRegistry;
|
|
7
|
+
private logger;
|
|
8
|
+
private readonly drainTimeout;
|
|
6
9
|
private constructor();
|
|
7
10
|
static start(options: SynkroOptions): Promise<Synkro>;
|
|
8
11
|
register(...instances: object[]): void;
|
|
9
|
-
on(eventType: string, handler: HandlerFunction, retry?: RetryConfig): void;
|
|
12
|
+
on(eventType: string, handler: HandlerFunction, retry?: RetryConfig, schema?: SchemaValidator): void;
|
|
13
|
+
off(eventType: string, handler?: HandlerFunction): void;
|
|
10
14
|
publish(event: string, payload?: unknown, requestId?: string): Promise<string>;
|
|
15
|
+
getWorkflowState(requestId: string, workflowName: string): Promise<WorkflowState | null>;
|
|
16
|
+
cancelWorkflow(requestId: string, workflowName: string): Promise<boolean>;
|
|
11
17
|
getEventMetrics(eventType: string): Promise<EventMetrics>;
|
|
12
18
|
introspect(): SynkroIntrospection;
|
|
13
19
|
stop(): Promise<void>;
|
package/dist/synkro.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"synkro.d.ts","sourceRoot":"","sources":["../src/synkro.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,YAAY,EACZ,eAAe,EAEf,WAAW,EACX,mBAAmB,EACnB,aAAa,EAEd,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"synkro.d.ts","sourceRoot":"","sources":["../src/synkro.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,YAAY,EACZ,eAAe,EAEf,WAAW,EACX,eAAe,EACf,mBAAmB,EACnB,aAAa,EAEd,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAKtE,qBAAa,MAAM;IACjB,OAAO,CAAC,SAAS,CAAmB;IACpC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IAEtC,OAAO;WASM,KAAK,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC;IAoD3D,QAAQ,CAAC,GAAG,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI;IAYtC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,KAAK,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,IAAI;IAIpG,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,IAAI;IAIjD,OAAO,CACX,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,OAAO,EACjB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC;IAoBZ,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAIxF,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIzE,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAI/D,UAAU,IAAI,mBAAmB;IAO3B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB3B,OAAO,CAAC,qBAAqB;CA4B9B"}
|