@flowcore/pathways 0.8.0 → 0.9.1

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 (33) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +95 -0
  3. package/esm/pathways/builder.d.ts +31 -1
  4. package/esm/pathways/builder.d.ts.map +1 -1
  5. package/esm/pathways/builder.js +47 -5
  6. package/esm/pathways/kv/kv-adapter.d.ts +59 -2
  7. package/esm/pathways/kv/kv-adapter.d.ts.map +1 -1
  8. package/esm/pathways/kv/kv-adapter.js +31 -1
  9. package/esm/pathways/postgres/postgres-pathway-state.d.ts +131 -1
  10. package/esm/pathways/postgres/postgres-pathway-state.d.ts.map +1 -1
  11. package/esm/pathways/postgres/postgres-pathway-state.js +131 -1
  12. package/esm/pathways/session-pathway.d.ts +63 -1
  13. package/esm/pathways/session-pathway.d.ts.map +1 -1
  14. package/esm/pathways/session-pathway.js +65 -0
  15. package/esm/router/index.d.ts +83 -2
  16. package/esm/router/index.d.ts.map +1 -1
  17. package/esm/router/index.js +83 -2
  18. package/package.json +4 -5
  19. package/script/pathways/builder.d.ts +31 -1
  20. package/script/pathways/builder.d.ts.map +1 -1
  21. package/script/pathways/builder.js +47 -5
  22. package/script/pathways/kv/kv-adapter.d.ts +59 -2
  23. package/script/pathways/kv/kv-adapter.d.ts.map +1 -1
  24. package/script/pathways/kv/kv-adapter.js +31 -1
  25. package/script/pathways/postgres/postgres-pathway-state.d.ts +131 -1
  26. package/script/pathways/postgres/postgres-pathway-state.d.ts.map +1 -1
  27. package/script/pathways/postgres/postgres-pathway-state.js +131 -1
  28. package/script/pathways/session-pathway.d.ts +63 -1
  29. package/script/pathways/session-pathway.d.ts.map +1 -1
  30. package/script/pathways/session-pathway.js +65 -0
  31. package/script/router/index.d.ts +83 -2
  32. package/script/router/index.d.ts.map +1 -1
  33. package/script/router/index.js +83 -2
@@ -4,6 +4,47 @@ import { createPostgresAdapter } from "./postgres-adapter.js";
4
4
  *
5
5
  * This class provides persistent storage of pathway state using a PostgreSQL database,
6
6
  * which allows for state to be shared across multiple instances of the application.
7
+ *
8
+ * Key features:
9
+ * - Persistent storage of pathway processing state across application restarts
10
+ * - Automatic table and index creation
11
+ * - Configurable TTL (time-to-live) for processed events
12
+ * - Automatic cleanup of expired records
13
+ * - Support for horizontal scaling across multiple instances
14
+ * - Connection pooling for efficient database usage
15
+ *
16
+ * Use cases:
17
+ * - Production deployments that require durability and persistence
18
+ * - Distributed systems where multiple instances process events
19
+ * - Applications with high reliability requirements
20
+ * - Scenarios where in-memory state is insufficient
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * // Create PostgreSQL pathway state with connection string
25
+ * const postgresState = createPostgresPathwayState({
26
+ * connectionString: "postgres://user:password@localhost:5432/mydb",
27
+ * tableName: "event_processing_state", // Optional
28
+ * ttlMs: 24 * 60 * 60 * 1000 // 24 hours (optional)
29
+ * });
30
+ *
31
+ * // Or with individual parameters
32
+ * const postgresState = createPostgresPathwayState({
33
+ * host: "localhost",
34
+ * port: 5432,
35
+ * user: "postgres",
36
+ * password: "postgres",
37
+ * database: "mydb",
38
+ * ssl: false,
39
+ * tableName: "event_processing_state", // Optional
40
+ * ttlMs: 30 * 60 * 1000 // 30 minutes (optional)
41
+ * });
42
+ *
43
+ * // Use with PathwaysBuilder
44
+ * const pathways = new PathwaysBuilder({
45
+ * // ... other config
46
+ * }).withPathwayState(postgresState);
47
+ * ```
7
48
  */
8
49
  export class PostgresPathwayState {
9
50
  /**
@@ -109,8 +150,30 @@ export class PostgresPathwayState {
109
150
  /**
110
151
  * Checks if an event has already been processed
111
152
  *
153
+ * This method checks the PostgreSQL database to determine if an event with the given ID
154
+ * has been marked as processed. If the event exists in the database and is marked as processed,
155
+ * the method returns true.
156
+ *
157
+ * Before performing the check, this method also triggers cleanup of expired event records
158
+ * to maintain database performance.
159
+ *
112
160
  * @param {string} eventId - The ID of the event to check
113
161
  * @returns {Promise<boolean>} True if the event has been processed, false otherwise
162
+ *
163
+ * @example
164
+ * ```typescript
165
+ * // Check if an event has been processed
166
+ * const processed = await postgresState.isProcessed("event-123");
167
+ * if (processed) {
168
+ * console.log("Event has already been processed, skipping");
169
+ * } else {
170
+ * console.log("Processing event for the first time");
171
+ * // Process the event
172
+ * await processEvent(event);
173
+ * // Mark as processed
174
+ * await postgresState.setProcessed("event-123");
175
+ * }
176
+ * ```
114
177
  */
115
178
  async isProcessed(eventId) {
116
179
  await this.initialize();
@@ -125,8 +188,37 @@ export class PostgresPathwayState {
125
188
  /**
126
189
  * Marks an event as processed
127
190
  *
191
+ * This method inserts or updates a record in the PostgreSQL database to mark an event
192
+ * as processed. If the event already exists in the database, the record is updated;
193
+ * otherwise, a new record is created.
194
+ *
195
+ * Each processed event is stored with an expiration timestamp based on the configured TTL.
196
+ * After this time elapses, the record may be automatically removed during cleanup operations.
197
+ *
128
198
  * @param {string} eventId - The ID of the event to mark as processed
129
199
  * @returns {Promise<void>}
200
+ *
201
+ * @example
202
+ * ```typescript
203
+ * // Process an event and mark it as processed
204
+ * async function handleEvent(event) {
205
+ * // Check if already processed to implement idempotency
206
+ * if (await postgresState.isProcessed(event.id)) {
207
+ * return; // Skip already processed events
208
+ * }
209
+ *
210
+ * try {
211
+ * // Process the event
212
+ * await processEvent(event);
213
+ *
214
+ * // Mark as processed after successful processing
215
+ * await postgresState.setProcessed(event.id);
216
+ * } catch (error) {
217
+ * console.error("Failed to process event:", error);
218
+ * // Not marking as processed, so it can be retried
219
+ * }
220
+ * }
221
+ * ```
130
222
  */
131
223
  async setProcessed(eventId) {
132
224
  await this.initialize();
@@ -188,8 +280,46 @@ Object.defineProperty(PostgresPathwayState, "DEFAULT_TABLE_NAME", {
188
280
  /**
189
281
  * Creates a new PostgreSQL pathway state instance
190
282
  *
191
- * @param config The PostgreSQL configuration
283
+ * This is a factory function that simplifies the creation of PostgresPathwayState instances.
284
+ * It accepts either a connection string or individual connection parameters, along with
285
+ * optional configuration for table name and TTL.
286
+ *
287
+ * The PostgresPathwayState is lazily initialized, meaning the database connection and
288
+ * table creation only happen when the first operation is performed. This makes it safe
289
+ * to create instances early in the application lifecycle.
290
+ *
291
+ * @param config The PostgreSQL configuration (connection string or parameters)
192
292
  * @returns A new PostgresPathwayState instance
293
+ *
294
+ * @example
295
+ * ```typescript
296
+ * // With connection string
297
+ * const state = createPostgresPathwayState({
298
+ * connectionString: "postgres://user:pass@localhost:5432/db?sslmode=require"
299
+ * });
300
+ *
301
+ * // With individual parameters
302
+ * const state = createPostgresPathwayState({
303
+ * host: "localhost",
304
+ * port: 5432,
305
+ * user: "postgres",
306
+ * password: "secret",
307
+ * database: "events_db",
308
+ * ssl: true
309
+ * });
310
+ *
311
+ * // With custom table name and TTL
312
+ * const state = createPostgresPathwayState({
313
+ * connectionString: "postgres://user:pass@localhost:5432/db",
314
+ * tableName: "my_custom_event_state",
315
+ * ttlMs: 7 * 24 * 60 * 60 * 1000 // 1 week
316
+ * });
317
+ *
318
+ * // Use with PathwaysBuilder
319
+ * const pathways = new PathwaysBuilder({
320
+ * // Other config
321
+ * }).withPathwayState(state);
322
+ * ```
193
323
  */
194
324
  export function createPostgresPathwayState(config) {
195
325
  const state = new PostgresPathwayState(config);
@@ -1,4 +1,4 @@
1
- import type { PathwaysBuilder } from "./builder.js";
1
+ import type { PathwaysBuilder, UserIdResolver } from "./builder.js";
2
2
  import type { EventMetadata, PathwayWriteOptions } from "./types.js";
3
3
  /**
4
4
  * SessionPathwayBuilder wraps a PathwaysBuilder instance and automatically
@@ -6,6 +6,38 @@ import type { EventMetadata, PathwayWriteOptions } from "./types.js";
6
6
  *
7
7
  * This provides a convenient way to track operations within a user session
8
8
  * by automatically including the session ID in metadata.
9
+ *
10
+ * Key features:
11
+ * - Automatic session ID generation if none is provided
12
+ * - Cross-platform UUID generation (works in Deno, Bun, and Node.js)
13
+ * - Simple API for accessing the current session ID
14
+ * - Convenient integration with session-specific user resolvers
15
+ * - Automatic inclusion of session ID in all write operations
16
+ * - Support for overriding the session ID on specific writes
17
+ *
18
+ * Use cases:
19
+ * - Tracking user actions across multiple pathway writes
20
+ * - Connecting related events in a single user session
21
+ * - Supporting multi-user environments where different users' operations need to be tracked separately
22
+ * - Building user activity logs with session grouping
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * // Create a session pathway with auto-generated ID
27
+ * const session = new SessionPathwayBuilder(pathwaysBuilder);
28
+ *
29
+ * // Get the auto-generated session ID
30
+ * const sessionId = session.getSessionId();
31
+ *
32
+ * // Register a user resolver for this session
33
+ * session.withUserResolver(async () => getCurrentUserId());
34
+ *
35
+ * // Write events with session context
36
+ * await session.write("order/placed", orderData);
37
+ * await session.write("user/action", actionData);
38
+ *
39
+ * // All events will be associated with the same session ID
40
+ * ```
9
41
  */
10
42
  export declare class SessionPathwayBuilder<TPathway extends Record<string, unknown> = {}, TWritablePaths extends keyof TPathway = never> {
11
43
  private readonly pathwaysBuilder;
@@ -23,6 +55,36 @@ export declare class SessionPathwayBuilder<TPathway extends Record<string, unkno
23
55
  * @returns The session ID associated with this instance
24
56
  */
25
57
  getSessionId(): string;
58
+ /**
59
+ * Registers a user resolver for this session
60
+ *
61
+ * This is a convenience method that calls `pathwaysBuilder.withSessionUserResolver`
62
+ * with the current session ID, allowing you to set up a resolver specific to this session
63
+ * without having to manually pass the session ID.
64
+ *
65
+ * The resolver will be called whenever events are written through this session,
66
+ * and the resolved user ID will be included in the event metadata.
67
+ *
68
+ * @param resolver The function that resolves to the user ID for this session
69
+ * @returns The SessionPathwayBuilder instance for chaining
70
+ *
71
+ * @throws Error if the underlying PathwaysBuilder does not have session user resolvers configured
72
+ *
73
+ * @example
74
+ * ```typescript
75
+ * const session = new SessionPathwayBuilder(pathwaysBuilder);
76
+ *
77
+ * // Register a user resolver for this session
78
+ * session.withUserResolver(async () => {
79
+ * // Get the user ID associated with this session
80
+ * return getUserIdFromSession();
81
+ * });
82
+ *
83
+ * // When writing events, the user ID will be automatically included
84
+ * await session.write("user/action", actionData);
85
+ * ```
86
+ */
87
+ withUserResolver(resolver: UserIdResolver): this;
26
88
  /**
27
89
  * Writes data to a pathway, proxying to the underlying PathwaysBuilder
28
90
  *
@@ -1 +1 @@
1
- {"version":3,"file":"session-pathway.d.ts","sourceRoot":"","sources":["../../src/pathways/session-pathway.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAqBrE;;;;;;GAMG;AACH,qBAAa,qBAAqB,CAEhC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,EAC7C,cAAc,SAAS,MAAM,QAAQ,GAAG,KAAK;IAE7C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA4C;IAC5E,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IAEnC;;;;;OAKG;gBAED,eAAe,EAAE,eAAe,CAAC,QAAQ,EAAE,cAAc,CAAC,EAC1D,SAAS,CAAC,EAAE,MAAM;IAMpB;;;;OAIG;IACH,YAAY,IAAI,MAAM;IAItB;;;;;;;;OAQG;IACG,KAAK,CAAC,KAAK,SAAS,cAAc,EACtC,IAAI,EAAE,KAAK,EACX,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,EACrB,QAAQ,CAAC,EAAE,aAAa,EACxB,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC;CAU9B"}
1
+ {"version":3,"file":"session-pathway.d.ts","sourceRoot":"","sources":["../../src/pathways/session-pathway.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAqBrE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,qBAAa,qBAAqB,CAEhC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,EAC7C,cAAc,SAAS,MAAM,QAAQ,GAAG,KAAK;IAE7C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA4C;IAC5E,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IAEnC;;;;;OAKG;gBAED,eAAe,EAAE,eAAe,CAAC,QAAQ,EAAE,cAAc,CAAC,EAC1D,SAAS,CAAC,EAAE,MAAM;IAMpB;;;;OAIG;IACH,YAAY,IAAI,MAAM;IAItB;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACH,gBAAgB,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI;IAKhD;;;;;;;;OAQG;IACG,KAAK,CAAC,KAAK,SAAS,cAAc,EACtC,IAAI,EAAE,KAAK,EACX,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,EACrB,QAAQ,CAAC,EAAE,aAAa,EACxB,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC;CAU9B"}
@@ -21,6 +21,38 @@ function generateUUID() {
21
21
  *
22
22
  * This provides a convenient way to track operations within a user session
23
23
  * by automatically including the session ID in metadata.
24
+ *
25
+ * Key features:
26
+ * - Automatic session ID generation if none is provided
27
+ * - Cross-platform UUID generation (works in Deno, Bun, and Node.js)
28
+ * - Simple API for accessing the current session ID
29
+ * - Convenient integration with session-specific user resolvers
30
+ * - Automatic inclusion of session ID in all write operations
31
+ * - Support for overriding the session ID on specific writes
32
+ *
33
+ * Use cases:
34
+ * - Tracking user actions across multiple pathway writes
35
+ * - Connecting related events in a single user session
36
+ * - Supporting multi-user environments where different users' operations need to be tracked separately
37
+ * - Building user activity logs with session grouping
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * // Create a session pathway with auto-generated ID
42
+ * const session = new SessionPathwayBuilder(pathwaysBuilder);
43
+ *
44
+ * // Get the auto-generated session ID
45
+ * const sessionId = session.getSessionId();
46
+ *
47
+ * // Register a user resolver for this session
48
+ * session.withUserResolver(async () => getCurrentUserId());
49
+ *
50
+ * // Write events with session context
51
+ * await session.write("order/placed", orderData);
52
+ * await session.write("user/action", actionData);
53
+ *
54
+ * // All events will be associated with the same session ID
55
+ * ```
24
56
  */
25
57
  export class SessionPathwayBuilder {
26
58
  /**
@@ -53,6 +85,39 @@ export class SessionPathwayBuilder {
53
85
  getSessionId() {
54
86
  return this.sessionId;
55
87
  }
88
+ /**
89
+ * Registers a user resolver for this session
90
+ *
91
+ * This is a convenience method that calls `pathwaysBuilder.withSessionUserResolver`
92
+ * with the current session ID, allowing you to set up a resolver specific to this session
93
+ * without having to manually pass the session ID.
94
+ *
95
+ * The resolver will be called whenever events are written through this session,
96
+ * and the resolved user ID will be included in the event metadata.
97
+ *
98
+ * @param resolver The function that resolves to the user ID for this session
99
+ * @returns The SessionPathwayBuilder instance for chaining
100
+ *
101
+ * @throws Error if the underlying PathwaysBuilder does not have session user resolvers configured
102
+ *
103
+ * @example
104
+ * ```typescript
105
+ * const session = new SessionPathwayBuilder(pathwaysBuilder);
106
+ *
107
+ * // Register a user resolver for this session
108
+ * session.withUserResolver(async () => {
109
+ * // Get the user ID associated with this session
110
+ * return getUserIdFromSession();
111
+ * });
112
+ *
113
+ * // When writing events, the user ID will be automatically included
114
+ * await session.write("user/action", actionData);
115
+ * ```
116
+ */
117
+ withUserResolver(resolver) {
118
+ this.pathwaysBuilder.withSessionUserResolver(this.sessionId, resolver);
119
+ return this;
120
+ }
56
121
  /**
57
122
  * Writes data to a pathway, proxying to the underlying PathwaysBuilder
58
123
  *
@@ -11,6 +11,49 @@ import type { PathwaysBuilder } from "../pathways/index.js";
11
11
  import type { Logger } from "../pathways/logger.js";
12
12
  /**
13
13
  * Router class that handles directing events to the appropriate pathway handlers
14
+ *
15
+ * The PathwayRouter serves as a bridge between incoming webhook events and the PathwaysBuilder,
16
+ * ensuring events are routed to the correct pathway handlers based on flow type and event type.
17
+ *
18
+ * Key features:
19
+ * - Secure authentication using a secret key
20
+ * - Automatic mapping of events to the correct pathway handlers
21
+ * - Compatibility with both legacy and modern Flowcore event formats
22
+ * - Detailed error handling and logging
23
+ *
24
+ * Use cases:
25
+ * - Building webhook endpoints that receive Flowcore events
26
+ * - Creating API routes that process events from external systems
27
+ * - Implementing event-driven microservices that consume Flowcore events
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * // Create a router with authentication
32
+ * const SECRET_KEY = "your-webhook-secret";
33
+ * const router = new PathwayRouter(pathwaysBuilder, SECRET_KEY);
34
+ *
35
+ * // In your HTTP handler:
36
+ * async function handleWebhook(req: Request) {
37
+ * const event = await req.json();
38
+ * const secret = req.headers.get("X-Webhook-Secret");
39
+ *
40
+ * try {
41
+ * const result = await router.processEvent(event, secret);
42
+ * return new Response(JSON.stringify(result), {
43
+ * status: 200,
44
+ * headers: { "Content-Type": "application/json" }
45
+ * });
46
+ * } catch (error) {
47
+ * console.error("Error processing event:", error);
48
+ * return new Response(JSON.stringify({
49
+ * error: error.message
50
+ * }), {
51
+ * status: 401,
52
+ * headers: { "Content-Type": "application/json" }
53
+ * });
54
+ * }
55
+ * }
56
+ * ```
14
57
  */
15
58
  export declare class PathwayRouter {
16
59
  private readonly pathways;
@@ -28,10 +71,48 @@ export declare class PathwayRouter {
28
71
  /**
29
72
  * Process an incoming event by routing it to the appropriate pathway handler
30
73
  *
31
- * @param event The event to process
74
+ * This method handles the complete lifecycle of an incoming event:
75
+ * 1. Validates the authentication using the provided secret key
76
+ * 2. Maps the event to the correct pathway based on flowType and eventType
77
+ * 3. Delegates processing to the PathwaysBuilder
78
+ * 4. Provides detailed error handling and feedback
79
+ *
80
+ * The method supports both modern Flowcore events and legacy events that used
81
+ * the "aggregator" field instead of "flowType". It automatically converts legacy
82
+ * events to the modern format before processing.
83
+ *
84
+ * @param event The event to process, containing flowType, eventType, and payload
32
85
  * @param providedSecret The secret key provided for authentication
33
86
  * @returns Result of the event processing with success status and message
34
- * @throws Error if authentication fails, pathway is not found, or processing fails
87
+ *
88
+ * @throws Error if authentication fails (401 unauthorized)
89
+ * @throws Error if the pathway is not found (404 not found)
90
+ * @throws Error if processing fails (includes the original error message)
91
+ *
92
+ * @example
93
+ * ```typescript
94
+ * // Basic usage
95
+ * try {
96
+ * const result = await router.processEvent(incomingEvent, secretFromHeader);
97
+ * console.log("Success:", result.message);
98
+ * } catch (error) {
99
+ * console.error("Failed to process event:", error.message);
100
+ * }
101
+ *
102
+ * // With error handling for different error types
103
+ * try {
104
+ * const result = await router.processEvent(event, secret);
105
+ * return { status: 200, body: result };
106
+ * } catch (error) {
107
+ * if (error.message.includes("Invalid secret key")) {
108
+ * return { status: 401, body: { error: "Unauthorized" } };
109
+ * } else if (error.message.includes("not found")) {
110
+ * return { status: 404, body: { error: "Pathway not found" } };
111
+ * } else {
112
+ * return { status: 500, body: { error: "Processing failed" } };
113
+ * }
114
+ * }
115
+ * ```
35
116
  */
36
117
  processEvent(event: FlowcoreLegacyEvent, providedSecret: string): Promise<{
37
118
  success: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/router/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AAErE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAC3D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAGnD;;GAEG;AACH,qBAAa,aAAa;IAatB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAb5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC;;;;;;;OAOG;gBAGgB,QAAQ,EAAE,eAAe,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,EAC9C,SAAS,EAAE,MAAM,EAClC,MAAM,CAAC,EAAE,MAAM;IAajB;;;;;;;OAOG;IACG,YAAY,CAAC,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAkDvH"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/router/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AAErE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAC3D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAGnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,qBAAa,aAAa;IAatB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAb5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC;;;;;;;OAOG;gBAGgB,QAAQ,EAAE,eAAe,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,EAC9C,SAAS,EAAE,MAAM,EAClC,MAAM,CAAC,EAAE,MAAM;IAajB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6CG;IACG,YAAY,CAAC,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAkDvH"}
@@ -1,6 +1,49 @@
1
1
  import { NoopLogger } from "../pathways/logger.js";
2
2
  /**
3
3
  * Router class that handles directing events to the appropriate pathway handlers
4
+ *
5
+ * The PathwayRouter serves as a bridge between incoming webhook events and the PathwaysBuilder,
6
+ * ensuring events are routed to the correct pathway handlers based on flow type and event type.
7
+ *
8
+ * Key features:
9
+ * - Secure authentication using a secret key
10
+ * - Automatic mapping of events to the correct pathway handlers
11
+ * - Compatibility with both legacy and modern Flowcore event formats
12
+ * - Detailed error handling and logging
13
+ *
14
+ * Use cases:
15
+ * - Building webhook endpoints that receive Flowcore events
16
+ * - Creating API routes that process events from external systems
17
+ * - Implementing event-driven microservices that consume Flowcore events
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * // Create a router with authentication
22
+ * const SECRET_KEY = "your-webhook-secret";
23
+ * const router = new PathwayRouter(pathwaysBuilder, SECRET_KEY);
24
+ *
25
+ * // In your HTTP handler:
26
+ * async function handleWebhook(req: Request) {
27
+ * const event = await req.json();
28
+ * const secret = req.headers.get("X-Webhook-Secret");
29
+ *
30
+ * try {
31
+ * const result = await router.processEvent(event, secret);
32
+ * return new Response(JSON.stringify(result), {
33
+ * status: 200,
34
+ * headers: { "Content-Type": "application/json" }
35
+ * });
36
+ * } catch (error) {
37
+ * console.error("Error processing event:", error);
38
+ * return new Response(JSON.stringify({
39
+ * error: error.message
40
+ * }), {
41
+ * status: 401,
42
+ * headers: { "Content-Type": "application/json" }
43
+ * });
44
+ * }
45
+ * }
46
+ * ```
4
47
  */
5
48
  export class PathwayRouter {
6
49
  /**
@@ -43,10 +86,48 @@ export class PathwayRouter {
43
86
  /**
44
87
  * Process an incoming event by routing it to the appropriate pathway handler
45
88
  *
46
- * @param event The event to process
89
+ * This method handles the complete lifecycle of an incoming event:
90
+ * 1. Validates the authentication using the provided secret key
91
+ * 2. Maps the event to the correct pathway based on flowType and eventType
92
+ * 3. Delegates processing to the PathwaysBuilder
93
+ * 4. Provides detailed error handling and feedback
94
+ *
95
+ * The method supports both modern Flowcore events and legacy events that used
96
+ * the "aggregator" field instead of "flowType". It automatically converts legacy
97
+ * events to the modern format before processing.
98
+ *
99
+ * @param event The event to process, containing flowType, eventType, and payload
47
100
  * @param providedSecret The secret key provided for authentication
48
101
  * @returns Result of the event processing with success status and message
49
- * @throws Error if authentication fails, pathway is not found, or processing fails
102
+ *
103
+ * @throws Error if authentication fails (401 unauthorized)
104
+ * @throws Error if the pathway is not found (404 not found)
105
+ * @throws Error if processing fails (includes the original error message)
106
+ *
107
+ * @example
108
+ * ```typescript
109
+ * // Basic usage
110
+ * try {
111
+ * const result = await router.processEvent(incomingEvent, secretFromHeader);
112
+ * console.log("Success:", result.message);
113
+ * } catch (error) {
114
+ * console.error("Failed to process event:", error.message);
115
+ * }
116
+ *
117
+ * // With error handling for different error types
118
+ * try {
119
+ * const result = await router.processEvent(event, secret);
120
+ * return { status: 200, body: result };
121
+ * } catch (error) {
122
+ * if (error.message.includes("Invalid secret key")) {
123
+ * return { status: 401, body: { error: "Unauthorized" } };
124
+ * } else if (error.message.includes("not found")) {
125
+ * return { status: 404, body: { error: "Pathway not found" } };
126
+ * } else {
127
+ * return { status: 500, body: { error: "Processing failed" } };
128
+ * }
129
+ * }
130
+ * ```
50
131
  */
51
132
  async processEvent(event, providedSecret) {
52
133
  // Validate secret key
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@flowcore/pathways",
3
- "version": "0.8.0",
3
+ "version": "0.9.1",
4
4
  "description": "A TypeScript Library for creating Flowcore Pathways, simplifying the integration with the flowcore platform",
5
- "homepage": "https://github.com/flowcore-io/flowcore-sdk#readme",
5
+ "homepage": "https://github.com/flowcore-io/flowcore-pathways#readme",
6
6
  "repository": {
7
7
  "type": "git",
8
- "url": "git+https://github.com/flowcore-io/flowcore-sdk.git"
8
+ "url": "git+https://github.com/flowcore-io/flowcore-pathways.git"
9
9
  },
10
10
  "license": "MIT",
11
11
  "bugs": {
12
- "url": "https://github.com/flowcore-io/flowcore-sdk/issues"
12
+ "url": "https://github.com/flowcore-io/flowcore-pathways/issues"
13
13
  },
14
14
  "main": "./script/mod.js",
15
15
  "module": "./esm/mod.js",
@@ -25,7 +25,6 @@
25
25
  "dependencies": {
26
26
  "@flowcore/sdk-transformer-core": "^2.3.6",
27
27
  "@sinclair/typebox": "^0.34.27",
28
- "bun-sqlite-key-value": "1.13.1",
29
28
  "node-cache": "5.1.2",
30
29
  "postgres": "^3.4.3",
31
30
  "rxjs": "^7.8.1"
@@ -1,6 +1,7 @@
1
1
  import type { Static, TSchema } from "@sinclair/typebox";
2
2
  import type { WebhookSendOptions } from "@flowcore/sdk-transformer-core";
3
3
  import type { FlowcoreEvent } from "../contracts/event.js";
4
+ import type { KvAdapter } from "./kv/kv-adapter.js";
4
5
  import type { Logger } from "./logger.js";
5
6
  import type { EventMetadata, PathwayContract, PathwayKey, PathwayState, PathwayWriteOptions, WritablePathway } from "./types.js";
6
7
  /**
@@ -77,14 +78,16 @@ export declare class PathwaysBuilder<TPathway extends Record<string, unknown> =
77
78
  * @param options.apiKey The API key for authentication
78
79
  * @param options.pathwayTimeoutMs Optional timeout for pathway processing in milliseconds
79
80
  * @param options.logger Optional logger instance
81
+ * @param options.sessionUserResolvers Optional KvAdapter instance for session-specific user resolvers
80
82
  */
81
- constructor({ baseUrl, tenant, dataCore, apiKey, pathwayTimeoutMs, logger, }: {
83
+ constructor({ baseUrl, tenant, dataCore, apiKey, pathwayTimeoutMs, logger, sessionUserResolvers, }: {
82
84
  baseUrl: string;
83
85
  tenant: string;
84
86
  dataCore: string;
85
87
  apiKey: string;
86
88
  pathwayTimeoutMs?: number;
87
89
  logger?: Logger;
90
+ sessionUserResolvers?: KvAdapter;
88
91
  });
89
92
  /**
90
93
  * Configures the PathwaysBuilder to use a custom pathway state implementation
@@ -106,9 +109,36 @@ export declare class PathwaysBuilder<TPathway extends Record<string, unknown> =
106
109
  withUserResolver(resolver: UserIdResolver): PathwaysBuilder<TPathway, TWritablePaths>;
107
110
  /**
108
111
  * Registers a user resolver for a specific session
112
+ *
113
+ * Session-specific user resolvers allow you to associate different user IDs with different
114
+ * sessions, which is useful in multi-user applications or when tracking user actions across
115
+ * different sessions.
116
+ *
117
+ * The resolver is stored in a key-value store with a TTL (time to live), and will be used
118
+ * to resolve the user ID when operations are performed with the given session ID. If the resolver
119
+ * expires, it will need to be registered again.
120
+ *
121
+ * This feature works in conjunction with the SessionPathwayBuilder to provide a complete
122
+ * session management solution.
123
+ *
109
124
  * @param sessionId The session ID to associate with this resolver
110
125
  * @param resolver The resolver function that resolves to the user ID for this session
111
126
  * @returns The PathwaysBuilder instance for chaining
127
+ *
128
+ * @throws Error if session user resolvers are not configured (sessionUserResolvers not provided in constructor)
129
+ *
130
+ * @example
131
+ * ```typescript
132
+ * // Register a resolver for a specific session
133
+ * pathwaysBuilder.withSessionUserResolver("session-123", async () => {
134
+ * return "user-456"; // Return the user ID for this session
135
+ * });
136
+ *
137
+ * // Use with SessionPathwayBuilder
138
+ * const session = new SessionPathwayBuilder(pathwaysBuilder, "session-123");
139
+ * await session.write("user/action", actionData);
140
+ * // The user ID will be automatically included in the metadata
141
+ * ```
112
142
  */
113
143
  withSessionUserResolver(sessionId: string, resolver: UserIdResolver): PathwaysBuilder<TPathway, TWritablePaths>;
114
144
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/pathways/builder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/pathways/builder.ts"],"names":[],"mappings":"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"}