@flowcore/pathways 0.7.0 → 0.9.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/CHANGELOG.md +19 -0
- package/README.md +95 -0
- package/esm/pathways/builder.d.ts +45 -6
- package/esm/pathways/builder.d.ts.map +1 -1
- package/esm/pathways/builder.js +106 -43
- package/esm/pathways/index.d.ts +2 -0
- package/esm/pathways/index.d.ts.map +1 -1
- package/esm/pathways/index.js +2 -0
- package/esm/pathways/kv/kv-adapter.d.ts +59 -2
- package/esm/pathways/kv/kv-adapter.d.ts.map +1 -1
- package/esm/pathways/kv/kv-adapter.js +31 -1
- package/esm/pathways/postgres/postgres-pathway-state.d.ts +131 -1
- package/esm/pathways/postgres/postgres-pathway-state.d.ts.map +1 -1
- package/esm/pathways/postgres/postgres-pathway-state.js +131 -1
- package/esm/pathways/session-pathway.d.ts +99 -0
- package/esm/pathways/session-pathway.d.ts.map +1 -0
- package/esm/pathways/session-pathway.js +138 -0
- package/esm/pathways/types.d.ts +5 -0
- package/esm/pathways/types.d.ts.map +1 -1
- package/esm/router/index.d.ts +83 -2
- package/esm/router/index.d.ts.map +1 -1
- package/esm/router/index.js +83 -2
- package/package.json +1 -1
- package/script/pathways/builder.d.ts +45 -6
- package/script/pathways/builder.d.ts.map +1 -1
- package/script/pathways/builder.js +106 -43
- package/script/pathways/index.d.ts +2 -0
- package/script/pathways/index.d.ts.map +1 -1
- package/script/pathways/index.js +2 -0
- package/script/pathways/kv/kv-adapter.d.ts +59 -2
- package/script/pathways/kv/kv-adapter.d.ts.map +1 -1
- package/script/pathways/kv/kv-adapter.js +31 -1
- package/script/pathways/postgres/postgres-pathway-state.d.ts +131 -1
- package/script/pathways/postgres/postgres-pathway-state.d.ts.map +1 -1
- package/script/pathways/postgres/postgres-pathway-state.js +131 -1
- package/script/pathways/session-pathway.d.ts +99 -0
- package/script/pathways/session-pathway.d.ts.map +1 -0
- package/script/pathways/session-pathway.js +142 -0
- package/script/pathways/types.d.ts +5 -0
- package/script/pathways/types.d.ts.map +1 -1
- package/script/router/index.d.ts +83 -2
- package/script/router/index.d.ts.map +1 -1
- package/script/router/index.js +83 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.9.0](https://github.com/flowcore-io/flowcore-pathways/compare/v0.8.0...v0.9.0) (2025-03-18)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **pathways:** :sparkles: Introduce Session Pathways for session management ([5ad1f1d](https://github.com/flowcore-io/flowcore-pathways/commit/5ad1f1d706dcfb4ba517c38a2748274d43762cb6))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **pathways:** :art: Change import of KvAdapter to type import ([732da2d](https://github.com/flowcore-io/flowcore-pathways/commit/732da2d191b87781b2be3adf9efa150e2eaab3ef))
|
|
14
|
+
|
|
15
|
+
## [0.8.0](https://github.com/flowcore-io/flowcore-pathways/compare/v0.7.0...v0.8.0) (2025-03-18)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* **pathways:** :sparkles: Add session-specific user resolver functionality ([0e0c074](https://github.com/flowcore-io/flowcore-pathways/commit/0e0c074b451b15d3a83ea49f0d838ed559306290))
|
|
21
|
+
|
|
3
22
|
## [0.7.0](https://github.com/flowcore-io/flowcore-pathways/compare/v0.6.0...v0.7.0) (2025-03-18)
|
|
4
23
|
|
|
5
24
|
|
package/README.md
CHANGED
|
@@ -21,6 +21,7 @@ A TypeScript Library for creating Flowcore Pathways, simplifying the integration
|
|
|
21
21
|
- [Auditing](#auditing)
|
|
22
22
|
- [Custom Loggers](#custom-loggers)
|
|
23
23
|
- [Retry Mechanisms](#retry-mechanisms)
|
|
24
|
+
- [Session Pathways](#session-pathways)
|
|
24
25
|
- [API Reference](#api-reference)
|
|
25
26
|
|
|
26
27
|
## Installation
|
|
@@ -415,6 +416,100 @@ pathways.register({
|
|
|
415
416
|
});
|
|
416
417
|
```
|
|
417
418
|
|
|
419
|
+
### Session Pathways
|
|
420
|
+
|
|
421
|
+
The `SessionPathwayBuilder` provides a way to associate session IDs with pathway operations, making it easier to track and manage user sessions in your application.
|
|
422
|
+
|
|
423
|
+
#### Setting Up Session Support
|
|
424
|
+
|
|
425
|
+
To use session-specific functionality, first configure your `PathwaysBuilder` with session support:
|
|
426
|
+
|
|
427
|
+
```typescript
|
|
428
|
+
import { PathwaysBuilder, createKvAdapter } from "@flowcore/pathways";
|
|
429
|
+
|
|
430
|
+
// Create a KV adapter for storing session information
|
|
431
|
+
const sessionStore = await createKvAdapter();
|
|
432
|
+
|
|
433
|
+
// Configure the builder with session support
|
|
434
|
+
const pathways = new PathwaysBuilder({
|
|
435
|
+
baseUrl: "https://api.flowcore.io",
|
|
436
|
+
tenant: "your-tenant",
|
|
437
|
+
dataCore: "your-data-core",
|
|
438
|
+
apiKey: "your-api-key",
|
|
439
|
+
sessionUserResolvers: sessionStore // Enable session-specific resolvers
|
|
440
|
+
});
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
#### Creating Session Pathways
|
|
444
|
+
|
|
445
|
+
Create a session-specific pathway wrapper:
|
|
446
|
+
|
|
447
|
+
```typescript
|
|
448
|
+
import { SessionPathwayBuilder } from "@flowcore/pathways";
|
|
449
|
+
|
|
450
|
+
// Create a session with an auto-generated session ID
|
|
451
|
+
const session = new SessionPathwayBuilder(pathways);
|
|
452
|
+
const sessionId = session.getSessionId(); // Get the auto-generated ID
|
|
453
|
+
|
|
454
|
+
// Or create a session with a specific session ID
|
|
455
|
+
const customSession = new SessionPathwayBuilder(pathways, "user-session-123");
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
#### Session-Specific User Resolvers
|
|
459
|
+
|
|
460
|
+
You can register different user resolvers for different sessions, allowing you to associate users with specific sessions:
|
|
461
|
+
|
|
462
|
+
```typescript
|
|
463
|
+
// Register a user resolver for a specific session
|
|
464
|
+
pathways.withSessionUserResolver("user-session-123", async () => {
|
|
465
|
+
// Return the user ID for this session
|
|
466
|
+
return "user-456";
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
// Alternative: Register directly through the session instance
|
|
470
|
+
session.withUserResolver(async () => {
|
|
471
|
+
return "user-789";
|
|
472
|
+
});
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
#### Writing Events with Session Context
|
|
476
|
+
|
|
477
|
+
Events written through a session builder automatically include the session ID:
|
|
478
|
+
|
|
479
|
+
```typescript
|
|
480
|
+
// Write an event with session context
|
|
481
|
+
await session.write("order/placed", {
|
|
482
|
+
orderId: "ord-123",
|
|
483
|
+
userId: "user-456",
|
|
484
|
+
total: 99.99,
|
|
485
|
+
items: [{ id: "item-1", quantity: 2 }]
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
// You can override the session ID for a specific write
|
|
489
|
+
await session.write(
|
|
490
|
+
"order/placed",
|
|
491
|
+
orderData,
|
|
492
|
+
{}, // No metadata
|
|
493
|
+
{ sessionId: "different-session" }
|
|
494
|
+
);
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
#### Session ID in Audit Events
|
|
498
|
+
|
|
499
|
+
When auditing is enabled, the session ID is included in the audit metadata:
|
|
500
|
+
|
|
501
|
+
```typescript
|
|
502
|
+
// Enable auditing
|
|
503
|
+
pathways.withAudit((path, event) => {
|
|
504
|
+
console.log(`Audit: ${path} event ${event.eventId}`);
|
|
505
|
+
// The session ID will be included in event metadata
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
// Now when writing events through a session
|
|
509
|
+
await session.write("order/placed", orderData);
|
|
510
|
+
// The session ID is automatically included in the audit metadata
|
|
511
|
+
```
|
|
512
|
+
|
|
418
513
|
## API Reference
|
|
419
514
|
|
|
420
515
|
For a complete API reference, please see the [API documentation](https://jsr.io/@flowcore/pathways).
|
|
@@ -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
|
/**
|
|
@@ -62,6 +63,7 @@ export declare class PathwaysBuilder<TPathway extends Record<string, unknown> =
|
|
|
62
63
|
private pathwayTimeoutMs;
|
|
63
64
|
private auditHandler?;
|
|
64
65
|
private userIdResolver?;
|
|
66
|
+
private readonly sessionUserResolvers;
|
|
65
67
|
private readonly logger;
|
|
66
68
|
private readonly baseUrl;
|
|
67
69
|
private readonly tenant;
|
|
@@ -76,14 +78,16 @@ export declare class PathwaysBuilder<TPathway extends Record<string, unknown> =
|
|
|
76
78
|
* @param options.apiKey The API key for authentication
|
|
77
79
|
* @param options.pathwayTimeoutMs Optional timeout for pathway processing in milliseconds
|
|
78
80
|
* @param options.logger Optional logger instance
|
|
81
|
+
* @param options.sessionUserResolvers Optional KvAdapter instance for session-specific user resolvers
|
|
79
82
|
*/
|
|
80
|
-
constructor({ baseUrl, tenant, dataCore, apiKey, pathwayTimeoutMs, logger, }: {
|
|
83
|
+
constructor({ baseUrl, tenant, dataCore, apiKey, pathwayTimeoutMs, logger, sessionUserResolvers, }: {
|
|
81
84
|
baseUrl: string;
|
|
82
85
|
tenant: string;
|
|
83
86
|
dataCore: string;
|
|
84
87
|
apiKey: string;
|
|
85
88
|
pathwayTimeoutMs?: number;
|
|
86
89
|
logger?: Logger;
|
|
90
|
+
sessionUserResolvers?: KvAdapter;
|
|
87
91
|
});
|
|
88
92
|
/**
|
|
89
93
|
* Configures the PathwaysBuilder to use a custom pathway state implementation
|
|
@@ -103,6 +107,46 @@ export declare class PathwaysBuilder<TPathway extends Record<string, unknown> =
|
|
|
103
107
|
* @returns The PathwaysBuilder instance with custom user ID resolver configured
|
|
104
108
|
*/
|
|
105
109
|
withUserResolver(resolver: UserIdResolver): PathwaysBuilder<TPathway, TWritablePaths>;
|
|
110
|
+
/**
|
|
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
|
+
*
|
|
124
|
+
* @param sessionId The session ID to associate with this resolver
|
|
125
|
+
* @param resolver The resolver function that resolves to the user ID for this session
|
|
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
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
withSessionUserResolver(sessionId: string, resolver: UserIdResolver): PathwaysBuilder<TPathway, TWritablePaths>;
|
|
144
|
+
/**
|
|
145
|
+
* Gets a user resolver for a specific session ID
|
|
146
|
+
* @param sessionId The session ID to get the resolver for
|
|
147
|
+
* @returns The resolver function for the session, or undefined if none exists
|
|
148
|
+
*/
|
|
149
|
+
getSessionUserResolver(sessionId: string): UserIdResolver | undefined;
|
|
106
150
|
/**
|
|
107
151
|
* Process a pathway event with error handling and retries
|
|
108
152
|
* @param pathway The pathway to process
|
|
@@ -189,10 +233,5 @@ export declare class PathwaysBuilder<TPathway extends Record<string, unknown> =
|
|
|
189
233
|
* @throws Error if the timeout is exceeded
|
|
190
234
|
*/
|
|
191
235
|
private waitForPathwayToBeProcessed;
|
|
192
|
-
/**
|
|
193
|
-
* Creates a new instance of PathwaysBuilder with the same configuration
|
|
194
|
-
* @returns A new PathwaysBuilder instance with the same type parameters and configuration
|
|
195
|
-
*/
|
|
196
|
-
clone(): PathwaysBuilder<TPathway, TWritablePaths>;
|
|
197
236
|
}
|
|
198
237
|
//# sourceMappingURL=builder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/pathways/builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAExD,OAAO,KAAK,EAAyD,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AAG/H,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAE1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,mBAAmB,EAA6B,eAAe,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/pathways/builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAExD,OAAO,KAAK,EAAyD,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AAG/H,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAE1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AACnD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,mBAAmB,EAA6B,eAAe,EAAE,MAAM,YAAY,CAAA;AAsB3J;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAA;AAEzC;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,KAAK,IAAI,CAAA;AAEvE;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;AAElD;;GAEG;AACH,MAAM,WAAW,uBAAwB,SAAQ,kBAAkB;IACjE;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACjC;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,eAAe,CAE1B,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,EAC7C,cAAc,SAAS,MAAM,QAAQ,GAAG,KAAK;IAE7C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2B;IACpD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAGxB;IACD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAGhC;IACD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAG9B;IACD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAG9B;IACD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAyE;IAC5G,OAAO,CAAC,QAAQ,CAAC,OAAO,CAGvB;IACD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyE;IACjG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAyE;IAClG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuE;IAChG,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuE;IAClG,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuE;IACnG,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAiC;IAC9D,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAA0B;IAChE,OAAO,CAAC,YAAY,CAA2C;IAC/D,OAAO,CAAC,gBAAgB,CAAqC;IAG7D,OAAO,CAAC,YAAY,CAAC,CAAc;IACnC,OAAO,CAAC,cAAc,CAAC,CAAgB;IAGvC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAyB;IAG9D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;IAG/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAQ;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;IAC/B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;IAE/B;;;;;;;;;;OAUG;gBACS,EACV,OAAO,EACP,MAAM,EACN,QAAQ,EACR,MAAM,EACN,gBAAgB,EAChB,MAAM,EACN,oBAAoB,GACrB,EAAE;QACD,OAAO,EAAE,MAAM,CAAA;QACf,MAAM,EAAE,MAAM,CAAA;QACd,QAAQ,EAAE,MAAM,CAAA;QAChB,MAAM,EAAE,MAAM,CAAA;QACd,gBAAgB,CAAC,EAAE,MAAM,CAAA;QACzB,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,oBAAoB,CAAC,EAAE,SAAS,CAAA;KACjC;IAsCD;;;;OAIG;IACH,gBAAgB,CAAC,KAAK,EAAE,YAAY,GAAG,eAAe,CAAC,QAAQ,EAAE,cAAc,CAAC;IAMhF;;;;OAIG;IACH,SAAS,CAAC,OAAO,EAAE,YAAY,GAAG,eAAe,CAAC,QAAQ,EAAE,cAAc,CAAC;IAM3E;;;;OAIG;IACH,gBAAgB,CAAC,QAAQ,EAAE,cAAc,GAAG,eAAe,CAAC,QAAQ,EAAE,cAAc,CAAC;IAMrF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;IACH,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,eAAe,CAAC,QAAQ,EAAE,cAAc,CAAC;IAU/G;;;;OAIG;IACH,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAQrE;;;;;OAKG;IACU,OAAO,CAAC,OAAO,EAAE,MAAM,QAAQ,EAAE,IAAI,EAAE,aAAa;IA6IjE;;;;;;;;OAQG;IACH,QAAQ,CACN,CAAC,SAAS,MAAM,EAChB,CAAC,SAAS,MAAM,EAChB,CAAC,SAAS,OAAO,EACjB,CAAC,SAAS,OAAO,GAAG,IAAI,EAExB,QAAQ,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG;QAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,GAChG,eAAe,CAChB,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAC9C,cAAc,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CACtD;IA4DD;;;;;;OAMG;IACH,GAAG,CAAC,KAAK,SAAS,MAAM,QAAQ,EAAE,IAAI,EAAE,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;IAK/D;;;;;;;;;;OAUG;IACH,MAAM,CAAC,KAAK,SAAS,MAAM,QAAQ,EACjC,IAAI,EAAE,KAAK,EACX,OAAO,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,SAAS,CAAC,GAAG;QAAE,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAA;KAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GACxG,IAAI;IAqBP;;;;;OAKG;IACH,SAAS,CAAC,KAAK,SAAS,MAAM,QAAQ,EACpC,IAAI,EAAE,KAAK,EACX,OAAO,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,SAAS,CAAC,GAAG;QAAE,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAA;KAAE,KAAK,IAAI,EACvF,IAAI,GAAE,QAAQ,GAAG,OAAO,GAAG,KAAgB,GAC1C,IAAI;IA4BP;;;;OAIG;IACH,OAAO,CAAC,KAAK,SAAS,MAAM,QAAQ,EAClC,IAAI,EAAE,KAAK,EACX,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,SAAS,CAAC,GAAG;QAAE,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAA;KAAE,KAAK,IAAI,GACpG,IAAI;IAmBP;;;OAGG;IACH,UAAU,CACR,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,GACrE,IAAI;IAMP;;;;;;;OAOG;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;IAuH7B;;;;;;;;;;OAUG;YACW,2BAA2B;CA4C1C"}
|
package/esm/pathways/builder.js
CHANGED
|
@@ -15,6 +15,10 @@ const DEFAULT_MAX_RETRIES = 3;
|
|
|
15
15
|
* Default delay between retry attempts in milliseconds
|
|
16
16
|
*/
|
|
17
17
|
const DEFAULT_RETRY_DELAY_MS = 500;
|
|
18
|
+
/**
|
|
19
|
+
* Default TTL for session-specific user resolvers in milliseconds (10seconds)
|
|
20
|
+
*/
|
|
21
|
+
const DEFAULT_SESSION_USER_RESOLVER_TTL_MS = 10 * 1000;
|
|
18
22
|
/**
|
|
19
23
|
* Main builder class for creating and managing Flowcore pathways
|
|
20
24
|
*
|
|
@@ -39,8 +43,9 @@ export class PathwaysBuilder {
|
|
|
39
43
|
* @param options.apiKey The API key for authentication
|
|
40
44
|
* @param options.pathwayTimeoutMs Optional timeout for pathway processing in milliseconds
|
|
41
45
|
* @param options.logger Optional logger instance
|
|
46
|
+
* @param options.sessionUserResolvers Optional KvAdapter instance for session-specific user resolvers
|
|
42
47
|
*/
|
|
43
|
-
constructor({ baseUrl, tenant, dataCore, apiKey, pathwayTimeoutMs, logger, }) {
|
|
48
|
+
constructor({ baseUrl, tenant, dataCore, apiKey, pathwayTimeoutMs, logger, sessionUserResolvers, }) {
|
|
44
49
|
Object.defineProperty(this, "pathways", {
|
|
45
50
|
enumerable: true,
|
|
46
51
|
configurable: true,
|
|
@@ -150,6 +155,13 @@ export class PathwaysBuilder {
|
|
|
150
155
|
writable: true,
|
|
151
156
|
value: void 0
|
|
152
157
|
});
|
|
158
|
+
// Session-specific user resolvers
|
|
159
|
+
Object.defineProperty(this, "sessionUserResolvers", {
|
|
160
|
+
enumerable: true,
|
|
161
|
+
configurable: true,
|
|
162
|
+
writable: true,
|
|
163
|
+
value: null
|
|
164
|
+
});
|
|
153
165
|
// Logger instance (but not using it yet due to TypeScript errors)
|
|
154
166
|
Object.defineProperty(this, "logger", {
|
|
155
167
|
enumerable: true,
|
|
@@ -189,6 +201,9 @@ export class PathwaysBuilder {
|
|
|
189
201
|
this.tenant = tenant;
|
|
190
202
|
this.dataCore = dataCore;
|
|
191
203
|
this.apiKey = apiKey;
|
|
204
|
+
if (sessionUserResolvers) {
|
|
205
|
+
this.sessionUserResolvers = sessionUserResolvers;
|
|
206
|
+
}
|
|
192
207
|
this.logger.debug('Initializing PathwaysBuilder', {
|
|
193
208
|
baseUrl,
|
|
194
209
|
tenant,
|
|
@@ -240,6 +255,59 @@ export class PathwaysBuilder {
|
|
|
240
255
|
this.userIdResolver = resolver;
|
|
241
256
|
return this;
|
|
242
257
|
}
|
|
258
|
+
/**
|
|
259
|
+
* Registers a user resolver for a specific session
|
|
260
|
+
*
|
|
261
|
+
* Session-specific user resolvers allow you to associate different user IDs with different
|
|
262
|
+
* sessions, which is useful in multi-user applications or when tracking user actions across
|
|
263
|
+
* different sessions.
|
|
264
|
+
*
|
|
265
|
+
* The resolver is stored in a key-value store with a TTL (time to live), and will be used
|
|
266
|
+
* to resolve the user ID when operations are performed with the given session ID. If the resolver
|
|
267
|
+
* expires, it will need to be registered again.
|
|
268
|
+
*
|
|
269
|
+
* This feature works in conjunction with the SessionPathwayBuilder to provide a complete
|
|
270
|
+
* session management solution.
|
|
271
|
+
*
|
|
272
|
+
* @param sessionId The session ID to associate with this resolver
|
|
273
|
+
* @param resolver The resolver function that resolves to the user ID for this session
|
|
274
|
+
* @returns The PathwaysBuilder instance for chaining
|
|
275
|
+
*
|
|
276
|
+
* @throws Error if session user resolvers are not configured (sessionUserResolvers not provided in constructor)
|
|
277
|
+
*
|
|
278
|
+
* @example
|
|
279
|
+
* ```typescript
|
|
280
|
+
* // Register a resolver for a specific session
|
|
281
|
+
* pathwaysBuilder.withSessionUserResolver("session-123", async () => {
|
|
282
|
+
* return "user-456"; // Return the user ID for this session
|
|
283
|
+
* });
|
|
284
|
+
*
|
|
285
|
+
* // Use with SessionPathwayBuilder
|
|
286
|
+
* const session = new SessionPathwayBuilder(pathwaysBuilder, "session-123");
|
|
287
|
+
* await session.write("user/action", actionData);
|
|
288
|
+
* // The user ID will be automatically included in the metadata
|
|
289
|
+
* ```
|
|
290
|
+
*/
|
|
291
|
+
withSessionUserResolver(sessionId, resolver) {
|
|
292
|
+
if (!this.sessionUserResolvers) {
|
|
293
|
+
throw new Error('Session user resolvers not configured');
|
|
294
|
+
}
|
|
295
|
+
this.logger.debug('Configuring session-specific user resolver', { sessionId });
|
|
296
|
+
this.sessionUserResolvers.set(sessionId, resolver, DEFAULT_SESSION_USER_RESOLVER_TTL_MS);
|
|
297
|
+
return this;
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Gets a user resolver for a specific session ID
|
|
301
|
+
* @param sessionId The session ID to get the resolver for
|
|
302
|
+
* @returns The resolver function for the session, or undefined if none exists
|
|
303
|
+
*/
|
|
304
|
+
getSessionUserResolver(sessionId) {
|
|
305
|
+
if (!this.sessionUserResolvers) {
|
|
306
|
+
return undefined;
|
|
307
|
+
}
|
|
308
|
+
const resolver = this.sessionUserResolvers.get(sessionId);
|
|
309
|
+
return resolver;
|
|
310
|
+
}
|
|
243
311
|
/**
|
|
244
312
|
* Process a pathway event with error handling and retries
|
|
245
313
|
* @param pathway The pathway to process
|
|
@@ -534,7 +602,8 @@ export class PathwaysBuilder {
|
|
|
534
602
|
pathway: pathStr,
|
|
535
603
|
metadata,
|
|
536
604
|
options: {
|
|
537
|
-
fireAndForget: options?.fireAndForget
|
|
605
|
+
fireAndForget: options?.fireAndForget,
|
|
606
|
+
sessionId: options?.sessionId
|
|
538
607
|
}
|
|
539
608
|
});
|
|
540
609
|
if (!this.pathways[path]) {
|
|
@@ -558,17 +627,43 @@ export class PathwaysBuilder {
|
|
|
558
627
|
}
|
|
559
628
|
// Create a copy of the metadata to avoid modifying the original
|
|
560
629
|
const finalMetadata = metadata ? { ...metadata } : {};
|
|
630
|
+
// Check for session-specific user resolver
|
|
631
|
+
let userId;
|
|
632
|
+
if (options?.sessionId) {
|
|
633
|
+
const sessionUserResolver = this.getSessionUserResolver(options.sessionId);
|
|
634
|
+
if (sessionUserResolver) {
|
|
635
|
+
try {
|
|
636
|
+
userId = await sessionUserResolver();
|
|
637
|
+
this.logger.debug(`Using session-specific user resolver`, {
|
|
638
|
+
pathway: pathStr,
|
|
639
|
+
sessionId: options.sessionId,
|
|
640
|
+
userId
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
catch (error) {
|
|
644
|
+
this.logger.error(`Error resolving session user ID`, error instanceof Error ? error : new Error(String(error)), {
|
|
645
|
+
pathway: pathStr,
|
|
646
|
+
sessionId: options.sessionId
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
}
|
|
561
651
|
// Process audit metadata if audit is configured
|
|
562
652
|
if (this.userIdResolver) {
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
653
|
+
// Only use global resolver if we don't already have a user ID from a session resolver
|
|
654
|
+
if (!userId) {
|
|
655
|
+
this.logger.debug(`Resolving user ID for audit metadata`, { pathway: pathStr });
|
|
656
|
+
userId = await this.userIdResolver();
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
// Determine the audit mode: default is "user" unless explicitly specified as "system"
|
|
660
|
+
const auditMode = options?.auditMode ?? "user";
|
|
661
|
+
this.logger.debug(`Adding audit metadata`, {
|
|
662
|
+
pathway: pathStr,
|
|
663
|
+
auditMode,
|
|
664
|
+
userId
|
|
665
|
+
});
|
|
666
|
+
if (userId) {
|
|
572
667
|
// Add appropriate audit metadata based on mode
|
|
573
668
|
if (auditMode === "system") {
|
|
574
669
|
finalMetadata["audit/user-id"] = "system";
|
|
@@ -654,36 +749,4 @@ export class PathwaysBuilder {
|
|
|
654
749
|
attempts
|
|
655
750
|
});
|
|
656
751
|
}
|
|
657
|
-
/**
|
|
658
|
-
* Creates a new instance of PathwaysBuilder with the same configuration
|
|
659
|
-
* @returns A new PathwaysBuilder instance with the same type parameters and configuration
|
|
660
|
-
*/
|
|
661
|
-
clone() {
|
|
662
|
-
this.logger.debug('Building new PathwaysBuilder instance with same configuration');
|
|
663
|
-
// Create new instance with same base configuration
|
|
664
|
-
const builder = new PathwaysBuilder({
|
|
665
|
-
baseUrl: this.baseUrl,
|
|
666
|
-
tenant: this.tenant,
|
|
667
|
-
dataCore: this.dataCore,
|
|
668
|
-
apiKey: this.apiKey,
|
|
669
|
-
pathwayTimeoutMs: this.pathwayTimeoutMs,
|
|
670
|
-
logger: this.logger
|
|
671
|
-
});
|
|
672
|
-
// Copy pathway state configuration if custom
|
|
673
|
-
if (!(this.pathwayState instanceof InternalPathwayState)) {
|
|
674
|
-
builder.withPathwayState(this.pathwayState);
|
|
675
|
-
}
|
|
676
|
-
// Copy audit configuration if present
|
|
677
|
-
if (this.auditHandler) {
|
|
678
|
-
builder.withAudit(this.auditHandler);
|
|
679
|
-
}
|
|
680
|
-
// Copy user resolver if present
|
|
681
|
-
if (this.userIdResolver) {
|
|
682
|
-
builder.withUserResolver(this.userIdResolver);
|
|
683
|
-
}
|
|
684
|
-
// The new instance will have the same type parameters but
|
|
685
|
-
// it will be empty of pathways until they are registered again
|
|
686
|
-
this.logger.info('New PathwaysBuilder instance created');
|
|
687
|
-
return builder;
|
|
688
|
-
}
|
|
689
752
|
}
|
package/esm/pathways/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Exports all components needed to build and manage pathways including:
|
|
5
5
|
* - Pathway builder
|
|
6
|
+
* - Session pathway builder
|
|
6
7
|
* - State management
|
|
7
8
|
* - Storage adapters (KV, Postgres)
|
|
8
9
|
* - Logging
|
|
@@ -15,5 +16,6 @@ export * from "./internal-pathway.state.js";
|
|
|
15
16
|
export * from "./kv/kv-adapter.js";
|
|
16
17
|
export * from "./logger.js";
|
|
17
18
|
export * from "./postgres/index.js";
|
|
19
|
+
export * from "./session-pathway.js";
|
|
18
20
|
export * from "./types.js";
|
|
19
21
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/pathways/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/pathways/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,cAAc,cAAc,CAAC;AAC7B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,YAAY,CAAC"}
|
package/esm/pathways/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Exports all components needed to build and manage pathways including:
|
|
5
5
|
* - Pathway builder
|
|
6
|
+
* - Session pathway builder
|
|
6
7
|
* - State management
|
|
7
8
|
* - Storage adapters (KV, Postgres)
|
|
8
9
|
* - Logging
|
|
@@ -15,4 +16,5 @@ export * from "./internal-pathway.state.js";
|
|
|
15
16
|
export * from "./kv/kv-adapter.js";
|
|
16
17
|
export * from "./logger.js";
|
|
17
18
|
export * from "./postgres/index.js";
|
|
19
|
+
export * from "./session-pathway.js";
|
|
18
20
|
export * from "./types.js";
|
|
@@ -2,7 +2,34 @@
|
|
|
2
2
|
* Interface for key-value storage adapters
|
|
3
3
|
*
|
|
4
4
|
* Provides a common interface for different KV storage implementations
|
|
5
|
-
* that can be used for storing pathway state.
|
|
5
|
+
* that can be used for storing pathway state and other application data.
|
|
6
|
+
*
|
|
7
|
+
* This interface abstracts away the details of specific storage backends,
|
|
8
|
+
* allowing the application to work with different storage providers
|
|
9
|
+
* without changing the core logic.
|
|
10
|
+
*
|
|
11
|
+
* The Flowcore Pathways library includes several implementations of this interface:
|
|
12
|
+
* - BunKvAdapter: Uses Bun's built-in KV store
|
|
13
|
+
* - NodeKvAdapter: Uses node-cache for in-memory storage
|
|
14
|
+
* - DenoKvAdapter: Uses Deno's KV store (when available)
|
|
15
|
+
*
|
|
16
|
+
* Custom implementations can be created for other storage backends
|
|
17
|
+
* by implementing this interface.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* // Create a KV adapter
|
|
22
|
+
* const store = await createKvAdapter();
|
|
23
|
+
*
|
|
24
|
+
* // Store a value with a TTL
|
|
25
|
+
* await store.set("session:123", { userId: "user-456" }, 3600000); // 1 hour TTL
|
|
26
|
+
*
|
|
27
|
+
* // Retrieve the value
|
|
28
|
+
* const session = await store.get<{ userId: string }>("session:123");
|
|
29
|
+
* if (session) {
|
|
30
|
+
* console.log("User ID:", session.userId);
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
6
33
|
*/
|
|
7
34
|
export interface KvAdapter {
|
|
8
35
|
/**
|
|
@@ -26,9 +53,39 @@ export interface KvAdapter {
|
|
|
26
53
|
/**
|
|
27
54
|
* Creates an appropriate KV adapter based on the runtime environment
|
|
28
55
|
*
|
|
29
|
-
*
|
|
56
|
+
* This function automatically detects the current runtime environment and creates
|
|
57
|
+
* the most suitable KV adapter implementation:
|
|
58
|
+
*
|
|
59
|
+
* - In Bun: Returns a BunKvAdapter using Bun's built-in KV store
|
|
60
|
+
* - In Deno with KV access: Returns a DenoKvAdapter
|
|
61
|
+
* - Otherwise: Returns a NodeKvAdapter using an in-memory cache
|
|
62
|
+
*
|
|
63
|
+
* Using this factory function rather than directly instantiating a specific adapter
|
|
64
|
+
* implementation makes your code more portable across different JavaScript runtimes.
|
|
65
|
+
*
|
|
66
|
+
* The adapter is lazily initialized, so any necessary setup only happens when
|
|
67
|
+
* you first interact with the adapter.
|
|
30
68
|
*
|
|
31
69
|
* @returns A KV adapter instance for the current runtime
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* // Create a runtime-specific KV adapter
|
|
74
|
+
* const kv = await createKvAdapter();
|
|
75
|
+
*
|
|
76
|
+
* // Use with PathwaysBuilder for session user resolvers
|
|
77
|
+
* const pathways = new PathwaysBuilder({
|
|
78
|
+
* baseUrl: "https://api.flowcore.io",
|
|
79
|
+
* tenant: "my-tenant",
|
|
80
|
+
* dataCore: "my-data-core",
|
|
81
|
+
* apiKey: "my-api-key",
|
|
82
|
+
* sessionUserResolvers: kv
|
|
83
|
+
* });
|
|
84
|
+
*
|
|
85
|
+
* // Use as a general-purpose key-value store
|
|
86
|
+
* await kv.set("cache:user:123", userData, 60 * 60 * 1000); // 1 hour TTL
|
|
87
|
+
* const cachedUser = await kv.get("cache:user:123");
|
|
88
|
+
* ```
|
|
32
89
|
*/
|
|
33
90
|
export declare function createKvAdapter(): Promise<KvAdapter>;
|
|
34
91
|
//# sourceMappingURL=kv-adapter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kv-adapter.d.ts","sourceRoot":"","sources":["../../../src/pathways/kv/kv-adapter.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"kv-adapter.d.ts","sourceRoot":"","sources":["../../../src/pathways/kv/kv-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,WAAW,SAAS;IACxB;;;;;;OAMG;IACH,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IAEpD;;;;;;;OAOG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;CACzE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,SAAS,CAAC,CAU1D"}
|
|
@@ -1,9 +1,39 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Creates an appropriate KV adapter based on the runtime environment
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* This function automatically detects the current runtime environment and creates
|
|
5
|
+
* the most suitable KV adapter implementation:
|
|
6
|
+
*
|
|
7
|
+
* - In Bun: Returns a BunKvAdapter using Bun's built-in KV store
|
|
8
|
+
* - In Deno with KV access: Returns a DenoKvAdapter
|
|
9
|
+
* - Otherwise: Returns a NodeKvAdapter using an in-memory cache
|
|
10
|
+
*
|
|
11
|
+
* Using this factory function rather than directly instantiating a specific adapter
|
|
12
|
+
* implementation makes your code more portable across different JavaScript runtimes.
|
|
13
|
+
*
|
|
14
|
+
* The adapter is lazily initialized, so any necessary setup only happens when
|
|
15
|
+
* you first interact with the adapter.
|
|
5
16
|
*
|
|
6
17
|
* @returns A KV adapter instance for the current runtime
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* // Create a runtime-specific KV adapter
|
|
22
|
+
* const kv = await createKvAdapter();
|
|
23
|
+
*
|
|
24
|
+
* // Use with PathwaysBuilder for session user resolvers
|
|
25
|
+
* const pathways = new PathwaysBuilder({
|
|
26
|
+
* baseUrl: "https://api.flowcore.io",
|
|
27
|
+
* tenant: "my-tenant",
|
|
28
|
+
* dataCore: "my-data-core",
|
|
29
|
+
* apiKey: "my-api-key",
|
|
30
|
+
* sessionUserResolvers: kv
|
|
31
|
+
* });
|
|
32
|
+
*
|
|
33
|
+
* // Use as a general-purpose key-value store
|
|
34
|
+
* await kv.set("cache:user:123", userData, 60 * 60 * 1000); // 1 hour TTL
|
|
35
|
+
* const cachedUser = await kv.get("cache:user:123");
|
|
36
|
+
* ```
|
|
7
37
|
*/
|
|
8
38
|
export async function createKvAdapter() {
|
|
9
39
|
try {
|