@zwave-js/waddle 1.1.0 → 1.2.0

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
@@ -211,7 +211,39 @@ async function* fetchResourcesTask() {
211
211
  }
212
212
  ```
213
213
 
214
- When using TypeScript, you may need to assert the return type due to limits in type inference in generator functions:
214
+ When using TypeScript, you will likely hit limits in type inference in generator functions:
215
+
216
+ ```ts
217
+ async function* fetchResourcesTask() {
218
+ // async function doLongRunningWork1(): Promise<string> { ... }
219
+ const result1 = yield () => doLongRunningWork1(); // unknown ⚠️
220
+ // async function doLongRunningWork2(): Promise<number> { ... }
221
+ const result2 = yield () => doLongRunningWork2(); // unknown ⚠️
222
+ // async function doLongRunningWork3(): Promise<boolean> { ... }
223
+ const result3 = yield () => doLongRunningWork3(); // unknown ⚠️
224
+
225
+ // ...
226
+ }
227
+ ```
228
+
229
+ To help mitigate this, we recommend using the `waitFor` utility function together with `yield*` instead. Note that this expects a Promise, not a function!
230
+
231
+ ```ts
232
+ import { waitFor } from "@zwave-js/waddle";
233
+
234
+ async function* fetchResourcesTask() {
235
+ // async function doLongRunningWork1(): Promise<string> { ... }
236
+ const result1 = yield* waitFor(doLongRunningWork1()); // string ✅
237
+ // async function doLongRunningWork2(): Promise<number> { ... }
238
+ const result2 = yield* waitFor(doLongRunningWork2()); // number ✅
239
+ // async function doLongRunningWork3(): Promise<boolean> { ... }
240
+ const result3 = yield* waitFor(doLongRunningWork3()); // boolean ✅
241
+
242
+ // ...
243
+ }
244
+ ```
245
+
246
+ Alternatively, you can assert the return type manually, but this is not type-safe:
215
247
 
216
248
  ```ts
217
249
  async function* fetchResourcesTask() {
@@ -317,22 +349,22 @@ To use concurrency groups, specify the `group` property in the task builder:
317
349
 
318
350
  ```ts
319
351
  const task1 = scheduler.queueTask({
320
- priority: TaskPriority.Normal,
321
- group: {
322
- id: "my-concurrency-group",
323
- },
352
+ priority: TaskPriority.Normal,
353
+ group: {
354
+ id: "my-concurrency-group",
355
+ },
324
356
  task: async function* () {
325
- // ...
357
+ // ...
326
358
  },
327
359
  });
328
360
 
329
361
  const task2 = scheduler.queueTask({
330
- priority: TaskPriority.Normal,
331
- group: {
332
- id: "my-concurrency-group",
333
- },
362
+ priority: TaskPriority.Normal,
363
+ group: {
364
+ id: "my-concurrency-group",
365
+ },
334
366
  task: async function* () {
335
- // ...
367
+ // ...
336
368
  },
337
369
  });
338
370
  ```
@@ -449,6 +481,10 @@ const scheduler = new TaskScheduler(() => new Error("We are all doomed!"));
449
481
  ```
450
482
 
451
483
  ## Changelog
484
+ ### 1.2.0 (2025-06-24)
485
+
486
+ - Add utility method `waitFor` for type-safe yielding of Promises
487
+
452
488
  ### 1.1.0 (2025-06-24)
453
489
 
454
490
  - Add support for task concurrency groups, preventing interleaving related tasks
@@ -1,2 +1,3 @@
1
1
  export { type Task, type TaskBuilder, TaskInterruptBehavior, TaskPriority, type TaskReturnType, TaskScheduler, TaskState, type TaskStepResult, type TaskConcurrencyGroup, } from "./Task.js";
2
+ export { waitFor } from "./utils.js";
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -21,15 +21,18 @@ __export(index_exports, {
21
21
  TaskInterruptBehavior: () => import_Task.TaskInterruptBehavior,
22
22
  TaskPriority: () => import_Task.TaskPriority,
23
23
  TaskScheduler: () => import_Task.TaskScheduler,
24
- TaskState: () => import_Task.TaskState
24
+ TaskState: () => import_Task.TaskState,
25
+ waitFor: () => import_utils.waitFor
25
26
  });
26
27
  module.exports = __toCommonJS(index_exports);
27
28
  var import_Task = require("./Task.js");
29
+ var import_utils = require("./utils.js");
28
30
  // Annotate the CommonJS export names for ESM import in node:
29
31
  0 && (module.exports = {
30
32
  TaskInterruptBehavior,
31
33
  TaskPriority,
32
34
  TaskScheduler,
33
- TaskState
35
+ TaskState,
36
+ waitFor
34
37
  });
35
38
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/index.ts"],
4
- "sourcesContent": ["export {\n\ttype Task,\n\ttype TaskBuilder,\n\tTaskInterruptBehavior,\n\tTaskPriority,\n\ttype TaskReturnType,\n\tTaskScheduler,\n\tTaskState,\n\ttype TaskStepResult,\n\ttype TaskConcurrencyGroup,\n} from \"./Task.js\";\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;;;;;;;;AAAA,kBAUO;",
4
+ "sourcesContent": ["export {\n\ttype Task,\n\ttype TaskBuilder,\n\tTaskInterruptBehavior,\n\tTaskPriority,\n\ttype TaskReturnType,\n\tTaskScheduler,\n\tTaskState,\n\ttype TaskStepResult,\n\ttype TaskConcurrencyGroup,\n} from \"./Task.js\";\nexport { waitFor } from \"./utils.js\";\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;;;;;;;;;AAAA,kBAUO;AACP,mBAAwB;",
6
6
  "names": []
7
7
  }
@@ -5,4 +5,5 @@ export declare function noop(): void;
5
5
  export type FnOrStatic<TArgs extends any[], TReturn> = ((...args: TArgs) => TReturn) | TReturn;
6
6
  export type ReturnTypeOrStatic<T> = T extends (...args: any[]) => infer R ? R : T;
7
7
  export declare function evalOrStatic<T>(fnOrConst: T, ...args: any[]): ReturnTypeOrStatic<T>;
8
+ export declare function waitFor<T>(promise: Promise<T>): AsyncGenerator<() => Promise<T>, T>;
8
9
  //# sourceMappingURL=utils.d.ts.map
@@ -21,7 +21,8 @@ var utils_exports = {};
21
21
  __export(utils_exports, {
22
22
  evalOrStatic: () => evalOrStatic,
23
23
  highResTimestamp: () => highResTimestamp,
24
- noop: () => noop
24
+ noop: () => noop,
25
+ waitFor: () => waitFor
25
26
  });
26
27
  module.exports = __toCommonJS(utils_exports);
27
28
  function highResTimestamp() {
@@ -42,10 +43,16 @@ function evalOrStatic(fnOrConst, ...args) {
42
43
  return typeof fnOrConst === "function" ? fnOrConst(...args) : fnOrConst;
43
44
  }
44
45
  __name(evalOrStatic, "evalOrStatic");
46
+ async function* waitFor(promise) {
47
+ const result = yield () => promise;
48
+ return result;
49
+ }
50
+ __name(waitFor, "waitFor");
45
51
  // Annotate the CommonJS export names for ESM import in node:
46
52
  0 && (module.exports = {
47
53
  evalOrStatic,
48
54
  highResTimestamp,
49
- noop
55
+ noop,
56
+ waitFor
50
57
  });
51
58
  //# sourceMappingURL=utils.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils.ts"],
4
- "sourcesContent": ["/** Returns a timestamp with nano-second precision */\nexport function highResTimestamp(): number {\n\tif (typeof process !== \"undefined\") {\n\t\tconst [s, ns] = process.hrtime();\n\t\treturn s * 1e9 + ns;\n\t} else if (performance != undefined) {\n\t\treturn performance.now() * 1e6;\n\t} else {\n\t\tthrow new Error(\"No high-resolution timer available\");\n\t}\n}\n\n/** Does nothing. Can be used for empty `.catch(...)` calls. */\nexport function noop(): void {\n\t// intentionally empty\n}\n\nexport type FnOrStatic<TArgs extends any[], TReturn> =\n\t| ((...args: TArgs) => TReturn)\n\t| TReturn;\n\nexport type ReturnTypeOrStatic<T> = T extends (...args: any[]) => infer R\n\t? R\n\t: T;\n\nexport function evalOrStatic<T>(\n\tfnOrConst: T,\n\t...args: any[]\n): ReturnTypeOrStatic<T> {\n\t// @ts-expect-error https://github.com/microsoft/TypeScript/issues/61337\n\treturn typeof fnOrConst === \"function\" ? fnOrConst(...args) : fnOrConst;\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;AAAA;;;;;;;AACM,SAAU,mBAAgB;AAC/B,MAAI,OAAO,YAAY,aAAa;AACnC,UAAM,CAAC,GAAG,EAAE,IAAI,QAAQ,OAAM;AAC9B,WAAO,IAAI,MAAM;EAClB,WAAW,eAAe,QAAW;AACpC,WAAO,YAAY,IAAG,IAAK;EAC5B,OAAO;AACN,UAAM,IAAI,MAAM,oCAAoC;EACrD;AACD;AATgB;AAYV,SAAU,OAAI;AAEpB;AAFgB;AAYV,SAAU,aACf,cACG,MAAW;AAGd,SAAO,OAAO,cAAc,aAAa,UAAU,GAAG,IAAI,IAAI;AAC/D;AANgB;",
4
+ "sourcesContent": ["/** Returns a timestamp with nano-second precision */\nexport function highResTimestamp(): number {\n\tif (typeof process !== \"undefined\") {\n\t\tconst [s, ns] = process.hrtime();\n\t\treturn s * 1e9 + ns;\n\t} else if (performance != undefined) {\n\t\treturn performance.now() * 1e6;\n\t} else {\n\t\tthrow new Error(\"No high-resolution timer available\");\n\t}\n}\n\n/** Does nothing. Can be used for empty `.catch(...)` calls. */\nexport function noop(): void {\n\t// intentionally empty\n}\n\nexport type FnOrStatic<TArgs extends any[], TReturn> =\n\t| ((...args: TArgs) => TReturn)\n\t| TReturn;\n\nexport type ReturnTypeOrStatic<T> = T extends (...args: any[]) => infer R\n\t? R\n\t: T;\n\nexport function evalOrStatic<T>(\n\tfnOrConst: T,\n\t...args: any[]\n): ReturnTypeOrStatic<T> {\n\t// @ts-expect-error https://github.com/microsoft/TypeScript/issues/61337\n\treturn typeof fnOrConst === \"function\" ? fnOrConst(...args) : fnOrConst;\n}\n\nexport async function* waitFor<T>(\n\tpromise: Promise<T>,\n): AsyncGenerator<() => Promise<T>, T> {\n\tconst result = yield () => promise;\n\treturn result;\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;AACM,SAAU,mBAAgB;AAC/B,MAAI,OAAO,YAAY,aAAa;AACnC,UAAM,CAAC,GAAG,EAAE,IAAI,QAAQ,OAAM;AAC9B,WAAO,IAAI,MAAM;EAClB,WAAW,eAAe,QAAW;AACpC,WAAO,YAAY,IAAG,IAAK;EAC5B,OAAO;AACN,UAAM,IAAI,MAAM,oCAAoC;EACrD;AACD;AATgB;AAYV,SAAU,OAAI;AAEpB;AAFgB;AAYV,SAAU,aACf,cACG,MAAW;AAGd,SAAO,OAAO,cAAc,aAAa,UAAU,GAAG,IAAI,IAAI;AAC/D;AANgB;AAQhB,gBAAuB,QACtB,SAAmB;AAEnB,QAAM,SAAS,MAAM,MAAM;AAC3B,SAAO;AACR;AALuB;",
6
6
  "names": []
7
7
  }
@@ -1,2 +1,3 @@
1
1
  export { type Task, type TaskBuilder, TaskInterruptBehavior, TaskPriority, type TaskReturnType, TaskScheduler, TaskState, type TaskStepResult, type TaskConcurrencyGroup, } from "./Task.js";
2
+ export { waitFor } from "./utils.js";
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,IAAI,EACT,KAAK,WAAW,EAChB,qBAAqB,EACrB,YAAY,EACZ,KAAK,cAAc,EACnB,aAAa,EACb,SAAS,EACT,KAAK,cAAc,EACnB,KAAK,oBAAoB,GACzB,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,IAAI,EACT,KAAK,WAAW,EAChB,qBAAqB,EACrB,YAAY,EACZ,KAAK,cAAc,EACnB,aAAa,EACb,SAAS,EACT,KAAK,cAAc,EACnB,KAAK,oBAAoB,GACzB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC"}
@@ -1,2 +1,3 @@
1
1
  export { TaskInterruptBehavior, TaskPriority, TaskScheduler, TaskState, } from "./Task.js";
2
+ export { waitFor } from "./utils.js";
2
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,qBAAqB,EACrB,YAAY,EAEZ,aAAa,EACb,SAAS,GAGT,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,qBAAqB,EACrB,YAAY,EAEZ,aAAa,EACb,SAAS,GAGT,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC"}
@@ -5,4 +5,5 @@ export declare function noop(): void;
5
5
  export type FnOrStatic<TArgs extends any[], TReturn> = ((...args: TArgs) => TReturn) | TReturn;
6
6
  export type ReturnTypeOrStatic<T> = T extends (...args: any[]) => infer R ? R : T;
7
7
  export declare function evalOrStatic<T>(fnOrConst: T, ...args: any[]): ReturnTypeOrStatic<T>;
8
+ export declare function waitFor<T>(promise: Promise<T>): AsyncGenerator<() => Promise<T>, T>;
8
9
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,wBAAgB,gBAAgB,IAAI,MAAM,CASzC;AAED,+DAA+D;AAC/D,wBAAgB,IAAI,IAAI,IAAI,CAE3B;AAED,MAAM,MAAM,UAAU,CAAC,KAAK,SAAS,GAAG,EAAE,EAAE,OAAO,IAChD,CAAC,CAAC,GAAG,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,GAC7B,OAAO,CAAC;AAEX,MAAM,MAAM,kBAAkB,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,MAAM,CAAC,GACtE,CAAC,GACD,CAAC,CAAC;AAEL,wBAAgB,YAAY,CAAC,CAAC,EAC7B,SAAS,EAAE,CAAC,EACZ,GAAG,IAAI,EAAE,GAAG,EAAE,GACZ,kBAAkB,CAAC,CAAC,CAAC,CAGvB"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,wBAAgB,gBAAgB,IAAI,MAAM,CASzC;AAED,+DAA+D;AAC/D,wBAAgB,IAAI,IAAI,IAAI,CAE3B;AAED,MAAM,MAAM,UAAU,CAAC,KAAK,SAAS,GAAG,EAAE,EAAE,OAAO,IAChD,CAAC,CAAC,GAAG,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,GAC7B,OAAO,CAAC;AAEX,MAAM,MAAM,kBAAkB,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,MAAM,CAAC,GACtE,CAAC,GACD,CAAC,CAAC;AAEL,wBAAgB,YAAY,CAAC,CAAC,EAC7B,SAAS,EAAE,CAAC,EACZ,GAAG,IAAI,EAAE,GAAG,EAAE,GACZ,kBAAkB,CAAC,CAAC,CAAC,CAGvB;AAED,wBAAuB,OAAO,CAAC,CAAC,EAC/B,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GACjB,cAAc,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAGrC"}
@@ -19,4 +19,8 @@ export function evalOrStatic(fnOrConst, ...args) {
19
19
  // @ts-expect-error https://github.com/microsoft/TypeScript/issues/61337
20
20
  return typeof fnOrConst === "function" ? fnOrConst(...args) : fnOrConst;
21
21
  }
22
+ export async function* waitFor(promise) {
23
+ const result = yield () => promise;
24
+ return result;
25
+ }
22
26
  //# sourceMappingURL=utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,MAAM,UAAU,gBAAgB;IAC/B,IAAI,OAAO,OAAO,KAAK,WAAW,EAAE,CAAC;QACpC,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;QACjC,OAAO,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC;IACrB,CAAC;SAAM,IAAI,WAAW,IAAI,SAAS,EAAE,CAAC;QACrC,OAAO,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,CAAC;IAChC,CAAC;SAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACvD,CAAC;AACF,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,IAAI;IACnB,sBAAsB;AACvB,CAAC;AAUD,MAAM,UAAU,YAAY,CAC3B,SAAY,EACZ,GAAG,IAAW;IAEd,wEAAwE;IACxE,OAAO,OAAO,SAAS,KAAK,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACzE,CAAC"}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,MAAM,UAAU,gBAAgB;IAC/B,IAAI,OAAO,OAAO,KAAK,WAAW,EAAE,CAAC;QACpC,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;QACjC,OAAO,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC;IACrB,CAAC;SAAM,IAAI,WAAW,IAAI,SAAS,EAAE,CAAC;QACrC,OAAO,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,CAAC;IAChC,CAAC;SAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACvD,CAAC;AACF,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,IAAI;IACnB,sBAAsB;AACvB,CAAC;AAUD,MAAM,UAAU,YAAY,CAC3B,SAAY,EACZ,GAAG,IAAW;IAEd,wEAAwE;IACxE,OAAO,OAAO,SAAS,KAAK,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACzE,CAAC;AAED,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,OAAO,CAC7B,OAAmB;IAEnB,MAAM,MAAM,GAAG,MAAM,GAAG,EAAE,CAAC,OAAO,CAAC;IACnC,OAAO,MAAM,CAAC;AACf,CAAC"}
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "access": "public"
5
5
  },
6
6
  "description": "A cooperative task scheduler based on generator functions",
7
- "version": "1.1.0",
7
+ "version": "1.2.0",
8
8
  "license": "MIT",
9
9
  "type": "module",
10
10
  "module": "build/index.js",