@hotmeshio/hotmesh 0.5.0 → 0.5.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 (49) hide show
  1. package/README.md +234 -237
  2. package/build/modules/errors.d.ts +9 -0
  3. package/build/modules/errors.js +9 -0
  4. package/build/package.json +16 -14
  5. package/build/services/hotmesh/index.d.ts +9 -11
  6. package/build/services/hotmesh/index.js +9 -11
  7. package/build/services/memflow/entity.d.ts +168 -4
  8. package/build/services/memflow/entity.js +177 -15
  9. package/build/services/memflow/index.d.ts +8 -0
  10. package/build/services/memflow/index.js +8 -0
  11. package/build/services/memflow/worker.js +25 -0
  12. package/build/services/memflow/workflow/execChild.js +1 -0
  13. package/build/services/memflow/workflow/execHook.d.ts +2 -2
  14. package/build/services/memflow/workflow/execHook.js +19 -9
  15. package/build/services/memflow/workflow/index.d.ts +2 -4
  16. package/build/services/memflow/workflow/index.js +2 -4
  17. package/build/services/memflow/workflow/interruption.d.ts +28 -0
  18. package/build/services/memflow/workflow/interruption.js +43 -0
  19. package/build/services/memflow/workflow/proxyActivities.js +1 -0
  20. package/build/services/memflow/workflow/sleepFor.js +1 -0
  21. package/build/services/memflow/workflow/waitFor.js +4 -4
  22. package/build/services/search/index.d.ts +10 -0
  23. package/build/services/search/providers/postgres/postgres.d.ts +12 -0
  24. package/build/services/search/providers/postgres/postgres.js +209 -0
  25. package/build/services/search/providers/redis/ioredis.d.ts +4 -0
  26. package/build/services/search/providers/redis/ioredis.js +13 -0
  27. package/build/services/search/providers/redis/redis.d.ts +4 -0
  28. package/build/services/search/providers/redis/redis.js +13 -0
  29. package/build/services/store/providers/postgres/kvsql.d.ts +13 -37
  30. package/build/services/store/providers/postgres/kvsql.js +2 -2
  31. package/build/services/store/providers/postgres/kvtypes/hash/basic.d.ts +16 -0
  32. package/build/services/store/providers/postgres/kvtypes/hash/basic.js +480 -0
  33. package/build/services/store/providers/postgres/kvtypes/hash/expire.d.ts +5 -0
  34. package/build/services/store/providers/postgres/kvtypes/hash/expire.js +33 -0
  35. package/build/services/store/providers/postgres/kvtypes/hash/index.d.ts +29 -0
  36. package/build/services/store/providers/postgres/kvtypes/hash/index.js +190 -0
  37. package/build/services/store/providers/postgres/kvtypes/hash/jsonb.d.ts +14 -0
  38. package/build/services/store/providers/postgres/kvtypes/hash/jsonb.js +699 -0
  39. package/build/services/store/providers/postgres/kvtypes/hash/scan.d.ts +10 -0
  40. package/build/services/store/providers/postgres/kvtypes/hash/scan.js +91 -0
  41. package/build/services/store/providers/postgres/kvtypes/hash/types.d.ts +19 -0
  42. package/build/services/store/providers/postgres/kvtypes/hash/types.js +2 -0
  43. package/build/services/store/providers/postgres/kvtypes/hash/utils.d.ts +18 -0
  44. package/build/services/store/providers/postgres/kvtypes/hash/utils.js +90 -0
  45. package/build/types/memflow.d.ts +1 -1
  46. package/build/types/meshdata.d.ts +1 -1
  47. package/package.json +16 -14
  48. package/build/services/store/providers/postgres/kvtypes/hash.d.ts +0 -60
  49. package/build/services/store/providers/postgres/kvtypes/hash.js +0 -1287
@@ -19,6 +19,7 @@ exports.SetStateError = SetStateError;
19
19
  class MemFlowWaitForError extends Error {
20
20
  constructor(params) {
21
21
  super(`WaitFor Interruption`);
22
+ this.type = 'MemFlowWaitForError';
22
23
  this.signalId = params.signalId;
23
24
  this.index = params.index;
24
25
  this.workflowDimension = params.workflowDimension;
@@ -29,6 +30,7 @@ exports.MemFlowWaitForError = MemFlowWaitForError;
29
30
  class MemFlowProxyError extends Error {
30
31
  constructor(params) {
31
32
  super(`ProxyActivity Interruption`);
33
+ this.type = 'MemFlowProxyError';
32
34
  this.arguments = params.arguments;
33
35
  this.workflowId = params.workflowId;
34
36
  this.workflowTopic = params.workflowTopic;
@@ -48,6 +50,7 @@ exports.MemFlowProxyError = MemFlowProxyError;
48
50
  class MemFlowChildError extends Error {
49
51
  constructor(params) {
50
52
  super(`ExecChild Interruption`);
53
+ this.type = 'MemFlowChildError';
51
54
  this.arguments = params.arguments;
52
55
  this.workflowId = params.workflowId;
53
56
  this.workflowTopic = params.workflowTopic;
@@ -70,6 +73,7 @@ exports.MemFlowChildError = MemFlowChildError;
70
73
  class MemFlowWaitForAllError extends Error {
71
74
  constructor(params) {
72
75
  super(`Collation Interruption`);
76
+ this.type = 'MemFlowWaitForAllError';
73
77
  this.items = params.items;
74
78
  this.size = params.size;
75
79
  this.workflowId = params.workflowId;
@@ -85,6 +89,7 @@ exports.MemFlowWaitForAllError = MemFlowWaitForAllError;
85
89
  class MemFlowSleepError extends Error {
86
90
  constructor(params) {
87
91
  super(`SleepFor Interruption`);
92
+ this.type = 'MemFlowSleepError';
88
93
  this.duration = params.duration;
89
94
  this.workflowId = params.workflowId;
90
95
  this.index = params.index;
@@ -96,6 +101,7 @@ exports.MemFlowSleepError = MemFlowSleepError;
96
101
  class MemFlowTimeoutError extends Error {
97
102
  constructor(message, stack) {
98
103
  super(message);
104
+ this.type = 'MemFlowTimeoutError';
99
105
  if (this.stack) {
100
106
  this.stack = stack;
101
107
  }
@@ -106,6 +112,7 @@ exports.MemFlowTimeoutError = MemFlowTimeoutError;
106
112
  class MemFlowMaxedError extends Error {
107
113
  constructor(message, stackTrace) {
108
114
  super(message);
115
+ this.type = 'MemFlowMaxedError';
109
116
  if (stackTrace) {
110
117
  this.stack = stackTrace;
111
118
  }
@@ -116,6 +123,7 @@ exports.MemFlowMaxedError = MemFlowMaxedError;
116
123
  class MemFlowFatalError extends Error {
117
124
  constructor(message, stackTrace) {
118
125
  super(message);
126
+ this.type = 'MemFlowFatalError';
119
127
  if (stackTrace) {
120
128
  this.stack = stackTrace;
121
129
  }
@@ -126,6 +134,7 @@ exports.MemFlowFatalError = MemFlowFatalError;
126
134
  class MemFlowRetryError extends Error {
127
135
  constructor(message, stackTrace) {
128
136
  super(message);
137
+ this.type = 'MemFlowRetryError';
129
138
  if (stackTrace) {
130
139
  this.stack = stackTrace;
131
140
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hotmeshio/hotmesh",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
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:cycle": "NODE_ENV=test jest ./tests/functional/cycle/*.test.ts --detectOpenHandles --forceExit --verbose",
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/*.test.ts --detectOpenHandles --forceExit --verbose",
39
- "test:memflow:hook": "NODE_ENV=test jest ./tests/memflow/hook/*.test.ts --detectOpenHandles --forceExit --verbose",
40
- "test:memflow:interrupt": "NODE_ENV=test jest ./tests/memflow/interrupt/*.test.ts --detectOpenHandles --forceExit --verbose",
41
- "test:memflow:loopactivity": "NODE_ENV=test jest ./tests/memflow/loopactivity/*.test.ts --detectOpenHandles --forceExit --verbose",
42
- "test:memflow:nested": "NODE_ENV=test jest ./tests/memflow/nested/*.test.ts --detectOpenHandles --forceExit --verbose",
43
- "test:memflow:retry": "NODE_ENV=test jest ./tests/memflow/retry/*.test.ts --detectOpenHandles --forceExit --verbose",
44
- "test:memflow:sleep": "NODE_ENV=test jest ./tests/memflow/sleep/*.test.ts --detectOpenHandles --forceExit --verbose",
45
- "test:memflow:signal": "NODE_ENV=test jest ./tests/memflow/signal/*.test.ts --detectOpenHandles --forceExit --verbose",
46
- "test:memflow:unknown": "NODE_ENV=test jest ./tests/memflow/unknown/*.test.ts --detectOpenHandles --forceExit --verbose",
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
- * Redis, Postgres, or NATS into a resilient service mesh capable of running
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 Redis from 'ioredis';
58
+ * import { Client as Postgres } from 'pg';
63
59
  *
64
- * // Initialize with Redis backend
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: Redis,
70
- * options: { host: 'localhost', port: 6379 }
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/docs} - Complete documentation
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} - Academic paper on the architecture
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
- * Redis, Postgres, or NATS into a resilient service mesh capable of running
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 Redis from 'ioredis';
59
+ * import { Client as Postgres } from 'pg';
64
60
  *
65
- * // Initialize with Redis backend
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: Redis,
71
- * options: { host: 'localhost', port: 6379 }
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/docs} - Complete documentation
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} - Academic paper on the architecture
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: any): Promise<any>;
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<any>;
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
- * @private
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
- private deepMerge;
306
+ static createIndex(entity: string, field: string, hotMeshClient: HotMesh, indexType?: 'gin'): Promise<void>;
143
307
  }
@@ -71,7 +71,7 @@ class Entity {
71
71
  '@context': JSON.stringify(value),
72
72
  [ssGuid]: '', // Pass replay ID to hash module for transactional replay storage
73
73
  });
74
- return result || value;
74
+ return result;
75
75
  }
76
76
  /**
77
77
  * Deep merges the provided object with the existing entity
@@ -278,22 +278,184 @@ class Entity {
278
278
  });
279
279
  return newValue;
280
280
  }
281
+ // Static readonly find methods for cross-entity querying (not tied to specific workflow)
281
282
  /**
282
- * @private
283
+ * Finds entity records matching complex conditions using JSONB/SQL queries.
284
+ * This is a readonly operation that queries across all entities of a given type.
285
+ *
286
+ * @example
287
+ * ```typescript
288
+ * // Basic find with simple conditions
289
+ * const activeUsers = await Entity.find(
290
+ * 'user',
291
+ * { status: 'active', country: 'US' },
292
+ * hotMeshClient
293
+ * );
294
+ *
295
+ * // Complex query with comparison operators
296
+ * const seniorUsers = await Entity.find(
297
+ * 'user',
298
+ * {
299
+ * age: { $gte: 65 },
300
+ * status: 'active',
301
+ * 'preferences.notifications': true
302
+ * },
303
+ * hotMeshClient,
304
+ * { limit: 10, offset: 0 }
305
+ * );
306
+ *
307
+ * // Query with multiple conditions and nested objects
308
+ * const premiumUsers = await Entity.find(
309
+ * 'user',
310
+ * {
311
+ * 'subscription.type': 'premium',
312
+ * 'subscription.status': 'active',
313
+ * 'billing.amount': { $gt: 100 },
314
+ * 'profile.verified': true
315
+ * },
316
+ * hotMeshClient,
317
+ * { limit: 20 }
318
+ * );
319
+ *
320
+ * // Array conditions
321
+ * const taggedPosts = await Entity.find(
322
+ * 'post',
323
+ * {
324
+ * 'tags': { $in: ['typescript', 'javascript'] },
325
+ * 'status': 'published',
326
+ * 'views': { $gte: 1000 }
327
+ * },
328
+ * hotMeshClient
329
+ * );
330
+ * ```
283
331
  */
284
- deepMerge(target, source) {
285
- if (!source)
286
- return target;
287
- const output = { ...target };
288
- Object.keys(source).forEach(key => {
289
- if (source[key] instanceof Object && key in target) {
290
- output[key] = this.deepMerge(target[key], source[key]);
291
- }
292
- else {
293
- output[key] = source[key];
294
- }
295
- });
296
- return output;
332
+ static async find(entity, conditions, hotMeshClient, options) {
333
+ // Use SearchService for JSONB/SQL querying
334
+ const searchClient = hotMeshClient.engine.search;
335
+ return await searchClient.findEntities(entity, conditions, options);
336
+ }
337
+ /**
338
+ * Finds a specific entity record by its ID using direct JSONB/SQL queries.
339
+ * This is the most efficient method for retrieving a single entity record.
340
+ *
341
+ * @example
342
+ * ```typescript
343
+ * // Basic findById usage
344
+ * const user = await Entity.findById('user', 'user123', hotMeshClient);
345
+ *
346
+ * // Example with type checking
347
+ * interface User {
348
+ * id: string;
349
+ * name: string;
350
+ * email: string;
351
+ * preferences: {
352
+ * theme: 'light' | 'dark';
353
+ * notifications: boolean;
354
+ * };
355
+ * }
356
+ *
357
+ * const typedUser = await Entity.findById<User>('user', 'user456', hotMeshClient);
358
+ * console.log(typedUser.preferences.theme); // 'light' | 'dark'
359
+ *
360
+ * // Error handling example
361
+ * try {
362
+ * const order = await Entity.findById('order', 'order789', hotMeshClient);
363
+ * if (!order) {
364
+ * console.log('Order not found');
365
+ * return;
366
+ * }
367
+ * console.log('Order details:', order);
368
+ * } catch (error) {
369
+ * console.error('Error fetching order:', error);
370
+ * }
371
+ * ```
372
+ */
373
+ static async findById(entity, id, hotMeshClient) {
374
+ // Use SearchService for JSONB/SQL querying
375
+ const searchClient = hotMeshClient.engine.search;
376
+ return await searchClient.findEntityById(entity, id);
377
+ }
378
+ /**
379
+ * Finds entity records matching a specific field condition using JSONB/SQL queries.
380
+ * Supports various operators for flexible querying across all entities of a type.
381
+ *
382
+ * @example
383
+ * ```typescript
384
+ * // Basic equality search
385
+ * const activeUsers = await Entity.findByCondition(
386
+ * 'user',
387
+ * 'status',
388
+ * 'active',
389
+ * '=',
390
+ * hotMeshClient,
391
+ * { limit: 20 }
392
+ * );
393
+ *
394
+ * // Numeric comparison
395
+ * const highValueOrders = await Entity.findByCondition(
396
+ * 'order',
397
+ * 'total_amount',
398
+ * 1000,
399
+ * '>=',
400
+ * hotMeshClient
401
+ * );
402
+ *
403
+ * // Pattern matching with LIKE
404
+ * const gmailUsers = await Entity.findByCondition(
405
+ * 'user',
406
+ * 'email',
407
+ * '%@gmail.com',
408
+ * 'LIKE',
409
+ * hotMeshClient
410
+ * );
411
+ *
412
+ * // IN operator for multiple values
413
+ * const specificProducts = await Entity.findByCondition(
414
+ * 'product',
415
+ * 'category',
416
+ * ['electronics', 'accessories'],
417
+ * 'IN',
418
+ * hotMeshClient
419
+ * );
420
+ *
421
+ * // Not equals operator
422
+ * const nonPremiumUsers = await Entity.findByCondition(
423
+ * 'user',
424
+ * 'subscription_type',
425
+ * 'premium',
426
+ * '!=',
427
+ * hotMeshClient
428
+ * );
429
+ *
430
+ * // Date comparison
431
+ * const recentOrders = await Entity.findByCondition(
432
+ * 'order',
433
+ * 'created_at',
434
+ * new Date('2024-01-01'),
435
+ * '>',
436
+ * hotMeshClient,
437
+ * { limit: 50 }
438
+ * );
439
+ * ```
440
+ */
441
+ static async findByCondition(entity, field, value, operator = '=', hotMeshClient, options) {
442
+ // Use SearchService for JSONB/SQL querying
443
+ const searchClient = hotMeshClient.engine.search;
444
+ return await searchClient.findEntitiesByCondition(entity, field, value, operator, options);
445
+ }
446
+ /**
447
+ * Creates an efficient GIN index for a specific entity field to optimize queries.
448
+ *
449
+ * @example
450
+ * ```typescript
451
+ * await Entity.createIndex('user', 'email', hotMeshClient);
452
+ * await Entity.createIndex('user', 'status', hotMeshClient);
453
+ * ```
454
+ */
455
+ static async createIndex(entity, field, hotMeshClient, indexType = 'gin') {
456
+ // Use SearchService for index creation
457
+ const searchClient = hotMeshClient.engine.search;
458
+ return await searchClient.createEntityIndex(entity, field, indexType);
297
459
  }
298
460
  }
299
461
  exports.Entity = Entity;