mutts 1.0.5 → 1.0.7

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 (114) hide show
  1. package/README.md +2 -1
  2. package/dist/browser.d.ts +2 -0
  3. package/dist/browser.esm.js +70 -0
  4. package/dist/browser.esm.js.map +1 -0
  5. package/dist/browser.js +161 -0
  6. package/dist/browser.js.map +1 -0
  7. package/dist/chunks/{index-Cvxdw6Ax.js → index-BFYK02LG.js} +5377 -4059
  8. package/dist/chunks/index-BFYK02LG.js.map +1 -0
  9. package/dist/chunks/{index-qiWwozOc.esm.js → index-CNR6QRUl.esm.js} +5247 -3963
  10. package/dist/chunks/index-CNR6QRUl.esm.js.map +1 -0
  11. package/dist/mutts.umd.js +1 -1
  12. package/dist/mutts.umd.js.map +1 -1
  13. package/dist/mutts.umd.min.js +1 -1
  14. package/dist/mutts.umd.min.js.map +1 -1
  15. package/dist/node.d.ts +2 -0
  16. package/dist/node.esm.js +45 -0
  17. package/dist/node.esm.js.map +1 -0
  18. package/dist/node.js +136 -0
  19. package/dist/node.js.map +1 -0
  20. package/docs/ai/api-reference.md +0 -2
  21. package/docs/ai/manual.md +14 -95
  22. package/docs/reactive/advanced.md +7 -111
  23. package/docs/reactive/collections.md +0 -125
  24. package/docs/reactive/core.md +27 -24
  25. package/docs/reactive/debugging.md +168 -0
  26. package/docs/reactive/project.md +1 -1
  27. package/docs/reactive/scan.md +78 -0
  28. package/docs/reactive.md +8 -6
  29. package/docs/std-decorators.md +1 -0
  30. package/docs/zone.md +88 -0
  31. package/package.json +47 -65
  32. package/src/async/browser.ts +87 -0
  33. package/src/async/index.ts +8 -0
  34. package/src/async/node.ts +46 -0
  35. package/src/decorator.ts +15 -9
  36. package/src/destroyable.ts +4 -4
  37. package/src/index.ts +54 -0
  38. package/src/indexable.ts +42 -0
  39. package/src/mixins.ts +2 -2
  40. package/src/reactive/array.ts +149 -141
  41. package/src/reactive/buffer.ts +168 -0
  42. package/src/reactive/change.ts +3 -3
  43. package/src/reactive/debug.ts +1 -1
  44. package/src/reactive/deep-touch.ts +1 -1
  45. package/src/reactive/deep-watch.ts +1 -1
  46. package/src/reactive/effect-context.ts +15 -91
  47. package/src/reactive/effects.ts +138 -170
  48. package/src/reactive/index.ts +10 -13
  49. package/src/reactive/interface.ts +20 -33
  50. package/src/reactive/map.ts +48 -61
  51. package/src/reactive/memoize.ts +87 -31
  52. package/src/reactive/project.ts +43 -22
  53. package/src/reactive/proxy.ts +18 -43
  54. package/src/reactive/record.ts +3 -3
  55. package/src/reactive/register.ts +5 -7
  56. package/src/reactive/registry.ts +59 -0
  57. package/src/reactive/set.ts +42 -56
  58. package/src/reactive/tracking.ts +5 -62
  59. package/src/reactive/types.ts +79 -19
  60. package/src/std-decorators.ts +9 -9
  61. package/src/utils.ts +203 -19
  62. package/src/zone.ts +127 -0
  63. package/dist/chunks/_tslib-BgjropY9.js +0 -81
  64. package/dist/chunks/_tslib-BgjropY9.js.map +0 -1
  65. package/dist/chunks/_tslib-Mzh1rNsX.esm.js +0 -75
  66. package/dist/chunks/_tslib-Mzh1rNsX.esm.js.map +0 -1
  67. package/dist/chunks/decorator-DLvrD0UF.js +0 -265
  68. package/dist/chunks/decorator-DLvrD0UF.js.map +0 -1
  69. package/dist/chunks/decorator-DqiszP7i.esm.js +0 -253
  70. package/dist/chunks/decorator-DqiszP7i.esm.js.map +0 -1
  71. package/dist/chunks/index-Cvxdw6Ax.js.map +0 -1
  72. package/dist/chunks/index-qiWwozOc.esm.js.map +0 -1
  73. package/dist/decorator.d.ts +0 -107
  74. package/dist/decorator.esm.js +0 -2
  75. package/dist/decorator.esm.js.map +0 -1
  76. package/dist/decorator.js +0 -11
  77. package/dist/decorator.js.map +0 -1
  78. package/dist/destroyable.d.ts +0 -90
  79. package/dist/destroyable.esm.js +0 -109
  80. package/dist/destroyable.esm.js.map +0 -1
  81. package/dist/destroyable.js +0 -116
  82. package/dist/destroyable.js.map +0 -1
  83. package/dist/eventful.d.ts +0 -20
  84. package/dist/eventful.esm.js +0 -66
  85. package/dist/eventful.esm.js.map +0 -1
  86. package/dist/eventful.js +0 -68
  87. package/dist/eventful.js.map +0 -1
  88. package/dist/index.d.ts +0 -19
  89. package/dist/index.esm.js +0 -8
  90. package/dist/index.esm.js.map +0 -1
  91. package/dist/index.js +0 -95
  92. package/dist/index.js.map +0 -1
  93. package/dist/indexable.d.ts +0 -243
  94. package/dist/indexable.esm.js +0 -285
  95. package/dist/indexable.esm.js.map +0 -1
  96. package/dist/indexable.js +0 -291
  97. package/dist/indexable.js.map +0 -1
  98. package/dist/promiseChain.d.ts +0 -21
  99. package/dist/promiseChain.esm.js +0 -78
  100. package/dist/promiseChain.esm.js.map +0 -1
  101. package/dist/promiseChain.js +0 -80
  102. package/dist/promiseChain.js.map +0 -1
  103. package/dist/reactive.d.ts +0 -885
  104. package/dist/reactive.esm.js +0 -5
  105. package/dist/reactive.esm.js.map +0 -1
  106. package/dist/reactive.js +0 -59
  107. package/dist/reactive.js.map +0 -1
  108. package/dist/std-decorators.d.ts +0 -52
  109. package/dist/std-decorators.esm.js +0 -196
  110. package/dist/std-decorators.esm.js.map +0 -1
  111. package/dist/std-decorators.js +0 -204
  112. package/dist/std-decorators.js.map +0 -1
  113. package/src/reactive/mapped.ts +0 -129
  114. package/src/reactive/zone.ts +0 -208
@@ -3,7 +3,7 @@ import { bubbleUpChange, objectsWithDeepWatchers } from './deep-watch-state'
3
3
  import { getActiveEffect, isRunning } from './effect-context'
4
4
  import { batch, effectTrackers, hasBatched, opaqueEffects, recordActivation } from './effects'
5
5
  import { unwrap } from './proxy-state'
6
- import { watchers } from './tracking'
6
+ import { watchers } from './registry'
7
7
  import { allProps, type Evolution, options, type ScopedCallback, type State } from './types'
8
8
 
9
9
  const states = new WeakMap<object, State>()
@@ -46,7 +46,7 @@ export function collectEffects(
46
46
  for (const effect of deps) {
47
47
  const runningChain = isRunning(effect)
48
48
  if (runningChain) {
49
- options.skipRunningEffect(effect, runningChain as any)
49
+ options.skipRunningEffect(effect)
50
50
  continue
51
51
  }
52
52
  if (!effects.has(effect)) {
@@ -118,7 +118,7 @@ export function touchedOpaque(obj: any, evolution: Evolution, prop: any) {
118
118
 
119
119
  const runningChain = isRunning(effect)
120
120
  if (runningChain) {
121
- options.skipRunningEffect(effect, runningChain as any)
121
+ options.skipRunningEffect(effect)
122
122
  continue
123
123
  }
124
124
  effects.add(effect)
@@ -5,7 +5,7 @@
5
5
  * - Provides graph data for tooling (DevTools panel, etc.)
6
6
  */
7
7
 
8
- import { effectParent, effectToReactiveObjects, getRoot } from './tracking'
8
+ import { effectParent, effectToReactiveObjects, getRoot } from './registry'
9
9
  import { allProps, type Evolution, options, type ScopedCallback } from './types'
10
10
 
11
11
  const EXTERNAL_SOURCE = Symbol('external-source')
@@ -3,7 +3,7 @@ import { bubbleUpChange, objectsWithDeepWatchers } from './deep-watch-state'
3
3
  import { batch } from './effects'
4
4
  import { isNonReactive } from './non-reactive-state'
5
5
  import { unwrap } from './proxy-state'
6
- import { effectParent, watchers } from './tracking'
6
+ import { effectParent, watchers } from './registry'
7
7
  import { allProps, type Evolution, options, type ScopedCallback } from './types'
8
8
 
9
9
  function isObject(value: any): value is object {
@@ -6,7 +6,7 @@ import {
6
6
  import { effect } from './effects'
7
7
  import { isNonReactive } from './non-reactive-state'
8
8
  import { reactive, unwrap } from './proxy'
9
- import { markWithRoot } from './tracking'
9
+ import { markWithRoot } from './registry'
10
10
  import { options, type ScopedCallback } from './types'
11
11
 
12
12
  function isObject(value: any): value is object {
@@ -1,94 +1,18 @@
1
- import { effectParent, getRoot } from './tracking'
2
- import { ReactiveError, type ScopedCallback } from './types'
3
-
4
- /**
5
- * Effect context stack for nested tracking (front = active, next = parent)
6
- */
7
- const stack: (ScopedCallback | undefined)[] = []
8
- export const effectStack = stack
9
-
10
- export function captureEffectStack() {
11
- return stack.slice()
12
- }
13
- export function isRunning(effect: ScopedCallback): (ScopedCallback | undefined)[] | false {
14
- const rootEffect = getRoot(effect)
15
-
16
- // Check if the effect is directly in the stack
17
- const rootIndex = stack.indexOf(rootEffect)
18
- if (rootIndex !== -1) {
19
- return stack.slice(0, rootIndex + 1).reverse()
20
- }
21
-
22
- // Check if any effect in the stack is a descendant of this effect
23
- // (i.e., walk up the parent chain from each stack effect to see if we reach this effect)
24
- for (let i = 0; i < stack.length; i++) {
25
- const stackEffect = stack[i]
26
- let current: ScopedCallback | undefined = stackEffect
27
- const visited = new WeakSet<ScopedCallback>()
28
- const ancestorChain: ScopedCallback[] = []
29
- // TODO: That's perhaps a lot of computations for an `assert`
30
- // Walk up the parent chain to find if this effect is an ancestor
31
- while (current && !visited.has(current)) {
32
- visited.add(current)
33
- const currentRoot = getRoot(current)
34
- ancestorChain.push(currentRoot)
35
- if (currentRoot === rootEffect) {
36
- // Found a descendant - build the full chain from ancestor to active
37
- // The ancestorChain contains [descendant, parent, ..., ancestor] (walking up)
38
- // We need [ancestor (effect), ..., parent, descendant, ...stack from descendant to active]
39
- const chainFromAncestor = ancestorChain.reverse() // [ancestor, ..., descendant]
40
- // Prepend the actual effect we're checking (in case current is a wrapper)
41
- if (chainFromAncestor[0] !== rootEffect) {
42
- chainFromAncestor.unshift(rootEffect)
43
- }
44
- // Append the rest of the stack from the descendant to the active effect
45
- const stackFromDescendant = stack.slice(0, i + 1).reverse() // [descendant, ..., active]
46
- // Remove duplicate descendant (it's both at end of chainFromAncestor and start of stackFromDescendant)
47
- if (chainFromAncestor.length > 0 && stackFromDescendant.length > 0) {
48
- stackFromDescendant.shift() // Remove duplicate descendant
49
- }
50
- return [...chainFromAncestor, ...stackFromDescendant]
51
- }
52
- current = effectParent.get(current)
53
- }
54
- }
55
-
56
- return false
57
- }
58
- export function withEffectStack<T>(snapshot: (ScopedCallback | undefined)[], fn: () => T): T {
59
- const previousStack = stack.slice()
60
- assignStack(snapshot)
61
- try {
62
- return fn()
63
- } finally {
64
- assignStack(previousStack)
65
- }
1
+ import { tag } from '../utils'
2
+ import { asyncZone, ZoneAggregator, ZoneHistory } from '../zone'
3
+ import { getRoot } from './registry'
4
+ import { type ScopedCallback } from './types'
5
+
6
+ export const effectHistory = tag(new ZoneHistory<ScopedCallback>(), 'effectHistory')
7
+ tag(effectHistory.present, 'effectHistory.present')
8
+ asyncZone.add(effectHistory)
9
+ export const effectAggregator = tag(new ZoneAggregator(effectHistory.present), 'effectAggregator')
10
+
11
+ export function isRunning(effect: ScopedCallback): boolean {
12
+ const root = getRoot(effect)
13
+ return effectHistory.some((e) => getRoot(e) === root)
66
14
  }
67
15
 
68
16
  export function getActiveEffect() {
69
- return stack[0]
70
- }
71
-
72
- /**
73
- * Executes a function with a specific effect context
74
- * @param effect - The effect to use as context
75
- * @param fn - The function to execute
76
- * @param keepParent - Whether to keep the parent effect context
77
- * @returns The result of the function
78
- */
79
- export function withEffect<T>(effect: ScopedCallback | undefined, fn: () => T): T {
80
- // console.log('[Mutts] withEffect', effect ? 'Active' : 'NULL');
81
- if (getRoot(effect) === getRoot(getActiveEffect())) return fn()
82
- stack.unshift(effect)
83
- try {
84
- return fn()
85
- } finally {
86
- const recoveredEffect = stack.shift()
87
- if (recoveredEffect !== effect) throw new ReactiveError('[reactive] Effect stack mismatch')
88
- }
89
- }
90
-
91
- function assignStack(values: (ScopedCallback | undefined)[]) {
92
- stack.length = 0
93
- stack.push(...values)
94
- }
17
+ return effectHistory.present.active
18
+ }