@synkro/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +146 -0
- package/dist/handler-registry.d.ts +10 -0
- package/dist/handler-registry.d.ts.map +1 -0
- package/dist/handler-registry.js +23 -0
- package/dist/handler-registry.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +7 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +20 -0
- package/dist/logger.js.map +1 -0
- package/dist/redis.d.ts +13 -0
- package/dist/redis.d.ts.map +1 -0
- package/dist/redis.js +50 -0
- package/dist/redis.js.map +1 -0
- package/dist/types.d.ts +24 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/workflow-registry.d.ts +20 -0
- package/dist/workflow-registry.d.ts.map +1 -0
- package/dist/workflow-registry.js +98 -0
- package/dist/workflow-registry.js.map +1 -0
- package/package.json +49 -0
package/README.md
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# @synkro/core
|
|
2
|
+
|
|
3
|
+
Lightweight workflow and state machine orchestrator powered by Redis. Define event-driven workflows via configuration or code.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Standalone Events** — Simple pub/sub event handlers with Redis
|
|
8
|
+
- **Sequential Workflows** — Multi-step workflows that execute in order, with state tracked in Redis
|
|
9
|
+
- **Simple API** — Single `Synkro` class with minimal configuration
|
|
10
|
+
- **TypeScript** — Full type support out of the box
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install @synkro/core
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
> Requires a running Redis instance.
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { Synkro } from "@synkro/core";
|
|
24
|
+
|
|
25
|
+
const synkro = await Synkro.start({
|
|
26
|
+
redisUrl: "redis://localhost:6379",
|
|
27
|
+
events: [
|
|
28
|
+
{
|
|
29
|
+
type: "UserSignedUp",
|
|
30
|
+
handler: async (ctx) => {
|
|
31
|
+
console.log("New user:", ctx.payload);
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
await synkro.publish("UserSignedUp", { email: "user@example.com" });
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Workflows
|
|
41
|
+
|
|
42
|
+
Define multi-step sequential workflows. Each step runs after the previous one completes, with state persisted in Redis.
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
const synkro = await Synkro.start({
|
|
46
|
+
redisUrl: "redis://localhost:6379",
|
|
47
|
+
workflows: [
|
|
48
|
+
{
|
|
49
|
+
name: "ProcessOrder",
|
|
50
|
+
steps: [
|
|
51
|
+
{
|
|
52
|
+
type: "ValidateStock",
|
|
53
|
+
handler: async (ctx) => {
|
|
54
|
+
console.log("Checking stock for order:", ctx.requestId);
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
type: "ProcessPayment",
|
|
59
|
+
handler: async (ctx) => {
|
|
60
|
+
console.log("Processing payment...");
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
type: "SendConfirmation",
|
|
65
|
+
handler: async (ctx) => {
|
|
66
|
+
console.log("Order confirmed!");
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Triggers all 3 steps in sequence
|
|
75
|
+
await synkro.publish("ProcessOrder", { orderId: "abc-123", amount: 49.99 });
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## API
|
|
79
|
+
|
|
80
|
+
### `Synkro.start(options): Promise<Synkro>`
|
|
81
|
+
|
|
82
|
+
Creates and returns a running instance.
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
type SynkroOptions = {
|
|
86
|
+
redisUrl: string;
|
|
87
|
+
events?: SynkroEvent[];
|
|
88
|
+
workflows?: SynkroWorkflow[];
|
|
89
|
+
};
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### `synkro.on(eventType, handler): void`
|
|
93
|
+
|
|
94
|
+
Registers an event handler at runtime.
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
synkro.on("StockUpdate", async (ctx) => {
|
|
98
|
+
console.log(ctx.requestId, ctx.payload);
|
|
99
|
+
});
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### `synkro.publish(event, payload?, requestId?): Promise<string>`
|
|
103
|
+
|
|
104
|
+
Publishes an event or starts a workflow. Returns a `requestId` for correlation. A UUID is generated by default, but you can provide your own ID.
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
// Auto-generated UUID
|
|
108
|
+
const id = await synkro.publish("UserSignedUp", { email: "user@example.com" });
|
|
109
|
+
|
|
110
|
+
// Custom request ID
|
|
111
|
+
const id = await synkro.publish("UserSignedUp", { email: "user@example.com" }, "my-custom-id");
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### `synkro.stop(): Promise<void>`
|
|
115
|
+
|
|
116
|
+
Disconnects all Redis clients.
|
|
117
|
+
|
|
118
|
+
## Types
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
type SynkroEvent = {
|
|
122
|
+
type: string;
|
|
123
|
+
handler: HandlerFunction;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
type SynkroWorkflow = {
|
|
127
|
+
name: string;
|
|
128
|
+
steps: SynkroWorkflowStep[];
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
type SynkroWorkflowStep = {
|
|
132
|
+
type: string;
|
|
133
|
+
handler: HandlerFunction;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
type HandlerCtx = {
|
|
137
|
+
requestId: string;
|
|
138
|
+
payload: unknown;
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
type HandlerFunction = (ctx: HandlerCtx) => void | Promise<void>;
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## License
|
|
145
|
+
|
|
146
|
+
ISC
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { RedisManager } from "./redis.js";
|
|
2
|
+
import type { HandlerFunction } from "./types.js";
|
|
3
|
+
export declare class HandlerRegistry {
|
|
4
|
+
private redis;
|
|
5
|
+
private handlers;
|
|
6
|
+
constructor(redis: RedisManager);
|
|
7
|
+
register(eventType: string, handlerFn: HandlerFunction): void;
|
|
8
|
+
private handleMessage;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=handler-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler-registry.d.ts","sourceRoot":"","sources":["../package/handler-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAc,eAAe,EAAE,MAAM,YAAY,CAAC;AAE9D,qBAAa,eAAe;IAGd,OAAO,CAAC,KAAK;IAFzB,OAAO,CAAC,QAAQ,CAAsC;gBAElC,KAAK,EAAE,YAAY;IAEvC,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,GAAG,IAAI;YAQ/C,aAAa;CAkB5B"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export class HandlerRegistry {
|
|
2
|
+
redis;
|
|
3
|
+
handlers = new Map();
|
|
4
|
+
constructor(redis) {
|
|
5
|
+
this.redis = redis;
|
|
6
|
+
}
|
|
7
|
+
register(eventType, handlerFn) {
|
|
8
|
+
this.handlers.set(eventType, handlerFn);
|
|
9
|
+
this.redis.subscribeToChannel(eventType, (message) => {
|
|
10
|
+
this.handleMessage(eventType, message);
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
async handleMessage(eventType, message) {
|
|
14
|
+
const handler = this.handlers.get(eventType);
|
|
15
|
+
if (!handler) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const event = JSON.parse(message);
|
|
19
|
+
await handler({ requestId: event.requestId, payload: event.payload });
|
|
20
|
+
this.redis.publishMessage(`event:${eventType}:completed`, JSON.stringify({ requestId: event.requestId, payload: event.payload }));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=handler-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler-registry.js","sourceRoot":"","sources":["../package/handler-registry.ts"],"names":[],"mappings":"AAGA,MAAM,OAAO,eAAe;IAGN;IAFZ,QAAQ,GAAG,IAAI,GAAG,EAA2B,CAAC;IAEtD,YAAoB,KAAmB;QAAnB,UAAK,GAAL,KAAK,CAAc;IAAG,CAAC;IAE3C,QAAQ,CAAC,SAAiB,EAAE,SAA0B;QACpD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAExC,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,SAAS,EAAE,CAAC,OAAe,EAAE,EAAE;YAC3D,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,aAAa,CACzB,SAAiB,EACjB,OAAe;QAEf,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC7C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAe,CAAC;QAEhD,MAAM,OAAO,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAEtE,IAAI,CAAC,KAAK,CAAC,cAAc,CACvB,SAAS,SAAS,YAAY,EAC9B,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CACvE,CAAC;IACJ,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { HandlerFunction, SynkroOptions } from "./types.js";
|
|
2
|
+
export declare class Synkro {
|
|
3
|
+
private redis;
|
|
4
|
+
private handlerRegistry;
|
|
5
|
+
private workflowRegistry;
|
|
6
|
+
private constructor();
|
|
7
|
+
static start(options: SynkroOptions): Promise<Synkro>;
|
|
8
|
+
on(eventType: string, handler: HandlerFunction): void;
|
|
9
|
+
publish(event: string, payload?: unknown, requestId?: string): Promise<string>;
|
|
10
|
+
stop(): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
export type { HandlerCtx, HandlerFunction, SynkroEvent, SynkroOptions, SynkroWorkflow, SynkroWorkflowStep, } from "./types.js";
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../package/index.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEjE,qBAAa,MAAM;IACjB,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,gBAAgB,CAAmB;IAE3C,OAAO;WAMM,KAAK,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC;IAkB3D,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI;IAI/C,OAAO,CACX,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,OAAO,EACjB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC;IAeZ,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAG5B;AAED,YAAY,EACV,UAAU,EACV,eAAe,EACf,WAAW,EACX,aAAa,EACb,cAAc,EACd,kBAAkB,GACnB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { HandlerRegistry } from "./handler-registry.js";
|
|
3
|
+
import { setDebug } from "./logger.js";
|
|
4
|
+
import { RedisManager } from "./redis.js";
|
|
5
|
+
import { WorkflowRegistry } from "./workflow-registry.js";
|
|
6
|
+
export class Synkro {
|
|
7
|
+
redis;
|
|
8
|
+
handlerRegistry;
|
|
9
|
+
workflowRegistry;
|
|
10
|
+
constructor(redis) {
|
|
11
|
+
this.redis = redis;
|
|
12
|
+
this.handlerRegistry = new HandlerRegistry(redis);
|
|
13
|
+
this.workflowRegistry = new WorkflowRegistry(redis, this.handlerRegistry);
|
|
14
|
+
}
|
|
15
|
+
static async start(options) {
|
|
16
|
+
setDebug(options.debug ?? false);
|
|
17
|
+
const redis = new RedisManager(options.redisUrl);
|
|
18
|
+
const instance = new Synkro(redis);
|
|
19
|
+
if (options.events) {
|
|
20
|
+
for (const event of options.events) {
|
|
21
|
+
instance.on(event.type, event.handler);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (options.workflows) {
|
|
25
|
+
instance.workflowRegistry.registerWorkflows(options.workflows);
|
|
26
|
+
}
|
|
27
|
+
return instance;
|
|
28
|
+
}
|
|
29
|
+
on(eventType, handler) {
|
|
30
|
+
this.handlerRegistry.register(eventType, handler);
|
|
31
|
+
}
|
|
32
|
+
async publish(event, payload, requestId) {
|
|
33
|
+
requestId = requestId ?? randomUUID();
|
|
34
|
+
if (this.workflowRegistry.hasWorkflow(event)) {
|
|
35
|
+
await this.workflowRegistry.startWorkflow(event, requestId, payload);
|
|
36
|
+
return requestId;
|
|
37
|
+
}
|
|
38
|
+
this.redis.publishMessage(event, JSON.stringify({ requestId, payload }));
|
|
39
|
+
return requestId;
|
|
40
|
+
}
|
|
41
|
+
async stop() {
|
|
42
|
+
await this.redis.disconnect();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../package/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAI1D,MAAM,OAAO,MAAM;IACT,KAAK,CAAe;IACpB,eAAe,CAAkB;IACjC,gBAAgB,CAAmB;IAE3C,YAAoB,KAAmB;QACrC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,eAAe,GAAG,IAAI,eAAe,CAAC,KAAK,CAAC,CAAC;QAClD,IAAI,CAAC,gBAAgB,GAAG,IAAI,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;IAC5E,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,OAAsB;QACvC,QAAQ,CAAC,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC;QACjC,MAAM,KAAK,GAAG,IAAI,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACjD,MAAM,QAAQ,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;QAEnC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBACnC,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YACzC,CAAC;QACH,CAAC;QAED,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;YACtB,QAAQ,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACjE,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,EAAE,CAAC,SAAiB,EAAE,OAAwB;QAC5C,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,OAAO,CACX,KAAa,EACb,OAAiB,EACjB,SAAkB;QAElB,SAAS,GAAG,SAAS,IAAI,UAAU,EAAE,CAAC;QAEtC,IAAI,IAAI,CAAC,gBAAgB,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7C,MAAM,IAAI,CAAC,gBAAgB,CAAC,aAAa,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;YACrE,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,cAAc,CACvB,KAAK,EACL,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CACvC,CAAC;QACF,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,IAAI;QACR,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;IAChC,CAAC;CACF"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../package/logger.ts"],"names":[],"mappings":"AAEA,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAE/C;AAED,eAAO,MAAM,MAAM;mBACF,OAAO,EAAE,GAAG,IAAI;kBAKjB,OAAO,EAAE,GAAG,IAAI;mBAKf,OAAO,EAAE,GAAG,IAAI;CAGhC,CAAC"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
let debugEnabled = false;
|
|
2
|
+
export function setDebug(enabled) {
|
|
3
|
+
debugEnabled = enabled;
|
|
4
|
+
}
|
|
5
|
+
export const logger = {
|
|
6
|
+
debug(...args) {
|
|
7
|
+
if (debugEnabled) {
|
|
8
|
+
console.log(...args);
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
warn(...args) {
|
|
12
|
+
if (debugEnabled) {
|
|
13
|
+
console.warn(...args);
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
error(...args) {
|
|
17
|
+
console.error(...args);
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../package/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,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IACD,KAAK,CAAC,GAAG,IAAe;QACtB,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IACzB,CAAC;CACF,CAAC"}
|
package/dist/redis.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare class RedisManager {
|
|
2
|
+
private publisher;
|
|
3
|
+
private subscriber;
|
|
4
|
+
private cacheClient;
|
|
5
|
+
constructor(redisUrl: string);
|
|
6
|
+
publishMessage(channel: string, message: string): void;
|
|
7
|
+
subscribeToChannel(channel: string, callback: (message: string) => void): void;
|
|
8
|
+
getCache(key: string): Promise<string | null>;
|
|
9
|
+
setCache(key: string, value: string, ttlSeconds?: number): Promise<void>;
|
|
10
|
+
deleteCache(key: string): Promise<void>;
|
|
11
|
+
disconnect(): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=redis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../package/redis.ts"],"names":[],"mappings":"AAIA,qBAAa,YAAY;IACvB,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,WAAW,CAAQ;gBAEf,QAAQ,EAAE,MAAM;IAM5B,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAItD,kBAAkB,CAChB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAClC,IAAI;IAmBD,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAI7C,QAAQ,CACZ,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC;IAQV,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CAKlC"}
|
package/dist/redis.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Redis } from "ioredis";
|
|
2
|
+
import { logger } from "./logger.js";
|
|
3
|
+
export class RedisManager {
|
|
4
|
+
publisher;
|
|
5
|
+
subscriber;
|
|
6
|
+
cacheClient;
|
|
7
|
+
constructor(redisUrl) {
|
|
8
|
+
this.publisher = new Redis(redisUrl);
|
|
9
|
+
this.subscriber = new Redis(redisUrl);
|
|
10
|
+
this.cacheClient = new Redis(redisUrl);
|
|
11
|
+
}
|
|
12
|
+
publishMessage(channel, message) {
|
|
13
|
+
this.publisher.publish(channel, message);
|
|
14
|
+
}
|
|
15
|
+
subscribeToChannel(channel, callback) {
|
|
16
|
+
this.subscriber
|
|
17
|
+
.subscribe(channel)
|
|
18
|
+
.then((count) => {
|
|
19
|
+
logger.debug(`Subscribed to ${count} channel(s). Listening on "${channel}".`);
|
|
20
|
+
})
|
|
21
|
+
.catch((err) => {
|
|
22
|
+
logger.error(`Failed to subscribe to channel ${channel}:`, err);
|
|
23
|
+
});
|
|
24
|
+
this.subscriber.on("message", (chan, message) => {
|
|
25
|
+
if (chan === channel) {
|
|
26
|
+
callback(message);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
async getCache(key) {
|
|
31
|
+
return await this.cacheClient.get(key);
|
|
32
|
+
}
|
|
33
|
+
async setCache(key, value, ttlSeconds) {
|
|
34
|
+
if (ttlSeconds) {
|
|
35
|
+
await this.cacheClient.set(key, value, "EX", ttlSeconds);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
await this.cacheClient.set(key, value);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async deleteCache(key) {
|
|
42
|
+
await this.cacheClient.del(key);
|
|
43
|
+
}
|
|
44
|
+
async disconnect() {
|
|
45
|
+
await this.publisher.quit();
|
|
46
|
+
await this.subscriber.quit();
|
|
47
|
+
await this.cacheClient.quit();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=redis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis.js","sourceRoot":"","sources":["../package/redis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,OAAO,YAAY;IACf,SAAS,CAAQ;IACjB,UAAU,CAAQ;IAClB,WAAW,CAAQ;IAE3B,YAAY,QAAgB;QAC1B,IAAI,CAAC,SAAS,GAAG,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC;QACrC,IAAI,CAAC,UAAU,GAAG,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC;QACtC,IAAI,CAAC,WAAW,GAAG,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC;IACzC,CAAC;IAED,cAAc,CAAC,OAAe,EAAE,OAAe;QAC7C,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC3C,CAAC;IAED,kBAAkB,CAChB,OAAe,EACf,QAAmC;QAEnC,IAAI,CAAC,UAAU;aACZ,SAAS,CAAC,OAAO,CAAC;aAClB,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;YACd,MAAM,CAAC,KAAK,CACV,iBAAiB,KAAK,8BAA8B,OAAO,IAAI,CAChE,CAAC;QACJ,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;YACtB,MAAM,CAAC,KAAK,CAAC,kCAAkC,OAAO,GAAG,EAAE,GAAG,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;QAEL,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,IAAY,EAAE,OAAe,EAAE,EAAE;YAC9D,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;gBACrB,QAAQ,CAAC,OAAO,CAAC,CAAC;YACpB,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,GAAW;QACxB,OAAO,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,QAAQ,CACZ,GAAW,EACX,KAAa,EACb,UAAmB;QAEnB,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;QAC3D,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,GAAW;QAC3B,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,UAAU;QACd,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;QAC5B,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QAC7B,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;IAChC,CAAC;CACF"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type SynkroEvent = {
|
|
2
|
+
type: string;
|
|
3
|
+
handler: HandlerFunction;
|
|
4
|
+
};
|
|
5
|
+
export type SynkroWorkflowStep = {
|
|
6
|
+
type: string;
|
|
7
|
+
handler: HandlerFunction;
|
|
8
|
+
};
|
|
9
|
+
export type SynkroWorkflow = {
|
|
10
|
+
name: string;
|
|
11
|
+
steps: SynkroWorkflowStep[];
|
|
12
|
+
};
|
|
13
|
+
export type SynkroOptions = {
|
|
14
|
+
redisUrl: string;
|
|
15
|
+
debug?: boolean;
|
|
16
|
+
events?: SynkroEvent[];
|
|
17
|
+
workflows?: SynkroWorkflow[];
|
|
18
|
+
};
|
|
19
|
+
export type HandlerCtx = {
|
|
20
|
+
requestId: string;
|
|
21
|
+
payload: unknown;
|
|
22
|
+
};
|
|
23
|
+
export type HandlerFunction = (ctx: HandlerCtx) => void | Promise<void>;
|
|
24
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../package/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,eAAe,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,eAAe,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,kBAAkB,EAAE,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,cAAc,EAAE,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE,UAAU,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../package/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { HandlerRegistry } from "./handler-registry.js";
|
|
2
|
+
import type { RedisManager } from "./redis.js";
|
|
3
|
+
import type { SynkroWorkflow } from "./types.js";
|
|
4
|
+
export declare class WorkflowRegistry {
|
|
5
|
+
private redis;
|
|
6
|
+
private handlerRegistry;
|
|
7
|
+
private workflows;
|
|
8
|
+
private eventToWorkflows;
|
|
9
|
+
constructor(redis: RedisManager, handlerRegistry: HandlerRegistry);
|
|
10
|
+
registerWorkflows(workflows: SynkroWorkflow[]): void;
|
|
11
|
+
hasWorkflow(name: string): boolean;
|
|
12
|
+
startWorkflow(workflowName: string, requestId: string, payload: unknown): Promise<void>;
|
|
13
|
+
private subscribeToWorkflowEvents;
|
|
14
|
+
private handleStepCompletion;
|
|
15
|
+
private stepChannel;
|
|
16
|
+
private stateKey;
|
|
17
|
+
private saveState;
|
|
18
|
+
private getState;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=workflow-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-registry.d.ts","sourceRoot":"","sources":["../package/workflow-registry.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAQjD,qBAAa,gBAAgB;IAQzB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,eAAe;IARzB,OAAO,CAAC,SAAS,CAAqC;IACtD,OAAO,CAAC,gBAAgB,CAGpB;gBAGM,KAAK,EAAE,YAAY,EACnB,eAAe,EAAE,eAAe;IAG1C,iBAAiB,CAAC,SAAS,EAAE,cAAc,EAAE,GAAG,IAAI;IAwBpD,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI5B,aAAa,CACjB,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,IAAI,CAAC;IA2BhB,OAAO,CAAC,yBAAyB;YAYnB,oBAAoB;IAiDlC,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,QAAQ;YAIF,SAAS;YAWT,QAAQ;CAKvB"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { logger } from "./logger.js";
|
|
2
|
+
export class WorkflowRegistry {
|
|
3
|
+
redis;
|
|
4
|
+
handlerRegistry;
|
|
5
|
+
workflows = new Map();
|
|
6
|
+
eventToWorkflows = new Map();
|
|
7
|
+
constructor(redis, handlerRegistry) {
|
|
8
|
+
this.redis = redis;
|
|
9
|
+
this.handlerRegistry = handlerRegistry;
|
|
10
|
+
}
|
|
11
|
+
registerWorkflows(workflows) {
|
|
12
|
+
for (const workflow of workflows) {
|
|
13
|
+
this.workflows.set(workflow.name, workflow);
|
|
14
|
+
for (let i = 0; i < workflow.steps.length; i++) {
|
|
15
|
+
const step = workflow.steps[i];
|
|
16
|
+
const key = step.type;
|
|
17
|
+
if (!this.eventToWorkflows.has(key)) {
|
|
18
|
+
this.eventToWorkflows.set(key, []);
|
|
19
|
+
}
|
|
20
|
+
this.eventToWorkflows.get(key).push({ workflow, stepIndex: i });
|
|
21
|
+
const channel = this.stepChannel(workflow.name, step.type);
|
|
22
|
+
this.handlerRegistry.register(channel, step.handler);
|
|
23
|
+
}
|
|
24
|
+
this.subscribeToWorkflowEvents(workflow);
|
|
25
|
+
logger.debug(`[WorkflowRegistry] - Workflow "${workflow.name}" registered with ${workflow.steps.length} steps`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
hasWorkflow(name) {
|
|
29
|
+
return this.workflows.has(name);
|
|
30
|
+
}
|
|
31
|
+
async startWorkflow(workflowName, requestId, payload) {
|
|
32
|
+
const workflow = this.workflows.get(workflowName);
|
|
33
|
+
if (!workflow) {
|
|
34
|
+
throw new Error(`[WorkflowRegistry] - Workflow "${workflowName}" not found`);
|
|
35
|
+
}
|
|
36
|
+
const state = {
|
|
37
|
+
workflowName,
|
|
38
|
+
currentStep: 0,
|
|
39
|
+
status: "running",
|
|
40
|
+
};
|
|
41
|
+
await this.saveState(requestId, state);
|
|
42
|
+
const firstStep = workflow.steps[0];
|
|
43
|
+
const channel = this.stepChannel(workflowName, firstStep.type);
|
|
44
|
+
logger.debug(`[WorkflowRegistry] - Starting workflow "${workflowName}" (requestId: ${requestId}), publishing "${firstStep.type}"`);
|
|
45
|
+
this.redis.publishMessage(channel, JSON.stringify({ requestId, payload }));
|
|
46
|
+
}
|
|
47
|
+
subscribeToWorkflowEvents(workflow) {
|
|
48
|
+
for (let i = 0; i < workflow.steps.length; i++) {
|
|
49
|
+
const step = workflow.steps[i];
|
|
50
|
+
const channel = this.stepChannel(workflow.name, step.type);
|
|
51
|
+
const completionChannel = `event:${channel}:completed`;
|
|
52
|
+
this.redis.subscribeToChannel(completionChannel, (message) => {
|
|
53
|
+
this.handleStepCompletion(workflow, i, message);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async handleStepCompletion(workflow, stepIndex, message) {
|
|
58
|
+
const { requestId, payload } = JSON.parse(message);
|
|
59
|
+
const state = await this.getState(requestId);
|
|
60
|
+
if (!state || state.workflowName !== workflow.name) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (state.currentStep !== stepIndex) {
|
|
64
|
+
logger.warn(`[WorkflowRegistry] - Step mismatch for "${workflow.name}" (requestId: ${requestId}): expected step ${state.currentStep}, got ${stepIndex}`);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const nextStepIndex = stepIndex + 1;
|
|
68
|
+
if (nextStepIndex >= workflow.steps.length) {
|
|
69
|
+
state.status = "completed";
|
|
70
|
+
state.currentStep = stepIndex;
|
|
71
|
+
await this.saveState(requestId, state);
|
|
72
|
+
logger.debug(`[WorkflowRegistry] - Workflow "${workflow.name}" completed (requestId: ${requestId})`);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
state.currentStep = nextStepIndex;
|
|
76
|
+
await this.saveState(requestId, state);
|
|
77
|
+
const nextStep = workflow.steps[nextStepIndex];
|
|
78
|
+
const nextChannel = this.stepChannel(workflow.name, nextStep.type);
|
|
79
|
+
logger.debug(`[WorkflowRegistry] - Workflow "${workflow.name}" advancing to step ${nextStepIndex}: "${nextStep.type}" (requestId: ${requestId})`);
|
|
80
|
+
this.redis.publishMessage(nextChannel, JSON.stringify({ requestId, payload }));
|
|
81
|
+
}
|
|
82
|
+
stepChannel(workflowName, stepType) {
|
|
83
|
+
return `workflow:${workflowName}:${stepType}`;
|
|
84
|
+
}
|
|
85
|
+
stateKey(requestId) {
|
|
86
|
+
return `workflow:state:${requestId}`;
|
|
87
|
+
}
|
|
88
|
+
async saveState(requestId, state) {
|
|
89
|
+
await this.redis.setCache(this.stateKey(requestId), JSON.stringify(state), 86400);
|
|
90
|
+
}
|
|
91
|
+
async getState(requestId) {
|
|
92
|
+
const raw = await this.redis.getCache(this.stateKey(requestId));
|
|
93
|
+
if (!raw)
|
|
94
|
+
return null;
|
|
95
|
+
return JSON.parse(raw);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=workflow-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-registry.js","sourceRoot":"","sources":["../package/workflow-registry.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@synkro/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Lightweight workflow and state machine orchestrator powered by Redis. Define event-driven workflows via configuration or code.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"require": "./dist/index.js",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc",
|
|
20
|
+
"type-check": "tsc --noEmit",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"test:watch": "vitest",
|
|
23
|
+
"prepublishOnly": "npm run build"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"workflow",
|
|
27
|
+
"state-machine",
|
|
28
|
+
"orchestrator",
|
|
29
|
+
"event-driven",
|
|
30
|
+
"redis"
|
|
31
|
+
],
|
|
32
|
+
"author": "buemura",
|
|
33
|
+
"license": "ISC",
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "https://github.com/buemura/synkro.git"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://github.com/buemura/synkro#readme",
|
|
39
|
+
"type": "module",
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"ioredis": "^5.10.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/node": "^25.3.3",
|
|
45
|
+
"tsx": "^4.21.0",
|
|
46
|
+
"typescript": "^5.9.3",
|
|
47
|
+
"vitest": "^4.0.18"
|
|
48
|
+
}
|
|
49
|
+
}
|