@hotmeshio/hotmesh 0.4.0 → 0.4.2

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 (284) hide show
  1. package/README.md +39 -14
  2. package/build/modules/enums.d.ts +110 -0
  3. package/build/modules/enums.js +134 -0
  4. package/build/modules/errors.d.ts +124 -0
  5. package/build/modules/errors.js +191 -0
  6. package/build/modules/key.d.ts +66 -0
  7. package/build/modules/key.js +190 -0
  8. package/build/modules/storage.d.ts +3 -0
  9. package/build/modules/storage.js +5 -0
  10. package/build/modules/utils.d.ts +119 -0
  11. package/build/modules/utils.js +374 -0
  12. package/build/package.json +1 -1
  13. package/build/services/activities/activity.d.ts +104 -0
  14. package/build/services/activities/activity.js +549 -0
  15. package/build/services/activities/await.d.ts +12 -0
  16. package/build/services/activities/await.js +114 -0
  17. package/build/services/activities/cycle.d.ts +19 -0
  18. package/build/services/activities/cycle.js +112 -0
  19. package/build/services/activities/hook.d.ts +27 -0
  20. package/build/services/activities/hook.js +168 -0
  21. package/build/services/activities/index.d.ts +19 -0
  22. package/build/services/activities/index.js +20 -0
  23. package/build/services/activities/interrupt.d.ts +16 -0
  24. package/build/services/activities/interrupt.js +158 -0
  25. package/build/services/activities/signal.d.ts +20 -0
  26. package/build/services/activities/signal.js +134 -0
  27. package/build/services/activities/trigger.d.ts +37 -0
  28. package/build/services/activities/trigger.js +246 -0
  29. package/build/services/activities/worker.d.ts +12 -0
  30. package/build/services/activities/worker.js +106 -0
  31. package/build/services/collator/index.d.ts +111 -0
  32. package/build/services/collator/index.js +293 -0
  33. package/build/services/compiler/deployer.d.ts +40 -0
  34. package/build/services/compiler/deployer.js +488 -0
  35. package/build/services/compiler/index.d.ts +32 -0
  36. package/build/services/compiler/index.js +112 -0
  37. package/build/services/compiler/validator.d.ts +34 -0
  38. package/build/services/compiler/validator.js +147 -0
  39. package/build/services/connector/factory.d.ts +22 -0
  40. package/build/services/connector/factory.js +99 -0
  41. package/build/services/connector/index.d.ts +30 -0
  42. package/build/services/connector/index.js +54 -0
  43. package/build/services/connector/providers/ioredis.d.ts +9 -0
  44. package/build/services/connector/providers/ioredis.js +26 -0
  45. package/build/services/connector/providers/nats.d.ts +9 -0
  46. package/build/services/connector/providers/nats.js +34 -0
  47. package/build/services/connector/providers/postgres.d.ts +20 -0
  48. package/build/services/connector/providers/postgres.js +102 -0
  49. package/build/services/connector/providers/redis.d.ts +9 -0
  50. package/build/services/connector/providers/redis.js +38 -0
  51. package/build/services/engine/index.d.ts +264 -0
  52. package/build/services/engine/index.js +761 -0
  53. package/build/services/exporter/index.d.ts +44 -0
  54. package/build/services/exporter/index.js +126 -0
  55. package/build/services/hotmesh/index.d.ts +483 -0
  56. package/build/services/hotmesh/index.js +622 -0
  57. package/build/services/logger/index.d.ts +16 -0
  58. package/build/services/logger/index.js +54 -0
  59. package/build/services/mapper/index.d.ts +28 -0
  60. package/build/services/mapper/index.js +81 -0
  61. package/build/services/memflow/client.d.ts +108 -0
  62. package/build/services/memflow/client.js +372 -0
  63. package/build/services/memflow/connection.d.ts +23 -0
  64. package/build/services/memflow/connection.js +33 -0
  65. package/build/services/memflow/context.d.ts +143 -0
  66. package/build/services/memflow/context.js +299 -0
  67. package/build/services/memflow/exporter.d.ts +51 -0
  68. package/build/services/memflow/exporter.js +215 -0
  69. package/build/services/memflow/handle.d.ts +90 -0
  70. package/build/services/memflow/handle.js +176 -0
  71. package/build/services/memflow/index.d.ts +116 -0
  72. package/build/services/memflow/index.js +122 -0
  73. package/build/services/memflow/schemas/factory.d.ts +29 -0
  74. package/build/services/memflow/schemas/factory.js +2492 -0
  75. package/build/services/memflow/search.d.ts +142 -0
  76. package/build/services/memflow/search.js +320 -0
  77. package/build/services/memflow/worker.d.ts +124 -0
  78. package/build/services/memflow/worker.js +514 -0
  79. package/build/services/memflow/workflow/all.d.ts +7 -0
  80. package/build/services/memflow/workflow/all.js +15 -0
  81. package/build/services/memflow/workflow/common.d.ts +20 -0
  82. package/build/services/memflow/workflow/common.js +47 -0
  83. package/build/services/memflow/workflow/context.d.ts +6 -0
  84. package/build/services/memflow/workflow/context.js +45 -0
  85. package/build/services/memflow/workflow/contextMethods.d.ts +14 -0
  86. package/build/services/memflow/workflow/contextMethods.js +33 -0
  87. package/build/services/memflow/workflow/didRun.d.ts +7 -0
  88. package/build/services/memflow/workflow/didRun.js +22 -0
  89. package/build/services/memflow/workflow/emit.d.ts +11 -0
  90. package/build/services/memflow/workflow/emit.js +29 -0
  91. package/build/services/memflow/workflow/enrich.d.ts +9 -0
  92. package/build/services/memflow/workflow/enrich.js +17 -0
  93. package/build/services/memflow/workflow/execChild.d.ts +18 -0
  94. package/build/services/memflow/workflow/execChild.js +102 -0
  95. package/build/services/memflow/workflow/execHook.d.ts +65 -0
  96. package/build/services/memflow/workflow/execHook.js +73 -0
  97. package/build/services/memflow/workflow/hook.d.ts +9 -0
  98. package/build/services/memflow/workflow/hook.js +56 -0
  99. package/build/services/memflow/workflow/index.d.ts +74 -0
  100. package/build/services/memflow/workflow/index.js +87 -0
  101. package/build/services/memflow/workflow/interrupt.d.ts +9 -0
  102. package/build/services/memflow/workflow/interrupt.js +24 -0
  103. package/build/services/memflow/workflow/isSideEffectAllowed.d.ts +10 -0
  104. package/build/services/memflow/workflow/isSideEffectAllowed.js +33 -0
  105. package/build/services/memflow/workflow/proxyActivities.d.ts +20 -0
  106. package/build/services/memflow/workflow/proxyActivities.js +97 -0
  107. package/build/services/memflow/workflow/random.d.ts +6 -0
  108. package/build/services/memflow/workflow/random.js +16 -0
  109. package/build/services/memflow/workflow/searchMethods.d.ts +6 -0
  110. package/build/services/memflow/workflow/searchMethods.js +25 -0
  111. package/build/services/memflow/workflow/signal.d.ts +29 -0
  112. package/build/services/memflow/workflow/signal.js +50 -0
  113. package/build/services/memflow/workflow/sleepFor.d.ts +24 -0
  114. package/build/services/memflow/workflow/sleepFor.js +51 -0
  115. package/build/services/memflow/workflow/trace.d.ts +14 -0
  116. package/build/services/memflow/workflow/trace.js +33 -0
  117. package/build/services/memflow/workflow/waitFor.d.ts +29 -0
  118. package/build/services/memflow/workflow/waitFor.js +56 -0
  119. package/build/services/meshcall/index.d.ts +194 -0
  120. package/build/services/meshcall/index.js +452 -0
  121. package/build/services/meshcall/schemas/factory.d.ts +9 -0
  122. package/build/services/meshcall/schemas/factory.js +189 -0
  123. package/build/services/meshdata/index.d.ts +795 -0
  124. package/build/services/meshdata/index.js +1235 -0
  125. package/build/services/meshos/index.d.ts +293 -0
  126. package/build/services/meshos/index.js +547 -0
  127. package/build/services/pipe/functions/array.d.ts +17 -0
  128. package/build/services/pipe/functions/array.js +74 -0
  129. package/build/services/pipe/functions/bitwise.d.ts +9 -0
  130. package/build/services/pipe/functions/bitwise.js +24 -0
  131. package/build/services/pipe/functions/conditional.d.ts +13 -0
  132. package/build/services/pipe/functions/conditional.js +36 -0
  133. package/build/services/pipe/functions/cron.d.ts +12 -0
  134. package/build/services/pipe/functions/cron.js +40 -0
  135. package/build/services/pipe/functions/date.d.ts +58 -0
  136. package/build/services/pipe/functions/date.js +171 -0
  137. package/build/services/pipe/functions/index.d.ts +29 -0
  138. package/build/services/pipe/functions/index.js +30 -0
  139. package/build/services/pipe/functions/json.d.ts +5 -0
  140. package/build/services/pipe/functions/json.js +12 -0
  141. package/build/services/pipe/functions/logical.d.ts +5 -0
  142. package/build/services/pipe/functions/logical.js +12 -0
  143. package/build/services/pipe/functions/math.d.ts +42 -0
  144. package/build/services/pipe/functions/math.js +184 -0
  145. package/build/services/pipe/functions/number.d.ts +21 -0
  146. package/build/services/pipe/functions/number.js +60 -0
  147. package/build/services/pipe/functions/object.d.ts +25 -0
  148. package/build/services/pipe/functions/object.js +81 -0
  149. package/build/services/pipe/functions/string.d.ts +23 -0
  150. package/build/services/pipe/functions/string.js +69 -0
  151. package/build/services/pipe/functions/symbol.d.ts +12 -0
  152. package/build/services/pipe/functions/symbol.js +33 -0
  153. package/build/services/pipe/functions/unary.d.ts +7 -0
  154. package/build/services/pipe/functions/unary.js +18 -0
  155. package/build/services/pipe/index.d.ts +48 -0
  156. package/build/services/pipe/index.js +242 -0
  157. package/build/services/quorum/index.d.ts +90 -0
  158. package/build/services/quorum/index.js +263 -0
  159. package/build/services/reporter/index.d.ts +50 -0
  160. package/build/services/reporter/index.js +348 -0
  161. package/build/services/router/config/index.d.ts +11 -0
  162. package/build/services/router/config/index.js +36 -0
  163. package/build/services/router/consumption/index.d.ts +34 -0
  164. package/build/services/router/consumption/index.js +395 -0
  165. package/build/services/router/error-handling/index.d.ts +8 -0
  166. package/build/services/router/error-handling/index.js +98 -0
  167. package/build/services/router/index.d.ts +57 -0
  168. package/build/services/router/index.js +121 -0
  169. package/build/services/router/lifecycle/index.d.ts +27 -0
  170. package/build/services/router/lifecycle/index.js +80 -0
  171. package/build/services/router/telemetry/index.d.ts +11 -0
  172. package/build/services/router/telemetry/index.js +32 -0
  173. package/build/services/router/throttling/index.d.ts +23 -0
  174. package/build/services/router/throttling/index.js +76 -0
  175. package/build/services/search/factory.d.ts +7 -0
  176. package/build/services/search/factory.js +24 -0
  177. package/build/services/search/index.d.ts +23 -0
  178. package/build/services/search/index.js +10 -0
  179. package/build/services/search/providers/postgres/postgres.d.ts +25 -0
  180. package/build/services/search/providers/postgres/postgres.js +149 -0
  181. package/build/services/search/providers/redis/ioredis.d.ts +19 -0
  182. package/build/services/search/providers/redis/ioredis.js +121 -0
  183. package/build/services/search/providers/redis/redis.d.ts +19 -0
  184. package/build/services/search/providers/redis/redis.js +134 -0
  185. package/build/services/serializer/index.d.ts +42 -0
  186. package/build/services/serializer/index.js +282 -0
  187. package/build/services/store/cache.d.ts +67 -0
  188. package/build/services/store/cache.js +128 -0
  189. package/build/services/store/factory.d.ts +8 -0
  190. package/build/services/store/factory.js +24 -0
  191. package/build/services/store/index.d.ts +89 -0
  192. package/build/services/store/index.js +9 -0
  193. package/build/services/store/providers/postgres/kvsql.d.ts +168 -0
  194. package/build/services/store/providers/postgres/kvsql.js +198 -0
  195. package/build/services/store/providers/postgres/kvtables.d.ts +20 -0
  196. package/build/services/store/providers/postgres/kvtables.js +441 -0
  197. package/build/services/store/providers/postgres/kvtransaction.d.ts +36 -0
  198. package/build/services/store/providers/postgres/kvtransaction.js +248 -0
  199. package/build/services/store/providers/postgres/kvtypes/hash.d.ts +60 -0
  200. package/build/services/store/providers/postgres/kvtypes/hash.js +1287 -0
  201. package/build/services/store/providers/postgres/kvtypes/list.d.ts +33 -0
  202. package/build/services/store/providers/postgres/kvtypes/list.js +194 -0
  203. package/build/services/store/providers/postgres/kvtypes/string.d.ts +20 -0
  204. package/build/services/store/providers/postgres/kvtypes/string.js +115 -0
  205. package/build/services/store/providers/postgres/kvtypes/zset.d.ts +41 -0
  206. package/build/services/store/providers/postgres/kvtypes/zset.js +214 -0
  207. package/build/services/store/providers/postgres/postgres.d.ts +178 -0
  208. package/build/services/store/providers/postgres/postgres.js +1244 -0
  209. package/build/services/store/providers/redis/_base.d.ts +137 -0
  210. package/build/services/store/providers/redis/_base.js +980 -0
  211. package/build/services/store/providers/redis/ioredis.d.ts +20 -0
  212. package/build/services/store/providers/redis/ioredis.js +180 -0
  213. package/build/services/store/providers/redis/redis.d.ts +18 -0
  214. package/build/services/store/providers/redis/redis.js +199 -0
  215. package/build/services/store/providers/store-initializable.d.ts +5 -0
  216. package/build/services/store/providers/store-initializable.js +2 -0
  217. package/build/services/stream/factory.d.ts +8 -0
  218. package/build/services/stream/factory.js +37 -0
  219. package/build/services/stream/index.d.ts +69 -0
  220. package/build/services/stream/index.js +11 -0
  221. package/build/services/stream/providers/nats/nats.d.ts +60 -0
  222. package/build/services/stream/providers/nats/nats.js +225 -0
  223. package/build/services/stream/providers/postgres/kvtables.d.ts +3 -0
  224. package/build/services/stream/providers/postgres/kvtables.js +146 -0
  225. package/build/services/stream/providers/postgres/postgres.d.ts +107 -0
  226. package/build/services/stream/providers/postgres/postgres.js +519 -0
  227. package/build/services/stream/providers/redis/ioredis.d.ts +61 -0
  228. package/build/services/stream/providers/redis/ioredis.js +272 -0
  229. package/build/services/stream/providers/redis/redis.d.ts +61 -0
  230. package/build/services/stream/providers/redis/redis.js +305 -0
  231. package/build/services/stream/providers/stream-initializable.d.ts +4 -0
  232. package/build/services/stream/providers/stream-initializable.js +2 -0
  233. package/build/services/sub/factory.d.ts +7 -0
  234. package/build/services/sub/factory.js +29 -0
  235. package/build/services/sub/index.d.ts +22 -0
  236. package/build/services/sub/index.js +10 -0
  237. package/build/services/sub/providers/nats/nats.d.ts +19 -0
  238. package/build/services/sub/providers/nats/nats.js +105 -0
  239. package/build/services/sub/providers/postgres/postgres.d.ts +19 -0
  240. package/build/services/sub/providers/postgres/postgres.js +92 -0
  241. package/build/services/sub/providers/redis/ioredis.d.ts +17 -0
  242. package/build/services/sub/providers/redis/ioredis.js +81 -0
  243. package/build/services/sub/providers/redis/redis.d.ts +17 -0
  244. package/build/services/sub/providers/redis/redis.js +72 -0
  245. package/build/services/task/index.d.ts +48 -0
  246. package/build/services/task/index.js +253 -0
  247. package/build/services/telemetry/index.d.ts +52 -0
  248. package/build/services/telemetry/index.js +306 -0
  249. package/build/services/worker/index.d.ts +77 -0
  250. package/build/services/worker/index.js +197 -0
  251. package/package.json +1 -1
  252. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -38
  253. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
  254. package/typedoc.json +0 -47
  255. package/types/activity.ts +0 -268
  256. package/types/app.ts +0 -20
  257. package/types/async.ts +0 -6
  258. package/types/cache.ts +0 -1
  259. package/types/collator.ts +0 -9
  260. package/types/error.ts +0 -56
  261. package/types/exporter.ts +0 -102
  262. package/types/hook.ts +0 -44
  263. package/types/hotmesh.ts +0 -314
  264. package/types/index.ts +0 -306
  265. package/types/job.ts +0 -233
  266. package/types/logger.ts +0 -8
  267. package/types/manifest.ts +0 -70
  268. package/types/map.ts +0 -5
  269. package/types/memflow.ts +0 -645
  270. package/types/meshcall.ts +0 -235
  271. package/types/meshdata.ts +0 -278
  272. package/types/ms.d.ts +0 -7
  273. package/types/nats.ts +0 -270
  274. package/types/pipe.ts +0 -90
  275. package/types/postgres.ts +0 -114
  276. package/types/provider.ts +0 -161
  277. package/types/quorum.ts +0 -167
  278. package/types/redis.ts +0 -404
  279. package/types/serializer.ts +0 -40
  280. package/types/stats.ts +0 -117
  281. package/types/stream.ts +0 -231
  282. package/types/task.ts +0 -7
  283. package/types/telemetry.ts +0 -16
  284. package/types/transition.ts +0 -20
@@ -0,0 +1,622 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HotMesh = void 0;
4
+ const key_1 = require("../../modules/key");
5
+ const utils_1 = require("../../modules/utils");
6
+ const factory_1 = require("../connector/factory");
7
+ const engine_1 = require("../engine");
8
+ const logger_1 = require("../logger");
9
+ const quorum_1 = require("../quorum");
10
+ const router_1 = require("../router");
11
+ const worker_1 = require("../worker");
12
+ const enums_1 = require("../../modules/enums");
13
+ /**
14
+ * HotMesh is a distributed, reentrant process orchestration engine that transforms
15
+ * Redis, Postgres, or NATS into a resilient service mesh capable of running
16
+ * fault-tolerant workflows across multiple services and systems.
17
+ *
18
+ * ## Core Concepts
19
+ *
20
+ * **Distributed Quorum Architecture**: HotMesh operates as a distributed quorum
21
+ * where multiple engine and worker instances coordinate using CQRS principles.
22
+ * Each member reads from assigned topic queues and writes results to other queues,
23
+ * creating emergent workflow orchestration without a central controller.
24
+ *
25
+ * **Reentrant Process Engine**: Unlike traditional workflow engines, HotMesh
26
+ * provides built-in retry logic, idempotency, and failure recovery. Your business
27
+ * logic doesn't need to handle timeouts or retries - the engine manages all of that.
28
+ *
29
+ * **Multi-Provider Support**: Supports Redis/ValKey, Postgres, and NATS as backend
30
+ * providers, allowing you to leverage existing infrastructure investments.
31
+ *
32
+ * ## Key Features
33
+ *
34
+ * - **Fault Tolerance**: Automatic retry, timeout, and failure recovery
35
+ * - **Distributed Execution**: No single point of failure
36
+ * - **Multi-Provider**: Redis, Postgres, NATS backend support
37
+ * - **YAML-Driven**: Model-driven development with declarative workflow definitions
38
+ * - **OpenTelemetry**: Built-in observability and tracing
39
+ * - **Durable State**: Workflow state persists across system restarts
40
+ * - **Pattern Matching**: Pub/sub with wildcard pattern support
41
+ * - **Throttling**: Dynamic flow control and backpressure management
42
+ *
43
+ * ## Architecture
44
+ *
45
+ * HotMesh consists of several specialized modules:
46
+ * - **HotMesh**: Core orchestration engine (this class)
47
+ * - **MemFlow**: Temporal.io-compatible workflow framework
48
+ * - **MeshCall**: Durable function execution (Temporal-like clone)
49
+ *
50
+ * ## Lifecycle Overview
51
+ *
52
+ * 1. **Initialize**: Create HotMesh instance with provider configuration
53
+ * 2. **Deploy**: Upload YAML workflow definitions to the backend
54
+ * 3. **Activate**: Coordinate quorum to enable the workflow version
55
+ * 4. **Execute**: Publish events to trigger workflow execution
56
+ * 5. **Monitor**: Track progress via OpenTelemetry and built-in observability
57
+ *
58
+ * ## Basic Usage
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * import { HotMesh } from '@hotmeshio/hotmesh';
63
+ * import Redis from 'ioredis';
64
+ *
65
+ * // Initialize with Redis backend
66
+ * const hotMesh = await HotMesh.init({
67
+ * appId: 'my-app',
68
+ * engine: {
69
+ * connection: {
70
+ * class: Redis,
71
+ * options: { host: 'localhost', port: 6379 }
72
+ * }
73
+ * }
74
+ * });
75
+ *
76
+ * // Deploy workflow definition
77
+ * await hotMesh.deploy(`
78
+ * app:
79
+ * id: my-app
80
+ * version: '1'
81
+ * graphs:
82
+ * - subscribes: order.process
83
+ * activities:
84
+ * validate:
85
+ * type: worker
86
+ * topic: order.validate
87
+ * approve:
88
+ * type: hook
89
+ * topic: order.approve
90
+ * fulfill:
91
+ * type: worker
92
+ * topic: order.fulfill
93
+ * transitions:
94
+ * validate:
95
+ * - to: approve
96
+ * approve:
97
+ * - to: fulfill
98
+ * `);
99
+ *
100
+ * // Activate the workflow version
101
+ * await hotMesh.activate('1');
102
+ *
103
+ * // Execute workflow (fire-and-forget)
104
+ * const jobId = await hotMesh.pub('order.process', {
105
+ * orderId: '12345',
106
+ * amount: 99.99
107
+ * });
108
+ *
109
+ * // Execute workflow and wait for result
110
+ * const result = await hotMesh.pubsub('order.process', {
111
+ * orderId: '12345',
112
+ * amount: 99.99
113
+ * });
114
+ * ```
115
+ *
116
+ * ## Postgres Backend Example
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * import { HotMesh } from '@hotmeshio/hotmesh';
121
+ * import { Client as Postgres } from 'pg';
122
+ *
123
+ * const hotMesh = await HotMesh.init({
124
+ * appId: 'my-app',
125
+ * engine: {
126
+ * connection: {
127
+ * class: Postgres,
128
+ * options: {
129
+ * connectionString: 'postgresql://user:pass@localhost:5432/db'
130
+ * }
131
+ * }
132
+ * }
133
+ * });
134
+ * ```
135
+ *
136
+ * ## Advanced Features
137
+ *
138
+ * **Pattern Subscriptions**: Listen to multiple workflow topics
139
+ * ```typescript
140
+ * await hotMesh.psub('order.*', (topic, message) => {
141
+ * console.log(`Received ${topic}:`, message);
142
+ * });
143
+ * ```
144
+ *
145
+ * **Throttling**: Control processing rates
146
+ * ```typescript
147
+ * // Pause all processing for 5 seconds
148
+ * await hotMesh.throttle({ throttle: 5000 });
149
+ *
150
+ * // Emergency stop (pause indefinitely)
151
+ * await hotMesh.throttle({ throttle: -1 });
152
+ * ```
153
+ *
154
+ * **Workflow Interruption**: Gracefully stop running workflows
155
+ * ```typescript
156
+ * await hotMesh.interrupt('order.process', jobId, {
157
+ * reason: 'User cancellation'
158
+ * });
159
+ * ```
160
+ *
161
+ * **State Inspection**: Query workflow state and progress
162
+ * ```typescript
163
+ * const state = await hotMesh.getState('order.process', jobId);
164
+ * const status = await hotMesh.getStatus(jobId);
165
+ * ```
166
+ *
167
+ * ## Distributed Coordination
168
+ *
169
+ * HotMesh automatically handles distributed coordination through its quorum system:
170
+ *
171
+ * ```typescript
172
+ * // Check quorum health
173
+ * const members = await hotMesh.rollCall();
174
+ *
175
+ * // Coordinate version activation across all instances
176
+ * await hotMesh.activate('2', 1000); // 1 second delay for consensus
177
+ * ```
178
+ *
179
+ * ## Integration with Higher-Level Modules
180
+ *
181
+ * For most use cases, consider using the higher-level modules:
182
+ * - **MemFlow**: For Temporal.io-style workflows with TypeScript functions
183
+ * - **MeshCall**: For durable function calls and RPC patterns
184
+ *
185
+ * ## Cleanup
186
+ *
187
+ * Always clean up resources when shutting down:
188
+ * ```typescript
189
+ * // Stop this instance
190
+ * hotMesh.stop();
191
+ *
192
+ * // Stop all instances (typically in signal handlers)
193
+ * await HotMesh.stop();
194
+ * ```
195
+ *
196
+ * @see {@link https://hotmesh.io/docs} - Complete documentation
197
+ * @see {@link https://github.com/hotmeshio/samples-typescript} - Examples and tutorials
198
+ * @see {@link https://zenodo.org/records/12168558} - Academic paper on the architecture
199
+ */
200
+ class HotMesh {
201
+ /**
202
+ * @private
203
+ */
204
+ verifyAndSetNamespace(namespace) {
205
+ if (!namespace) {
206
+ this.namespace = key_1.HMNS;
207
+ }
208
+ else if (!namespace.match(/^[A-Za-z0-9-]+$/)) {
209
+ throw new Error(`config.namespace [${namespace}] is invalid`);
210
+ }
211
+ else {
212
+ this.namespace = namespace;
213
+ }
214
+ }
215
+ /**
216
+ * @private
217
+ */
218
+ verifyAndSetAppId(appId) {
219
+ if (!appId?.match(/^[A-Za-z0-9-]+$/)) {
220
+ throw new Error(`config.appId [${appId}] is invalid`);
221
+ }
222
+ else if (appId === 'a') {
223
+ throw new Error(`config.appId [${appId}] is reserved`);
224
+ }
225
+ else {
226
+ this.appId = appId;
227
+ }
228
+ }
229
+ /**
230
+ * Instance initializer. Workers are configured
231
+ * similarly to the engine, but as an array with
232
+ * multiple worker objects.
233
+ *
234
+ * @example
235
+ * ```typescript
236
+ * const config: HotMeshConfig = {
237
+ * appId: 'myapp',
238
+ * engine: {
239
+ * connection: {
240
+ * class: Postgres,
241
+ * options: {
242
+ * connectionString: 'postgresql://usr:pwd@localhost:5432/db',
243
+ * }
244
+ * }
245
+ * },
246
+ * workers [...]
247
+ * };
248
+ * const hotMesh = await HotMesh.init(config);
249
+ * ```
250
+ */
251
+ static async init(config) {
252
+ const instance = new HotMesh();
253
+ instance.guid = config.guid ?? (0, utils_1.guid)();
254
+ instance.verifyAndSetNamespace(config.namespace);
255
+ instance.verifyAndSetAppId(config.appId);
256
+ instance.logger = new logger_1.LoggerService(config.appId, instance.guid, config.name || '', config.logLevel);
257
+ await instance.initEngine(config, instance.logger);
258
+ await instance.initQuorum(config, instance.engine, instance.logger);
259
+ await instance.doWork(config, instance.logger);
260
+ return instance;
261
+ }
262
+ /**
263
+ * returns a guid using the same core guid
264
+ * generator used by the HotMesh (nanoid)
265
+ */
266
+ static guid() {
267
+ return (0, utils_1.guid)();
268
+ }
269
+ /**
270
+ * @private
271
+ */
272
+ async initEngine(config, logger) {
273
+ if (config.engine) {
274
+ //connections that are 'readonly' transfer
275
+ //this property directly to the engine,
276
+ //and ALWAYS take precendence.
277
+ if (config.engine.connection.readonly) {
278
+ config.engine.readonly = true;
279
+ }
280
+ await factory_1.ConnectorService.initClients(config.engine);
281
+ this.engine = await engine_1.EngineService.init(this.namespace, this.appId, this.guid, config, logger);
282
+ }
283
+ }
284
+ /**
285
+ * @private
286
+ */
287
+ async initQuorum(config, engine, logger) {
288
+ if (engine) {
289
+ this.quorum = await quorum_1.QuorumService.init(this.namespace, this.appId, this.guid, config, engine, logger);
290
+ }
291
+ }
292
+ /**
293
+ * @private
294
+ */
295
+ constructor() {
296
+ /**
297
+ * @private
298
+ */
299
+ this.engine = null;
300
+ /**
301
+ * @private
302
+ */
303
+ this.quorum = null;
304
+ /**
305
+ * @private
306
+ */
307
+ this.workers = [];
308
+ }
309
+ /**
310
+ * @private
311
+ */
312
+ async doWork(config, logger) {
313
+ this.workers = await worker_1.WorkerService.init(this.namespace, this.appId, this.guid, config, logger);
314
+ }
315
+ // ************* PUB/SUB METHODS *************
316
+ /**
317
+ * Starts a workflow
318
+ * @example
319
+ * ```typescript
320
+ * await hotMesh.pub('a.b.c', { key: 'value' });
321
+ * ```
322
+ */
323
+ async pub(topic, data = {}, context, extended) {
324
+ return await this.engine?.pub(topic, data, context, extended);
325
+ }
326
+ /**
327
+ * Subscribe (listen) to all output and interim emissions of a single
328
+ * workflow topic. NOTE: Postgres does not support patterned
329
+ * unsubscription, so this method is not supported for Postgres.
330
+ *
331
+ * @example
332
+ * ```typescript
333
+ * await hotMesh.psub('a.b.c', (topic, message) => {
334
+ * console.log(message);
335
+ * });
336
+ * ```
337
+ */
338
+ async sub(topic, callback) {
339
+ return await this.engine?.sub(topic, callback);
340
+ }
341
+ /**
342
+ * Stop listening in on a single workflow topic
343
+ */
344
+ async unsub(topic) {
345
+ return await this.engine?.unsub(topic);
346
+ }
347
+ /**
348
+ * Listen to all output and interim emissions of a workflow topic
349
+ * matching a wildcard pattern.
350
+ * @example
351
+ * ```typescript
352
+ * await hotMesh.psub('a.b.c*', (topic, message) => {
353
+ * console.log(message);
354
+ * });
355
+ * ```
356
+ */
357
+ async psub(wild, callback) {
358
+ return await this.engine?.psub(wild, callback);
359
+ }
360
+ /**
361
+ * Patterned unsubscribe. NOTE: Postgres does not support patterned
362
+ * unsubscription, so this method is not supported for Postgres.
363
+ */
364
+ async punsub(wild) {
365
+ return await this.engine?.punsub(wild);
366
+ }
367
+ /**
368
+ * Starts a workflow and awaits the response
369
+ * @example
370
+ * ```typescript
371
+ * await hotMesh.pubsub('a.b.c', { key: 'value' });
372
+ * ```
373
+ */
374
+ async pubsub(topic, data = {}, context, timeout) {
375
+ return await this.engine?.pubsub(topic, data, context, timeout);
376
+ }
377
+ /**
378
+ * Add a transition message to the workstream, resuming leg 2 of a paused
379
+ * reentrant activity (e.g., await, worker, hook)
380
+ */
381
+ async add(streamData) {
382
+ return (await this.engine.add(streamData));
383
+ }
384
+ // ************* QUORUM METHODS *************
385
+ /**
386
+ * Request a roll call from the quorum (engine and workers)
387
+ */
388
+ async rollCall(delay) {
389
+ return await this.quorum?.rollCall(delay);
390
+ }
391
+ /**
392
+ * Sends a throttle message to the quorum (engine and/or workers)
393
+ * to limit the rate of processing. Pass `-1` to throttle indefinitely.
394
+ * The value must be a non-negative integer and not exceed `MAX_DELAY` ms.
395
+ *
396
+ * When throttling is set, the quorum will pause for the specified time
397
+ * before processing the next message. Target specific engines and
398
+ * workers by passing a `guid` and/or `topic`. Pass no arguments to
399
+ * throttle the entire quorum.
400
+ *
401
+ * In this example, all processing has been paused indefinitely for
402
+ * the entire quorum. This is equivalent to an emergency stop.
403
+ *
404
+ * HotMesh is a stateless sequence engine, so the throttle can be adjusted up
405
+ * and down with no loss of data.
406
+ *
407
+ *
408
+ * @example
409
+ * ```typescript
410
+ * await hotMesh.throttle({ throttle: -1 });
411
+ * ```
412
+ */
413
+ async throttle(options) {
414
+ let throttle;
415
+ if (options.throttle === -1) {
416
+ throttle = enums_1.MAX_DELAY;
417
+ }
418
+ else {
419
+ throttle = options.throttle;
420
+ }
421
+ if (!Number.isInteger(throttle) || throttle < 0 || throttle > enums_1.MAX_DELAY) {
422
+ throw new Error(`Throttle must be a non-negative integer and not exceed ${enums_1.MAX_DELAY} ms; send -1 to throttle indefinitely`);
423
+ }
424
+ const throttleMessage = {
425
+ type: 'throttle',
426
+ throttle: throttle,
427
+ };
428
+ if (options.guid) {
429
+ throttleMessage.guid = options.guid;
430
+ }
431
+ if (options.topic !== undefined) {
432
+ throttleMessage.topic = options.topic;
433
+ }
434
+ await this.engine.store.setThrottleRate(throttleMessage);
435
+ return await this.quorum?.pub(throttleMessage);
436
+ }
437
+ /**
438
+ * Publish a message to the quorum (engine and/or workers)
439
+ */
440
+ async pubQuorum(quorumMessage) {
441
+ return await this.quorum?.pub(quorumMessage);
442
+ }
443
+ /**
444
+ * Subscribe to quorum events (engine and workers)
445
+ */
446
+ async subQuorum(callback) {
447
+ return await this.quorum?.sub(callback);
448
+ }
449
+ /**
450
+ * Unsubscribe from quorum events (engine and workers)
451
+ */
452
+ async unsubQuorum(callback) {
453
+ return await this.quorum?.unsub(callback);
454
+ }
455
+ // ************* LIFECYCLE METHODS *************
456
+ /**
457
+ * Preview changes and provide an analysis of risk
458
+ * prior to deployment
459
+ * @private
460
+ */
461
+ async plan(path) {
462
+ return await this.engine?.plan(path);
463
+ }
464
+ /**
465
+ * When the app YAML descriptor file is ready, the `deploy` function can be called.
466
+ * This function is responsible for merging all referenced YAML source
467
+ * files and writing the JSON output to the file system and to the provider backend. It
468
+ * is also possible to embed the YAML in-line as a string.
469
+ *
470
+ * *The version will not be active until activation is explicitly called.*
471
+ */
472
+ async deploy(pathOrYAML) {
473
+ return await this.engine?.deploy(pathOrYAML);
474
+ }
475
+ /**
476
+ * Once the app YAML file is deployed to the provider backend, the `activate` function can be
477
+ * called to enable it for the entire quorum at the same moment.
478
+ *
479
+ * The approach is to establish the coordinated health of the system through series
480
+ * of call/response exchanges. Once it is established that the quorum is healthy,
481
+ * the quorum is instructed to run their engine in `no-cache` mode, ensuring
482
+ * that the provider backend is consulted for the active app version each time a
483
+ * call is processed. This ensures that all engines are running the same version
484
+ * of the app, switching over at the same moment and then enabling `cache` mode
485
+ * to improve performance.
486
+ *
487
+ * *Add a delay for the quorum to reach consensus if traffic is busy, but
488
+ * also consider throttling traffic flow to an acceptable level.*
489
+ */
490
+ async activate(version, delay) {
491
+ return await this.quorum?.activate(version, delay);
492
+ }
493
+ /**
494
+ * Returns the job state as a JSON object, useful
495
+ * for understanding dependency chains
496
+ */
497
+ async export(jobId) {
498
+ return await this.engine?.export(jobId);
499
+ }
500
+ /**
501
+ * Returns all data (HGETALL) for a job.
502
+ */
503
+ async getRaw(jobId) {
504
+ return await this.engine?.getRaw(jobId);
505
+ }
506
+ /**
507
+ * Reporter-related method to get the status of a job
508
+ * @private
509
+ */
510
+ async getStats(topic, query) {
511
+ return await this.engine?.getStats(topic, query);
512
+ }
513
+ /**
514
+ * Returns the status of a job. This is a numeric
515
+ * semaphore value that indicates the job's state.
516
+ * Any non-positive value indicates a completed job.
517
+ * Jobs with a value of `-1` are pending and will
518
+ * automatically be scrubbed after a set period.
519
+ * Jobs a value around -1billion have been interrupted
520
+ * and will be scrubbed after a set period. Jobs with
521
+ * a value of 0 completed normally. Jobs with a
522
+ * positive value are still running.
523
+ */
524
+ async getStatus(jobId) {
525
+ return this.engine?.getStatus(jobId);
526
+ }
527
+ /**
528
+ * Returns the job state (data and metadata) for a job.
529
+ */
530
+ async getState(topic, jobId) {
531
+ return this.engine?.getState(topic, jobId);
532
+ }
533
+ /**
534
+ * Returns searchable/queryable data for a job. In this
535
+ * example a literal field is also searched (the colon
536
+ * is used to track job status and is a reserved field;
537
+ * it can be read but not written).
538
+ *
539
+ * @example
540
+ * ```typescript
541
+ * const fields = ['fred', 'barney', '":"'];
542
+ * const queryState = await hotMesh.getQueryState('123', fields);
543
+ * //returns { fred: 'flintstone', barney: 'rubble', ':': '1' }
544
+ * ```
545
+ */
546
+ async getQueryState(jobId, fields) {
547
+ return await this.engine?.getQueryState(jobId, fields);
548
+ }
549
+ /**
550
+ * @private
551
+ */
552
+ async getIds(topic, query, queryFacets = []) {
553
+ return await this.engine?.getIds(topic, query, queryFacets);
554
+ }
555
+ /**
556
+ * @private
557
+ */
558
+ async resolveQuery(topic, query) {
559
+ return await this.engine?.resolveQuery(topic, query);
560
+ }
561
+ /**
562
+ * Interrupt an active job
563
+ */
564
+ async interrupt(topic, jobId, options = {}) {
565
+ return await this.engine?.interrupt(topic, jobId, options);
566
+ }
567
+ /**
568
+ * Immediately deletes (DEL) a completed job from the system.
569
+ *
570
+ * *Scrubbed jobs must be complete with a non-positive `status` value*
571
+ */
572
+ async scrub(jobId) {
573
+ await this.engine?.scrub(jobId);
574
+ }
575
+ /**
576
+ * Re/entry point for an active job. This is used to resume a paused job
577
+ * and close the reentry point or leave it open for subsequent reentry.
578
+ * Because `hooks` are public entry points, they include a `topic`
579
+ * which is established in the app YAML file.
580
+ *
581
+ * When this method is called, a hook rule will be located to establish
582
+ * the exact activity and activity dimension for reentry.
583
+ */
584
+ async hook(topic, data, status, code) {
585
+ return await this.engine?.hook(topic, data, status, code);
586
+ }
587
+ /**
588
+ * @private
589
+ */
590
+ async hookAll(hookTopic, data, query, queryFacets = []) {
591
+ return await this.engine?.hookAll(hookTopic, data, query, queryFacets);
592
+ }
593
+ /**
594
+ * Stop all points of presence, workers and engines
595
+ */
596
+ static async stop() {
597
+ if (!this.disconnecting) {
598
+ this.disconnecting = true;
599
+ await router_1.Router.stopConsuming();
600
+ await factory_1.ConnectorService.disconnectAll();
601
+ }
602
+ }
603
+ /**
604
+ * Stop this point of presence, workers and engines
605
+ */
606
+ stop() {
607
+ this.engine?.taskService.cancelCleanup();
608
+ this.quorum?.stop();
609
+ this.workers?.forEach((worker) => {
610
+ worker.stop();
611
+ });
612
+ }
613
+ /**
614
+ * @private
615
+ * @deprecated
616
+ */
617
+ async compress(terms) {
618
+ return await this.engine?.compress(terms);
619
+ }
620
+ }
621
+ exports.HotMesh = HotMesh;
622
+ HotMesh.disconnecting = false;
@@ -0,0 +1,16 @@
1
+ import { Logger } from 'winston';
2
+ import { ILogger } from '../../types/logger';
3
+ declare class LoggerService implements ILogger {
4
+ private appId;
5
+ private instanceId;
6
+ private name;
7
+ private logLevel;
8
+ private logger;
9
+ constructor(appId?: string, instanceId?: string, name?: string, logLevel?: string, customLogger?: Logger);
10
+ private createDefaultLogger;
11
+ info(message: string, ...meta: any[]): void;
12
+ error(message: string, ...meta: any[]): void;
13
+ warn(message: string, ...meta: any[]): void;
14
+ debug(message: string, ...meta: any[]): void;
15
+ }
16
+ export { LoggerService, ILogger };
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LoggerService = void 0;
4
+ const winston_1 = require("winston");
5
+ class LoggerService {
6
+ constructor(appId = 'appId', instanceId = 'instanceId', name = 'name', logLevel = 'info', customLogger) {
7
+ this.appId = appId;
8
+ this.instanceId = instanceId;
9
+ this.name = name;
10
+ this.logLevel = logLevel;
11
+ this.logger = customLogger || this.createDefaultLogger();
12
+ }
13
+ createDefaultLogger() {
14
+ // Custom format to ensure error objects include message and stack
15
+ const errorFormat = (0, winston_1.format)((info) => {
16
+ if (info.error instanceof Error) {
17
+ return {
18
+ ...info,
19
+ error: {
20
+ message: info.error.message,
21
+ stack: info.error.stack,
22
+ },
23
+ };
24
+ }
25
+ return info;
26
+ });
27
+ return (0, winston_1.createLogger)({
28
+ level: this.logLevel,
29
+ format: winston_1.format.combine(winston_1.format.timestamp(), winston_1.format.errors({ stack: true }), errorFormat(), (0, winston_1.format)((info) => {
30
+ info.ts = info.timestamp;
31
+ delete info.timestamp;
32
+ return info;
33
+ })(), winston_1.format.json()),
34
+ transports: [new winston_1.transports.Console()],
35
+ defaultMeta: {
36
+ app: this.name || this.appId,
37
+ id: this.instanceId,
38
+ },
39
+ });
40
+ }
41
+ info(message, ...meta) {
42
+ this.logger.info(message, ...meta);
43
+ }
44
+ error(message, ...meta) {
45
+ this.logger.error(message, ...meta);
46
+ }
47
+ warn(message, ...meta) {
48
+ this.logger.warn(message, ...meta);
49
+ }
50
+ debug(message, ...meta) {
51
+ this.logger.debug(message, ...meta);
52
+ }
53
+ }
54
+ exports.LoggerService = LoggerService;