@homer0/extend-promise 3.0.8 → 3.0.10
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/esm/index.js +4 -8
- package/dist/esm/index.js.map +1 -1
- package/dist/index.js +4 -6
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/dist/esm/index.js
CHANGED
|
@@ -1,19 +1,15 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
-
|
|
5
1
|
// src/index.ts
|
|
6
2
|
var PromiseExtender = class {
|
|
3
|
+
/**
|
|
4
|
+
* The proxied promise.
|
|
5
|
+
*/
|
|
6
|
+
promise;
|
|
7
7
|
/**
|
|
8
8
|
* @param promise The promise to extend.
|
|
9
9
|
* @param properties A dictionary of custom properties to _inject_ in the promise
|
|
10
10
|
* chain.
|
|
11
11
|
*/
|
|
12
12
|
constructor(promise, properties) {
|
|
13
|
-
/**
|
|
14
|
-
* The proxied promise.
|
|
15
|
-
*/
|
|
16
|
-
__publicField(this, "promise");
|
|
17
13
|
this.promise = this.extend(promise, properties);
|
|
18
14
|
}
|
|
19
15
|
/**
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.ts"],"sourcesContent":["type ExtractGeneric<Type> = Type extends Promise<infer X> ? X : never;\n\ntype ExtendedPromise<T extends Promise<unknown>, P, V = ExtractGeneric<T>> = Omit<\n T,\n 'then' | 'catch' | 'finally'\n> &\n P & {\n then: (...args: Parameters<T['then']>) => ExtendedPromise<Promise<V>, P>;\n catch: (...args: Parameters<T['catch']>) => ExtendedPromise<Promise<V>, P>;\n finally: (...args: Parameters<T['finally']>) => ExtendedPromise<Promise<V>, P>;\n };\ntype GenericFn = (...args: unknown[]) => unknown;\ntype ExtendedFn<F extends GenericFn, P> = F & P;\n\n/**\n * Helper class that creates a proxy for a {@link Promise} in order to add custom\n * properties.\n *\n * The only reason this class exists is so it can \"scope\" the necessary methods to extend\n * {@link Promise} and avoid workarounds in order to declare them, as they need to call\n * themselves recursively.\n */\nclass PromiseExtender<T extends Promise<unknown>, P extends Record<string, unknown>> {\n /**\n * The proxied promise.\n */\n readonly promise: ExtendedPromise<T, P>;\n /**\n * @param promise The promise to extend.\n * @param properties A dictionary of custom properties to _inject_ in the promise\n * chain.\n */\n constructor(promise: T, properties: P) {\n this.promise = this.extend(promise, properties);\n }\n /**\n * The method that actually extends a promise: it creates a proxy of the promise in\n * order to intercept the getters so it can return the custom properties if requested,\n * and return new proxies when `then`, `catch` and `finally` are called; the reason new\n * proxies are created is because those methods return new promises, and without being\n * proxied, the custom properties would be lost.\n *\n * @param promise The promise to proxy.\n * @param properties A dictionary of custom properties to _inject_ in the promise\n * chain.\n * @throws {Error} If `promise` is not a valid instance of {@link Promise}.\n * @throws {Error} If `properties` is not an object or if it doesn't have any\n * properties.\n */\n extend(promise: T, properties: P): ExtendedPromise<T, P> {\n if (!(promise instanceof Promise)) {\n throw new Error(\"'promise' must be a valid Promise instance\");\n }\n\n if (!properties || !Object.keys(properties).length) {\n throw new Error(\"'properties' must be an object with at least one key\");\n }\n\n const extended = new Proxy(promise, {\n /**\n * This is a trap for when something is trying to read/access a property for the\n * promise.\n * The function first validates if it's one of the functions\n * (`then`/`catch`/`finally`) in order to return a proxied function; then, if it's\n * another function (one that doesn't return another promise), it just calls the\n * original; finally, before doing a fallback to the original promise, it checks if\n * it's one of the custom properties that exented the promise.\n *\n * @param target The original promise.\n * @param name The name of the property.\n */\n get: (target, name) => {\n const targetKey = name as keyof typeof target;\n if (\n typeof name === 'string' &&\n ['then', 'catch', 'finally'].includes(name) &&\n name in target\n ) {\n const fn = target[targetKey] as unknown as GenericFn;\n return this.extendFunction(fn.bind(target), properties);\n }\n\n if (name in target) {\n const possibleFn = target[targetKey] as unknown as Record<string, unknown>;\n // eslint-disable-next-line dot-notation\n if (typeof possibleFn['bind'] === 'function') {\n // eslint-disable-next-line dot-notation\n return possibleFn['bind'](target);\n }\n }\n\n const key = name as keyof P;\n return properties[key];\n },\n });\n\n return extended as unknown as ExtendedPromise<T, P>;\n }\n /**\n * Creates a proxy for a promise function (`then`/`catch`/`finally`) so the returned\n * promise can also be extended.\n *\n * @param fn The promise function to proxy.\n * @param properties A dictionary of custom properties to _inject_ in the promise\n * chain.\n */\n protected extendFunction<F extends GenericFn>(fn: F, properties: P): ExtendedFn<F, P> {\n return new Proxy(fn, {\n /**\n * This is a trap for when a function gets called (remember this gets used for\n * `then`/\n * `catch`/`finally`); it processes the result using the oringinal function and\n * since promise methods return a promise, instead of returning the original result,\n * it returns an _extended_ version of it.\n *\n * @param target The original function.\n * @param thisArg The promise the function belongs to.\n * @param args The list of arguments sent to the trap.\n */\n apply: (target, thisArg, args) => {\n const value = target.bind(thisArg)(...args);\n return this.extend(value as T, properties);\n },\n }) as ExtendedFn<F, P>;\n }\n}\n\n/**\n * Extends a {@link Promise} by injecting custom properties using a {@link Proxy}. The\n * custom properties will be available on the promise chain no matter how many `then`s,\n * `catch`s or `finally`s are added.\n *\n * @param promise The promise to extend.\n * @param properties A dictionary of custom properties to _inject_ in the promise\n * chain.\n * @throws {Error} If `promise` is not a valid instance of {@link Promise}.\n * @throws {Error} If `properties` is not an object or if it doesn't have any\n * properties.\n */\nexport const extendPromise = <\n T extends Promise<unknown>,\n P extends Record<string, unknown>,\n>(\n promise: T,\n properties: P,\n): ExtendedPromise<T, P> => new PromiseExtender(promise, properties).promise;\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts"],"sourcesContent":["type ExtractGeneric<Type> = Type extends Promise<infer X> ? X : never;\n\ntype ExtendedPromise<T extends Promise<unknown>, P, V = ExtractGeneric<T>> = Omit<\n T,\n 'then' | 'catch' | 'finally'\n> &\n P & {\n then: (...args: Parameters<T['then']>) => ExtendedPromise<Promise<V>, P>;\n catch: (...args: Parameters<T['catch']>) => ExtendedPromise<Promise<V>, P>;\n finally: (...args: Parameters<T['finally']>) => ExtendedPromise<Promise<V>, P>;\n };\ntype GenericFn = (...args: unknown[]) => unknown;\ntype ExtendedFn<F extends GenericFn, P> = F & P;\n\n/**\n * Helper class that creates a proxy for a {@link Promise} in order to add custom\n * properties.\n *\n * The only reason this class exists is so it can \"scope\" the necessary methods to extend\n * {@link Promise} and avoid workarounds in order to declare them, as they need to call\n * themselves recursively.\n */\nclass PromiseExtender<T extends Promise<unknown>, P extends Record<string, unknown>> {\n /**\n * The proxied promise.\n */\n readonly promise: ExtendedPromise<T, P>;\n /**\n * @param promise The promise to extend.\n * @param properties A dictionary of custom properties to _inject_ in the promise\n * chain.\n */\n constructor(promise: T, properties: P) {\n this.promise = this.extend(promise, properties);\n }\n /**\n * The method that actually extends a promise: it creates a proxy of the promise in\n * order to intercept the getters so it can return the custom properties if requested,\n * and return new proxies when `then`, `catch` and `finally` are called; the reason new\n * proxies are created is because those methods return new promises, and without being\n * proxied, the custom properties would be lost.\n *\n * @param promise The promise to proxy.\n * @param properties A dictionary of custom properties to _inject_ in the promise\n * chain.\n * @throws {Error} If `promise` is not a valid instance of {@link Promise}.\n * @throws {Error} If `properties` is not an object or if it doesn't have any\n * properties.\n */\n extend(promise: T, properties: P): ExtendedPromise<T, P> {\n if (!(promise instanceof Promise)) {\n throw new Error(\"'promise' must be a valid Promise instance\");\n }\n\n if (!properties || !Object.keys(properties).length) {\n throw new Error(\"'properties' must be an object with at least one key\");\n }\n\n const extended = new Proxy(promise, {\n /**\n * This is a trap for when something is trying to read/access a property for the\n * promise.\n * The function first validates if it's one of the functions\n * (`then`/`catch`/`finally`) in order to return a proxied function; then, if it's\n * another function (one that doesn't return another promise), it just calls the\n * original; finally, before doing a fallback to the original promise, it checks if\n * it's one of the custom properties that exented the promise.\n *\n * @param target The original promise.\n * @param name The name of the property.\n */\n get: (target, name) => {\n const targetKey = name as keyof typeof target;\n if (\n typeof name === 'string' &&\n ['then', 'catch', 'finally'].includes(name) &&\n name in target\n ) {\n const fn = target[targetKey] as unknown as GenericFn;\n return this.extendFunction(fn.bind(target), properties);\n }\n\n if (name in target) {\n const possibleFn = target[targetKey] as unknown as Record<string, unknown>;\n // eslint-disable-next-line dot-notation\n if (typeof possibleFn['bind'] === 'function') {\n // eslint-disable-next-line dot-notation\n return possibleFn['bind'](target);\n }\n }\n\n const key = name as keyof P;\n return properties[key];\n },\n });\n\n return extended as unknown as ExtendedPromise<T, P>;\n }\n /**\n * Creates a proxy for a promise function (`then`/`catch`/`finally`) so the returned\n * promise can also be extended.\n *\n * @param fn The promise function to proxy.\n * @param properties A dictionary of custom properties to _inject_ in the promise\n * chain.\n */\n protected extendFunction<F extends GenericFn>(fn: F, properties: P): ExtendedFn<F, P> {\n return new Proxy(fn, {\n /**\n * This is a trap for when a function gets called (remember this gets used for\n * `then`/\n * `catch`/`finally`); it processes the result using the oringinal function and\n * since promise methods return a promise, instead of returning the original result,\n * it returns an _extended_ version of it.\n *\n * @param target The original function.\n * @param thisArg The promise the function belongs to.\n * @param args The list of arguments sent to the trap.\n */\n apply: (target, thisArg, args) => {\n const value = target.bind(thisArg)(...args);\n return this.extend(value as T, properties);\n },\n }) as ExtendedFn<F, P>;\n }\n}\n\n/**\n * Extends a {@link Promise} by injecting custom properties using a {@link Proxy}. The\n * custom properties will be available on the promise chain no matter how many `then`s,\n * `catch`s or `finally`s are added.\n *\n * @param promise The promise to extend.\n * @param properties A dictionary of custom properties to _inject_ in the promise\n * chain.\n * @throws {Error} If `promise` is not a valid instance of {@link Promise}.\n * @throws {Error} If `properties` is not an object or if it doesn't have any\n * properties.\n */\nexport const extendPromise = <\n T extends Promise<unknown>,\n P extends Record<string, unknown>,\n>(\n promise: T,\n properties: P,\n): ExtendedPromise<T, P> => new PromiseExtender(promise, properties).promise;\n"],"mappings":";AAsBA,IAAM,kBAAN,MAAqF;AAAA;AAAA;AAAA;AAAA,EAI1E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMT,YAAY,SAAY,YAAe;AACrC,SAAK,UAAU,KAAK,OAAO,SAAS,UAAU;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,OAAO,SAAY,YAAsC;AACvD,QAAI,EAAE,mBAAmB,UAAU;AACjC,YAAM,IAAI,MAAM,4CAA4C;AAAA,IAC9D;AAEA,QAAI,CAAC,cAAc,CAAC,OAAO,KAAK,UAAU,EAAE,QAAQ;AAClD,YAAM,IAAI,MAAM,sDAAsD;AAAA,IACxE;AAEA,UAAM,WAAW,IAAI,MAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAalC,KAAK,CAAC,QAAQ,SAAS;AACrB,cAAM,YAAY;AAClB,YACE,OAAO,SAAS,YAChB,CAAC,QAAQ,SAAS,SAAS,EAAE,SAAS,IAAI,KAC1C,QAAQ,QACR;AACA,gBAAM,KAAK,OAAO,SAAS;AAC3B,iBAAO,KAAK,eAAe,GAAG,KAAK,MAAM,GAAG,UAAU;AAAA,QACxD;AAEA,YAAI,QAAQ,QAAQ;AAClB,gBAAM,aAAa,OAAO,SAAS;AAEnC,cAAI,OAAO,WAAW,MAAM,MAAM,YAAY;AAE5C,mBAAO,WAAW,MAAM,EAAE,MAAM;AAAA,UAClC;AAAA,QACF;AAEA,cAAM,MAAM;AACZ,eAAO,WAAW,GAAG;AAAA,MACvB;AAAA,IACF,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASU,eAAoC,IAAO,YAAiC;AACpF,WAAO,IAAI,MAAM,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAYnB,OAAO,CAAC,QAAQ,SAAS,SAAS;AAChC,cAAM,QAAQ,OAAO,KAAK,OAAO,EAAE,GAAG,IAAI;AAC1C,eAAO,KAAK,OAAO,OAAY,UAAU;AAAA,MAC3C;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAcO,IAAM,gBAAgB,CAI3B,SACA,eAC0B,IAAI,gBAAgB,SAAS,UAAU,EAAE;","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,6 @@ var __defProp = Object.defineProperty;
|
|
|
3
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
7
6
|
var __export = (target, all) => {
|
|
8
7
|
for (var name in all)
|
|
9
8
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -17,7 +16,6 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
16
|
return to;
|
|
18
17
|
};
|
|
19
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
21
19
|
|
|
22
20
|
// src/index.ts
|
|
23
21
|
var index_exports = {};
|
|
@@ -26,16 +24,16 @@ __export(index_exports, {
|
|
|
26
24
|
});
|
|
27
25
|
module.exports = __toCommonJS(index_exports);
|
|
28
26
|
var PromiseExtender = class {
|
|
27
|
+
/**
|
|
28
|
+
* The proxied promise.
|
|
29
|
+
*/
|
|
30
|
+
promise;
|
|
29
31
|
/**
|
|
30
32
|
* @param promise The promise to extend.
|
|
31
33
|
* @param properties A dictionary of custom properties to _inject_ in the promise
|
|
32
34
|
* chain.
|
|
33
35
|
*/
|
|
34
36
|
constructor(promise, properties) {
|
|
35
|
-
/**
|
|
36
|
-
* The proxied promise.
|
|
37
|
-
*/
|
|
38
|
-
__publicField(this, "promise");
|
|
39
37
|
this.promise = this.extend(promise, properties);
|
|
40
38
|
}
|
|
41
39
|
/**
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["type ExtractGeneric<Type> = Type extends Promise<infer X> ? X : never;\n\ntype ExtendedPromise<T extends Promise<unknown>, P, V = ExtractGeneric<T>> = Omit<\n T,\n 'then' | 'catch' | 'finally'\n> &\n P & {\n then: (...args: Parameters<T['then']>) => ExtendedPromise<Promise<V>, P>;\n catch: (...args: Parameters<T['catch']>) => ExtendedPromise<Promise<V>, P>;\n finally: (...args: Parameters<T['finally']>) => ExtendedPromise<Promise<V>, P>;\n };\ntype GenericFn = (...args: unknown[]) => unknown;\ntype ExtendedFn<F extends GenericFn, P> = F & P;\n\n/**\n * Helper class that creates a proxy for a {@link Promise} in order to add custom\n * properties.\n *\n * The only reason this class exists is so it can \"scope\" the necessary methods to extend\n * {@link Promise} and avoid workarounds in order to declare them, as they need to call\n * themselves recursively.\n */\nclass PromiseExtender<T extends Promise<unknown>, P extends Record<string, unknown>> {\n /**\n * The proxied promise.\n */\n readonly promise: ExtendedPromise<T, P>;\n /**\n * @param promise The promise to extend.\n * @param properties A dictionary of custom properties to _inject_ in the promise\n * chain.\n */\n constructor(promise: T, properties: P) {\n this.promise = this.extend(promise, properties);\n }\n /**\n * The method that actually extends a promise: it creates a proxy of the promise in\n * order to intercept the getters so it can return the custom properties if requested,\n * and return new proxies when `then`, `catch` and `finally` are called; the reason new\n * proxies are created is because those methods return new promises, and without being\n * proxied, the custom properties would be lost.\n *\n * @param promise The promise to proxy.\n * @param properties A dictionary of custom properties to _inject_ in the promise\n * chain.\n * @throws {Error} If `promise` is not a valid instance of {@link Promise}.\n * @throws {Error} If `properties` is not an object or if it doesn't have any\n * properties.\n */\n extend(promise: T, properties: P): ExtendedPromise<T, P> {\n if (!(promise instanceof Promise)) {\n throw new Error(\"'promise' must be a valid Promise instance\");\n }\n\n if (!properties || !Object.keys(properties).length) {\n throw new Error(\"'properties' must be an object with at least one key\");\n }\n\n const extended = new Proxy(promise, {\n /**\n * This is a trap for when something is trying to read/access a property for the\n * promise.\n * The function first validates if it's one of the functions\n * (`then`/`catch`/`finally`) in order to return a proxied function; then, if it's\n * another function (one that doesn't return another promise), it just calls the\n * original; finally, before doing a fallback to the original promise, it checks if\n * it's one of the custom properties that exented the promise.\n *\n * @param target The original promise.\n * @param name The name of the property.\n */\n get: (target, name) => {\n const targetKey = name as keyof typeof target;\n if (\n typeof name === 'string' &&\n ['then', 'catch', 'finally'].includes(name) &&\n name in target\n ) {\n const fn = target[targetKey] as unknown as GenericFn;\n return this.extendFunction(fn.bind(target), properties);\n }\n\n if (name in target) {\n const possibleFn = target[targetKey] as unknown as Record<string, unknown>;\n // eslint-disable-next-line dot-notation\n if (typeof possibleFn['bind'] === 'function') {\n // eslint-disable-next-line dot-notation\n return possibleFn['bind'](target);\n }\n }\n\n const key = name as keyof P;\n return properties[key];\n },\n });\n\n return extended as unknown as ExtendedPromise<T, P>;\n }\n /**\n * Creates a proxy for a promise function (`then`/`catch`/`finally`) so the returned\n * promise can also be extended.\n *\n * @param fn The promise function to proxy.\n * @param properties A dictionary of custom properties to _inject_ in the promise\n * chain.\n */\n protected extendFunction<F extends GenericFn>(fn: F, properties: P): ExtendedFn<F, P> {\n return new Proxy(fn, {\n /**\n * This is a trap for when a function gets called (remember this gets used for\n * `then`/\n * `catch`/`finally`); it processes the result using the oringinal function and\n * since promise methods return a promise, instead of returning the original result,\n * it returns an _extended_ version of it.\n *\n * @param target The original function.\n * @param thisArg The promise the function belongs to.\n * @param args The list of arguments sent to the trap.\n */\n apply: (target, thisArg, args) => {\n const value = target.bind(thisArg)(...args);\n return this.extend(value as T, properties);\n },\n }) as ExtendedFn<F, P>;\n }\n}\n\n/**\n * Extends a {@link Promise} by injecting custom properties using a {@link Proxy}. The\n * custom properties will be available on the promise chain no matter how many `then`s,\n * `catch`s or `finally`s are added.\n *\n * @param promise The promise to extend.\n * @param properties A dictionary of custom properties to _inject_ in the promise\n * chain.\n * @throws {Error} If `promise` is not a valid instance of {@link Promise}.\n * @throws {Error} If `properties` is not an object or if it doesn't have any\n * properties.\n */\nexport const extendPromise = <\n T extends Promise<unknown>,\n P extends Record<string, unknown>,\n>(\n promise: T,\n properties: P,\n): ExtendedPromise<T, P> => new PromiseExtender(promise, properties).promise;\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["type ExtractGeneric<Type> = Type extends Promise<infer X> ? X : never;\n\ntype ExtendedPromise<T extends Promise<unknown>, P, V = ExtractGeneric<T>> = Omit<\n T,\n 'then' | 'catch' | 'finally'\n> &\n P & {\n then: (...args: Parameters<T['then']>) => ExtendedPromise<Promise<V>, P>;\n catch: (...args: Parameters<T['catch']>) => ExtendedPromise<Promise<V>, P>;\n finally: (...args: Parameters<T['finally']>) => ExtendedPromise<Promise<V>, P>;\n };\ntype GenericFn = (...args: unknown[]) => unknown;\ntype ExtendedFn<F extends GenericFn, P> = F & P;\n\n/**\n * Helper class that creates a proxy for a {@link Promise} in order to add custom\n * properties.\n *\n * The only reason this class exists is so it can \"scope\" the necessary methods to extend\n * {@link Promise} and avoid workarounds in order to declare them, as they need to call\n * themselves recursively.\n */\nclass PromiseExtender<T extends Promise<unknown>, P extends Record<string, unknown>> {\n /**\n * The proxied promise.\n */\n readonly promise: ExtendedPromise<T, P>;\n /**\n * @param promise The promise to extend.\n * @param properties A dictionary of custom properties to _inject_ in the promise\n * chain.\n */\n constructor(promise: T, properties: P) {\n this.promise = this.extend(promise, properties);\n }\n /**\n * The method that actually extends a promise: it creates a proxy of the promise in\n * order to intercept the getters so it can return the custom properties if requested,\n * and return new proxies when `then`, `catch` and `finally` are called; the reason new\n * proxies are created is because those methods return new promises, and without being\n * proxied, the custom properties would be lost.\n *\n * @param promise The promise to proxy.\n * @param properties A dictionary of custom properties to _inject_ in the promise\n * chain.\n * @throws {Error} If `promise` is not a valid instance of {@link Promise}.\n * @throws {Error} If `properties` is not an object or if it doesn't have any\n * properties.\n */\n extend(promise: T, properties: P): ExtendedPromise<T, P> {\n if (!(promise instanceof Promise)) {\n throw new Error(\"'promise' must be a valid Promise instance\");\n }\n\n if (!properties || !Object.keys(properties).length) {\n throw new Error(\"'properties' must be an object with at least one key\");\n }\n\n const extended = new Proxy(promise, {\n /**\n * This is a trap for when something is trying to read/access a property for the\n * promise.\n * The function first validates if it's one of the functions\n * (`then`/`catch`/`finally`) in order to return a proxied function; then, if it's\n * another function (one that doesn't return another promise), it just calls the\n * original; finally, before doing a fallback to the original promise, it checks if\n * it's one of the custom properties that exented the promise.\n *\n * @param target The original promise.\n * @param name The name of the property.\n */\n get: (target, name) => {\n const targetKey = name as keyof typeof target;\n if (\n typeof name === 'string' &&\n ['then', 'catch', 'finally'].includes(name) &&\n name in target\n ) {\n const fn = target[targetKey] as unknown as GenericFn;\n return this.extendFunction(fn.bind(target), properties);\n }\n\n if (name in target) {\n const possibleFn = target[targetKey] as unknown as Record<string, unknown>;\n // eslint-disable-next-line dot-notation\n if (typeof possibleFn['bind'] === 'function') {\n // eslint-disable-next-line dot-notation\n return possibleFn['bind'](target);\n }\n }\n\n const key = name as keyof P;\n return properties[key];\n },\n });\n\n return extended as unknown as ExtendedPromise<T, P>;\n }\n /**\n * Creates a proxy for a promise function (`then`/`catch`/`finally`) so the returned\n * promise can also be extended.\n *\n * @param fn The promise function to proxy.\n * @param properties A dictionary of custom properties to _inject_ in the promise\n * chain.\n */\n protected extendFunction<F extends GenericFn>(fn: F, properties: P): ExtendedFn<F, P> {\n return new Proxy(fn, {\n /**\n * This is a trap for when a function gets called (remember this gets used for\n * `then`/\n * `catch`/`finally`); it processes the result using the oringinal function and\n * since promise methods return a promise, instead of returning the original result,\n * it returns an _extended_ version of it.\n *\n * @param target The original function.\n * @param thisArg The promise the function belongs to.\n * @param args The list of arguments sent to the trap.\n */\n apply: (target, thisArg, args) => {\n const value = target.bind(thisArg)(...args);\n return this.extend(value as T, properties);\n },\n }) as ExtendedFn<F, P>;\n }\n}\n\n/**\n * Extends a {@link Promise} by injecting custom properties using a {@link Proxy}. The\n * custom properties will be available on the promise chain no matter how many `then`s,\n * `catch`s or `finally`s are added.\n *\n * @param promise The promise to extend.\n * @param properties A dictionary of custom properties to _inject_ in the promise\n * chain.\n * @throws {Error} If `promise` is not a valid instance of {@link Promise}.\n * @throws {Error} If `properties` is not an object or if it doesn't have any\n * properties.\n */\nexport const extendPromise = <\n T extends Promise<unknown>,\n P extends Record<string, unknown>,\n>(\n promise: T,\n properties: P,\n): ExtendedPromise<T, P> => new PromiseExtender(promise, properties).promise;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAsBA,IAAM,kBAAN,MAAqF;AAAA;AAAA;AAAA;AAAA,EAI1E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMT,YAAY,SAAY,YAAe;AACrC,SAAK,UAAU,KAAK,OAAO,SAAS,UAAU;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,OAAO,SAAY,YAAsC;AACvD,QAAI,EAAE,mBAAmB,UAAU;AACjC,YAAM,IAAI,MAAM,4CAA4C;AAAA,IAC9D;AAEA,QAAI,CAAC,cAAc,CAAC,OAAO,KAAK,UAAU,EAAE,QAAQ;AAClD,YAAM,IAAI,MAAM,sDAAsD;AAAA,IACxE;AAEA,UAAM,WAAW,IAAI,MAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAalC,KAAK,CAAC,QAAQ,SAAS;AACrB,cAAM,YAAY;AAClB,YACE,OAAO,SAAS,YAChB,CAAC,QAAQ,SAAS,SAAS,EAAE,SAAS,IAAI,KAC1C,QAAQ,QACR;AACA,gBAAM,KAAK,OAAO,SAAS;AAC3B,iBAAO,KAAK,eAAe,GAAG,KAAK,MAAM,GAAG,UAAU;AAAA,QACxD;AAEA,YAAI,QAAQ,QAAQ;AAClB,gBAAM,aAAa,OAAO,SAAS;AAEnC,cAAI,OAAO,WAAW,MAAM,MAAM,YAAY;AAE5C,mBAAO,WAAW,MAAM,EAAE,MAAM;AAAA,UAClC;AAAA,QACF;AAEA,cAAM,MAAM;AACZ,eAAO,WAAW,GAAG;AAAA,MACvB;AAAA,IACF,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASU,eAAoC,IAAO,YAAiC;AACpF,WAAO,IAAI,MAAM,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAYnB,OAAO,CAAC,QAAQ,SAAS,SAAS;AAChC,cAAM,QAAQ,OAAO,KAAK,OAAO,EAAE,GAAG,IAAI;AAC1C,eAAO,KAAK,OAAO,OAAY,UAAU;AAAA,MAC3C;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAcO,IAAM,gBAAgB,CAI3B,SACA,eAC0B,IAAI,gBAAgB,SAAS,UAAU,EAAE;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@homer0/extend-promise",
|
|
3
3
|
"description": "Extends a promise with custom properties",
|
|
4
|
-
"version": "3.0.
|
|
4
|
+
"version": "3.0.10",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "https://github.com/homer0/packages.git",
|
|
@@ -23,12 +23,12 @@
|
|
|
23
23
|
"dist/"
|
|
24
24
|
],
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@homer0/eslint-plugin": "12.0.
|
|
27
|
-
"@homer0/tsconfig": "
|
|
26
|
+
"@homer0/eslint-plugin": "12.0.10",
|
|
27
|
+
"@homer0/tsconfig": "2.0.0",
|
|
28
28
|
"jest": "^29.7.0",
|
|
29
|
-
"ts-jest": "^29.2
|
|
30
|
-
"tsup": "^8.
|
|
31
|
-
"typescript": "^5.
|
|
29
|
+
"ts-jest": "^29.3.2",
|
|
30
|
+
"tsup": "^8.4.0",
|
|
31
|
+
"typescript": "^5.8.3"
|
|
32
32
|
},
|
|
33
33
|
"engine-strict": true,
|
|
34
34
|
"engines": {
|
|
@@ -44,5 +44,5 @@
|
|
|
44
44
|
"build": "tsup src/index.ts",
|
|
45
45
|
"prepublishOnly": "pnpm run build"
|
|
46
46
|
},
|
|
47
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "76482b0d3b5237b9a24e538d8bdf650295caa729"
|
|
48
48
|
}
|