codehooks-js 1.3.14 → 1.3.16

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 CHANGED
@@ -1,10 +1,11 @@
1
- # codehooks-js
1
+ # codehooks-js
2
2
 
3
3
  The official JavaScript/TypeScript library for [Codehooks.io](https://codehooks.io) - a serverless backend platform that provides everything you need to build and deploy backend applications.
4
4
 
5
5
  ## What is Codehooks.io?
6
6
 
7
7
  Codehooks.io is a complete serverless backend platform that combines:
8
+
8
9
  - **Database** - NoSQL document storage with MongoDB-like queries
9
10
  - **API Server** - Express.js-style routing and middleware
10
11
  - **Background Jobs** - Queues, workers, and scheduled tasks
@@ -16,7 +17,7 @@ All in one platform with zero infrastructure management.
16
17
 
17
18
  ## Quick Start
18
19
 
19
- Install the [Codehooks CLI](https://codehooks.io/docs/cli):
20
+ Install the [Codehooks CLI](https://codehooks.io/docs/cli):
20
21
 
21
22
  ```shell
22
23
  $ npm install -g codehooks
@@ -34,59 +35,65 @@ Example code for a serverless backend API and NoSQL database:
34
35
 
35
36
  ```javascript
36
37
  /*
37
- * REST API with NoSQL database storage.
38
- * Codehooks (c) example code.
39
- */
38
+ * REST API with NoSQL database storage.
39
+ * Codehooks (c) example code.
40
+ */
40
41
 
41
- import {app, datastore} from 'codehooks-js';
42
+ import { app, datastore } from 'codehooks-js';
42
43
 
43
44
  // Example GET route and a NoSQL database insert operation
44
45
  app.get('/myroute', async (req, res) => {
45
- console.log("GET")
46
- const conn = await datastore.open()
47
- const doc = await conn.insertOne('greetings', {"message": "Hello World!", "when": new Date()})
48
- res.json({...doc})
46
+ console.log('GET');
47
+ const conn = await datastore.open();
48
+ const doc = await conn.insertOne('greetings', {
49
+ message: 'Hello World!',
50
+ when: new Date(),
51
+ });
52
+ res.json({ ...doc });
49
53
  });
50
54
 
51
55
  // Serve web content from the uploaded directory /static
52
- app.static({directory: "/static"})
56
+ app.static({ directory: '/static' });
53
57
 
54
58
  // CRUD REST API for any collection
55
- app.crudlify({}, {prefix: "/"})
59
+ app.crudlify({}, { prefix: '/' });
56
60
 
57
61
  // return app to serverless runtime engine
58
- export default app.init()
62
+ export default app.init();
59
63
  ```
60
64
 
61
65
  ## TypeScript development
62
66
 
63
67
  Rename the index.js to index.ts or create a new index.ts file.
64
- Start developing using TypeScript and strong types shown in the example code below.
68
+ Start developing using TypeScript and strong types shown in the example code below.
65
69
 
66
70
  ```typescript
67
71
  /*
68
- * REST API with NoSQL database storage.
69
- * Codehooks (c) example code in TypeScript.
70
- */
72
+ * REST API with NoSQL database storage.
73
+ * Codehooks (c) example code in TypeScript.
74
+ */
71
75
 
72
- import {app, datastore, httpResponse, httpRequest} from 'codehooks-js';
76
+ import { app, datastore, httpResponse, httpRequest } from 'codehooks-js';
73
77
 
74
78
  // Example GET route and a NoSQL database insert operation
75
79
  app.get('/myroute', async (req: httpRequest, res: httpResponse) => {
76
- console.log("GET")
77
- const conn = await datastore.open()
78
- const doc = await conn.insertOne('greetings', {"message": "Hello World!", "when": new Date()})
79
- res.json({...doc})
80
+ console.log('GET');
81
+ const conn = await datastore.open();
82
+ const doc = await conn.insertOne('greetings', {
83
+ message: 'Hello World!',
84
+ when: new Date(),
85
+ });
86
+ res.json({ ...doc });
80
87
  });
81
88
 
82
89
  // Serve web content from the uploaded directory /static
83
- app.static({directory: "/static"})
90
+ app.static({ directory: '/static' });
84
91
 
85
92
  // CRUD REST API for any collection
86
- app.crudlify({}, {prefix: "/"})
93
+ app.crudlify({}, { prefix: '/' });
87
94
 
88
95
  // return app to serverless runtime engine
89
- export default app.init()
96
+ export default app.init();
90
97
  ```
91
98
 
92
99
  ## Compile
@@ -95,16 +102,11 @@ When running the `coho compile` command, it will automatically create a `tsconfi
95
102
 
96
103
  ```json
97
104
  {
98
- "files": [
99
- "./index.ts"
100
- ],
101
- "compilerOptions": {
102
- "allowJs": true,
103
- "lib": [
104
- "ES6",
105
- "dom"
106
- ]
107
- }
105
+ "files": ["./index.ts"],
106
+ "compilerOptions": {
107
+ "allowJs": true,
108
+ "lib": ["ES6", "dom"]
109
+ }
108
110
  }
109
111
  ```
110
112
 
@@ -131,7 +133,8 @@ Your backend application is now available at your project's endpoint URL. For ex
131
133
 
132
134
  ## Deploy
133
135
 
134
- From the project directory run:
136
+ From the project directory run:
137
+
135
138
  ```shell
136
139
  $ codehooks deploy
137
140
  ```
@@ -147,44 +150,50 @@ For complete documentation, visit [https://codehooks.io/docs](https://codehooks.
147
150
  The Codehooks class provides a comprehensive backend application framework with the following APIs:
148
151
 
149
152
  ### **HTTP Routing APIs**
153
+
150
154
  - **`post(path, ...hook)`** - Register POST route handlers
151
- - **`get(path, ...hook)`** - Register GET route handlers
155
+ - **`get(path, ...hook)`** - Register GET route handlers
152
156
  - **`put(path, ...hook)`** - Register PUT route handlers
153
157
  - **`patch(path, ...hook)`** - Register PATCH route handlers
154
158
  - **`delete(path, ...hook)`** - Register DELETE route handlers
155
159
  - **`all(path, ...hook)`** - Register handlers for all HTTP methods
156
160
 
157
161
  ### **Middleware & Authentication APIs**
162
+
158
163
  - **`use(...hook)`** - Register global middleware (supports string paths, RegExp, or function)
159
164
  - **`useRoute(route, ...hook)`** - Register route-specific middleware
160
165
  - **`auth(path, ...hook)`** - Register authentication middleware for specific paths
161
166
 
162
167
  ### **Background Processing APIs**
168
+
163
169
  - **`queue(topic, ...hook)`** - Register queue handlers for background processing
164
170
  - **`worker(name, ...hook)`** - Register worker functions (also adds to queues for legacy support)
165
171
  - **`job(cronExpression, ...hook)`** - Register scheduled cron jobs
166
172
 
167
173
  ### **Static File Serving APIs**
174
+
168
175
  - **`static(options, hook)`** - Serve static files from source code directory
169
176
  - **`storage(options, hook)`** - Serve files from blob storage directory
170
177
 
171
178
  ### **Template & Configuration APIs**
179
+
172
180
  - **`set(key, val)`** - Set application configuration settings
173
181
  - **`render(view, data, cb)`** - Render templates with data
174
182
  - **`crudlify(schema, options)`** - Auto-generate CRUD REST API endpoints
175
183
 
176
184
  ### **Real-time Communication APIs**
185
+
177
186
  - **`realtime(path, ...hook)`** - Set up server-sent events (SSE) channels for real-time communication
178
187
 
179
188
  ### **Workflow Management APIs**
189
+
180
190
  - **`createWorkflow(name, description, steps, options)`** - Create and register a new workflow instance
181
191
 
182
192
  ### **Application Lifecycle APIs**
193
+
183
194
  - **`init(hook)`** - Initialize the application and return manifest
184
195
  - **`start(hook)`** - Alias for `init()` method
185
196
 
186
-
187
-
188
197
  The Codehooks class serves as a comprehensive backend application framework that combines HTTP routing, background processing, real-time communication, and workflow management capabilities in a single, cohesive API.
189
198
 
190
199
  ## Datastore API Reference
@@ -192,18 +201,21 @@ The Codehooks class serves as a comprehensive backend application framework that
192
201
  The Datastore provides a unified interface for both NoSQL document storage and Key-Value operations. It supports MongoDB-like query syntax and provides streaming capabilities for large datasets.
193
202
 
194
203
  ### **Connection & Collection Management**
204
+
195
205
  - **`open()`** - Connect to the Datastore and return the API interface
196
206
  - **`collection(name)`** - Get a NoSQL collection by name for document operations
197
207
 
198
208
  ### **NoSQL Document Operations**
199
209
 
200
210
  #### **Read Operations**
211
+
201
212
  - **`getOne(collection, query)`** - Get a single document by ID or query
202
213
  - **`findOne(collection, query)`** - Alias for getOne
203
214
  - **`getMany(collection, query?, options?)`** - Get a stream of documents matching query
204
215
  - **`find(collection, query?, options?)`** - Alias for getMany
205
216
 
206
217
  #### **Write Operations**
218
+
207
219
  - **`insertOne(collection, document)`** - Insert a new document into a collection
208
220
  - **`updateOne(collection, query, document, updateOperators?, options?)`** - Update one document (patches existing data)
209
221
  - **`updateMany(collection, query, document, updateOperators?)`** - Update multiple documents
@@ -211,32 +223,38 @@ The Datastore provides a unified interface for both NoSQL document storage and K
211
223
  - **`replaceMany(collection, query, document, options?)`** - Replace multiple documents
212
224
 
213
225
  #### **Delete Operations**
226
+
214
227
  - **`removeOne(collection, query)`** - Remove one document by ID or query
215
228
  - **`removeMany(collection, query)`** - Remove multiple documents matching query
216
229
 
217
230
  #### **Schema Management**
231
+
218
232
  - **`createSchema(collection, schema)`** - Validate collection data against JSON-Schema
219
233
  - **`setSchema(collection, schema)`** - Alias for createSchema
220
234
  - **`removeSchema(collection)`** - Remove JSON-schema validation for collection
221
235
  - **`getSchema(collection)`** - Get JSON-schema for collection
222
236
 
223
237
  #### **Utility Operations**
238
+
224
239
  - **`count(collection)`** - Count documents in a collection
225
240
 
226
241
  ### **Key-Value Operations**
227
242
 
228
243
  #### **Basic Key-Value Operations**
244
+
229
245
  - **`set(key, value, options?)`** - Set a key-value pair
230
246
  - **`get(key, options?)`** - Get a value by key
231
247
  - **`getAll(keyPattern, options?)`** - Get all key-value pairs matching pattern
232
- - **`del(key, value)`** - Delete a key-value pair
248
+ - **`del(key, options?)`** - Delete a key-value pair
233
249
  - **`delAll(keyPattern, options?)`** - Delete all key-value pairs matching pattern
234
250
 
235
251
  #### **Numeric Operations**
252
+
236
253
  - **`incr(key, value, options?)`** - Increment a numeric value
237
254
  - **`decr(key, value, options?)`** - Decrement a numeric value
238
255
 
239
256
  ### **Queue Operations**
257
+
240
258
  - **`enqueue(topic, document, options?)`** - Add a job to a queue for background processing
241
259
  - **`enqueueFromQuery(collection, query, topic, options?)`** - Queue each item from a database query
242
260
 
@@ -258,7 +276,10 @@ import { datastore } from 'codehooks-js';
258
276
  const conn = await datastore.open();
259
277
 
260
278
  // NoSQL operations
261
- const doc = await conn.insertOne('users', { name: 'John', email: 'john@example.com' });
279
+ const doc = await conn.insertOne('users', {
280
+ name: 'John',
281
+ email: 'john@example.com',
282
+ });
262
283
  const user = await conn.getOne('users', { _id: doc._id });
263
284
  const users = await conn.getMany('users', { active: true }).toArray();
264
285
  await conn.updateOne('users', { _id: doc._id }, { lastLogin: new Date() });
@@ -269,7 +290,10 @@ const session = await conn.get('user:123:session');
269
290
  await conn.incr('visits', 1);
270
291
 
271
292
  // Queue operations
272
- await conn.enqueue('emailWorker', { to: 'user@example.com', template: 'welcome' });
293
+ await conn.enqueue('emailWorker', {
294
+ to: 'user@example.com',
295
+ template: 'welcome',
296
+ });
273
297
  ```
274
298
 
275
299
  ### **Query Syntax**
@@ -278,22 +302,48 @@ The Datastore supports MongoDB-like query syntax:
278
302
 
279
303
  ```javascript
280
304
  // Simple equality
281
- { status: 'active' }
305
+ {
306
+ status: 'active';
307
+ }
282
308
 
283
309
  // Comparison operators
284
- { age: { $gt: 18 } }
285
- { price: { $lte: 100 } }
310
+ {
311
+ age: {
312
+ $gt: 18;
313
+ }
314
+ }
315
+ {
316
+ price: {
317
+ $lte: 100;
318
+ }
319
+ }
286
320
 
287
321
  // Logical operators
288
- { $and: [{ status: 'active' }, { age: { $gte: 18 } }] }
289
- { $or: [{ category: 'A' }, { category: 'B' }] }
322
+ {
323
+ $and: [{ status: 'active' }, { age: { $gte: 18 } }];
324
+ }
325
+ {
326
+ $or: [{ category: 'A' }, { category: 'B' }];
327
+ }
290
328
 
291
329
  // Array operations
292
- { tags: { $in: ['javascript', 'nodejs'] } }
293
- { tags: { $all: ['javascript', 'nodejs'] } }
330
+ {
331
+ tags: {
332
+ $in: ['javascript', 'nodejs'];
333
+ }
334
+ }
335
+ {
336
+ tags: {
337
+ $all: ['javascript', 'nodejs'];
338
+ }
339
+ }
294
340
 
295
341
  // Regular expressions
296
- { name: { $regex: /john/i } }
342
+ {
343
+ name: {
344
+ $regex: /john/i;
345
+ }
346
+ }
297
347
  ```
298
348
 
299
349
  ### **Options**
@@ -302,14 +352,20 @@ Many operations accept an options object for additional configuration:
302
352
 
303
353
  ```javascript
304
354
  // Upsert option for updates
305
- await conn.updateOne('users', { email: 'john@example.com' },
306
- { lastLogin: new Date() }, {}, { upsert: true });
355
+ await conn.updateOne(
356
+ 'users',
357
+ { email: 'john@example.com' },
358
+ { lastLogin: new Date() },
359
+ {},
360
+ { upsert: true }
361
+ );
307
362
 
308
363
  // Key-Value options
309
364
  await conn.set('key', 'value', { ttl: 3600000 }); // 1 hour TTL
310
365
  ```
311
366
 
312
367
  ### **Key Features:**
368
+
313
369
  1. **Express-style routing** with support for all HTTP methods
314
370
  2. **Middleware system** with global and route-specific middleware
315
371
  3. **Background processing** with queues, workers, and scheduled jobs
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codehooks-js",
3
- "version": "1.3.14",
3
+ "version": "1.3.16",
4
4
  "type": "module",
5
5
  "description": "Codehooks.io official library - provides express.JS like syntax",
6
6
  "main": "index.js",
package/types/index.d.ts CHANGED
@@ -401,7 +401,7 @@ export type DatastoreAPI = {
401
401
  /**
402
402
  * - Delete a key-value pair in the current Datastore
403
403
  */
404
- del: (key: string, value: object) => Promise<any>;
404
+ del: (key: string, options?: object) => Promise<any>;
405
405
  /**
406
406
  * - Delete a range of key-value pairs in the current Datastore
407
407
  */
@@ -466,11 +466,11 @@ export type DatastoreAPI = {
466
466
  * @returns Promise with result
467
467
  */
468
468
  getSchema: (collection: string) => Promise<object>;
469
- /**
470
- * Count database collection items
471
- * @returns Promise result
472
- */
473
- count: (collection: string) => Promise<object>;
469
+ /**
470
+ * Count database collection items
471
+ * @returns Promise result
472
+ */
473
+ count: (collection: string) => Promise<object>;
474
474
  };
475
475
  /**
476
476
  * Persistent NoSql and Kev-Value datastore
@@ -956,8 +956,8 @@ export class Codehooks {
956
956
  * })
957
957
  * @returns void
958
958
  */
959
- static: (options: any,
960
- ...hook: ((
959
+ static: (options: any,
960
+ ...hook: ((
961
961
  request: httpRequest,
962
962
  response: httpResponse,
963
963
  next: nextFunction
@@ -967,12 +967,12 @@ export class Codehooks {
967
967
  * @param {Object} options - {route: "/documents", directory: "/docs"}
968
968
  * @returns void
969
969
  */
970
- storage: (options: any,
970
+ storage: (options: any,
971
971
  ...hook: ((
972
- request: httpRequest,
973
- response: httpResponse,
974
- next: nextFunction
975
- ) => any)[]) => void;
972
+ request: httpRequest,
973
+ response: httpResponse,
974
+ next: nextFunction
975
+ ) => any)[]) => void;
976
976
  /**
977
977
  * Configuration settings
978
978
  * @param {string} key
@@ -1067,31 +1067,31 @@ export type WorkflowEvents = {
1067
1067
  * @event
1068
1068
  */
1069
1069
  'workflowCreated': { name: string; description: string };
1070
-
1070
+
1071
1071
  /**
1072
1072
  * Emitted when a new workflow instance is started
1073
1073
  * @event
1074
1074
  */
1075
1075
  'workflowStarted': { name: string; initialState: any };
1076
-
1076
+
1077
1077
  /**
1078
1078
  * Emitted when a step begins execution
1079
1079
  * @event
1080
1080
  */
1081
1081
  'stepStarted': { workflowName: string; step: string; state: any; instanceId: string };
1082
-
1082
+
1083
1083
  /**
1084
1084
  * Emitted when a step's state is updated
1085
1085
  * @event
1086
1086
  */
1087
1087
  'stateUpdated': { workflowName: string; state: any; instanceId: string };
1088
-
1088
+
1089
1089
  /**
1090
1090
  * Emitted when a step is enqueued for execution
1091
1091
  * @event
1092
1092
  */
1093
1093
  'stepEnqueued': { workflowName: string; step: string; state: any; instanceId: string };
1094
-
1094
+
1095
1095
  /**
1096
1096
  * Emitted when a workflow instance is continued after waiting
1097
1097
  * @event
@@ -1103,7 +1103,7 @@ export type WorkflowEvents = {
1103
1103
  * @event
1104
1104
  */
1105
1105
  'completed': { message: string; state: any };
1106
-
1106
+
1107
1107
  /**
1108
1108
  * Emitted when a workflow instance is cancelled
1109
1109
  * @event
@@ -1121,9 +1121,9 @@ export type WorkflowEvents = {
1121
1121
  * Definition of a workflow step function
1122
1122
  */
1123
1123
  export type WorkflowDefinition = Record<string, (
1124
- state: any,
1125
- callback: (nextStep: string | string[] | null, newState: any, options?: any) => void,
1126
- waiterFunction?: (waiter?: any) => void
1124
+ state: any,
1125
+ callback: (nextStep: string | string[] | null, newState: any, options?: any) => void,
1126
+ waiterFunction?: (waiter?: any) => void
1127
1127
  ) => Promise<void>>;
1128
1128
 
1129
1129
  /**
@@ -1255,14 +1255,14 @@ export type Workflow = {
1255
1255
  * @returns Promise with the registered workflow name
1256
1256
  */
1257
1257
  register: (app: Codehooks) => Promise<string>;
1258
-
1258
+
1259
1259
  /**
1260
1260
  * Start a new workflow instance
1261
1261
  * @param initialState - Initial state for the workflow instance
1262
1262
  * @returns Promise with the workflow instance
1263
1263
  */
1264
1264
  start: (initialState: any) => Promise<any>;
1265
-
1265
+
1266
1266
  /**
1267
1267
  * Update the state of a workflow instance
1268
1268
  * @param instanceId - ID of the workflow instance
@@ -1271,7 +1271,7 @@ export type Workflow = {
1271
1271
  * @returns Promise with the updated state
1272
1272
  */
1273
1273
  updateState: (instanceId: string, state: any, options?: UpdateOptions) => Promise<any>;
1274
-
1274
+
1275
1275
  /**
1276
1276
  * Set the complete state of a workflow instance
1277
1277
  * @param instanceId - ID of the workflow instance
@@ -1279,7 +1279,7 @@ export type Workflow = {
1279
1279
  * @returns Promise<void>
1280
1280
  */
1281
1281
  setState: (instanceId: string, stateData: { _id: string; state: any }) => Promise<void>;
1282
-
1282
+
1283
1283
  /**
1284
1284
  * Continue a paused workflow instance
1285
1285
  * @param instanceId - ID of the workflow instance
@@ -1287,21 +1287,21 @@ export type Workflow = {
1287
1287
  * @returns Promise with the queue ID for the continued step
1288
1288
  */
1289
1289
  continue: (instanceId: string, reset?: boolean) => Promise<{ instanceId: string }>;
1290
-
1290
+
1291
1291
  /**
1292
1292
  * Get the status of a workflow instance
1293
1293
  * @param id - ID of the workflow instance
1294
1294
  * @returns Promise with the workflow status
1295
1295
  */
1296
1296
  getStepsStatus: (id: string) => Promise<any>;
1297
-
1297
+
1298
1298
  /**
1299
1299
  * Get all workflow instances matching a filter
1300
1300
  * @param filter - Filter criteria for workflows
1301
1301
  * @returns Promise with list of workflow instances
1302
1302
  */
1303
1303
  getInstances: (filter: any) => Promise<any[]>;
1304
-
1304
+
1305
1305
  /**
1306
1306
  * Cancel a workflow instance
1307
1307
  * @param id - ID of the workflow instance to cancel
@@ -1309,6 +1309,27 @@ export type Workflow = {
1309
1309
  */
1310
1310
  cancelSteps: (id: string) => Promise<any>;
1311
1311
 
1312
+ /**
1313
+ * Get the status of a workflow instance (alias for getStepsStatus)
1314
+ * @param id - ID of the workflow instance
1315
+ * @returns Promise with the workflow status
1316
+ */
1317
+ getWorkflowStatus: (id: string) => Promise<any>;
1318
+
1319
+ /**
1320
+ * Get the state of a workflow instance (alias for getStepsStatus)
1321
+ * @param id - ID of the workflow instance
1322
+ * @returns Promise with the workflow state
1323
+ */
1324
+ getState: (id: string) => Promise<any>;
1325
+
1326
+ /**
1327
+ * Cancel a workflow instance (alias for cancelSteps)
1328
+ * @param id - ID of the workflow instance to cancel
1329
+ * @returns Promise with the cancellation result
1330
+ */
1331
+ cancelWorkflow: (id: string) => Promise<any>;
1332
+
1312
1333
  /**
1313
1334
  * Register an event listener
1314
1335
  * @param event - Name of the event to listen for
@@ -1319,21 +1340,21 @@ export type Workflow = {
1319
1340
  * });
1320
1341
  */
1321
1342
  on: (event: WorkflowEvent, listener: (data: WorkflowEventData) => void) => Workflow;
1322
-
1343
+
1323
1344
  /**
1324
1345
  * Register a one-time event listener
1325
1346
  * @param event - Name of the event to listen for
1326
1347
  * @param listener - Callback function to handle the event
1327
1348
  */
1328
1349
  once: (event: WorkflowEvent, listener: (data: WorkflowEventData) => void) => Workflow;
1329
-
1350
+
1330
1351
  /**
1331
1352
  * Remove an event listener
1332
1353
  * @param event - Name of the event
1333
1354
  * @param listener - Callback function to remove
1334
1355
  */
1335
1356
  off: (event: WorkflowEvent, listener: (data: WorkflowEventData) => void) => Workflow;
1336
-
1357
+
1337
1358
  /**
1338
1359
  * Emit an event
1339
1360
  * @param event - Name of the event to emit
@@ -1345,7 +1366,7 @@ export type Workflow = {
1345
1366
  * Continue all timed out workflow instances
1346
1367
  * @returns Promise with array of results containing queue IDs for continued workflows
1347
1368
  */
1348
- continueAllTimedOut: () => Promise<Array<{instanceId: string}>>;
1369
+ continueAllTimedOut: () => Promise<Array<{ instanceId: string }>>;
1349
1370
 
1350
1371
  /**
1351
1372
  * Check if a specific step in a workflow instance has timed out
@@ -1427,7 +1448,7 @@ export type UpdateOptions = {
1427
1448
  /**
1428
1449
  * Workflow event types
1429
1450
  */
1430
- export type WorkflowEvent =
1451
+ export type WorkflowEvent =
1431
1452
  | 'workflowCreated'
1432
1453
  | 'workflowStarted'
1433
1454
  | 'workflowContinued'
@@ -117,5 +117,23 @@ declare class StepsEngine {
117
117
  * @returns {Promise<Object>} The cancellation result
118
118
  */
119
119
  cancelSteps(id: string): Promise<any>;
120
+ /**
121
+ * Get the status of a workflow instance (alias for getStepsStatus)
122
+ * @param {string} id - ID of the workflow instance
123
+ * @returns {Promise<Object>} The workflow status
124
+ */
125
+ getWorkflowStatus(id: string): Promise<any>;
126
+ /**
127
+ * Get the state of a workflow instance (alias for getStepsStatus)
128
+ * @param {string} id - ID of the workflow instance
129
+ * @returns {Promise<Object>} The workflow state
130
+ */
131
+ getState(id: string): Promise<any>;
132
+ /**
133
+ * Cancel a workflow instance (alias for cancelSteps)
134
+ * @param {string} id - ID of the workflow instance to cancel
135
+ * @returns {Promise<Object>} The cancellation result
136
+ */
137
+ cancelWorkflow(id: string): Promise<any>;
120
138
  }
121
139
  //# sourceMappingURL=engine.d.mts.map
@@ -38,7 +38,7 @@ class Workflow extends EventEmitter {
38
38
  this.#definitions = new Map();
39
39
  this.#name = name;
40
40
  this.#description = description;
41
-
41
+
42
42
  // Apply any configuration options
43
43
  if (options) {
44
44
  this.configure(options);
@@ -120,7 +120,7 @@ class Workflow extends EventEmitter {
120
120
  * @throws {Error} If maxStepCount is not a positive number
121
121
  */
122
122
  setMaxStepCount(maxStepCount) {
123
- if (typeof maxStepCount !== 'number' || maxStepCount <= 0) {
123
+ if (typeof maxStepCount !== 'number' || maxStepCount <= 0) {
124
124
  throw new Error('Maximum step count must be a positive number');
125
125
  }
126
126
  this.#maxStepCount = maxStepCount;
@@ -226,13 +226,13 @@ class Workflow extends EventEmitter {
226
226
  * @throws {Error} If step execution fails
227
227
  */
228
228
  async handleNextStep(stepsName, nextStep, newState, instanceId, options) {
229
-
229
+
230
230
  // open the connection to the database
231
- const connection = await DB.open();
231
+ const connection = await DB.open();
232
232
 
233
233
  // Handle single next step
234
234
  this.emit('stepStarted', { workflowName: stepsName, step: nextStep, state: newState, instanceId });
235
-
235
+
236
236
  // remove the _id from the newState
237
237
  delete newState._id;
238
238
  // increment the step count
@@ -247,9 +247,9 @@ class Workflow extends EventEmitter {
247
247
  newState = await connection.updateOne(this.#collectionName,
248
248
  { _id: instanceId },
249
249
  { $set: { ...newState, nextStep: nextStep, updatedAt: new Date().toISOString(), stepCount: newState.stepCount } });
250
-
251
- this.emit('stateUpdated', { workflowName: stepsName, state: newState, instanceId });
252
-
250
+
251
+ this.emit('stateUpdated', { workflowName: stepsName, state: newState, instanceId });
252
+
253
253
  try {
254
254
  // Get the next step function
255
255
  const func = this.getDefinition(stepsName, nextStep);
@@ -267,14 +267,14 @@ class Workflow extends EventEmitter {
267
267
  console.debug('waiter', state);
268
268
  await connection.updateOne(this.#collectionName,
269
269
  { _id: instanceId },
270
- { $set: { ...state, updatedAt: new Date().toISOString() } });
270
+ { $set: { ...state, updatedAt: new Date().toISOString() } });
271
271
  resolve();
272
272
  return;
273
273
  } else {
274
274
  resolve(); // no state update
275
275
  }
276
276
  }
277
- await func({...newState, instanceId: newState._id}, async (nextStep, userState, options) => {
277
+ await func({ ...newState, instanceId: newState._id }, async (nextStep, userState, options) => {
278
278
  try {
279
279
  // Protect system-level properties
280
280
  const protectedState = {
@@ -288,7 +288,7 @@ class Workflow extends EventEmitter {
288
288
  parallelSteps: newState.parallelSteps,
289
289
  previousStep: newState.nextStep
290
290
  };
291
-
291
+
292
292
  // Merge states with userState taking precedence, but protecting system fields
293
293
  const mergedState = {
294
294
  ...userState,
@@ -302,14 +302,14 @@ class Workflow extends EventEmitter {
302
302
  // update the parallel steps metadata
303
303
  if (mergedState.parallelSteps && mergedState.parallelSteps[mergedState.nextStep]) {
304
304
  // get a fresh copy of the parallel steps
305
- const fresh = await connection.findOne(this.#collectionName, { _id: instanceId });
305
+ const fresh = await connection.findOne(this.#collectionName, { _id: instanceId });
306
306
  fresh.parallelSteps[mergedState.nextStep].done = true;
307
307
  fresh.parallelSteps[mergedState.nextStep].nextStep = nextStep;
308
308
  //fresh.parallelSteps[mergedState.nextStep].previousStep = mergedState.previousStep || null;
309
309
  delete fresh._id;
310
310
  const updated = await connection.updateOne(this.#collectionName,
311
311
  { _id: instanceId },
312
- { $set: { ...fresh, parallelSteps: fresh.parallelSteps } });
312
+ { $set: { ...fresh, parallelSteps: fresh.parallelSteps } });
313
313
  //console.debug('updated', updated.parallelSteps);
314
314
  mergedState.parallelSteps = fresh.parallelSteps;
315
315
  // Check if all parallel steps are done
@@ -335,12 +335,12 @@ class Workflow extends EventEmitter {
335
335
  if (nextStep === null) {
336
336
  delete mergedState._id;
337
337
  const completionTime = (new Date(mergedState.updatedAt) - new Date(mergedState.createdAt));
338
-
338
+
339
339
  const finalresult = await connection.updateOne(this.#collectionName,
340
340
  { _id: instanceId },
341
- { $set: { ...mergedState, nextStep: null, updatedAt: new Date().toISOString(), totalTime: completionTime } });
341
+ { $set: { ...mergedState, nextStep: null, updatedAt: new Date().toISOString(), totalTime: completionTime } });
342
342
  console.log(`Workflow ${stepsName} ${instanceId} is completed in time: ${completionTime / 1000}s 🎉`);
343
- this.emit('completed', { ...finalresult});
343
+ this.emit('completed', { ...finalresult });
344
344
  resolve();
345
345
  return;
346
346
  }
@@ -370,13 +370,13 @@ class Workflow extends EventEmitter {
370
370
  } else {
371
371
  console.debug('enqueue step', nextStep, instanceId);
372
372
  await connection.enqueue(`${this.#queuePrefix}_${stepsName}_${nextStep}`, {
373
- stepsName: stepsName,
374
- goto: nextStep,
375
- state: mergedState,
376
- options: options,
377
- instanceId: instanceId
378
- });
379
- }
373
+ stepsName: stepsName,
374
+ goto: nextStep,
375
+ state: mergedState,
376
+ options: options,
377
+ instanceId: instanceId
378
+ });
379
+ }
380
380
  this.emit('stepEnqueued', { workflowName: stepsName, step: nextStep, state: newState, instanceId });
381
381
  resolve();
382
382
  } catch (error) {
@@ -393,7 +393,7 @@ class Workflow extends EventEmitter {
393
393
  } catch (error) {
394
394
  console.error('error in handleNextStep outer', error.message);
395
395
  throw error;
396
- }
396
+ }
397
397
  }
398
398
 
399
399
  /**
@@ -424,15 +424,15 @@ class Workflow extends EventEmitter {
424
424
  * @private
425
425
  */
426
426
  async registerWithApp(app, name, description, definition) {
427
- this.emit('workflowCreated', { name, description });
427
+ this.emit('workflowCreated', { name, description });
428
428
 
429
429
  // Validate each step in the definition
430
430
  for (const [stepName, step] of Object.entries(definition)) {
431
431
  try {
432
432
  if (stepName !== undefined) {
433
433
  console.debug('registering queue for step', `${this.#queuePrefix}_${name}_${stepName}`);
434
- app.worker(`${this.#queuePrefix}_${name}_${stepName}`, async (req, res) => {
435
- try {
434
+ app.worker(`${this.#queuePrefix}_${name}_${stepName}`, async (req, res) => {
435
+ try {
436
436
  const { stepsName, goto, state, instanceId, options } = req.body.payload;
437
437
  console.debug('dequeue step', stepName, instanceId);
438
438
  const qid = await this.handleNextStep(stepsName, goto, state, instanceId, options);
@@ -460,7 +460,7 @@ class Workflow extends EventEmitter {
460
460
  }
461
461
 
462
462
  // Store the definition
463
- this.#definitions.set(name, definition);
463
+ this.#definitions.set(name, definition);
464
464
 
465
465
  return name;
466
466
  }
@@ -472,13 +472,13 @@ class Workflow extends EventEmitter {
472
472
  * @throws {Error} If starting steps fails
473
473
  */
474
474
  async start(initialState) {
475
- this.emit('workflowStarted', { name: this.#name, initialState });
475
+ this.emit('workflowStarted', { name: this.#name, initialState });
476
476
 
477
477
  return new Promise(async (resolve, reject) => {
478
478
  try {
479
479
  console.debug('Starting workflow', this.#name);
480
480
  const funcs = this.#definitions.get(this.#name);
481
-
481
+
482
482
  if (!funcs) {
483
483
  reject(new Error(`No workflow definition found for: ${this.#name}`));
484
484
  return;
@@ -486,7 +486,7 @@ class Workflow extends EventEmitter {
486
486
 
487
487
  const firstStepName = Object.keys(funcs)[0];
488
488
  const firstStep = funcs[firstStepName];
489
-
489
+
490
490
  if (!firstStep) {
491
491
  reject(new Error('No start step defined in workflow'));
492
492
  return;
@@ -495,7 +495,7 @@ class Workflow extends EventEmitter {
495
495
  const connection = await DB.open();
496
496
  // Create a new workflow state in the database
497
497
  const newState = await connection.insertOne(this.#collectionName,
498
- { ...initialState, nextStep: firstStepName, createdAt: new Date().toISOString(), workflowName: this.#name, stepCount: { } });
498
+ { ...initialState, nextStep: firstStepName, createdAt: new Date().toISOString(), workflowName: this.#name, stepCount: {} });
499
499
  const { _id: ID } = await connection.enqueue(`${this.#queuePrefix}_${this.#name}_${firstStepName}`, {
500
500
  stepsName: this.#name,
501
501
  goto: firstStepName,
@@ -518,17 +518,17 @@ class Workflow extends EventEmitter {
518
518
  * @param {Object} options - Options for the update, { continue: false } to avoid continuing the the step
519
519
  * @returns {Promise<Object>} The updated state
520
520
  */
521
- async updateState(instanceId, state, options={continue: true}) {
521
+ async updateState(instanceId, state, options = { continue: true }) {
522
522
  this.emit('stepsStateUpdating', { name: this.#name, instanceId, state });
523
523
  const connection = await DB.open();
524
524
  return new Promise(async (resolve, reject) => {
525
- const doc = await connection.updateOne(this.#collectionName,
526
- { _id: instanceId },
525
+ const doc = await connection.updateOne(this.#collectionName,
526
+ { _id: instanceId },
527
527
  { $set: { ...state, updatedAt: new Date().toISOString() } });
528
528
  if (options.continue) {
529
529
  await this.continue(instanceId, false);
530
- }
531
- resolve({ ...doc });
530
+ }
531
+ resolve({ ...doc });
532
532
  });
533
533
  }
534
534
 
@@ -549,7 +549,7 @@ class Workflow extends EventEmitter {
549
549
  * @returns {Promise<{qId: string}>} Queue ID for the continued step
550
550
  * @throws {Error} If steps instance not found
551
551
  */
552
- async continue(instanceId, reset=false) {
552
+ async continue(instanceId, reset = false) {
553
553
  const connection = await DB.open();
554
554
  const state = await connection.findOne(this.#collectionName, { _id: instanceId });
555
555
  if (!state) {
@@ -565,10 +565,10 @@ class Workflow extends EventEmitter {
565
565
  // update the step count
566
566
  state.stepCount[state.nextStep] = { visits: 0, startTime: new Date().toISOString() };
567
567
  }
568
-
568
+
569
569
  await connection.updateOne(this.#collectionName, { _id: instanceId }, { $set: { stepCount: state.stepCount } });
570
570
  console.debug('continue state', state);
571
- this.emit('workflowContinued', { name: this.#name, step: state.nextStep, instanceId });
571
+ this.emit('workflowContinued', { name: this.#name, step: state.nextStep, instanceId });
572
572
 
573
573
  return new Promise(async (resolve, reject) => {
574
574
  const { _id: ID } = await connection.enqueue(`${this.#queuePrefix}_${this.#name}_${state.nextStep}`, {
@@ -589,7 +589,7 @@ class Workflow extends EventEmitter {
589
589
  */
590
590
  async continueAllTimedOut() {
591
591
  const db = await DB.open();
592
- const timedOutWorkflows = await db.collection(this.#collectionName).find({nextStep: {$ne: null}}).toArray();
592
+ const timedOutWorkflows = await db.collection(this.#collectionName).find({ nextStep: { $ne: null } }).toArray();
593
593
  const now = new Date();
594
594
  const results = [];
595
595
  for (const workflow of timedOutWorkflows) {
@@ -598,7 +598,7 @@ class Workflow extends EventEmitter {
598
598
  if (diffMillis > this.#timeout) {
599
599
  const diffMinutes = diffMillis / (1000 * 60);
600
600
  console.log('Timed out:', workflow._id, workflow.nextStep, `(${diffMinutes.toFixed(1)} minutes old)`);
601
- const result = await this.continue(workflow._id, true);
601
+ const result = await this.continue(workflow._id, true);
602
602
  console.log('Continued:', result._id);
603
603
  results.push(result);
604
604
  }
@@ -642,13 +642,40 @@ class Workflow extends EventEmitter {
642
642
  this.emit('cancelled', { id });
643
643
  return new Promise(async (resolve, reject) => {
644
644
  const connection = await DB.open();
645
- const state = await connection.updateOne(this.#collectionName,
646
- { _id: id },
647
- { $set: { status: 'cancelled' } });
645
+ const state = await connection.updateOne(this.#collectionName,
646
+ { _id: id },
647
+ { $set: { status: 'cancelled' } });
648
648
  resolve(state);
649
649
  });
650
650
  }
651
651
 
652
+ /**
653
+ * Get the status of a workflow instance (alias for getStepsStatus)
654
+ * @param {string} id - ID of the workflow instance
655
+ * @returns {Promise<Object>} The workflow status
656
+ */
657
+ async getWorkflowStatus(id) {
658
+ return this.getStepsStatus(id);
659
+ }
660
+
661
+ /**
662
+ * Get the state of a workflow instance (alias for getStepsStatus)
663
+ * @param {string} id - ID of the workflow instance
664
+ * @returns {Promise<Object>} The workflow state
665
+ */
666
+ async getState(id) {
667
+ return this.getStepsStatus(id);
668
+ }
669
+
670
+ /**
671
+ * Cancel a workflow instance (alias for cancelSteps)
672
+ * @param {string} id - ID of the workflow instance to cancel
673
+ * @returns {Promise<Object>} The cancellation result
674
+ */
675
+ async cancelWorkflow(id) {
676
+ return this.cancelSteps(id);
677
+ }
678
+
652
679
  /**
653
680
  * Check if a specific step in a workflow instance has timed out
654
681
  * @param {Object} workflow - The workflow instance
@@ -658,7 +685,7 @@ class Workflow extends EventEmitter {
658
685
  isStepTimedOut(workflow) {
659
686
  // Use previousStep if no stepName provided
660
687
  const stepToCheck = workflow.nextStep;
661
-
688
+
662
689
  if (!stepToCheck || !workflow.stepCount || !workflow.stepCount[stepToCheck]) {
663
690
  console.debug('no step', stepToCheck, workflow.stepCount);
664
691
  return {
@@ -669,12 +696,12 @@ class Workflow extends EventEmitter {
669
696
  }
670
697
 
671
698
  const step = workflow.stepCount[stepToCheck];
672
-
699
+
673
700
  // Get the timeout value for this step
674
701
  // First try step-specific config, then default options, finally fallback to global timeout
675
702
  const stepConfig = this.#steps[stepToCheck];
676
703
  const stepTimeout = stepConfig?.timeout ?? this.#defaultStepOptions.timeout ?? this.#timeout;
677
-
704
+
678
705
  // If the step hasn't finished, check if it's been running too long
679
706
  console.debug('isStepTimedOut', stepToCheck, stepTimeout);
680
707
  if (!step.finishTime) {
@@ -716,7 +743,7 @@ class Workflow extends EventEmitter {
716
743
  */
717
744
  async findTimedOutSteps(filter = {}) {
718
745
  const db = await DB.open();
719
- const workflows = await db.getMany(this.#collectionName, {"nextStep": {$ne: null}}).toArray();
746
+ const workflows = await db.getMany(this.#collectionName, { "nextStep": { $ne: null } }).toArray();
720
747
  if (workflows.length > 0) {
721
748
  console.debug('TimedOutSteps', workflows.length);
722
749
  }