@hotmeshio/hotmesh 0.5.1 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -48
- package/build/package.json +16 -14
- package/build/services/hotmesh/index.d.ts +9 -11
- package/build/services/hotmesh/index.js +9 -11
- package/build/services/memflow/entity.d.ts +168 -4
- package/build/services/memflow/entity.js +177 -15
- package/build/services/memflow/workflow/index.d.ts +2 -4
- package/build/services/memflow/workflow/index.js +2 -4
- package/build/services/memflow/workflow/interruption.d.ts +6 -4
- package/build/services/memflow/workflow/interruption.js +6 -4
- package/build/services/memflow/workflow/waitFor.js +1 -0
- package/build/services/search/index.d.ts +10 -0
- package/build/services/search/providers/postgres/postgres.d.ts +12 -0
- package/build/services/search/providers/postgres/postgres.js +209 -0
- package/build/services/search/providers/redis/ioredis.d.ts +4 -0
- package/build/services/search/providers/redis/ioredis.js +13 -0
- package/build/services/search/providers/redis/redis.d.ts +4 -0
- package/build/services/search/providers/redis/redis.js +13 -0
- package/build/services/store/providers/postgres/kvsql.d.ts +13 -37
- package/build/services/store/providers/postgres/kvsql.js +2 -2
- package/build/services/store/providers/postgres/kvtypes/hash/basic.d.ts +16 -0
- package/build/services/store/providers/postgres/kvtypes/hash/basic.js +480 -0
- package/build/services/store/providers/postgres/kvtypes/hash/expire.d.ts +5 -0
- package/build/services/store/providers/postgres/kvtypes/hash/expire.js +33 -0
- package/build/services/store/providers/postgres/kvtypes/hash/index.d.ts +29 -0
- package/build/services/store/providers/postgres/kvtypes/hash/index.js +190 -0
- package/build/services/store/providers/postgres/kvtypes/hash/jsonb.d.ts +14 -0
- package/build/services/store/providers/postgres/kvtypes/hash/jsonb.js +699 -0
- package/build/services/store/providers/postgres/kvtypes/hash/scan.d.ts +10 -0
- package/build/services/store/providers/postgres/kvtypes/hash/scan.js +91 -0
- package/build/services/store/providers/postgres/kvtypes/hash/types.d.ts +19 -0
- package/build/services/store/providers/postgres/kvtypes/hash/types.js +2 -0
- package/build/services/store/providers/postgres/kvtypes/hash/utils.d.ts +18 -0
- package/build/services/store/providers/postgres/kvtypes/hash/utils.js +90 -0
- package/build/types/memflow.d.ts +1 -1
- package/build/types/meshdata.d.ts +1 -1
- package/package.json +16 -14
- package/build/services/store/providers/postgres/kvtypes/hash.d.ts +0 -60
- package/build/services/store/providers/postgres/kvtypes/hash.js +0 -1287
package/README.md
CHANGED
|
@@ -16,11 +16,11 @@ Use HotMesh to:
|
|
|
16
16
|
|
|
17
17
|
## Table of Contents
|
|
18
18
|
|
|
19
|
-
1. [Quick Start](
|
|
20
|
-
2. [Permanent Memory Architecture](
|
|
21
|
-
3. [Durable AI Agents](
|
|
22
|
-
4. [Building Pipelines with State](
|
|
23
|
-
5. [Documentation & Links](
|
|
19
|
+
1. [Quick Start](#quick-start)
|
|
20
|
+
2. [Permanent Memory Architecture](#permanent-memory-architecture)
|
|
21
|
+
3. [Durable AI Agents](#durable-ai-agents)
|
|
22
|
+
4. [Building Pipelines with State](#building-pipelines-with-state)
|
|
23
|
+
5. [Documentation & Links](#documentation--links)
|
|
24
24
|
|
|
25
25
|
---
|
|
26
26
|
|
|
@@ -106,9 +106,9 @@ This index improves performance for filtered queries while reducing index size.
|
|
|
106
106
|
|
|
107
107
|
## Durable AI Agents
|
|
108
108
|
|
|
109
|
-
Agents often require memory—context that persists between invocations, spans multiple perspectives, or outlives a single process.
|
|
109
|
+
Agents often require memory—context that persists between invocations, spans multiple perspectives, or outlives a single process.
|
|
110
110
|
|
|
111
|
-
The following example builds a "research agent" that
|
|
111
|
+
The following example builds a "research agent" that executes hooks with different perspectives and then synthesizes. The data-first approach sets up initial state and then uses temporary hook functions to augment over the lifecycle of the entity record.
|
|
112
112
|
|
|
113
113
|
### Research Agent Example
|
|
114
114
|
|
|
@@ -116,54 +116,57 @@ The following example builds a "research agent" that runs sub-flows and self-ref
|
|
|
116
116
|
|
|
117
117
|
```ts
|
|
118
118
|
export async function researchAgent(query: string): Promise<any> {
|
|
119
|
-
const
|
|
119
|
+
const agent = await MemFlow.workflow.entity();
|
|
120
120
|
|
|
121
121
|
// Set up shared memory for this agent session
|
|
122
|
-
|
|
122
|
+
const initialState = {
|
|
123
123
|
query,
|
|
124
124
|
findings: [],
|
|
125
125
|
perspectives: {},
|
|
126
126
|
confidence: 0,
|
|
127
|
-
|
|
128
|
-
|
|
127
|
+
verification: {},
|
|
128
|
+
status: 'researching',
|
|
129
|
+
startTime: new Date().toISOString(),
|
|
130
|
+
}
|
|
131
|
+
await agent.set<typeof initialState>(initialState);
|
|
129
132
|
|
|
130
|
-
// Launch perspective hooks in parallel
|
|
131
|
-
|
|
133
|
+
// Launch perspective hooks in parallel
|
|
134
|
+
await MemFlow.workflow.execHook({
|
|
132
135
|
taskQueue: 'agents',
|
|
133
136
|
workflowName: 'optimisticPerspective',
|
|
134
|
-
args: [query]
|
|
137
|
+
args: [query],
|
|
138
|
+
signalId: 'optimistic-complete'
|
|
135
139
|
});
|
|
136
140
|
|
|
137
|
-
|
|
141
|
+
await MemFlow.workflow.execHook({
|
|
138
142
|
taskQueue: 'agents',
|
|
139
143
|
workflowName: 'skepticalPerspective',
|
|
140
|
-
args: [query]
|
|
144
|
+
args: [query],
|
|
145
|
+
signalId: 'skeptical-complete'
|
|
141
146
|
});
|
|
142
147
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
workflowName: 'factCheckAgent',
|
|
147
|
-
workflowId: `fact-check-${Date.now()}`,
|
|
148
|
+
await MemFlow.workflow.execHook({
|
|
149
|
+
taskQueue: 'agents',
|
|
150
|
+
workflowName: 'verificationHook',
|
|
148
151
|
args: [query],
|
|
149
|
-
|
|
152
|
+
signalId: 'verification-complete'
|
|
150
153
|
});
|
|
151
154
|
|
|
152
|
-
// Wait for all views to complete before analyzing
|
|
153
|
-
await Promise.all([optimistic, skeptical, factChecker]);
|
|
154
|
-
|
|
155
|
-
// Final synthesis: aggregate and compare all perspectives
|
|
156
155
|
await MemFlow.workflow.execHook({
|
|
157
156
|
taskQueue: 'perspectives',
|
|
158
157
|
workflowName: 'synthesizePerspectives',
|
|
159
|
-
args: []
|
|
158
|
+
args: [],
|
|
159
|
+
signalId: 'synthesis-complete',
|
|
160
160
|
});
|
|
161
161
|
|
|
162
|
-
return
|
|
162
|
+
// return analysis, verification, and synthesis
|
|
163
|
+
return await agent.get();
|
|
163
164
|
}
|
|
164
165
|
```
|
|
165
166
|
|
|
166
|
-
|
|
167
|
+
> 💡 A complete implementation of this Research Agent example with tests, OpenAI integration, and multi-perspective analysis can be found in the [agent test suite](https://github.com/hotmeshio/sdk-typescript/tree/main/tests/memflow/agent).
|
|
168
|
+
|
|
169
|
+
#### Perspective Hooks
|
|
167
170
|
|
|
168
171
|
```ts
|
|
169
172
|
// Optimistic hook looks for affirming evidence
|
|
@@ -182,27 +185,11 @@ export async function skepticalPerspective(query: string, config: {signal: strin
|
|
|
182
185
|
await entity.merge({ perspectives: { skeptical: { counterEvidence, confidence: 0.6 }}});
|
|
183
186
|
await MemFlow.workflow.signal(config.signal, {});
|
|
184
187
|
}
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
#### Child Agent: Fact Checker
|
|
188
|
-
|
|
189
|
-
```ts
|
|
190
|
-
// A dedicated child agent with its own entity type and context
|
|
191
|
-
export async function factCheckAgent(query: string): Promise<any> {
|
|
192
|
-
const entity = await MemFlow.workflow.entity();
|
|
193
|
-
await entity.set({ query, sources: [], verifications: [] });
|
|
194
188
|
|
|
195
|
-
|
|
196
|
-
taskQueue: 'agents',
|
|
197
|
-
workflowName: 'verifySourceCredibility',
|
|
198
|
-
args: [query]
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
return await entity.get();
|
|
202
|
-
}
|
|
189
|
+
// Other hooks...
|
|
203
190
|
```
|
|
204
191
|
|
|
205
|
-
#### Synthesis
|
|
192
|
+
#### Synthesis Hook
|
|
206
193
|
|
|
207
194
|
```ts
|
|
208
195
|
// Synthesis hook aggregates different viewpoints
|
|
@@ -229,7 +216,7 @@ export async function synthesizePerspectives(config: {signal: string}): Promise<
|
|
|
229
216
|
|
|
230
217
|
## Building Pipelines with State
|
|
231
218
|
|
|
232
|
-
HotMesh treats pipelines as long-lived records
|
|
219
|
+
HotMesh treats pipelines as long-lived records. Every pipeline run is stateful, resumable, and traceable.
|
|
233
220
|
|
|
234
221
|
### Setup a Data Pipeline
|
|
235
222
|
|
|
@@ -355,6 +342,8 @@ export async function triggerRefresh() {
|
|
|
355
342
|
}
|
|
356
343
|
```
|
|
357
344
|
|
|
345
|
+
> 💡 A complete implementation of this Pipeline example with OpenAI Vision integration, processing hooks, and document workflow automation can be found in the [pipeline test suite](https://github.com/hotmeshio/sdk-typescript/tree/main/tests/memflow/pipeline).
|
|
346
|
+
|
|
358
347
|
---
|
|
359
348
|
|
|
360
349
|
## Documentation & Links
|
package/build/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hotmeshio/hotmesh",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "Permanent-Memory Workflows & AI Agents",
|
|
5
5
|
"main": "./build/index.js",
|
|
6
6
|
"types": "./build/index.d.ts",
|
|
@@ -27,26 +27,27 @@
|
|
|
27
27
|
"test:connect:postgres": "NODE_ENV=test jest ./tests/unit/services/connector/providers/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
28
28
|
"test:connect:redis": "NODE_ENV=test jest ./tests/unit/services/connector/providers/redis.test.ts --detectOpenHandles --forceExit --verbose",
|
|
29
29
|
"test:connect:nats": "NODE_ENV=test jest ./tests/unit/services/connector/providers/nats.test.ts --detectOpenHandles --forceExit --verbose",
|
|
30
|
-
"test:
|
|
31
|
-
"test:memflow": "NODE_ENV=test jest ./tests/memflow/*/*.test.ts --detectOpenHandles --forceExit --verbose",
|
|
30
|
+
"test:memflow": "NODE_ENV=test jest ./tests/memflow/*/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
32
31
|
"test:memflow:basic": "HMSH_LOGLEVEL=info NODE_ENV=test jest ./tests/memflow/basic/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
33
32
|
"test:memflow:collision": "NODE_ENV=test jest ./tests/memflow/collision/*.test.ts --detectOpenHandles --forceExit --verbose",
|
|
34
33
|
"test:memflow:fatal": "NODE_ENV=test jest ./tests/memflow/fatal/*.test.ts --detectOpenHandles --forceExit --verbose",
|
|
35
34
|
"test:memflow:goodbye": "NODE_ENV=test jest ./tests/memflow/goodbye/*.test.ts --detectOpenHandles --forceExit --verbose",
|
|
36
35
|
"test:memflow:entity": "NODE_ENV=test HMSH_LOGLEVEL=debug jest ./tests/memflow/entity/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
37
36
|
"test:memflow:agent": "NODE_ENV=test HMSH_LOGLEVEL=debug jest ./tests/memflow/agent/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
38
|
-
"test:memflow:hello": "HMSH_TELEMETRY=debug HMSH_LOGLEVEL=debug HMSH_IS_CLUSTER=true NODE_ENV=test jest ./tests/memflow/helloworld
|
|
39
|
-
"test:memflow:hook": "NODE_ENV=test jest ./tests/memflow/hook
|
|
40
|
-
"test:memflow:interrupt": "NODE_ENV=test jest ./tests/memflow/interrupt
|
|
41
|
-
"test:memflow:loopactivity": "NODE_ENV=test jest ./tests/memflow/loopactivity
|
|
42
|
-
"test:memflow:nested": "NODE_ENV=test jest ./tests/memflow/nested
|
|
43
|
-
"test:memflow:
|
|
44
|
-
"test:memflow:
|
|
45
|
-
"test:memflow:
|
|
46
|
-
"test:memflow:
|
|
37
|
+
"test:memflow:hello": "HMSH_TELEMETRY=debug HMSH_LOGLEVEL=debug HMSH_IS_CLUSTER=true NODE_ENV=test jest ./tests/memflow/helloworld/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
38
|
+
"test:memflow:hook": "NODE_ENV=test jest ./tests/memflow/hook/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
39
|
+
"test:memflow:interrupt": "NODE_ENV=test jest ./tests/memflow/interrupt/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
40
|
+
"test:memflow:loopactivity": "NODE_ENV=test jest ./tests/memflow/loopactivity/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
41
|
+
"test:memflow:nested": "NODE_ENV=test jest ./tests/memflow/nested/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
42
|
+
"test:memflow:pipeline": "NODE_ENV=test jest ./tests/memflow/pipeline/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
43
|
+
"test:memflow:retry": "NODE_ENV=test jest ./tests/memflow/retry/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
44
|
+
"test:memflow:sleep": "NODE_ENV=test jest ./tests/memflow/sleep/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
45
|
+
"test:memflow:signal": "NODE_ENV=test jest ./tests/memflow/signal/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
46
|
+
"test:memflow:unknown": "NODE_ENV=test jest ./tests/memflow/unknown/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
47
|
+
"test:cycle": "NODE_ENV=test jest ./tests/functional/cycle/*.test.ts --detectOpenHandles --forceExit --verbose",
|
|
48
|
+
"test:functional": "NODE_ENV=test jest ./tests/functional/* --detectOpenHandles --forceExit --verbose",
|
|
47
49
|
"test:emit": "NODE_ENV=test jest ./tests/functional/emit/*.test.ts --detectOpenHandles --forceExit --verbose",
|
|
48
50
|
"test:pending": "NODE_ENV=test jest ./tests/functional/pending/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
49
|
-
"test:functional": "NODE_ENV=test jest ./tests/functional/* --detectOpenHandles --forceExit --verbose",
|
|
50
51
|
"test:hmsh": "NODE_ENV=test jest ./tests/functional/*.test.ts --detectOpenHandles --verbose --forceExit",
|
|
51
52
|
"test:hook": "NODE_ENV=test jest ./tests/functional/hook/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
52
53
|
"test:interrupt": "NODE_ENV=test jest ./tests/functional/interrupt/*.test.ts --detectOpenHandles --forceExit --verbose",
|
|
@@ -74,7 +75,6 @@
|
|
|
74
75
|
"test:sub:postgres": "NODE_ENV=test jest ./tests/functional/sub/providers/postgres/postgres.test.ts --detectOpenHandles --forceExit --verbose",
|
|
75
76
|
"test:sub:nats": "NODE_ENV=test jest ./tests/functional/sub/providers/nats/nats.test.ts --detectOpenHandles --forceExit --verbose",
|
|
76
77
|
"test:trigger": "NODE_ENV=test jest ./tests/unit/services/activities/trigger.test.ts --detectOpenHandles --forceExit --verbose",
|
|
77
|
-
"test:meshdata": "NODE_ENV=test jest ./tests/meshdata/postgres.test.ts --forceExit --verbose --detectOpenHandles",
|
|
78
78
|
"test:meshos": "HMSH_LOGLEVEL=info NODE_ENV=test HMSH_IS_CLUSTER=true jest ./tests/meshos/*.test.ts --forceExit --verbose --detectOpenHandles",
|
|
79
79
|
"test:meshcall": "NODE_ENV=test jest ./tests/meshcall/*.test.ts --forceExit --verbose --detectOpenHandles",
|
|
80
80
|
"test:unit": "NODE_ENV=test jest ./tests/unit/*/*/index.test.ts --detectOpenHandles --forceExit --verbose"
|
|
@@ -109,6 +109,7 @@
|
|
|
109
109
|
"@types/pg": "^8.10.0",
|
|
110
110
|
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
|
111
111
|
"@typescript-eslint/parser": "^5.62.0",
|
|
112
|
+
"dotenv": "^16.3.1",
|
|
112
113
|
"eslint": "^8.57.0",
|
|
113
114
|
"eslint-config-prettier": "^9.1.0",
|
|
114
115
|
"eslint-plugin-import": "^2.29.1",
|
|
@@ -117,6 +118,7 @@
|
|
|
117
118
|
"javascript-obfuscator": "^4.1.1",
|
|
118
119
|
"jest": "^29.5.0",
|
|
119
120
|
"nats": "^2.28.0",
|
|
121
|
+
"openai": "^5.9.0",
|
|
120
122
|
"pg": "^8.10.0",
|
|
121
123
|
"redis": "^4.6.13",
|
|
122
124
|
"rimraf": "^4.4.1",
|
|
@@ -11,7 +11,7 @@ import { JobStatsInput, GetStatsOptions, IdsResponse, StatsResponse } from '../.
|
|
|
11
11
|
import { StreamCode, StreamData, StreamDataResponse, StreamStatus } from '../../types/stream';
|
|
12
12
|
/**
|
|
13
13
|
* HotMesh is a distributed, reentrant process orchestration engine that transforms
|
|
14
|
-
*
|
|
14
|
+
* Postgres into a resilient service mesh capable of running
|
|
15
15
|
* fault-tolerant workflows across multiple services and systems.
|
|
16
16
|
*
|
|
17
17
|
* ## Core Concepts
|
|
@@ -25,14 +25,10 @@ import { StreamCode, StreamData, StreamDataResponse, StreamStatus } from '../../
|
|
|
25
25
|
* provides built-in retry logic, idempotency, and failure recovery. Your business
|
|
26
26
|
* logic doesn't need to handle timeouts or retries - the engine manages all of that.
|
|
27
27
|
*
|
|
28
|
-
* **Multi-Provider Support**: Supports Redis/ValKey, Postgres, and NATS as backend
|
|
29
|
-
* providers, allowing you to leverage existing infrastructure investments.
|
|
30
|
-
*
|
|
31
28
|
* ## Key Features
|
|
32
29
|
*
|
|
33
30
|
* - **Fault Tolerance**: Automatic retry, timeout, and failure recovery
|
|
34
31
|
* - **Distributed Execution**: No single point of failure
|
|
35
|
-
* - **Multi-Provider**: Redis, Postgres, NATS backend support
|
|
36
32
|
* - **YAML-Driven**: Model-driven development with declarative workflow definitions
|
|
37
33
|
* - **OpenTelemetry**: Built-in observability and tracing
|
|
38
34
|
* - **Durable State**: Workflow state persists across system restarts
|
|
@@ -59,15 +55,17 @@ import { StreamCode, StreamData, StreamDataResponse, StreamStatus } from '../../
|
|
|
59
55
|
* @example
|
|
60
56
|
* ```typescript
|
|
61
57
|
* import { HotMesh } from '@hotmeshio/hotmesh';
|
|
62
|
-
* import
|
|
58
|
+
* import { Client as Postgres } from 'pg';
|
|
63
59
|
*
|
|
64
|
-
* // Initialize with
|
|
60
|
+
* // Initialize with Postgres backend
|
|
65
61
|
* const hotMesh = await HotMesh.init({
|
|
66
62
|
* appId: 'my-app',
|
|
67
63
|
* engine: {
|
|
68
64
|
* connection: {
|
|
69
|
-
* class:
|
|
70
|
-
* options: {
|
|
65
|
+
* class: Postgres,
|
|
66
|
+
* options: {
|
|
67
|
+
* connectionString: 'postgresql://user:pass@localhost:5432/db'
|
|
68
|
+
* }
|
|
71
69
|
* }
|
|
72
70
|
* }
|
|
73
71
|
* });
|
|
@@ -192,9 +190,9 @@ import { StreamCode, StreamData, StreamDataResponse, StreamStatus } from '../../
|
|
|
192
190
|
* await HotMesh.stop();
|
|
193
191
|
* ```
|
|
194
192
|
*
|
|
195
|
-
* @see {@link https://hotmesh.io/
|
|
193
|
+
* @see {@link https://docs.hotmesh.io/} - Complete documentation
|
|
196
194
|
* @see {@link https://github.com/hotmeshio/samples-typescript} - Examples and tutorials
|
|
197
|
-
* @see {@link https://zenodo.org/records/12168558} -
|
|
195
|
+
* @see {@link https://zenodo.org/records/12168558} - White paper on the architecture
|
|
198
196
|
*/
|
|
199
197
|
declare class HotMesh {
|
|
200
198
|
namespace: string;
|
|
@@ -12,7 +12,7 @@ const worker_1 = require("../worker");
|
|
|
12
12
|
const enums_1 = require("../../modules/enums");
|
|
13
13
|
/**
|
|
14
14
|
* HotMesh is a distributed, reentrant process orchestration engine that transforms
|
|
15
|
-
*
|
|
15
|
+
* Postgres into a resilient service mesh capable of running
|
|
16
16
|
* fault-tolerant workflows across multiple services and systems.
|
|
17
17
|
*
|
|
18
18
|
* ## Core Concepts
|
|
@@ -26,14 +26,10 @@ const enums_1 = require("../../modules/enums");
|
|
|
26
26
|
* provides built-in retry logic, idempotency, and failure recovery. Your business
|
|
27
27
|
* logic doesn't need to handle timeouts or retries - the engine manages all of that.
|
|
28
28
|
*
|
|
29
|
-
* **Multi-Provider Support**: Supports Redis/ValKey, Postgres, and NATS as backend
|
|
30
|
-
* providers, allowing you to leverage existing infrastructure investments.
|
|
31
|
-
*
|
|
32
29
|
* ## Key Features
|
|
33
30
|
*
|
|
34
31
|
* - **Fault Tolerance**: Automatic retry, timeout, and failure recovery
|
|
35
32
|
* - **Distributed Execution**: No single point of failure
|
|
36
|
-
* - **Multi-Provider**: Redis, Postgres, NATS backend support
|
|
37
33
|
* - **YAML-Driven**: Model-driven development with declarative workflow definitions
|
|
38
34
|
* - **OpenTelemetry**: Built-in observability and tracing
|
|
39
35
|
* - **Durable State**: Workflow state persists across system restarts
|
|
@@ -60,15 +56,17 @@ const enums_1 = require("../../modules/enums");
|
|
|
60
56
|
* @example
|
|
61
57
|
* ```typescript
|
|
62
58
|
* import { HotMesh } from '@hotmeshio/hotmesh';
|
|
63
|
-
* import
|
|
59
|
+
* import { Client as Postgres } from 'pg';
|
|
64
60
|
*
|
|
65
|
-
* // Initialize with
|
|
61
|
+
* // Initialize with Postgres backend
|
|
66
62
|
* const hotMesh = await HotMesh.init({
|
|
67
63
|
* appId: 'my-app',
|
|
68
64
|
* engine: {
|
|
69
65
|
* connection: {
|
|
70
|
-
* class:
|
|
71
|
-
* options: {
|
|
66
|
+
* class: Postgres,
|
|
67
|
+
* options: {
|
|
68
|
+
* connectionString: 'postgresql://user:pass@localhost:5432/db'
|
|
69
|
+
* }
|
|
72
70
|
* }
|
|
73
71
|
* }
|
|
74
72
|
* });
|
|
@@ -193,9 +191,9 @@ const enums_1 = require("../../modules/enums");
|
|
|
193
191
|
* await HotMesh.stop();
|
|
194
192
|
* ```
|
|
195
193
|
*
|
|
196
|
-
* @see {@link https://hotmesh.io/
|
|
194
|
+
* @see {@link https://docs.hotmesh.io/} - Complete documentation
|
|
197
195
|
* @see {@link https://github.com/hotmeshio/samples-typescript} - Examples and tutorials
|
|
198
|
-
* @see {@link https://zenodo.org/records/12168558} -
|
|
196
|
+
* @see {@link https://zenodo.org/records/12168558} - White paper on the architecture
|
|
199
197
|
*/
|
|
200
198
|
class HotMesh {
|
|
201
199
|
/**
|
|
@@ -62,7 +62,7 @@ export declare class Entity {
|
|
|
62
62
|
* const entity = await workflow.entity();
|
|
63
63
|
* await entity.set({ user: { id: 123, name: "John" } });
|
|
64
64
|
*/
|
|
65
|
-
set(value:
|
|
65
|
+
set<T>(value: T): Promise<T>;
|
|
66
66
|
/**
|
|
67
67
|
* Deep merges the provided object with the existing entity
|
|
68
68
|
*
|
|
@@ -79,7 +79,7 @@ export declare class Entity {
|
|
|
79
79
|
* const user = await entity.get("user");
|
|
80
80
|
* const email = await entity.get("user.email");
|
|
81
81
|
*/
|
|
82
|
-
get(path?: string): Promise<
|
|
82
|
+
get<T>(path?: string): Promise<T>;
|
|
83
83
|
/**
|
|
84
84
|
* Deletes a value from the entity by path
|
|
85
85
|
*
|
|
@@ -137,7 +137,171 @@ export declare class Entity {
|
|
|
137
137
|
*/
|
|
138
138
|
setIfNotExists(path: string, value: any): Promise<any>;
|
|
139
139
|
/**
|
|
140
|
-
*
|
|
140
|
+
* Finds entity records matching complex conditions using JSONB/SQL queries.
|
|
141
|
+
* This is a readonly operation that queries across all entities of a given type.
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```typescript
|
|
145
|
+
* // Basic find with simple conditions
|
|
146
|
+
* const activeUsers = await Entity.find(
|
|
147
|
+
* 'user',
|
|
148
|
+
* { status: 'active', country: 'US' },
|
|
149
|
+
* hotMeshClient
|
|
150
|
+
* );
|
|
151
|
+
*
|
|
152
|
+
* // Complex query with comparison operators
|
|
153
|
+
* const seniorUsers = await Entity.find(
|
|
154
|
+
* 'user',
|
|
155
|
+
* {
|
|
156
|
+
* age: { $gte: 65 },
|
|
157
|
+
* status: 'active',
|
|
158
|
+
* 'preferences.notifications': true
|
|
159
|
+
* },
|
|
160
|
+
* hotMeshClient,
|
|
161
|
+
* { limit: 10, offset: 0 }
|
|
162
|
+
* );
|
|
163
|
+
*
|
|
164
|
+
* // Query with multiple conditions and nested objects
|
|
165
|
+
* const premiumUsers = await Entity.find(
|
|
166
|
+
* 'user',
|
|
167
|
+
* {
|
|
168
|
+
* 'subscription.type': 'premium',
|
|
169
|
+
* 'subscription.status': 'active',
|
|
170
|
+
* 'billing.amount': { $gt: 100 },
|
|
171
|
+
* 'profile.verified': true
|
|
172
|
+
* },
|
|
173
|
+
* hotMeshClient,
|
|
174
|
+
* { limit: 20 }
|
|
175
|
+
* );
|
|
176
|
+
*
|
|
177
|
+
* // Array conditions
|
|
178
|
+
* const taggedPosts = await Entity.find(
|
|
179
|
+
* 'post',
|
|
180
|
+
* {
|
|
181
|
+
* 'tags': { $in: ['typescript', 'javascript'] },
|
|
182
|
+
* 'status': 'published',
|
|
183
|
+
* 'views': { $gte: 1000 }
|
|
184
|
+
* },
|
|
185
|
+
* hotMeshClient
|
|
186
|
+
* );
|
|
187
|
+
* ```
|
|
188
|
+
*/
|
|
189
|
+
static find(entity: string, conditions: Record<string, any>, hotMeshClient: HotMesh, options?: {
|
|
190
|
+
limit?: number;
|
|
191
|
+
offset?: number;
|
|
192
|
+
}): Promise<any[]>;
|
|
193
|
+
/**
|
|
194
|
+
* Finds a specific entity record by its ID using direct JSONB/SQL queries.
|
|
195
|
+
* This is the most efficient method for retrieving a single entity record.
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* ```typescript
|
|
199
|
+
* // Basic findById usage
|
|
200
|
+
* const user = await Entity.findById('user', 'user123', hotMeshClient);
|
|
201
|
+
*
|
|
202
|
+
* // Example with type checking
|
|
203
|
+
* interface User {
|
|
204
|
+
* id: string;
|
|
205
|
+
* name: string;
|
|
206
|
+
* email: string;
|
|
207
|
+
* preferences: {
|
|
208
|
+
* theme: 'light' | 'dark';
|
|
209
|
+
* notifications: boolean;
|
|
210
|
+
* };
|
|
211
|
+
* }
|
|
212
|
+
*
|
|
213
|
+
* const typedUser = await Entity.findById<User>('user', 'user456', hotMeshClient);
|
|
214
|
+
* console.log(typedUser.preferences.theme); // 'light' | 'dark'
|
|
215
|
+
*
|
|
216
|
+
* // Error handling example
|
|
217
|
+
* try {
|
|
218
|
+
* const order = await Entity.findById('order', 'order789', hotMeshClient);
|
|
219
|
+
* if (!order) {
|
|
220
|
+
* console.log('Order not found');
|
|
221
|
+
* return;
|
|
222
|
+
* }
|
|
223
|
+
* console.log('Order details:', order);
|
|
224
|
+
* } catch (error) {
|
|
225
|
+
* console.error('Error fetching order:', error);
|
|
226
|
+
* }
|
|
227
|
+
* ```
|
|
228
|
+
*/
|
|
229
|
+
static findById(entity: string, id: string, hotMeshClient: HotMesh): Promise<any>;
|
|
230
|
+
/**
|
|
231
|
+
* Finds entity records matching a specific field condition using JSONB/SQL queries.
|
|
232
|
+
* Supports various operators for flexible querying across all entities of a type.
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* ```typescript
|
|
236
|
+
* // Basic equality search
|
|
237
|
+
* const activeUsers = await Entity.findByCondition(
|
|
238
|
+
* 'user',
|
|
239
|
+
* 'status',
|
|
240
|
+
* 'active',
|
|
241
|
+
* '=',
|
|
242
|
+
* hotMeshClient,
|
|
243
|
+
* { limit: 20 }
|
|
244
|
+
* );
|
|
245
|
+
*
|
|
246
|
+
* // Numeric comparison
|
|
247
|
+
* const highValueOrders = await Entity.findByCondition(
|
|
248
|
+
* 'order',
|
|
249
|
+
* 'total_amount',
|
|
250
|
+
* 1000,
|
|
251
|
+
* '>=',
|
|
252
|
+
* hotMeshClient
|
|
253
|
+
* );
|
|
254
|
+
*
|
|
255
|
+
* // Pattern matching with LIKE
|
|
256
|
+
* const gmailUsers = await Entity.findByCondition(
|
|
257
|
+
* 'user',
|
|
258
|
+
* 'email',
|
|
259
|
+
* '%@gmail.com',
|
|
260
|
+
* 'LIKE',
|
|
261
|
+
* hotMeshClient
|
|
262
|
+
* );
|
|
263
|
+
*
|
|
264
|
+
* // IN operator for multiple values
|
|
265
|
+
* const specificProducts = await Entity.findByCondition(
|
|
266
|
+
* 'product',
|
|
267
|
+
* 'category',
|
|
268
|
+
* ['electronics', 'accessories'],
|
|
269
|
+
* 'IN',
|
|
270
|
+
* hotMeshClient
|
|
271
|
+
* );
|
|
272
|
+
*
|
|
273
|
+
* // Not equals operator
|
|
274
|
+
* const nonPremiumUsers = await Entity.findByCondition(
|
|
275
|
+
* 'user',
|
|
276
|
+
* 'subscription_type',
|
|
277
|
+
* 'premium',
|
|
278
|
+
* '!=',
|
|
279
|
+
* hotMeshClient
|
|
280
|
+
* );
|
|
281
|
+
*
|
|
282
|
+
* // Date comparison
|
|
283
|
+
* const recentOrders = await Entity.findByCondition(
|
|
284
|
+
* 'order',
|
|
285
|
+
* 'created_at',
|
|
286
|
+
* new Date('2024-01-01'),
|
|
287
|
+
* '>',
|
|
288
|
+
* hotMeshClient,
|
|
289
|
+
* { limit: 50 }
|
|
290
|
+
* );
|
|
291
|
+
* ```
|
|
292
|
+
*/
|
|
293
|
+
static findByCondition(entity: string, field: string, value: any, operator: '=' | '!=' | '>' | '<' | '>=' | '<=' | 'LIKE' | 'IN', hotMeshClient: HotMesh, options?: {
|
|
294
|
+
limit?: number;
|
|
295
|
+
offset?: number;
|
|
296
|
+
}): Promise<any[]>;
|
|
297
|
+
/**
|
|
298
|
+
* Creates an efficient GIN index for a specific entity field to optimize queries.
|
|
299
|
+
*
|
|
300
|
+
* @example
|
|
301
|
+
* ```typescript
|
|
302
|
+
* await Entity.createIndex('user', 'email', hotMeshClient);
|
|
303
|
+
* await Entity.createIndex('user', 'status', hotMeshClient);
|
|
304
|
+
* ```
|
|
141
305
|
*/
|
|
142
|
-
|
|
306
|
+
static createIndex(entity: string, field: string, hotMeshClient: HotMesh, indexType?: 'gin'): Promise<void>;
|
|
143
307
|
}
|