@hotmeshio/hotmesh 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/README.md +38 -23
  2. package/build/index.d.ts +12 -11
  3. package/build/index.js +15 -13
  4. package/build/modules/enums.d.ts +23 -34
  5. package/build/modules/enums.js +26 -38
  6. package/build/modules/errors.d.ts +16 -16
  7. package/build/modules/errors.js +37 -37
  8. package/build/package.json +23 -22
  9. package/build/services/activities/activity.js +1 -1
  10. package/build/services/dba/index.d.ts +171 -0
  11. package/build/services/dba/index.js +280 -0
  12. package/build/services/{memflow → durable}/client.d.ts +3 -3
  13. package/build/services/{memflow → durable}/client.js +13 -13
  14. package/build/services/{memflow → durable}/connection.d.ts +2 -2
  15. package/build/services/{memflow → durable}/connection.js +1 -1
  16. package/build/services/{memflow → durable}/exporter.d.ts +6 -6
  17. package/build/services/{memflow → durable}/exporter.js +2 -2
  18. package/build/services/{memflow → durable}/handle.d.ts +4 -4
  19. package/build/services/{memflow → durable}/handle.js +2 -2
  20. package/build/services/{memflow → durable}/index.d.ts +125 -33
  21. package/build/services/{memflow → durable}/index.js +145 -49
  22. package/build/services/{memflow → durable}/interceptor.d.ts +45 -22
  23. package/build/services/{memflow → durable}/interceptor.js +54 -21
  24. package/build/services/{memflow → durable}/schemas/factory.d.ts +4 -4
  25. package/build/services/{memflow → durable}/schemas/factory.js +5 -5
  26. package/build/services/{memflow → durable}/search.d.ts +1 -1
  27. package/build/services/{memflow → durable}/search.js +4 -4
  28. package/build/services/{memflow → durable}/worker.d.ts +11 -11
  29. package/build/services/{memflow → durable}/worker.js +61 -60
  30. package/build/services/{memflow → durable}/workflow/all.d.ts +5 -5
  31. package/build/services/{memflow → durable}/workflow/all.js +5 -5
  32. package/build/services/{memflow → durable}/workflow/common.d.ts +5 -5
  33. package/build/services/durable/workflow/common.js +47 -0
  34. package/build/services/{memflow → durable}/workflow/context.d.ts +5 -5
  35. package/build/services/{memflow → durable}/workflow/context.js +5 -5
  36. package/build/services/{memflow → durable}/workflow/emit.d.ts +5 -5
  37. package/build/services/{memflow → durable}/workflow/emit.js +5 -5
  38. package/build/services/{memflow → durable}/workflow/enrich.d.ts +4 -4
  39. package/build/services/{memflow → durable}/workflow/enrich.js +4 -4
  40. package/build/services/{memflow → durable}/workflow/entityMethods.d.ts +4 -4
  41. package/build/services/{memflow → durable}/workflow/entityMethods.js +4 -4
  42. package/build/services/{memflow → durable}/workflow/execChild.d.ts +9 -9
  43. package/build/services/{memflow → durable}/workflow/execChild.js +22 -22
  44. package/build/services/{memflow → durable}/workflow/execHook.d.ts +8 -8
  45. package/build/services/{memflow → durable}/workflow/execHook.js +10 -10
  46. package/build/services/{memflow → durable}/workflow/execHookBatch.d.ts +5 -5
  47. package/build/services/{memflow → durable}/workflow/execHookBatch.js +8 -8
  48. package/build/services/{memflow → durable}/workflow/hook.d.ts +5 -5
  49. package/build/services/{memflow → durable}/workflow/hook.js +11 -11
  50. package/build/services/{memflow → durable}/workflow/index.d.ts +6 -6
  51. package/build/services/{memflow → durable}/workflow/index.js +6 -6
  52. package/build/services/{memflow → durable}/workflow/interrupt.d.ts +7 -7
  53. package/build/services/{memflow → durable}/workflow/interrupt.js +7 -7
  54. package/build/services/{memflow → durable}/workflow/interruption.d.ts +10 -10
  55. package/build/services/{memflow → durable}/workflow/interruption.js +19 -19
  56. package/build/services/{memflow → durable}/workflow/proxyActivities.d.ts +7 -7
  57. package/build/services/{memflow → durable}/workflow/proxyActivities.js +31 -21
  58. package/build/services/{memflow → durable}/workflow/random.d.ts +4 -4
  59. package/build/services/{memflow → durable}/workflow/random.js +4 -4
  60. package/build/services/{memflow → durable}/workflow/searchMethods.d.ts +5 -5
  61. package/build/services/{memflow → durable}/workflow/searchMethods.js +5 -5
  62. package/build/services/{memflow → durable}/workflow/signal.d.ts +8 -8
  63. package/build/services/{memflow → durable}/workflow/signal.js +8 -8
  64. package/build/services/{memflow → durable}/workflow/sleepFor.d.ts +7 -7
  65. package/build/services/{memflow → durable}/workflow/sleepFor.js +10 -10
  66. package/build/services/{memflow → durable}/workflow/trace.d.ts +5 -5
  67. package/build/services/{memflow → durable}/workflow/trace.js +5 -5
  68. package/build/services/{memflow → durable}/workflow/waitFor.d.ts +9 -9
  69. package/build/services/{memflow → durable}/workflow/waitFor.js +12 -12
  70. package/build/services/hotmesh/index.d.ts +3 -3
  71. package/build/services/hotmesh/index.js +3 -3
  72. package/build/services/{meshcall → virtual}/index.d.ts +29 -29
  73. package/build/services/{meshcall → virtual}/index.js +49 -49
  74. package/build/services/{meshcall → virtual}/schemas/factory.d.ts +1 -1
  75. package/build/services/{meshcall → virtual}/schemas/factory.js +1 -1
  76. package/build/types/dba.d.ts +64 -0
  77. package/build/types/{memflow.d.ts → durable.d.ts} +74 -18
  78. package/build/types/error.d.ts +5 -5
  79. package/build/types/exporter.d.ts +1 -1
  80. package/build/types/index.d.ts +5 -4
  81. package/build/types/{meshcall.d.ts → virtual.d.ts} +15 -15
  82. package/build/types/virtual.js +2 -0
  83. package/index.ts +15 -13
  84. package/package.json +23 -22
  85. package/.claude/settings.local.json +0 -8
  86. package/build/services/memflow/workflow/common.js +0 -47
  87. package/build/vitest.config.d.ts +0 -2
  88. package/build/vitest.config.js +0 -18
  89. /package/build/services/{memflow → durable}/entity.d.ts +0 -0
  90. /package/build/services/{memflow → durable}/entity.js +0 -0
  91. /package/build/services/{memflow → durable}/workflow/didRun.d.ts +0 -0
  92. /package/build/services/{memflow → durable}/workflow/didRun.js +0 -0
  93. /package/build/services/{memflow → durable}/workflow/isSideEffectAllowed.d.ts +0 -0
  94. /package/build/services/{memflow → durable}/workflow/isSideEffectAllowed.js +0 -0
  95. /package/build/types/{memflow.js → dba.js} +0 -0
  96. /package/build/types/{meshcall.js → durable.js} +0 -0
@@ -1,4 +1,4 @@
1
- import { ContextType, WorkflowInterceptor } from '../../types/memflow';
1
+ import { ContextType, WorkflowInterceptor, ActivityInterceptor } from '../../types/durable';
2
2
  import { guid } from '../../modules/utils';
3
3
  import { ClientService } from './client';
4
4
  import { ConnectionService } from './connection';
@@ -9,9 +9,9 @@ import { WorkflowService } from './workflow';
9
9
  import { WorkflowHandleService } from './handle';
10
10
  import { didInterrupt } from './workflow/interruption';
11
11
  /**
12
- * The MemFlow service provides a Temporal-compatible workflow framework backed by
13
- * Postgres. It offers durable execution, entity-based memory management,
14
- * and composable workflows.
12
+ * The Durable service provides a Temporal-compatible workflow framework backed
13
+ * by Postgres. It offers entity-based memory management and composable,
14
+ * fault-tolerant workflows.
15
15
  *
16
16
  * ## Core Features
17
17
  *
@@ -19,7 +19,7 @@ import { didInterrupt } from './workflow/interruption';
19
19
  * Each workflow has a durable JSONB entity that serves as its memory:
20
20
  * ```typescript
21
21
  * export async function researchAgent(query: string) {
22
- * const agent = await MemFlow.workflow.entity();
22
+ * const agent = await Durable.workflow.entity();
23
23
  *
24
24
  * // Initialize entity state
25
25
  * await agent.set({
@@ -38,14 +38,14 @@ import { didInterrupt } from './workflow/interruption';
38
38
  * Spawn and coordinate multiple perspectives/phases:
39
39
  * ```typescript
40
40
  * // Launch parallel research perspectives
41
- * await MemFlow.workflow.execHook({
41
+ * await Durable.workflow.execHook({
42
42
  * taskQueue: 'research',
43
43
  * workflowName: 'optimisticView',
44
44
  * args: [query],
45
45
  * signalId: 'optimistic-complete'
46
46
  * });
47
47
  *
48
- * await MemFlow.workflow.execHook({
48
+ * await Durable.workflow.execHook({
49
49
  * taskQueue: 'research',
50
50
  * workflowName: 'skepticalView',
51
51
  * args: [query],
@@ -54,8 +54,8 @@ import { didInterrupt } from './workflow/interruption';
54
54
  *
55
55
  * // Wait for both perspectives
56
56
  * await Promise.all([
57
- * MemFlow.workflow.waitFor('optimistic-complete'),
58
- * MemFlow.workflow.waitFor('skeptical-complete')
57
+ * Durable.workflow.waitFor('optimistic-complete'),
58
+ * Durable.workflow.waitFor('skeptical-complete')
59
59
  * ]);
60
60
  * ```
61
61
  *
@@ -63,7 +63,7 @@ import { didInterrupt } from './workflow/interruption';
63
63
  * Define and execute durable activities with automatic retry:
64
64
  * ```typescript
65
65
  * // Default: activities use workflow's task queue
66
- * const activities = MemFlow.workflow.proxyActivities<{
66
+ * const activities = Durable.workflow.proxyActivities<{
67
67
  * analyzeDocument: typeof analyzeDocument;
68
68
  * validateFindings: typeof validateFindings;
69
69
  * }>({
@@ -83,7 +83,7 @@ import { didInterrupt } from './workflow/interruption';
83
83
  * Register activity workers explicitly before workflows start:
84
84
  * ```typescript
85
85
  * // Register shared activity pool for interceptors
86
- * await MemFlow.registerActivityWorker({
86
+ * await Durable.registerActivityWorker({
87
87
  * connection: {
88
88
  * class: Postgres,
89
89
  * options: { connectionString: 'postgresql://usr:pwd@localhost:5432/db' }
@@ -92,7 +92,7 @@ import { didInterrupt } from './workflow/interruption';
92
92
  * }, sharedActivities, 'shared-activities');
93
93
  *
94
94
  * // Register custom activity pool for specific use cases
95
- * await MemFlow.registerActivityWorker({
95
+ * await Durable.registerActivityWorker({
96
96
  * connection: {
97
97
  * class: Postgres,
98
98
  * options: { connectionString: 'postgresql://usr:pwd@localhost:5432/db' }
@@ -105,7 +105,7 @@ import { didInterrupt } from './workflow/interruption';
105
105
  * Build complex workflows through composition:
106
106
  * ```typescript
107
107
  * // Start a child workflow
108
- * const childResult = await MemFlow.workflow.execChild({
108
+ * const childResult = await Durable.workflow.execChild({
109
109
  * taskQueue: 'analysis',
110
110
  * workflowName: 'detailedAnalysis',
111
111
  * args: [data],
@@ -117,7 +117,7 @@ import { didInterrupt } from './workflow/interruption';
117
117
  * });
118
118
  *
119
119
  * // Fire-and-forget child workflow
120
- * await MemFlow.workflow.startChild({
120
+ * await Durable.workflow.startChild({
121
121
  * taskQueue: 'notifications',
122
122
  * workflowName: 'sendUpdates',
123
123
  * args: [updates]
@@ -128,7 +128,7 @@ import { didInterrupt } from './workflow/interruption';
128
128
  * Add cross-cutting concerns through interceptors that run as durable functions:
129
129
  * ```typescript
130
130
  * // First register shared activity worker for interceptors
131
- * await MemFlow.registerActivityWorker({
131
+ * await Durable.registerActivityWorker({
132
132
  * connection: {
133
133
  * class: Postgres,
134
134
  * options: { connectionString: 'postgresql://usr:pwd@localhost:5432/db' }
@@ -137,11 +137,11 @@ import { didInterrupt } from './workflow/interruption';
137
137
  * }, { auditLog }, 'interceptor-activities');
138
138
  *
139
139
  * // Add audit interceptor that uses activities with explicit taskQueue
140
- * MemFlow.registerInterceptor({
140
+ * Durable.registerInterceptor({
141
141
  * async execute(ctx, next) {
142
142
  * try {
143
143
  * // Interceptors use explicit taskQueue to prevent per-workflow queues
144
- * const { auditLog } = MemFlow.workflow.proxyActivities<typeof activities>({
144
+ * const { auditLog } = Durable.workflow.proxyActivities<typeof activities>({
145
145
  * activities: { auditLog },
146
146
  * taskQueue: 'interceptor-activities', // Explicit shared queue
147
147
  * retryPolicy: { maximumAttempts: 3 }
@@ -156,7 +156,7 @@ import { didInterrupt } from './workflow/interruption';
156
156
  * return result;
157
157
  * } catch (err) {
158
158
  * // CRITICAL: Always check for HotMesh interruptions
159
- * if (MemFlow.didInterrupt(err)) {
159
+ * if (Durable.didInterrupt(err)) {
160
160
  * throw err; // Rethrow for replay system
161
161
  * }
162
162
  * throw err;
@@ -165,15 +165,71 @@ import { didInterrupt } from './workflow/interruption';
165
165
  * });
166
166
  * ```
167
167
  *
168
+ * ### 7. Activity Interceptors
169
+ * Wrap individual proxied activity calls with cross-cutting logic.
170
+ * Unlike workflow interceptors (which wrap the entire workflow), activity
171
+ * interceptors execute around each `proxyActivities` call. They run inside
172
+ * the workflow's execution context and have access to all Durable workflow
173
+ * methods (`proxyActivities`, `sleepFor`, `waitFor`, `execChild`, etc.).
174
+ * Multiple activity interceptors execute in onion order (first registered
175
+ * is outermost).
176
+ * ```typescript
177
+ * // Simple logging interceptor
178
+ * Durable.registerActivityInterceptor({
179
+ * async execute(activityCtx, workflowCtx, next) {
180
+ * console.log(`Activity ${activityCtx.activityName} starting`);
181
+ * try {
182
+ * const result = await next();
183
+ * console.log(`Activity ${activityCtx.activityName} completed`);
184
+ * return result;
185
+ * } catch (err) {
186
+ * if (Durable.didInterrupt(err)) throw err;
187
+ * console.error(`Activity ${activityCtx.activityName} failed`);
188
+ * throw err;
189
+ * }
190
+ * }
191
+ * });
192
+ *
193
+ * // Interceptor that calls its own proxy activities
194
+ * await Durable.registerActivityWorker({
195
+ * connection: {
196
+ * class: Postgres,
197
+ * options: { connectionString: 'postgresql://usr:pwd@localhost:5432/db' }
198
+ * },
199
+ * taskQueue: 'audit-activities'
200
+ * }, { auditLog }, 'audit-activities');
201
+ *
202
+ * Durable.registerActivityInterceptor({
203
+ * async execute(activityCtx, workflowCtx, next) {
204
+ * try {
205
+ * const { auditLog } = Durable.workflow.proxyActivities<{
206
+ * auditLog: (id: string, action: string) => Promise<void>;
207
+ * }>({
208
+ * taskQueue: 'audit-activities',
209
+ * retryPolicy: { maximumAttempts: 3 }
210
+ * });
211
+ *
212
+ * await auditLog(workflowCtx.get('workflowId'), `before:${activityCtx.activityName}`);
213
+ * const result = await next();
214
+ * await auditLog(workflowCtx.get('workflowId'), `after:${activityCtx.activityName}`);
215
+ * return result;
216
+ * } catch (err) {
217
+ * if (Durable.didInterrupt(err)) throw err;
218
+ * throw err;
219
+ * }
220
+ * }
221
+ * });
222
+ * ```
223
+ *
168
224
  * ## Basic Usage Example
169
225
  *
170
226
  * ```typescript
171
- * import { Client, Worker, MemFlow } from '@hotmeshio/hotmesh';
227
+ * import { Client, Worker, Durable } from '@hotmeshio/hotmesh';
172
228
  * import { Client as Postgres } from 'pg';
173
229
  * import * as activities from './activities';
174
230
  *
175
231
  * // (Optional) Register shared activity workers for interceptors
176
- * await MemFlow.registerActivityWorker({
232
+ * await Durable.registerActivityWorker({
177
233
  * connection: {
178
234
  * class: Postgres,
179
235
  * options: { connectionString: 'postgresql://usr:pwd@localhost:5432/db' }
@@ -204,28 +260,28 @@ import { didInterrupt } from './workflow/interruption';
204
260
  * args: ['input data'],
205
261
  * taskQueue: 'default',
206
262
  * workflowName: 'example',
207
- * workflowId: MemFlow.guid()
263
+ * workflowId: Durable.guid()
208
264
  * });
209
265
  *
210
266
  * // Get result
211
267
  * const result = await handle.result();
212
268
  *
213
269
  * // Cleanup
214
- * await MemFlow.shutdown();
270
+ * await Durable.shutdown();
215
271
  * ```
216
272
  */
217
- declare class MemFlowClass {
273
+ declare class DurableClass {
218
274
  /**
219
275
  * @private
220
276
  */
221
277
  constructor();
222
278
  /**
223
- * The MemFlow `Client` service is functionally
279
+ * The Durable `Client` service is functionally
224
280
  * equivalent to the Temporal `Client` service.
225
281
  */
226
282
  static Client: typeof ClientService;
227
283
  /**
228
- * The MemFlow `Connection` service is functionally
284
+ * The Durable `Connection` service is functionally
229
285
  * equivalent to the Temporal `Connection` service.
230
286
  */
231
287
  static Connection: typeof ConnectionService;
@@ -241,11 +297,11 @@ declare class MemFlowClass {
241
297
  * The Handle provides methods to interact with a running
242
298
  * workflow. This includes exporting the workflow, sending signals, and
243
299
  * querying the state of the workflow. An instance of the Handle service
244
- * is typically accessed via the MemFlow.Client class (workflow.getHandle).
300
+ * is typically accessed via the Durable.Client class (workflow.getHandle).
245
301
  */
246
302
  static Handle: typeof WorkflowHandleService;
247
303
  /**
248
- * The MemFlow `Worker` service is functionally
304
+ * The Durable `Worker` service is functionally
249
305
  * equivalent to the Temporal `Worker` service.
250
306
  */
251
307
  static Worker: typeof WorkerService;
@@ -261,7 +317,7 @@ declare class MemFlowClass {
261
317
  * async sendEmail(to: string, msg: string) { /* ... *\/ }
262
318
  * };
263
319
  *
264
- * await MemFlow.registerActivityWorker({
320
+ * await Durable.registerActivityWorker({
265
321
  * connection: {
266
322
  * class: Postgres,
267
323
  * options: { connectionString: 'postgresql://usr:pwd@localhost:5432/db' }
@@ -271,7 +327,7 @@ declare class MemFlowClass {
271
327
  *
272
328
  * // Workflow worker (can be on different server)
273
329
  * async function orderWorkflow(amount: number) {
274
- * const { processPayment, sendEmail } = MemFlow.workflow.proxyActivities<{
330
+ * const { processPayment, sendEmail } = Durable.workflow.proxyActivities<{
275
331
  * processPayment: (amount: number) => Promise<string>;
276
332
  * sendEmail: (to: string, msg: string) => Promise<void>;
277
333
  * }>({
@@ -284,7 +340,7 @@ declare class MemFlowClass {
284
340
  * return result;
285
341
  * }
286
342
  *
287
- * await MemFlow.Worker.create({
343
+ * await Durable.Worker.create({
288
344
  * connection: { class: Postgres, options: { connectionString: '...' } },
289
345
  * taskQueue: 'orders',
290
346
  * workflow: orderWorkflow
@@ -293,7 +349,7 @@ declare class MemFlowClass {
293
349
  */
294
350
  static registerActivityWorker: typeof WorkerService.registerActivityWorker;
295
351
  /**
296
- * The MemFlow `workflow` service is functionally
352
+ * The Durable `workflow` service is functionally
297
353
  * equivalent to the Temporal `Workflow` service
298
354
  * with additional methods for managing workflows,
299
355
  * including: `execChild`, `waitFor`, `sleep`, etc
@@ -313,9 +369,45 @@ declare class MemFlowClass {
313
369
  */
314
370
  static registerInterceptor(interceptor: WorkflowInterceptor): void;
315
371
  /**
316
- * Clear all registered workflow interceptors
372
+ * Clear all registered interceptors (both workflow and activity)
317
373
  */
318
374
  static clearInterceptors(): void;
375
+ /**
376
+ * Register an activity interceptor that wraps individual proxied
377
+ * activity calls within workflows. Interceptors execute in registration
378
+ * order (first registered is outermost) using the onion pattern.
379
+ *
380
+ * Activity interceptors run inside the workflow's execution context
381
+ * and have access to all Durable workflow methods (`proxyActivities`,
382
+ * `sleepFor`, `waitFor`, `execChild`, etc.). The `activityCtx` parameter
383
+ * provides `activityName`, `args`, and `options` for the call being
384
+ * intercepted. The `workflowCtx` map provides workflow metadata
385
+ * (`workflowId`, `workflowName`, `namespace`, etc.).
386
+ *
387
+ * @param interceptor The activity interceptor to register
388
+ *
389
+ * @example
390
+ * ```typescript
391
+ * Durable.registerActivityInterceptor({
392
+ * async execute(activityCtx, workflowCtx, next) {
393
+ * const start = Date.now();
394
+ * try {
395
+ * const result = await next();
396
+ * console.log(`${activityCtx.activityName} took ${Date.now() - start}ms`);
397
+ * return result;
398
+ * } catch (err) {
399
+ * if (Durable.didInterrupt(err)) throw err;
400
+ * throw err;
401
+ * }
402
+ * }
403
+ * });
404
+ * ```
405
+ */
406
+ static registerActivityInterceptor(interceptor: ActivityInterceptor): void;
407
+ /**
408
+ * Clear all registered activity interceptors
409
+ */
410
+ static clearActivityInterceptors(): void;
319
411
  /**
320
412
  * Generate a unique identifier for workflow IDs
321
413
  */
@@ -326,5 +418,5 @@ declare class MemFlowClass {
326
418
  */
327
419
  static shutdown(): Promise<void>;
328
420
  }
329
- export { MemFlowClass as MemFlow };
421
+ export { DurableClass as Durable };
330
422
  export type { ContextType };