@hotmeshio/hotmesh 0.22.1 → 0.22.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.
@@ -34,7 +34,8 @@ export interface EscalationEntry {
34
34
  entity: string | null;
35
35
  description: string | null;
36
36
  role: string | null;
37
- status: 'pending' | 'claimed' | 'resolved' | 'cancelled' | 'expired';
37
+ /** Lifecycle status. Claims are implicit: status='pending' + assigned_to IS NOT NULL + assigned_until > NOW(). */
38
+ status: 'pending' | 'resolved' | 'cancelled' | 'expired';
38
39
  priority: number;
39
40
  assigned_to: string | null;
40
41
  assigned_until: Date | null;
@@ -53,8 +54,12 @@ export interface EscalationEntry {
53
54
  trace_id: string | null;
54
55
  span_id: string | null;
55
56
  expires_at: Date | null;
57
+ /** Nullable passthrough column — populated when downstream needs task-level context. */
58
+ task_id: string | null;
56
59
  created_at: Date;
57
60
  updated_at: Date;
61
+ /** Computed by list(): true when the row is claimable (no active assignee or expired claim). */
62
+ available?: boolean;
58
63
  }
59
64
  /**
60
65
  * Result of `claim()` — identifies whether failure was due to the row not
@@ -65,20 +70,21 @@ export interface EscalationEntry {
65
70
  export type ClaimEscalationResult = {
66
71
  ok: true;
67
72
  entry: EscalationEntry;
73
+ isExtension: boolean;
68
74
  } | {
69
75
  ok: false;
70
76
  reason: 'not-found' | 'conflict';
71
77
  };
72
78
  /**
73
- * Result of `claimByMetadata()`. Includes `candidatesExist` the total
74
- * count of rows matching the metadata filter regardless of claimability — so
75
- * callers can distinguish "nothing matching at all" from "found candidates but
76
- * all are locked or in-progress".
79
+ * Result of `claimByMetadata()`. Includes `candidatesExist` and `isExtension`:
80
+ * - `candidatesExist` — total count of rows matching the filter regardless of claimability
81
+ * - `isExtension` true when the same assignee re-claims a row they already hold (extends the expiry)
77
82
  */
78
83
  export type ClaimByMetadataResult = {
79
84
  ok: true;
80
85
  entry: EscalationEntry;
81
86
  candidatesExist: number;
87
+ isExtension: boolean;
82
88
  } | {
83
89
  ok: false;
84
90
  reason: 'not-found' | 'conflict';
@@ -86,12 +92,14 @@ export type ClaimByMetadataResult = {
86
92
  };
87
93
  export type ResolveEscalationResult = {
88
94
  ok: true;
95
+ entry: EscalationEntry;
89
96
  } | {
90
97
  ok: false;
91
- reason: 'not-found' | 'already-resolved' | 'already-cancelled' | 'signal-failed';
98
+ reason: 'not-found' | 'already-resolved' | 'already-cancelled';
92
99
  };
93
100
  export type ReleaseEscalationResult = {
94
101
  ok: true;
102
+ entry: EscalationEntry;
95
103
  } | {
96
104
  ok: false;
97
105
  reason: 'not-found' | 'wrong-assignee';
@@ -105,6 +113,8 @@ export type CancelEscalationResult = {
105
113
  export interface ListEscalationsParams {
106
114
  namespace?: string;
107
115
  role?: string;
116
+ /** Filter by one or more roles (OR semantics; takes precedence over `role` when both set). */
117
+ roles?: string[];
108
118
  type?: string;
109
119
  subtype?: string;
110
120
  entity?: string;
@@ -112,9 +122,53 @@ export interface ListEscalationsParams {
112
122
  assignedTo?: string;
113
123
  workflowId?: string;
114
124
  originId?: string;
125
+ /** When true, returns only rows without an active claim. When false, returns only actively claimed rows. */
126
+ available?: boolean;
127
+ /** Exact priority match. */
128
+ priority?: number;
129
+ /** JSONB containment filter — rows whose `metadata` contains all provided keys/values. */
130
+ metadata?: Record<string, unknown>;
131
+ /** Filter by a set of UUIDs. */
132
+ ids?: string[];
133
+ /** Filter by `task_id` column. */
134
+ taskId?: string;
135
+ sortBy?: 'created_at' | 'priority' | 'updated_at';
136
+ sortOrder?: 'asc' | 'desc';
137
+ /**
138
+ * Multi-column sort. When provided, supersedes `sortBy`/`sortOrder`.
139
+ * Columns are applied left to right.
140
+ */
141
+ orderBy?: Array<{
142
+ column: 'priority' | 'created_at' | 'updated_at' | 'resolved_at' | 'role' | 'type';
143
+ direction: 'asc' | 'desc';
144
+ }>;
115
145
  limit?: number;
116
146
  offset?: number;
117
147
  }
148
+ export interface StatsEscalationsParams {
149
+ namespace?: string;
150
+ /** RBAC scope — when an empty array is provided, all counts are zero. */
151
+ roles?: string[];
152
+ /** Counting window for created/resolved. Default: '24h'. */
153
+ period?: '1h' | '24h' | '7d' | '30d';
154
+ }
155
+ export interface EscalationStats {
156
+ pending: number;
157
+ claimed: number;
158
+ created: number;
159
+ resolved: number;
160
+ by_role: Array<{
161
+ role: string;
162
+ pending: number;
163
+ claimed: number;
164
+ }>;
165
+ by_type: Array<{
166
+ type: string;
167
+ pending: number;
168
+ claimed: number;
169
+ resolved: number;
170
+ }>;
171
+ }
118
172
  export interface CreateEscalationParams {
119
173
  namespace?: string;
120
174
  appId?: string;
@@ -135,6 +189,7 @@ export interface CreateEscalationParams {
135
189
  createdBy?: string;
136
190
  traceId?: string;
137
191
  spanId?: string;
192
+ taskId?: string;
138
193
  escalationPayload?: Record<string, unknown>;
139
194
  metadata?: Record<string, unknown>;
140
195
  envelope?: Record<string, unknown>;
@@ -152,6 +207,7 @@ export interface UpdateEscalationParams {
152
207
  description?: string;
153
208
  priority?: number;
154
209
  role?: string;
210
+ taskId?: string;
155
211
  /** Merged into existing metadata (keys overwritten, others preserved) */
156
212
  metadata?: Record<string, unknown>;
157
213
  /** Replaces existing envelope */
@@ -186,6 +242,8 @@ export interface ClaimByMetadataParams {
186
242
  assignee?: string;
187
243
  durationMinutes?: number;
188
244
  roles?: string[];
245
+ /** Merged (not replaced) into the claimed row's metadata in the same atomic UPDATE. */
246
+ metadata?: Record<string, unknown>;
189
247
  }
190
248
  export interface ReleaseEscalationParams {
191
249
  id: string;
@@ -210,6 +268,27 @@ export interface EscalateToRoleParams {
210
268
  targetRole: string;
211
269
  namespace?: string;
212
270
  }
271
+ export interface ClaimManyParams {
272
+ ids: string[];
273
+ namespace?: string;
274
+ assignee: string;
275
+ durationMinutes?: number;
276
+ }
277
+ export interface EscalateManyToRoleParams {
278
+ ids: string[];
279
+ namespace?: string;
280
+ targetRole: string;
281
+ }
282
+ export interface UpdateManyPriorityParams {
283
+ ids: string[];
284
+ namespace?: string;
285
+ priority: number;
286
+ }
287
+ export interface ResolveManyParams {
288
+ ids: string[];
289
+ namespace?: string;
290
+ resolverPayload?: Record<string, unknown>;
291
+ }
213
292
  /**
214
293
  * Full-fidelity migration params. Extends `CreateEscalationParams` with:
215
294
  * - `id` (required) — preserves the original UUID; no auto-generation
package/index.ts CHANGED
@@ -18,6 +18,7 @@ import * as KeyStore from './modules/key';
18
18
  import { ConnectorService as Connector } from './services/connector/factory';
19
19
  import { PostgresConnection as ConnectorPostgres } from './services/connector/providers/postgres';
20
20
  import { NatsConnection as ConnectorNATS } from './services/connector/providers/nats';
21
+ import { Escalations } from './services/escalations';
21
22
 
22
23
  export {
23
24
  //Provider Connectors
@@ -30,6 +31,7 @@ export {
30
31
  HotMeshConfig,
31
32
  Virtual,
32
33
  Durable,
34
+ Escalations,
33
35
  DBA,
34
36
 
35
37
  //Durable Submodules
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hotmeshio/hotmesh",
3
- "version": "0.22.1",
3
+ "version": "0.22.3",
4
4
  "description": "Durable Workflow",
5
5
  "main": "./build/index.js",
6
6
  "types": "./build/index.d.ts",
@@ -86,9 +86,9 @@
86
86
  "test:trigger": "vitest run tests/unit/services/activities/trigger.test.ts",
87
87
  "test:virtual": "vitest run tests/virtual",
88
88
  "test:unit": "vitest run tests/unit",
89
-
90
89
  "prove": "docker compose exec hotmesh npx vitest run tests/durable 2>&1 | tee /tmp/hmsh-durable.txt && grep -E 'FAIL|Tests |Files ' /tmp/hmsh-durable.txt | tail -5",
91
90
  "prove:escalations": "docker compose exec hotmesh npx vitest run tests/durable/escalations/postgres.test.ts 2>&1 | tee /tmp/hmsh-escalations.txt && grep -E 'FAIL|Tests |Files ' /tmp/hmsh-escalations.txt | tail -5",
91
+ "prove:migrations": "docker compose exec hotmesh npx vitest run tests/durable/migrations/postgres.test.ts 2>&1 | tee /tmp/hmsh-migrations.txt && grep -E 'FAIL|Tests |Files ' /tmp/hmsh-migrations.txt | tail -5",
92
92
  "prove:functional": "docker compose exec hotmesh npx vitest run tests/functional 2>&1 | tee /tmp/hmsh-functional.txt && grep -E 'FAIL|Tests |Files ' /tmp/hmsh-functional.txt | tail -5",
93
93
  "prove:all": "docker compose exec hotmesh npx vitest run tests/ 2>&1 | tee /tmp/hmsh-all.txt && grep -E 'FAIL|Tests |Files ' /tmp/hmsh-all.txt | tail -5",
94
94
  "prove:file": "f() { docker compose exec hotmesh npx vitest run \"$@\" 2>&1 | tee /tmp/hmsh-file.txt && grep -E 'FAIL|Tests |Files ' /tmp/hmsh-file.txt | tail -5; }; f"