@httptoolkit/util 0.1.3 → 0.1.5

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/dist/errors.d.ts CHANGED
@@ -19,7 +19,7 @@ export declare function isErrorLike(error: any): error is ErrorLike;
19
19
  * A convenience method to make something error-ish into an actual Error instance.
20
20
  */
21
21
  export declare function asErrorLike(error: any): ErrorLike;
22
- export declare class CustomError extends Error {
22
+ export declare class CustomError extends Error implements ErrorLike {
23
23
  constructor(message?: string, extras?: {
24
24
  code?: string;
25
25
  statusCode?: number;
package/dist/errors.js CHANGED
@@ -35,9 +35,12 @@ class CustomError extends Error {
35
35
  // This restores the details of the real error subclass:
36
36
  this.name = new.target.name;
37
37
  Object.setPrototypeOf(this, new.target.prototype);
38
- this.code = extras.code;
39
- this.statusCode = extras.statusCode;
40
- this.cause = extras.cause;
38
+ if (extras.code !== undefined)
39
+ this.code = extras.code;
40
+ if (extras.statusCode !== undefined)
41
+ this.statusCode = extras.statusCode;
42
+ if (extras.cause !== undefined)
43
+ this.cause = extras.cause;
41
44
  }
42
45
  }
43
46
  exports.CustomError = CustomError;
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";;;AAcA;;;GAGG;AACH,SAAgB,WAAW,CAAC,KAAU;IAClC,OAAO,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CACzC,KAAK,YAAY,KAAK;QACtB,KAAK,CAAC,OAAO;QACb,KAAK,CAAC,IAAI;QACV,KAAK,CAAC,KAAK,CACd,CAAA;AACL,CAAC;AAPD,kCAOC;AAED;;GAEG;AACH,SAAgB,WAAW,CAAC,KAAU;IAClC,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE;QACpB,OAAO,KAAkB,CAAC;KAC7B;SAAM,IAAI,KAAK,EAAE;QACd,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE,IAAI,iBAAiB,CAAC,CAAC;KAC5E;SAAM;QACH,OAAO,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;KACzC;AACL,CAAC;AARD,kCAQC;AAED,sFAAsF;AACtF,wDAAwD;AACxD,MAAa,WAAY,SAAQ,KAAK;IAClC,YAAY,OAAgB,EAAE,SAI1B,EAAE;QACF,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,sCAAsC;QAEtD,wDAAwD;QACxD,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;QAC5B,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAElD,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACxB,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;QACpC,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IAC9B,CAAC;CAKJ;AApBD,kCAoBC;AAED,MAAa,WAAY,SAAQ,WAAW;IACxC;IACI;;OAEG;IACH,UAAkB,EAClB,OAAe,EACf,SAGI,EAAE;QAEN,KAAK,CAAC,OAAO,EAAE,EAAE,GAAG,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAC;IAC1D,CAAC;CACJ;AAdD,kCAcC;AAED;;;GAGG;AACH,MAAa,gBAAiB,SAAQ,WAAW;IAE7C,qFAAqF;IACrF,mDAAmD;IACnD,YAAY,KAAY,EAAE,WAA4B,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1D,KAAK,CAAC,yBAAyB,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACtD,CAAC;CAEJ;AARD,4CAQC;AAED;;GAEG;AACI,MAAM,gBAAgB,GAAG,CAAC,KAAY,EAAE,WAA4B,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAS,EAAE;IAC1F,MAAM,IAAI,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;AAChD,CAAC,CAAA;AAFY,QAAA,gBAAgB,oBAE5B"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";;;AAcA;;;GAGG;AACH,SAAgB,WAAW,CAAC,KAAU;IAClC,OAAO,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CACzC,KAAK,YAAY,KAAK;QACtB,KAAK,CAAC,OAAO;QACb,KAAK,CAAC,IAAI;QACV,KAAK,CAAC,KAAK,CACd,CAAA;AACL,CAAC;AAPD,kCAOC;AAED;;GAEG;AACH,SAAgB,WAAW,CAAC,KAAU;IAClC,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE;QACpB,OAAO,KAAkB,CAAC;KAC7B;SAAM,IAAI,KAAK,EAAE;QACd,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE,IAAI,iBAAiB,CAAC,CAAC;KAC5E;SAAM;QACH,OAAO,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;KACzC;AACL,CAAC;AARD,kCAQC;AAED,sFAAsF;AACtF,wDAAwD;AACxD,MAAa,WAAY,SAAQ,KAAK;IAClC,YAAY,OAAgB,EAAE,SAI1B,EAAE;QACF,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,sCAAsC;QAEtD,wDAAwD;QACxD,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;QAC5B,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAElD,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS;YAAE,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACvD,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS;YAAE,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;QACzE,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS;YAAE,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IAC9D,CAAC;CAKJ;AApBD,kCAoBC;AAED,MAAa,WAAY,SAAQ,WAAW;IACxC;IACI;;OAEG;IACH,UAAkB,EAClB,OAAe,EACf,SAGI,EAAE;QAEN,KAAK,CAAC,OAAO,EAAE,EAAE,GAAG,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAC;IAC1D,CAAC;CACJ;AAdD,kCAcC;AAED;;;GAGG;AACH,MAAa,gBAAiB,SAAQ,WAAW;IAE7C,qFAAqF;IACrF,mDAAmD;IACnD,YAAY,KAAY,EAAE,WAA4B,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1D,KAAK,CAAC,yBAAyB,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACtD,CAAC;CAEJ;AARD,4CAQC;AAED;;GAEG;AACI,MAAM,gBAAgB,GAAG,CAAC,KAAY,EAAE,WAA4B,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAS,EAAE;IAC1F,MAAM,IAAI,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;AAChD,CAAC,CAAA;AAFY,QAAA,gBAAgB,oBAE5B"}
@@ -6,7 +6,7 @@ export declare const delay: (ms: number, options?: {
6
6
  * block the process shutdown.
7
7
  */
8
8
  unref?: boolean;
9
- }) => Promise<unknown>;
9
+ }) => Promise<void>;
10
10
  export declare function doWhile<T>(doFn: () => Promise<T>, whileFn: () => Promise<boolean> | boolean): Promise<void>;
11
11
  export interface Deferred<T> {
12
12
  resolve: (arg: T) => void;
@@ -14,3 +14,11 @@ export interface Deferred<T> {
14
14
  promise: Promise<T>;
15
15
  }
16
16
  export declare function getDeferred<T = void>(): Deferred<T>;
17
+ /**
18
+ * Wrap a function, so that any parallel calls which happen while the async function
19
+ * is pending return the same value as the first call (so the function is only run
20
+ * once, but the result is shared). This is useful for expensive async functions or
21
+ * race conditions. This ignores arguments completely, and is only applicable for
22
+ * functions that don't need any other input.
23
+ */
24
+ export declare function combineParallelCalls<T>(fn: () => Promise<T>): () => Promise<T>;
package/dist/promises.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getDeferred = exports.doWhile = exports.delay = void 0;
3
+ exports.combineParallelCalls = exports.getDeferred = exports.doWhile = exports.delay = void 0;
4
4
  const delay = (ms, options = {}) => new Promise((resolve) => {
5
5
  const timer = setTimeout(resolve, ms);
6
6
  if (options.unref && timer.unref) {
@@ -26,4 +26,23 @@ function getDeferred() {
26
26
  return { resolve, reject, promise };
27
27
  }
28
28
  exports.getDeferred = getDeferred;
29
+ /**
30
+ * Wrap a function, so that any parallel calls which happen while the async function
31
+ * is pending return the same value as the first call (so the function is only run
32
+ * once, but the result is shared). This is useful for expensive async functions or
33
+ * race conditions. This ignores arguments completely, and is only applicable for
34
+ * functions that don't need any other input.
35
+ */
36
+ function combineParallelCalls(fn) {
37
+ let pendingPromise;
38
+ return () => {
39
+ if (pendingPromise === undefined) {
40
+ pendingPromise = fn().finally(() => {
41
+ pendingPromise = undefined;
42
+ });
43
+ }
44
+ return pendingPromise;
45
+ };
46
+ }
47
+ exports.combineParallelCalls = combineParallelCalls;
29
48
  //# sourceMappingURL=promises.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"promises.js","sourceRoot":"","sources":["../src/promises.ts"],"names":[],"mappings":";;;AAEO,MAAM,KAAK,GAAG,CAAC,EAAU,EAAE,UAO9B,EAAE,EAAE,EAAE,CACN,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;IACpB,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAEtC,IAAI,OAAO,CAAC,KAAK,IAAK,KAAa,CAAC,KAAK,EAAE;QACtC,KAAa,CAAC,KAAK,EAAE,CAAC;KAC1B;AACL,CAAC,CAAC,CAAC;AAdM,QAAA,KAAK,SAcX;AAEA,KAAK,UAAU,OAAO,CACzB,IAAsB,EACtB,OAAyC;IAEzC,GAAG;QACC,MAAM,IAAI,EAAE,CAAC;KAChB,QAAQ,MAAM,OAAO,EAAE,EAAE;AAC9B,CAAC;AAPD,0BAOC;AAQD,SAAgB,WAAW;IACvB,IAAI,OAAO,GAAmC,SAAS,CAAC;IACxD,IAAI,MAAM,GAAsC,SAAS,CAAC;IAE1D,IAAI,OAAO,GAAG,IAAI,OAAO,CAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE;QACjD,OAAO,GAAG,SAAS,CAAC;QACpB,MAAM,GAAG,QAAQ,CAAC;IACtB,CAAC,CAAC,CAAC;IAEH,oEAAoE;IACpE,iDAAiD;IACjD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAS,CAAC;AAC/C,CAAC;AAZD,kCAYC"}
1
+ {"version":3,"file":"promises.js","sourceRoot":"","sources":["../src/promises.ts"],"names":[],"mappings":";;;AAEO,MAAM,KAAK,GAAG,CAAC,EAAU,EAAE,UAO9B,EAAE,EAAE,EAAE,CACN,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;IAC1B,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAEtC,IAAI,OAAO,CAAC,KAAK,IAAK,KAAa,CAAC,KAAK,EAAE;QACtC,KAAa,CAAC,KAAK,EAAE,CAAC;KAC1B;AACL,CAAC,CAAC,CAAC;AAdM,QAAA,KAAK,SAcX;AAEA,KAAK,UAAU,OAAO,CACzB,IAAsB,EACtB,OAAyC;IAEzC,GAAG;QACC,MAAM,IAAI,EAAE,CAAC;KAChB,QAAQ,MAAM,OAAO,EAAE,EAAE;AAC9B,CAAC;AAPD,0BAOC;AAQD,SAAgB,WAAW;IACvB,IAAI,OAAO,GAAmC,SAAS,CAAC;IACxD,IAAI,MAAM,GAAsC,SAAS,CAAC;IAE1D,IAAI,OAAO,GAAG,IAAI,OAAO,CAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE;QACjD,OAAO,GAAG,SAAS,CAAC;QACpB,MAAM,GAAG,QAAQ,CAAC;IACtB,CAAC,CAAC,CAAC;IAEH,oEAAoE;IACpE,iDAAiD;IACjD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAS,CAAC;AAC/C,CAAC;AAZD,kCAYC;AAED;;;;;;GAMG;AACH,SAAgB,oBAAoB,CAAI,EAAoB;IACxD,IAAI,cAAsC,CAAC;IAE3C,OAAO,GAAG,EAAE;QACR,IAAI,cAAc,KAAK,SAAS,EAAE;YAC9B,cAAc,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE;gBAC/B,cAAc,GAAG,SAAS,CAAC;YAC/B,CAAC,CAAC,CAAC;SACN;QAED,OAAO,cAAc,CAAC;IAC1B,CAAC,CAAC;AACN,CAAC;AAZD,oDAYC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@httptoolkit/util",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "A tiny utility package, sharing JS code widely used across HTTP Toolkit projects",
5
5
  "main": "dist/index.js",
6
6
  "files": [
package/src/errors.ts CHANGED
@@ -40,7 +40,7 @@ export function asErrorLike(error: any): ErrorLike {
40
40
 
41
41
  // Tiny wrapper to make it super easy to make custom error classes where .name behaves
42
42
  // correctly, and useful metafields can be easily added.
43
- export class CustomError extends Error {
43
+ export class CustomError extends Error implements ErrorLike {
44
44
  constructor(message?: string, extras: {
45
45
  code?: string,
46
46
  statusCode?: number,
@@ -52,9 +52,9 @@ export class CustomError extends Error {
52
52
  this.name = new.target.name;
53
53
  Object.setPrototypeOf(this, new.target.prototype);
54
54
 
55
- this.code = extras.code;
56
- this.statusCode = extras.statusCode;
57
- this.cause = extras.cause;
55
+ if (extras.code !== undefined) this.code = extras.code;
56
+ if (extras.statusCode !== undefined) this.statusCode = extras.statusCode;
57
+ if (extras.cause !== undefined) this.cause = extras.cause;
58
58
  }
59
59
 
60
60
  public readonly code?: string;
package/src/promises.ts CHANGED
@@ -8,7 +8,7 @@ export const delay = (ms: number, options: {
8
8
  */
9
9
  unref?: boolean
10
10
  } = {}) =>
11
- new Promise((resolve) => {
11
+ new Promise<void>((resolve) => {
12
12
  const timer = setTimeout(resolve, ms);
13
13
 
14
14
  if (options.unref && (timer as any).unref) {
@@ -43,4 +43,25 @@ export function getDeferred<T = void>(): Deferred<T> {
43
43
  // TS thinks we're using these before they're assigned, which is why
44
44
  // we need the undefined types, and the any here.
45
45
  return { resolve, reject, promise } as any;
46
+ }
47
+
48
+ /**
49
+ * Wrap a function, so that any parallel calls which happen while the async function
50
+ * is pending return the same value as the first call (so the function is only run
51
+ * once, but the result is shared). This is useful for expensive async functions or
52
+ * race conditions. This ignores arguments completely, and is only applicable for
53
+ * functions that don't need any other input.
54
+ */
55
+ export function combineParallelCalls<T>(fn: () => Promise<T>): () => Promise<T> {
56
+ let pendingPromise: Promise<T> | undefined;
57
+
58
+ return () => {
59
+ if (pendingPromise === undefined) {
60
+ pendingPromise = fn().finally(() => {
61
+ pendingPromise = undefined;
62
+ });
63
+ }
64
+
65
+ return pendingPromise;
66
+ };
46
67
  }