mutts 1.0.1 → 1.0.2

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.
Files changed (60) hide show
  1. package/README.md +24 -2
  2. package/dist/chunks/_tslib-C-cuVLvZ.js +73 -0
  3. package/dist/chunks/_tslib-C-cuVLvZ.js.map +1 -0
  4. package/dist/chunks/_tslib-CMEnd0VE.esm.js +68 -0
  5. package/dist/chunks/_tslib-CMEnd0VE.esm.js.map +1 -0
  6. package/dist/chunks/{decorator-8qjFb7dw.js → decorator-D4DU97Zg.js} +70 -4
  7. package/dist/chunks/decorator-D4DU97Zg.js.map +1 -0
  8. package/dist/chunks/{decorator-AbRkXM5O.esm.js → decorator-GnHw1Az7.esm.js} +67 -5
  9. package/dist/chunks/decorator-GnHw1Az7.esm.js.map +1 -0
  10. package/dist/chunks/index-DBScoeCX.esm.js +1960 -0
  11. package/dist/chunks/index-DBScoeCX.esm.js.map +1 -0
  12. package/dist/chunks/index-DOTmXL89.js +1983 -0
  13. package/dist/chunks/index-DOTmXL89.js.map +1 -0
  14. package/dist/decorator.d.ts +57 -0
  15. package/dist/decorator.esm.js +1 -1
  16. package/dist/decorator.js +1 -1
  17. package/dist/destroyable.d.ts +42 -0
  18. package/dist/destroyable.esm.js +19 -1
  19. package/dist/destroyable.esm.js.map +1 -1
  20. package/dist/destroyable.js +19 -1
  21. package/dist/destroyable.js.map +1 -1
  22. package/dist/eventful.d.ts +10 -1
  23. package/dist/eventful.esm.js +5 -27
  24. package/dist/eventful.esm.js.map +1 -1
  25. package/dist/eventful.js +15 -37
  26. package/dist/eventful.js.map +1 -1
  27. package/dist/index.d.ts +52 -3
  28. package/dist/index.esm.js +3 -2
  29. package/dist/index.esm.js.map +1 -1
  30. package/dist/index.js +17 -3
  31. package/dist/index.js.map +1 -1
  32. package/dist/indexable.d.ts +26 -0
  33. package/dist/indexable.esm.js +6 -0
  34. package/dist/indexable.esm.js.map +1 -1
  35. package/dist/indexable.js +6 -0
  36. package/dist/indexable.js.map +1 -1
  37. package/dist/mutts.umd.js +1 -1
  38. package/dist/mutts.umd.js.map +1 -1
  39. package/dist/mutts.umd.min.js +1 -1
  40. package/dist/mutts.umd.min.js.map +1 -1
  41. package/dist/promiseChain.d.ts +10 -0
  42. package/dist/promiseChain.esm.js +6 -0
  43. package/dist/promiseChain.esm.js.map +1 -1
  44. package/dist/promiseChain.js +6 -0
  45. package/dist/promiseChain.js.map +1 -1
  46. package/dist/reactive.d.ts +255 -18
  47. package/dist/reactive.esm.js +4 -1458
  48. package/dist/reactive.esm.js.map +1 -1
  49. package/dist/reactive.js +29 -1471
  50. package/dist/reactive.js.map +1 -1
  51. package/dist/std-decorators.d.ts +35 -0
  52. package/dist/std-decorators.esm.js +36 -1
  53. package/dist/std-decorators.esm.js.map +1 -1
  54. package/dist/std-decorators.js +36 -1
  55. package/dist/std-decorators.js.map +1 -1
  56. package/docs/mixin.md +229 -0
  57. package/docs/reactive.md +7739 -882
  58. package/package.json +1 -1
  59. package/dist/chunks/decorator-8qjFb7dw.js.map +0 -1
  60. package/dist/chunks/decorator-AbRkXM5O.esm.js.map +0 -1
@@ -2,9 +2,19 @@ type Resolved<T> = T extends Promise<infer U> ? Resolved<U> : T extends (...args
2
2
  [k in keyof T]: k extends 'then' | 'catch' | 'finally' ? T[k] : Resolved<T[k]>;
3
3
  } : T;
4
4
  type PromiseAnd<T> = Resolved<T> & Promise<Resolved<T>>;
5
+ /**
6
+ * Type that transforms promises into chainable objects
7
+ * Allows calling methods directly on promise results without awaiting them first
8
+ */
5
9
  type PromiseChain<T> = T extends (...args: infer Args) => infer R ? PromiseAnd<(...args: Args) => PromiseChain<Resolved<R>>> : T extends object ? PromiseAnd<{
6
10
  [k in keyof T]: k extends 'then' | 'catch' | 'finally' ? T[k] : PromiseChain<Resolved<T[k]>>;
7
11
  }> : Promise<Resolved<T>>;
12
+ /**
13
+ * Transforms a promise or value into a chainable object
14
+ * Allows calling methods directly on promise results without awaiting them first
15
+ * @param given - The promise or value to make chainable
16
+ * @returns A chainable version of the input
17
+ */
8
18
  declare function chainPromise<T>(given: Promise<T> | T): PromiseChain<T>;
9
19
 
10
20
  export { chainPromise };
@@ -47,6 +47,12 @@ function chainObject(given) {
47
47
  function chainable(x) {
48
48
  return x && ['function', 'object'].includes(typeof x);
49
49
  }
50
+ /**
51
+ * Transforms a promise or value into a chainable object
52
+ * Allows calling methods directly on promise results without awaiting them first
53
+ * @param given - The promise or value to make chainable
54
+ * @returns A chainable version of the input
55
+ */
50
56
  function chainPromise(given) {
51
57
  if (!chainable(given))
52
58
  return given;
@@ -1 +1 @@
1
- {"version":3,"file":"promiseChain.esm.js","sources":["../src/promiseChain.ts"],"sourcesContent":["type Resolved<T> = T extends Promise<infer U>\n\t? Resolved<U>\n\t: T extends (...args: infer Args) => infer R\n\t\t? (...args: Args) => Resolved<R>\n\t\t: T extends object\n\t\t\t? {\n\t\t\t\t\t[k in keyof T]: k extends 'then' | 'catch' | 'finally' ? T[k] : Resolved<T[k]>\n\t\t\t\t}\n\t\t\t: T\ntype PromiseAnd<T> = Resolved<T> & Promise<Resolved<T>>\nexport type PromiseChain<T> = T extends (...args: infer Args) => infer R\n\t? PromiseAnd<(...args: Args) => PromiseChain<Resolved<R>>>\n\t: T extends object\n\t\t? PromiseAnd<{\n\t\t\t\t[k in keyof T]: k extends 'then' | 'catch' | 'finally' ? T[k] : PromiseChain<Resolved<T[k]>>\n\t\t\t}>\n\t\t: Promise<Resolved<T>>\n\nconst forward =\n\t(name: string, target: any) =>\n\t(...args: any[]) => {\n\t\treturn target[name](...args)\n\t}\n\nconst alreadyChained = new WeakMap<any, PromiseChain<any>>()\nconst originals = new WeakMap<Promise<any>, any>()\n\nfunction cache(target: any, rv: PromiseChain<any>) {\n\toriginals.set(rv, target)\n\talreadyChained.set(target, rv)\n}\n\ntype ChainedFunction<T> = ((...args: any[]) => PromiseChain<T>) & {\n\tthen: Promise<T>['then']\n\tcatch: Promise<T>['catch']\n\tfinally: Promise<T>['finally']\n}\n\nconst promiseProxyHandler: ProxyHandler<ChainedFunction<any>> = {\n\t//@ts-expect-error\n\t[Symbol.toStringTag]: 'MutTs PromiseChain function',\n\tget(target, prop) {\n\t\tif (prop === Symbol.toStringTag) return 'PromiseProxy'\n\t\tif (typeof prop === 'string' && ['then', 'catch', 'finally'].includes(prop))\n\t\t\treturn target[prop as keyof typeof target]\n\t\treturn chainPromise(target.then((r) => r[prop as keyof typeof r]))\n\t},\n}\nconst promiseForward = (target: any) => ({\n\t// biome-ignore lint/suspicious/noThenProperty: This one is the whole point\n\tthen: forward('then', target),\n\tcatch: forward('catch', target),\n\tfinally: forward('finally', target),\n})\nconst objectProxyHandler: ProxyHandler<any> = {\n\t//@ts-expect-error\n\t[Symbol.toStringTag]: 'MutTs PromiseChain object',\n\tget(target, prop, receiver) {\n\t\tconst getter = Object.getOwnPropertyDescriptor(target, prop)?.get\n\t\tconst rv = getter ? getter.call(receiver) : target[prop]\n\t\t// Allows fct.call or fct.apply to bypass the chain system\n\t\tif (typeof target === 'function') return rv\n\t\treturn chainPromise(rv)\n\t},\n\tapply(target, thisArg, args) {\n\t\treturn chainPromise(target.apply(thisArg, args))\n\t},\n}\nfunction chainObject<T extends object | Function>(given: T): PromiseChain<T> {\n\tconst rv = new Proxy(given, objectProxyHandler) as PromiseChain<T>\n\tcache(given, rv)\n\treturn rv\n}\n\nfunction chainable(x: any): x is object | Function {\n\treturn x && ['function', 'object'].includes(typeof x)\n}\nexport function chainPromise<T>(given: Promise<T> | T): PromiseChain<T> {\n\tif (!chainable(given)) return given as PromiseChain<T>\n\tif (alreadyChained.has(given)) return alreadyChained.get(given) as PromiseChain<T>\n\tif (!(given instanceof Promise)) return chainObject(given)\n\t// @ts-expect-error It's ok as we check if it's an object above\n\tgiven = given.then((r) => (chainable(r) ? chainObject(r) : r))\n\tconst target = Object.assign(function (this: any, ...args: any[]) {\n\t\treturn chainPromise(\n\t\t\tgiven.then((r) => {\n\t\t\t\treturn this?.then\n\t\t\t\t\t? this.then((t: any) => (r as any).apply(t, args))\n\t\t\t\t\t: (r as any).apply(this, args)\n\t\t\t})\n\t\t)\n\t}, promiseForward(given)) as ChainedFunction<T>\n\tconst chained = new Proxy(\n\t\ttarget,\n\t\tpromiseProxyHandler as ProxyHandler<ChainedFunction<T>>\n\t) as PromiseChain<T>\n\tcache(given, chained as PromiseChain<any>)\n\treturn chained\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"promiseChain.esm.js","sources":["../src/promiseChain.ts"],"sourcesContent":["type Resolved<T> = T extends Promise<infer U>\n\t? Resolved<U>\n\t: T extends (...args: infer Args) => infer R\n\t\t? (...args: Args) => Resolved<R>\n\t\t: T extends object\n\t\t\t? {\n\t\t\t\t\t[k in keyof T]: k extends 'then' | 'catch' | 'finally' ? T[k] : Resolved<T[k]>\n\t\t\t\t}\n\t\t\t: T\ntype PromiseAnd<T> = Resolved<T> & Promise<Resolved<T>>\n/**\n * Type that transforms promises into chainable objects\n * Allows calling methods directly on promise results without awaiting them first\n */\nexport type PromiseChain<T> = T extends (...args: infer Args) => infer R\n\t? PromiseAnd<(...args: Args) => PromiseChain<Resolved<R>>>\n\t: T extends object\n\t\t? PromiseAnd<{\n\t\t\t\t[k in keyof T]: k extends 'then' | 'catch' | 'finally' ? T[k] : PromiseChain<Resolved<T[k]>>\n\t\t\t}>\n\t\t: Promise<Resolved<T>>\n\nconst forward =\n\t(name: string, target: any) =>\n\t(...args: any[]) => {\n\t\treturn target[name](...args)\n\t}\n\nconst alreadyChained = new WeakMap<any, PromiseChain<any>>()\nconst originals = new WeakMap<Promise<any>, any>()\n\nfunction cache(target: any, rv: PromiseChain<any>) {\n\toriginals.set(rv, target)\n\talreadyChained.set(target, rv)\n}\n\ntype ChainedFunction<T> = ((...args: any[]) => PromiseChain<T>) & {\n\tthen: Promise<T>['then']\n\tcatch: Promise<T>['catch']\n\tfinally: Promise<T>['finally']\n}\n\nconst promiseProxyHandler: ProxyHandler<ChainedFunction<any>> = {\n\t//@ts-expect-error\n\t[Symbol.toStringTag]: 'MutTs PromiseChain function',\n\tget(target, prop) {\n\t\tif (prop === Symbol.toStringTag) return 'PromiseProxy'\n\t\tif (typeof prop === 'string' && ['then', 'catch', 'finally'].includes(prop))\n\t\t\treturn target[prop as keyof typeof target]\n\t\treturn chainPromise(target.then((r) => r[prop as keyof typeof r]))\n\t},\n}\nconst promiseForward = (target: any) => ({\n\t// biome-ignore lint/suspicious/noThenProperty: This one is the whole point\n\tthen: forward('then', target),\n\tcatch: forward('catch', target),\n\tfinally: forward('finally', target),\n})\nconst objectProxyHandler: ProxyHandler<any> = {\n\t//@ts-expect-error\n\t[Symbol.toStringTag]: 'MutTs PromiseChain object',\n\tget(target, prop, receiver) {\n\t\tconst getter = Object.getOwnPropertyDescriptor(target, prop)?.get\n\t\tconst rv = getter ? getter.call(receiver) : target[prop]\n\t\t// Allows fct.call or fct.apply to bypass the chain system\n\t\tif (typeof target === 'function') return rv\n\t\treturn chainPromise(rv)\n\t},\n\tapply(target, thisArg, args) {\n\t\treturn chainPromise(target.apply(thisArg, args))\n\t},\n}\nfunction chainObject<T extends object | Function>(given: T): PromiseChain<T> {\n\tconst rv = new Proxy(given, objectProxyHandler) as PromiseChain<T>\n\tcache(given, rv)\n\treturn rv\n}\n\nfunction chainable(x: any): x is object | Function {\n\treturn x && ['function', 'object'].includes(typeof x)\n}\n/**\n * Transforms a promise or value into a chainable object\n * Allows calling methods directly on promise results without awaiting them first\n * @param given - The promise or value to make chainable\n * @returns A chainable version of the input\n */\nexport function chainPromise<T>(given: Promise<T> | T): PromiseChain<T> {\n\tif (!chainable(given)) return given as PromiseChain<T>\n\tif (alreadyChained.has(given)) return alreadyChained.get(given) as PromiseChain<T>\n\tif (!(given instanceof Promise)) return chainObject(given)\n\t// @ts-expect-error It's ok as we check if it's an object above\n\tgiven = given.then((r) => (chainable(r) ? chainObject(r) : r))\n\tconst target = Object.assign(function (this: any, ...args: any[]) {\n\t\treturn chainPromise(\n\t\t\tgiven.then((r) => {\n\t\t\t\treturn this?.then\n\t\t\t\t\t? this.then((t: any) => (r as any).apply(t, args))\n\t\t\t\t\t: (r as any).apply(this, args)\n\t\t\t})\n\t\t)\n\t}, promiseForward(given)) as ChainedFunction<T>\n\tconst chained = new Proxy(\n\t\ttarget,\n\t\tpromiseProxyHandler as ProxyHandler<ChainedFunction<T>>\n\t) as PromiseChain<T>\n\tcache(given, chained as PromiseChain<any>)\n\treturn chained\n}\n"],"names":[],"mappings":"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"}
@@ -49,6 +49,12 @@ function chainObject(given) {
49
49
  function chainable(x) {
50
50
  return x && ['function', 'object'].includes(typeof x);
51
51
  }
52
+ /**
53
+ * Transforms a promise or value into a chainable object
54
+ * Allows calling methods directly on promise results without awaiting them first
55
+ * @param given - The promise or value to make chainable
56
+ * @returns A chainable version of the input
57
+ */
52
58
  function chainPromise(given) {
53
59
  if (!chainable(given))
54
60
  return given;
@@ -1 +1 @@
1
- {"version":3,"file":"promiseChain.js","sources":["../src/promiseChain.ts"],"sourcesContent":["type Resolved<T> = T extends Promise<infer U>\n\t? Resolved<U>\n\t: T extends (...args: infer Args) => infer R\n\t\t? (...args: Args) => Resolved<R>\n\t\t: T extends object\n\t\t\t? {\n\t\t\t\t\t[k in keyof T]: k extends 'then' | 'catch' | 'finally' ? T[k] : Resolved<T[k]>\n\t\t\t\t}\n\t\t\t: T\ntype PromiseAnd<T> = Resolved<T> & Promise<Resolved<T>>\nexport type PromiseChain<T> = T extends (...args: infer Args) => infer R\n\t? PromiseAnd<(...args: Args) => PromiseChain<Resolved<R>>>\n\t: T extends object\n\t\t? PromiseAnd<{\n\t\t\t\t[k in keyof T]: k extends 'then' | 'catch' | 'finally' ? T[k] : PromiseChain<Resolved<T[k]>>\n\t\t\t}>\n\t\t: Promise<Resolved<T>>\n\nconst forward =\n\t(name: string, target: any) =>\n\t(...args: any[]) => {\n\t\treturn target[name](...args)\n\t}\n\nconst alreadyChained = new WeakMap<any, PromiseChain<any>>()\nconst originals = new WeakMap<Promise<any>, any>()\n\nfunction cache(target: any, rv: PromiseChain<any>) {\n\toriginals.set(rv, target)\n\talreadyChained.set(target, rv)\n}\n\ntype ChainedFunction<T> = ((...args: any[]) => PromiseChain<T>) & {\n\tthen: Promise<T>['then']\n\tcatch: Promise<T>['catch']\n\tfinally: Promise<T>['finally']\n}\n\nconst promiseProxyHandler: ProxyHandler<ChainedFunction<any>> = {\n\t//@ts-expect-error\n\t[Symbol.toStringTag]: 'MutTs PromiseChain function',\n\tget(target, prop) {\n\t\tif (prop === Symbol.toStringTag) return 'PromiseProxy'\n\t\tif (typeof prop === 'string' && ['then', 'catch', 'finally'].includes(prop))\n\t\t\treturn target[prop as keyof typeof target]\n\t\treturn chainPromise(target.then((r) => r[prop as keyof typeof r]))\n\t},\n}\nconst promiseForward = (target: any) => ({\n\t// biome-ignore lint/suspicious/noThenProperty: This one is the whole point\n\tthen: forward('then', target),\n\tcatch: forward('catch', target),\n\tfinally: forward('finally', target),\n})\nconst objectProxyHandler: ProxyHandler<any> = {\n\t//@ts-expect-error\n\t[Symbol.toStringTag]: 'MutTs PromiseChain object',\n\tget(target, prop, receiver) {\n\t\tconst getter = Object.getOwnPropertyDescriptor(target, prop)?.get\n\t\tconst rv = getter ? getter.call(receiver) : target[prop]\n\t\t// Allows fct.call or fct.apply to bypass the chain system\n\t\tif (typeof target === 'function') return rv\n\t\treturn chainPromise(rv)\n\t},\n\tapply(target, thisArg, args) {\n\t\treturn chainPromise(target.apply(thisArg, args))\n\t},\n}\nfunction chainObject<T extends object | Function>(given: T): PromiseChain<T> {\n\tconst rv = new Proxy(given, objectProxyHandler) as PromiseChain<T>\n\tcache(given, rv)\n\treturn rv\n}\n\nfunction chainable(x: any): x is object | Function {\n\treturn x && ['function', 'object'].includes(typeof x)\n}\nexport function chainPromise<T>(given: Promise<T> | T): PromiseChain<T> {\n\tif (!chainable(given)) return given as PromiseChain<T>\n\tif (alreadyChained.has(given)) return alreadyChained.get(given) as PromiseChain<T>\n\tif (!(given instanceof Promise)) return chainObject(given)\n\t// @ts-expect-error It's ok as we check if it's an object above\n\tgiven = given.then((r) => (chainable(r) ? chainObject(r) : r))\n\tconst target = Object.assign(function (this: any, ...args: any[]) {\n\t\treturn chainPromise(\n\t\t\tgiven.then((r) => {\n\t\t\t\treturn this?.then\n\t\t\t\t\t? this.then((t: any) => (r as any).apply(t, args))\n\t\t\t\t\t: (r as any).apply(this, args)\n\t\t\t})\n\t\t)\n\t}, promiseForward(given)) as ChainedFunction<T>\n\tconst chained = new Proxy(\n\t\ttarget,\n\t\tpromiseProxyHandler as ProxyHandler<ChainedFunction<T>>\n\t) as PromiseChain<T>\n\tcache(given, chained as PromiseChain<any>)\n\treturn chained\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"promiseChain.js","sources":["../src/promiseChain.ts"],"sourcesContent":["type Resolved<T> = T extends Promise<infer U>\n\t? Resolved<U>\n\t: T extends (...args: infer Args) => infer R\n\t\t? (...args: Args) => Resolved<R>\n\t\t: T extends object\n\t\t\t? {\n\t\t\t\t\t[k in keyof T]: k extends 'then' | 'catch' | 'finally' ? T[k] : Resolved<T[k]>\n\t\t\t\t}\n\t\t\t: T\ntype PromiseAnd<T> = Resolved<T> & Promise<Resolved<T>>\n/**\n * Type that transforms promises into chainable objects\n * Allows calling methods directly on promise results without awaiting them first\n */\nexport type PromiseChain<T> = T extends (...args: infer Args) => infer R\n\t? PromiseAnd<(...args: Args) => PromiseChain<Resolved<R>>>\n\t: T extends object\n\t\t? PromiseAnd<{\n\t\t\t\t[k in keyof T]: k extends 'then' | 'catch' | 'finally' ? T[k] : PromiseChain<Resolved<T[k]>>\n\t\t\t}>\n\t\t: Promise<Resolved<T>>\n\nconst forward =\n\t(name: string, target: any) =>\n\t(...args: any[]) => {\n\t\treturn target[name](...args)\n\t}\n\nconst alreadyChained = new WeakMap<any, PromiseChain<any>>()\nconst originals = new WeakMap<Promise<any>, any>()\n\nfunction cache(target: any, rv: PromiseChain<any>) {\n\toriginals.set(rv, target)\n\talreadyChained.set(target, rv)\n}\n\ntype ChainedFunction<T> = ((...args: any[]) => PromiseChain<T>) & {\n\tthen: Promise<T>['then']\n\tcatch: Promise<T>['catch']\n\tfinally: Promise<T>['finally']\n}\n\nconst promiseProxyHandler: ProxyHandler<ChainedFunction<any>> = {\n\t//@ts-expect-error\n\t[Symbol.toStringTag]: 'MutTs PromiseChain function',\n\tget(target, prop) {\n\t\tif (prop === Symbol.toStringTag) return 'PromiseProxy'\n\t\tif (typeof prop === 'string' && ['then', 'catch', 'finally'].includes(prop))\n\t\t\treturn target[prop as keyof typeof target]\n\t\treturn chainPromise(target.then((r) => r[prop as keyof typeof r]))\n\t},\n}\nconst promiseForward = (target: any) => ({\n\t// biome-ignore lint/suspicious/noThenProperty: This one is the whole point\n\tthen: forward('then', target),\n\tcatch: forward('catch', target),\n\tfinally: forward('finally', target),\n})\nconst objectProxyHandler: ProxyHandler<any> = {\n\t//@ts-expect-error\n\t[Symbol.toStringTag]: 'MutTs PromiseChain object',\n\tget(target, prop, receiver) {\n\t\tconst getter = Object.getOwnPropertyDescriptor(target, prop)?.get\n\t\tconst rv = getter ? getter.call(receiver) : target[prop]\n\t\t// Allows fct.call or fct.apply to bypass the chain system\n\t\tif (typeof target === 'function') return rv\n\t\treturn chainPromise(rv)\n\t},\n\tapply(target, thisArg, args) {\n\t\treturn chainPromise(target.apply(thisArg, args))\n\t},\n}\nfunction chainObject<T extends object | Function>(given: T): PromiseChain<T> {\n\tconst rv = new Proxy(given, objectProxyHandler) as PromiseChain<T>\n\tcache(given, rv)\n\treturn rv\n}\n\nfunction chainable(x: any): x is object | Function {\n\treturn x && ['function', 'object'].includes(typeof x)\n}\n/**\n * Transforms a promise or value into a chainable object\n * Allows calling methods directly on promise results without awaiting them first\n * @param given - The promise or value to make chainable\n * @returns A chainable version of the input\n */\nexport function chainPromise<T>(given: Promise<T> | T): PromiseChain<T> {\n\tif (!chainable(given)) return given as PromiseChain<T>\n\tif (alreadyChained.has(given)) return alreadyChained.get(given) as PromiseChain<T>\n\tif (!(given instanceof Promise)) return chainObject(given)\n\t// @ts-expect-error It's ok as we check if it's an object above\n\tgiven = given.then((r) => (chainable(r) ? chainObject(r) : r))\n\tconst target = Object.assign(function (this: any, ...args: any[]) {\n\t\treturn chainPromise(\n\t\t\tgiven.then((r) => {\n\t\t\t\treturn this?.then\n\t\t\t\t\t? this.then((t: any) => (r as any).apply(t, args))\n\t\t\t\t\t: (r as any).apply(this, args)\n\t\t\t})\n\t\t)\n\t}, promiseForward(given)) as ChainedFunction<T>\n\tconst chained = new Proxy(\n\t\ttarget,\n\t\tpromiseProxyHandler as ProxyHandler<ChainedFunction<T>>\n\t) as PromiseChain<T>\n\tcache(given, chained as PromiseChain<any>)\n\treturn chained\n}\n"],"names":[],"mappings":";;AAsBA,MAAM,OAAO,GACZ,CAAC,IAAY,EAAE,MAAW,KAC1B,CAAC,GAAG,IAAW,KAAI;IAClB,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;AAC7B,CAAC;AAEF,MAAM,cAAc,GAAG,IAAI,OAAO,EAA0B;AAC5D,MAAM,SAAS,GAAG,IAAI,OAAO,EAAqB;AAElD,SAAS,KAAK,CAAC,MAAW,EAAE,EAAqB,EAAA;AAChD,IAAA,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC;AACzB,IAAA,cAAc,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC;AAC/B;AAQA,MAAM,mBAAmB,GAAuC;;AAE/D,IAAA,CAAC,MAAM,CAAC,WAAW,GAAG,6BAA6B;IACnD,GAAG,CAAC,MAAM,EAAE,IAAI,EAAA;AACf,QAAA,IAAI,IAAI,KAAK,MAAM,CAAC,WAAW;AAAE,YAAA,OAAO,cAAc;AACtD,QAAA,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;AAC1E,YAAA,OAAO,MAAM,CAAC,IAA2B,CAAC;AAC3C,QAAA,OAAO,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAsB,CAAC,CAAC,CAAC;IACnE,CAAC;CACD;AACD,MAAM,cAAc,GAAG,CAAC,MAAW,MAAM;;AAExC,IAAA,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC;AAC7B,IAAA,KAAK,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC;AAC/B,IAAA,OAAO,EAAE,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC;AACnC,CAAA,CAAC;AACF,MAAM,kBAAkB,GAAsB;;AAE7C,IAAA,CAAC,MAAM,CAAC,WAAW,GAAG,2BAA2B;AACjD,IAAA,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAA;AACzB,QAAA,MAAM,MAAM,GAAG,MAAM,CAAC,wBAAwB,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG;AACjE,QAAA,MAAM,EAAE,GAAG,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC;;QAExD,IAAI,OAAO,MAAM,KAAK,UAAU;AAAE,YAAA,OAAO,EAAE;AAC3C,QAAA,OAAO,YAAY,CAAC,EAAE,CAAC;IACxB,CAAC;AACD,IAAA,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAA;QAC1B,OAAO,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACjD,CAAC;CACD;AACD,SAAS,WAAW,CAA8B,KAAQ,EAAA;IACzD,MAAM,EAAE,GAAG,IAAI,KAAK,CAAC,KAAK,EAAE,kBAAkB,CAAoB;AAClE,IAAA,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;AAChB,IAAA,OAAO,EAAE;AACV;AAEA,SAAS,SAAS,CAAC,CAAM,EAAA;AACxB,IAAA,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AACtD;AACA;;;;;AAKG;AACG,SAAU,YAAY,CAAI,KAAqB,EAAA;AACpD,IAAA,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;AAAE,QAAA,OAAO,KAAwB;AACtD,IAAA,IAAI,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC;AAAE,QAAA,OAAO,cAAc,CAAC,GAAG,CAAC,KAAK,CAAoB;AAClF,IAAA,IAAI,EAAE,KAAK,YAAY,OAAO,CAAC;AAAE,QAAA,OAAO,WAAW,CAAC,KAAK,CAAC;;AAE1D,IAAA,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,SAAS,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9D,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,UAAqB,GAAG,IAAW,EAAA;QAC/D,OAAO,YAAY,CAClB,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAI;YAChB,OAAO,IAAI,EAAE;AACZ,kBAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAM,KAAM,CAAS,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC;kBAC9C,CAAS,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC;QAChC,CAAC,CAAC,CACF;AACF,IAAA,CAAC,EAAE,cAAc,CAAC,KAAK,CAAC,CAAuB;IAC/C,MAAM,OAAO,GAAG,IAAI,KAAK,CACxB,MAAM,EACN,mBAAuD,CACpC;AACpB,IAAA,KAAK,CAAC,KAAK,EAAE,OAA4B,CAAC;AAC1C,IAAA,OAAO,OAAO;AACf;;;;"}
@@ -1,11 +1,79 @@
1
1
  import { LegacyPropertyDecorator, ModernMethodDecorator, LegacyClassDecorator, ModernClassDecorator, ModernGetterDecorator, ModernAccessorDecorator, GenericClassDecorator } from './decorator.js';
2
2
 
3
+ /**
4
+ * Function type for dependency tracking in effects and computed values
5
+ * Restores the active effect context for dependency tracking
6
+ */
3
7
  type DependencyFunction = <T>(cb: () => T) => T;
8
+ /**
9
+ * Dependency access passed to user callbacks within effects/computed/watch
10
+ * Provides functions to track dependencies and information about the effect execution
11
+ */
12
+ interface DependencyAccess {
13
+ /**
14
+ * Tracks dependencies in the current effect context
15
+ * Use this for normal dependency tracking within the effect
16
+ * @example
17
+ * ```typescript
18
+ * effect(({ tracked }) => {
19
+ * // In async context, use tracked to restore dependency tracking
20
+ * await someAsyncOperation()
21
+ * const value = tracked(() => state.count) // Tracks state.count in this effect
22
+ * })
23
+ * ```
24
+ */
25
+ tracked: DependencyFunction;
26
+ /**
27
+ * Tracks dependencies in the parent effect context
28
+ * Use this when child effects should track dependencies in the parent,
29
+ * allowing parent cleanup to manage child effects while dependencies trigger the parent
30
+ * @example
31
+ * ```typescript
32
+ * effect(({ ascend }) => {
33
+ * const length = inputs.length
34
+ * if (length > 0) {
35
+ * ascend(() => {
36
+ * // Dependencies here are tracked in the parent effect
37
+ * inputs.forEach(item => console.log(item))
38
+ * })
39
+ * }
40
+ * })
41
+ * ```
42
+ */
43
+ ascend: DependencyFunction;
44
+ /**
45
+ * Indicates whether this is the initial execution of the effect
46
+ * - `true`: First execution when the effect is created
47
+ * - `false`: Subsequent executions triggered by dependency changes
48
+ * @example
49
+ * ```typescript
50
+ * effect(({ init }) => {
51
+ * if (init) {
52
+ * console.log('Effect initialized')
53
+ * // Setup code that should only run once
54
+ * } else {
55
+ * console.log('Effect re-ran due to dependency change')
56
+ * // Code that runs on every update
57
+ * }
58
+ * })
59
+ * ```
60
+ */
61
+ init: boolean;
62
+ }
63
+ /**
64
+ * Type for effect cleanup functions
65
+ */
4
66
  type ScopedCallback = () => void;
67
+ /**
68
+ * Type for property evolution events
69
+ */
5
70
  type PropEvolution = {
6
71
  type: 'set' | 'del' | 'add' | 'invalidate';
7
72
  prop: any;
8
73
  };
74
+ /**
75
+ * Type for collection operation evolution events
76
+ */
9
77
  type BunchEvolution = {
10
78
  type: 'bunch';
11
79
  method: string;
@@ -15,12 +83,18 @@ type State = {
15
83
  evolution: Evolution;
16
84
  next: State;
17
85
  } | {};
86
+ /**
87
+ * Object containing internal reactive system state for debugging and profiling
88
+ */
18
89
  declare const profileInfo: any;
90
+ /**
91
+ * Error class for reactive system errors
92
+ */
19
93
  declare class ReactiveError extends Error {
20
94
  constructor(message: string);
21
95
  }
22
96
  /**
23
- * Options for the reactive system, can be configured at runtime
97
+ * Global options for the reactive system
24
98
  */
25
99
  declare const options: {
26
100
  /**
@@ -38,13 +112,36 @@ declare const options: {
38
112
  * @param target - The effect that is being triggered
39
113
  * @param caller - The effect that is calling the target
40
114
  */
41
- chain: (target: Function, caller?: Function) => void;
115
+ chain: (targets: Function[], caller?: Function) => void;
116
+ /**
117
+ * Debug purpose: called when an effect chain is started
118
+ * @param target - The effect that is being triggered
119
+ */
120
+ beginChain: (targets: Function[]) => void;
121
+ /**
122
+ * Debug purpose: called when an effect chain is ended
123
+ */
124
+ endChain: () => void;
125
+ /**
126
+ * Debug purpose: called when an object is touched
127
+ * @param obj - The object that is touched
128
+ * @param evolution - The type of change
129
+ * @param props - The properties that changed
130
+ * @param deps - The dependencies that changed
131
+ */
132
+ touched: (obj: any, evolution: Evolution, props?: any[], deps?: Set<ScopedCallback>) => void;
42
133
  /**
43
134
  * Debug purpose: maximum effect chain (like call stack max depth)
44
135
  * Used to prevent infinite loops
45
136
  * @default 100
46
137
  */
47
138
  maxEffectChain: number;
139
+ /**
140
+ * Debug purpose: maximum effect reaction (like call stack max depth)
141
+ * Used to prevent infinite loops
142
+ * @default 'throw'
143
+ */
144
+ maxEffectReaction: "throw" | "debug" | "warn";
48
145
  /**
49
146
  * Maximum depth for deep watching traversal
50
147
  * Used to prevent infinite recursion in circular references
@@ -57,59 +154,199 @@ declare const options: {
57
154
  * @default true
58
155
  */
59
156
  instanceMembers: boolean;
157
+ /**
158
+ * Ignore accessors (getters and setters) and only track direct properties
159
+ * @default true
160
+ */
161
+ ignoreAccessors: boolean;
60
162
  warn: (...args: any[]) => void;
61
163
  };
164
+ type EffectTracking = (obj: any, evolution: Evolution, prop: any) => void;
165
+ /**
166
+ * Registers a debug callback that is called when the current effect is triggered by a dependency change
167
+ *
168
+ * This function is useful for debugging purposes as it pin-points exactly which reactive property
169
+ * change triggered the effect. The callback receives information about:
170
+ * - The object that changed
171
+ * - The type of change (evolution)
172
+ * - The specific property that changed
173
+ *
174
+ * **Note:** The tracker callback is automatically removed after being called once. If you need
175
+ * to track multiple triggers, call `trackEffect` again within the effect.
176
+ *
177
+ * @param onTouch - Callback function that receives (obj, evolution, prop) when the effect is triggered
178
+ * @throws {Error} If called outside of an effect context
179
+ *
180
+ * @example
181
+ * ```typescript
182
+ * const state = reactive({ count: 0, name: 'John' })
183
+ *
184
+ * effect(() => {
185
+ * // Register a tracker to see what triggers this effect
186
+ * trackEffect((obj, evolution, prop) => {
187
+ * console.log(`Effect triggered by:`, {
188
+ * object: obj,
189
+ * change: evolution.type,
190
+ * property: prop
191
+ * })
192
+ * })
193
+ *
194
+ * // Access reactive properties
195
+ * console.log(state.count, state.name)
196
+ * })
197
+ *
198
+ * state.count = 5
199
+ * // Logs: Effect triggered by: { object: state, change: 'set', property: 'count' }
200
+ * ```
201
+ */
202
+ declare function trackEffect(onTouch: EffectTracking): void;
203
+ /**
204
+ * Gets the current state of a reactive object for evolution tracking
205
+ * @param obj - The reactive object
206
+ * @returns The current state object
207
+ */
62
208
  declare function getState(obj: any): State;
209
+ declare let activeEffect: ScopedCallback | undefined;
210
+ /**
211
+ * Adds a cleanup function to be called when the current batch of effects completes
212
+ * @param cleanup - The cleanup function to add
213
+ */
214
+ declare function addBatchCleanup(cleanup: ScopedCallback): void;
215
+ /**
216
+ * Decorator that makes methods atomic - batches all effects triggered within the method
217
+ */
63
218
  declare const atomic: LegacyPropertyDecorator<any> & ModernMethodDecorator<any> & (<Args extends any[], Return>(original: (...args: Args) => Return) => (...args: Args) => Return);
64
- declare class ReactiveBase {
65
- constructor();
66
- }
219
+ /**
220
+ * Base mixin for reactive classes that provides proper constructor reactivity
221
+ * Solves constructor reactivity issues in complex inheritance trees
222
+ */
223
+ declare const ReactiveBase: (new (...args: any[]) => {
224
+ [x: string]: any;
225
+ }) & (<Base>(base: abstract new (...args: any[]) => Base) => new (...args: any[]) => {
226
+ [x: string]: any;
227
+ } & Base);
228
+ /**
229
+ * Always-reactive mixin that makes classes inherently reactive
230
+ * Can be used as both a base class and a mixin function
231
+ */
232
+ declare const Reactive: (new (...args: any[]) => {
233
+ [x: string]: any;
234
+ }) & (<Base>(base: abstract new (...args: any[]) => Base) => new (...args: any[]) => {
235
+ [x: string]: any;
236
+ } & Base);
67
237
  declare function reactiveObject<T>(anyTarget: T): T;
238
+ /**
239
+ * Main decorator for making classes reactive
240
+ * Automatically makes class instances reactive when created
241
+ */
68
242
  declare const reactive: LegacyClassDecorator<new (...args: any[]) => any> & ModernClassDecorator<new (...args: any[]) => any> & typeof reactiveObject;
243
+ /**
244
+ * Gets the original, non-reactive object from a reactive proxy
245
+ * @param proxy - The reactive proxy
246
+ * @returns The original object
247
+ */
69
248
  declare function unwrap<T>(proxy: T): T;
249
+ /**
250
+ * Checks if an object is a reactive proxy
251
+ * @param obj - The object to check
252
+ * @returns True if the object is reactive
253
+ */
70
254
  declare function isReactive(obj: any): boolean;
71
- declare function untracked(fn: () => ScopedCallback | undefined | void): void;
255
+ /**
256
+ * Executes a function without tracking dependencies
257
+ * @param fn - The function to execute
258
+ */
259
+ declare function untracked<T>(fn: () => T): T;
72
260
  /**
73
261
  * @param fn - The effect function to run - provides the cleaner
74
262
  * @returns The cleanup function
75
263
  */
76
- declare function effect<Args extends any[]>(fn: (dep: DependencyFunction, ...args: Args) => ScopedCallback | undefined | void, ...args: Args): ScopedCallback;
77
264
  /**
78
- * Set of functions to test if an object is immutable
265
+ * Creates a reactive effect that automatically re-runs when dependencies change
266
+ * @param fn - The effect function that provides dependencies and may return a cleanup function
267
+ * @param args - Additional arguments that are forwarded to the effect function
268
+ * @returns A cleanup function to stop the effect
269
+ */
270
+ declare function effect<Args extends any[]>(fn: (access: DependencyAccess, ...args: Args) => ScopedCallback | undefined | void, ...args: Args): ScopedCallback;
271
+ /**
272
+ * Set of functions that test if objects are immutable
273
+ * Objects that pass these tests will not be made reactive
79
274
  */
80
275
  declare const immutables: Set<(tested: any) => boolean>;
81
276
  /**
82
- * Check if an object is marked as non-reactive (for testing purposes)
277
+ * Checks if an object is marked as non-reactive
83
278
  * @param obj - The object to check
84
- * @returns true if the object is marked as non-reactive
279
+ * @returns True if the object is non-reactive
85
280
  */
86
281
  declare function isNonReactive(obj: any): boolean;
87
282
 
88
283
  /**
89
- * When used in a computed property computation, it will register the callback to be called when the computed property is invalidated
284
+ * Registers a callback to be called when a computed property is invalidated
90
285
  * @param cb - The callback to register
91
286
  * @param warn - Whether to warn if used outside of a computed property
92
287
  */
93
288
  declare function invalidateComputed(cb: () => void, warn?: boolean): void;
94
- type ComputedFunction<T> = (dep: DependencyFunction) => T;
289
+ type ComputedFunction<T> = (dep: DependencyAccess) => T;
290
+ declare function computedFunction<T>(getter: ComputedFunction<T>): T;
95
291
  /**
96
- * Get the cached value of a computed function - cache is invalidated when the dependencies change
292
+ * Decorator and function for creating computed properties that cache their values
293
+ * Only recomputes when dependencies change
294
+ */
295
+ declare const computed: LegacyPropertyDecorator<any> & ModernGetterDecorator<any> & ModernAccessorDecorator<any> & typeof computedFunction & {
296
+ map: typeof computedMap;
297
+ memo: typeof computedMapMemo;
298
+ self: typeof selfReferencing;
299
+ };
300
+ /**
301
+ * Options for the watch function
97
302
  */
98
- declare const computed: LegacyPropertyDecorator<any> & ModernGetterDecorator<any> & ModernAccessorDecorator<any> & (<T>(getter: ComputedFunction<T>) => T);
99
303
  interface WatchOptions {
304
+ /** Whether to call the callback immediately */
100
305
  immediate?: boolean;
306
+ /** Whether to watch nested properties */
101
307
  deep?: boolean;
102
308
  }
103
- declare function watch<T>(value: (dep: DependencyFunction) => T, changed: (value: T, oldValue?: T) => void, options?: Omit<WatchOptions, 'deep'> & {
309
+ /**
310
+ * Watches a computed value and calls a callback when it changes
311
+ * @param value - Function that returns the value to watch
312
+ * @param changed - Callback to call when the value changes
313
+ * @param options - Watch options
314
+ * @returns Cleanup function to stop watching
315
+ */
316
+ declare function watch<T>(value: (dep: DependencyAccess) => T, changed: (value: T, oldValue?: T) => void, options?: Omit<WatchOptions, 'deep'> & {
104
317
  deep?: false;
105
318
  }): ScopedCallback;
106
- declare function watch<T extends object | any[]>(value: (dep: DependencyFunction) => T, changed: (value: T, oldValue?: T) => void, options?: Omit<WatchOptions, 'deep'> & {
319
+ /**
320
+ * Watches a computed value with deep watching enabled
321
+ * @param value - Function that returns the value to watch
322
+ * @param changed - Callback to call when the value changes
323
+ * @param options - Watch options with deep watching enabled
324
+ * @returns Cleanup function to stop watching
325
+ */
326
+ declare function watch<T extends object | any[]>(value: (dep: DependencyAccess) => T, changed: (value: T, oldValue?: T) => void, options?: Omit<WatchOptions, 'deep'> & {
107
327
  deep: true;
108
328
  }): ScopedCallback;
329
+ /**
330
+ * Watches a reactive object directly
331
+ * @param value - The reactive object to watch
332
+ * @param changed - Callback to call when the object changes
333
+ * @param options - Watch options
334
+ * @returns Cleanup function to stop watching
335
+ */
109
336
  declare function watch<T extends object | any[]>(value: T, changed: (value: T) => void, options?: WatchOptions): ScopedCallback;
110
337
  declare function unreactiveApplication<T extends object>(...args: (keyof T)[]): GenericClassDecorator<T>;
111
338
  declare function unreactiveApplication<T extends object>(obj: T): T;
339
+ /**
340
+ * Decorator that marks classes or properties as non-reactive
341
+ * Prevents objects from being made reactive
342
+ */
112
343
  declare const unreactive: LegacyClassDecorator<new (...args: any[]) => any> & ModernClassDecorator<new (...args: any[]) => any> & typeof unreactiveApplication;
344
+ declare function cleanedBy<T extends object>(obj: T, cleanup: ScopedCallback): T & {
345
+ cleanup: () => void;
346
+ };
347
+ declare function computedMap<T, U>(inputs: T[], compute: (input: T, index: number, oldValue?: U) => U, resize?: (newLength: number, oldLength: number) => void): U[];
348
+ declare function computedMapMemo<I, O>(inputs: I[] | (() => I[]), compute: (input: I) => O): O[];
349
+ declare function selfReferencing<T extends object>(compute: (dep: DependencyAccess) => T): T;
113
350
 
114
- export { ReactiveBase, ReactiveError, atomic, computed, effect, getState, immutables, invalidateComputed, isNonReactive, isReactive, profileInfo, reactive, options as reactiveOptions, unreactive, untracked, unwrap, watch };
115
- export type { ScopedCallback };
351
+ export { Reactive, ReactiveBase, ReactiveError, activeEffect, addBatchCleanup, atomic, cleanedBy, computed, effect, getState, immutables, invalidateComputed, isNonReactive, isReactive, profileInfo, reactive, options as reactiveOptions, trackEffect, unreactive, untracked, unwrap, watch };
352
+ export type { Evolution, ScopedCallback };