@oscarpalmer/mora 0.29.0 → 0.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/batch.mjs +15 -6
  2. package/dist/constants.d.mts +0 -1
  3. package/dist/constants.mjs +4 -3
  4. package/dist/effect.d.mts +5 -18
  5. package/dist/effect.mjs +23 -19
  6. package/dist/helpers/is.d.mts +9 -9
  7. package/dist/helpers/is.mjs +6 -0
  8. package/dist/helpers/proxy.d.mts +5 -9
  9. package/dist/helpers/proxy.mjs +4 -4
  10. package/dist/helpers/value.d.mts +3 -3
  11. package/dist/helpers/value.mjs +22 -5
  12. package/dist/index.d.mts +7 -8
  13. package/dist/index.mjs +1 -1
  14. package/dist/models.d.mts +356 -18
  15. package/dist/mora.full.mjs +448 -421
  16. package/dist/subscription.d.mts +1 -9
  17. package/dist/subscription.mjs +14 -15
  18. package/dist/value/array.d.mts +5 -133
  19. package/dist/value/array.mjs +91 -137
  20. package/dist/value/computed.d.mts +4 -12
  21. package/dist/value/computed.mjs +54 -50
  22. package/dist/value/reactive.d.mts +3 -49
  23. package/dist/value/reactive.mjs +10 -54
  24. package/dist/value/signal.d.mts +5 -21
  25. package/dist/value/signal.mjs +27 -49
  26. package/dist/value/store.d.mts +9 -92
  27. package/dist/value/store.mjs +42 -49
  28. package/package.json +7 -8
  29. package/src/batch.ts +22 -9
  30. package/src/constants.ts +3 -4
  31. package/src/effect.ts +35 -40
  32. package/src/helpers/is.ts +11 -10
  33. package/src/helpers/proxy.ts +23 -18
  34. package/src/helpers/value.ts +39 -5
  35. package/src/index.ts +6 -7
  36. package/src/models.ts +431 -16
  37. package/src/subscription.ts +20 -20
  38. package/src/value/array.ts +183 -265
  39. package/src/value/computed.ts +80 -74
  40. package/src/value/reactive.ts +16 -77
  41. package/src/value/signal.ts +34 -71
  42. package/src/value/store.ts +84 -177
  43. package/types/constants.d.ts +1 -1
  44. package/types/index.d.ts +1 -1
  45. package/types/value/array.d.ts +1 -1
  46. package/types/value/computed.d.ts +3 -0
  47. package/types/value/signal.d.ts +1 -1
  48. package/types/value/store.d.ts +1 -1
package/dist/batch.mjs CHANGED
@@ -1,13 +1,22 @@
1
1
  import { BATCH } from "./constants.mjs";
2
2
  import { runEffect } from "./effect.mjs";
3
- import { isEffect } from "./helpers/is.mjs";
4
3
  //#region src/batch.ts
5
4
  function flushHandlers() {
6
- while (BATCH.depth === 0 && BATCH.handlers.size > 0) {
7
- const handlers = [...BATCH.handlers];
8
- BATCH.handlers.clear();
9
- for (const handler of handlers) if (isEffect(handler)) runEffect(handler);
10
- else handler.callback(handler.state.value);
5
+ if (BATCH.flushing) return;
6
+ BATCH.flushing = true;
7
+ try {
8
+ while (BATCH.depth === 0 && BATCH.handlers.size > 0) {
9
+ const handlers = [...BATCH.handlers];
10
+ const { length } = handlers;
11
+ BATCH.handlers.clear();
12
+ for (let index = 0; index < length; index += 1) {
13
+ const handler = handlers[index];
14
+ if (typeof handler.destroy === "function") handler.callback(handler.state.value);
15
+ else runEffect(handler);
16
+ }
17
+ }
18
+ } finally {
19
+ BATCH.flushing = false;
11
20
  }
12
21
  }
13
22
  /**
@@ -1,5 +1,4 @@
1
1
  import { Active, Batch } from "./models.mjs";
2
-
3
2
  //#region src/constants.d.ts
4
3
  declare const ACTIVE: Active;
5
4
  declare const ARRAY_THRESHOLD = 100;
@@ -5,15 +5,16 @@ const ARRAY_OFFSET = 25;
5
5
  const ARRAY_PEEK = 10;
6
6
  const BATCH = {
7
7
  depth: 0,
8
+ flushing: false,
8
9
  handlers: /* @__PURE__ */ new Set()
9
10
  };
10
- const METHODS_AFFECTING_LENGTH = new Set([
11
+ const METHODS_AFFECTING_LENGTH = /* @__PURE__ */ new Set([
11
12
  "pop",
12
13
  "push",
13
14
  "shift",
14
15
  "unshift"
15
16
  ]);
16
- const METHODS_UPDATE = new Set([
17
+ const METHODS_UPDATE = /* @__PURE__ */ new Set([
17
18
  ...METHODS_AFFECTING_LENGTH,
18
19
  "copyWithin",
19
20
  "fill",
@@ -27,7 +28,7 @@ const NAME_EFFECT = "effect";
27
28
  const NAME_MORA = "$mora";
28
29
  const NAME_SIGNAL = "signal";
29
30
  const NAME_STORE = "store";
30
- const NAME_ALL = new Set([
31
+ const NAME_ALL = /* @__PURE__ */ new Set([
31
32
  NAME_ARRAY,
32
33
  NAME_COMPUTED,
33
34
  NAME_SIGNAL,
package/dist/effect.d.mts CHANGED
@@ -1,27 +1,14 @@
1
+ import { Effect, EffectState } from "./models.mjs";
1
2
  import { GenericCallback } from "@oscarpalmer/atoms/models";
2
-
3
3
  //#region src/effect.d.ts
4
- declare class Effect {
5
- /**
6
- * Internal name of the effect
7
- *
8
- * @internal
9
- */
10
- private readonly $mora;
11
- /**
12
- * Internal state of the effect
13
- *
14
- * @internal
15
- */
16
- private readonly state;
17
- constructor(callback: GenericCallback);
18
- }
19
- declare function runEffect(effect: Effect): void;
20
4
  /**
21
5
  * Create an effect
6
+ *
22
7
  * @param callback Callback for handling signal effects
23
8
  * @returns Effect
24
9
  */
25
10
  declare function effect(callback: GenericCallback): Effect;
11
+ declare function internalEffect(callback: GenericCallback): EffectState;
12
+ declare function runEffect(state: EffectState): void;
26
13
  //#endregion
27
- export { Effect, effect, runEffect };
14
+ export { effect, internalEffect, runEffect };
package/dist/effect.mjs CHANGED
@@ -1,28 +1,32 @@
1
- import { ACTIVE, NAME_EFFECT, NAME_MORA } from "./constants.mjs";
1
+ import { ACTIVE, NAME_EFFECT } from "./constants.mjs";
2
2
  //#region src/effect.ts
3
- var Effect = class {
4
- constructor(callback) {
5
- Object.defineProperty(this, NAME_MORA, { value: NAME_EFFECT });
6
- this.state = { callback };
7
- runEffect(this);
8
- }
9
- };
10
- function runEffect(effect) {
11
- const previousEffect = ACTIVE.effect;
12
- ACTIVE.effect = effect;
13
- try {
14
- effect.state.callback();
15
- } finally {
16
- ACTIVE.effect = previousEffect;
17
- }
18
- }
19
3
  /**
20
4
  * Create an effect
5
+ *
21
6
  * @param callback Callback for handling signal effects
22
7
  * @returns Effect
23
8
  */
24
9
  function effect(callback) {
25
- return typeof callback === "function" ? new Effect(callback) : void 0;
10
+ if (typeof callback !== "function") throw new TypeError("Effect callback must be a function");
11
+ return getEffect(callback)[0];
12
+ }
13
+ function getEffect(callback) {
14
+ const state = { callback };
15
+ const instance = Object.freeze({ $mora: NAME_EFFECT });
16
+ runEffect(state);
17
+ return [instance, state];
18
+ }
19
+ function internalEffect(callback) {
20
+ return getEffect(callback)[1];
21
+ }
22
+ function runEffect(state) {
23
+ const previousEffect = ACTIVE.effect;
24
+ ACTIVE.effect = state;
25
+ try {
26
+ state.callback();
27
+ } finally {
28
+ ACTIVE.effect = previousEffect;
29
+ }
26
30
  }
27
31
  //#endregion
28
- export { Effect, effect, runEffect };
32
+ export { effect, internalEffect, runEffect };
@@ -1,47 +1,47 @@
1
- import { Effect } from "../effect.mjs";
2
- import { Reactive } from "../value/reactive.mjs";
3
- import { Computed } from "../value/computed.mjs";
4
- import { Signal } from "../value/signal.mjs";
5
- import { ReactiveArray } from "../value/array.mjs";
6
- import { Store } from "../value/store.mjs";
1
+ import { Computed, Effect, Reactive, ReactiveArray, ReactiveStore, Signal } from "../models.mjs";
7
2
  import { PlainObject } from "@oscarpalmer/atoms/models";
8
-
9
3
  //#region src/helpers/is.d.ts
10
4
  /**
11
5
  * Is the value a reactive array?
6
+ *
12
7
  * @param value Value to check
13
8
  * @returns True if value is a {@link ReactiveArray}
14
9
  */
15
10
  declare function isArray<Item>(value: unknown): value is ReactiveArray<Item>;
16
11
  /**
17
12
  * Is the value a computed signal?
13
+ *
18
14
  * @param value Value to check
19
15
  * @returns True if value is a {@link Computed}
20
16
  */
21
17
  declare function isComputed<Value>(value: unknown): value is Computed<Value>;
22
18
  /**
23
19
  * Is the value an effect?
20
+ *
24
21
  * @param value Value to check
25
22
  * @returns True if value is an {@link Effect}
26
23
  */
27
24
  declare function isEffect(value: unknown): value is Effect;
28
25
  /**
29
26
  * Is the value reactive?
27
+ *
30
28
  * @param value Value to check
31
29
  * @returns True if value is a {@link Reactive}
32
30
  */
33
- declare function isReactive<Value, Equal = Value>(value: unknown): value is Reactive<Value, Equal>;
31
+ declare function isReactive<Value>(value: unknown): value is Reactive<Value>;
34
32
  /**
35
33
  * Is the value a signal?
34
+ *
36
35
  * @param value Value to check
37
36
  * @returns True if value is a {@link Signal}
38
37
  */
39
38
  declare function isSignal<Value>(value: unknown): value is Signal<Value>;
40
39
  /**
41
40
  * Is the value a reactive store?
41
+ *
42
42
  * @param value Value to check
43
43
  * @returns True if value is a {@link Store}
44
44
  */
45
- declare function isStore<Value extends PlainObject>(value: unknown): value is Store<Value>;
45
+ declare function isStore<Value extends PlainObject>(value: unknown): value is ReactiveStore<Value>;
46
46
  //#endregion
47
47
  export { isArray, isComputed, isEffect, isReactive, isSignal, isStore };
@@ -2,6 +2,7 @@ import { NAME_ALL, NAME_ARRAY, NAME_COMPUTED, NAME_EFFECT, NAME_SIGNAL, NAME_STO
2
2
  //#region src/helpers/is.ts
3
3
  /**
4
4
  * Is the value a reactive array?
5
+ *
5
6
  * @param value Value to check
6
7
  * @returns True if value is a {@link ReactiveArray}
7
8
  */
@@ -10,6 +11,7 @@ function isArray(value) {
10
11
  }
11
12
  /**
12
13
  * Is the value a computed signal?
14
+ *
13
15
  * @param value Value to check
14
16
  * @returns True if value is a {@link Computed}
15
17
  */
@@ -18,6 +20,7 @@ function isComputed(value) {
18
20
  }
19
21
  /**
20
22
  * Is the value an effect?
23
+ *
21
24
  * @param value Value to check
22
25
  * @returns True if value is an {@link Effect}
23
26
  */
@@ -29,6 +32,7 @@ function isMora(value, name) {
29
32
  }
30
33
  /**
31
34
  * Is the value reactive?
35
+ *
32
36
  * @param value Value to check
33
37
  * @returns True if value is a {@link Reactive}
34
38
  */
@@ -37,6 +41,7 @@ function isReactive(value) {
37
41
  }
38
42
  /**
39
43
  * Is the value a signal?
44
+ *
40
45
  * @param value Value to check
41
46
  * @returns True if value is a {@link Signal}
42
47
  */
@@ -45,6 +50,7 @@ function isSignal(value) {
45
50
  }
46
51
  /**
47
52
  * Is the value a reactive store?
53
+ *
48
54
  * @param value Value to check
49
55
  * @returns True if value is a {@link Store}
50
56
  */
@@ -1,14 +1,10 @@
1
- import { Computed } from "../value/computed.mjs";
2
- import { ReactiveState, SetValueInProxyParameters } from "../models.mjs";
3
- import { ReactiveArray } from "../value/array.mjs";
4
- import { Store } from "../value/store.mjs";
1
+ import { Computed, ComputedEffect, ReactiveArray, ReactiveState, ReactiveStore, SetValueInProxyParameters } from "../models.mjs";
5
2
  import { ArrayOrPlainObject, Key, PlainObject } from "@oscarpalmer/atoms/models";
6
-
7
3
  //#region src/helpers/proxy.d.ts
8
- declare function emityProxyValues<Value>(state: ReactiveState<Value, Value>, mapped: Map<Key, Computed<unknown>>): void;
9
- declare function emityProxyValues<Value>(state: ReactiveState<Value[], Value>, mapped: Map<Key, Computed<unknown>>): void;
10
- declare function getReactiveValueInProxy<Value>(array: ReactiveArray<Value>, mapped: Map<Key, Computed<unknown>>, index: number, isArray: true): Computed<unknown>;
11
- declare function getReactiveValueInProxy<Value extends PlainObject>(store: Store<Value>, mapped: Map<Key, Computed<unknown>>, key: Key, isArray: false): Computed<unknown>;
4
+ declare function emityProxyValues<Value>(state: ReactiveState<Value, Value>, mapped: Map<Key, [Computed<unknown>, ComputedEffect]>): void;
5
+ declare function emityProxyValues<Value>(state: ReactiveState<Value[], Value>, mapped: Map<Key, [Computed<unknown>, ComputedEffect]>): void;
6
+ declare function getReactiveValueInProxy<Value, Result = Value>(array: ReactiveArray<Value>, mapped: Map<Key, [Computed<unknown>, ComputedEffect]>, index: number, isArray: true): Computed<Result>;
7
+ declare function getReactiveValueInProxy<Value extends PlainObject>(store: ReactiveStore<Value>, mapped: Map<Key, [Computed<unknown>, ComputedEffect]>, key: Key, isArray: false): Computed<unknown>;
12
8
  declare function setProxyValue<Value, Item = Value>(array: boolean, state: ReactiveState<Value, Item>, isObject: (value: unknown) => value is Value | undefined, isProperty: (value: unknown) => boolean, setObject: (state: ReactiveState<Value, Item>, value: Value | undefined) => void, setProperty: (state: ReactiveState<Value, Item>, property: unknown, value: Item) => void, first?: unknown, second?: unknown): void;
13
9
  declare function setValueInProxy<Value extends ArrayOrPlainObject, Equal>(parameters: SetValueInProxyParameters<Value, Equal>): boolean;
14
10
  //#endregion
@@ -1,20 +1,20 @@
1
1
  import "../constants.mjs";
2
- import { computed } from "../value/computed.mjs";
3
2
  import { emitValue } from "./value.mjs";
3
+ import { internalComputed } from "../value/computed.mjs";
4
4
  //#region src/helpers/proxy.ts
5
5
  function emityProxyValues(state, mapped) {
6
6
  const values = [...mapped.values()];
7
7
  const { length } = values;
8
- for (let index = 0; index < length; index += 1) values[index].effect.dirty = true;
8
+ for (let index = 0; index < length; index += 1) values[index][1].dirty = true;
9
9
  emitValue(state);
10
10
  }
11
11
  function getReactiveValueInProxy(reactive, mapped, key, isArray) {
12
12
  let item = mapped.get(key);
13
13
  if (item == null) {
14
- item = computed(() => isArray ? reactive.get().at(key) : reactive.get()[key]);
14
+ item = internalComputed(() => isArray ? reactive.get().at(key) : reactive.get()[key]);
15
15
  mapped.set(key, item);
16
16
  }
17
- return item;
17
+ return item[0];
18
18
  }
19
19
  function setProxyValue(array, state, isObject, isProperty, setObject, setProperty, first, second) {
20
20
  if (array && first === "length") {
@@ -1,8 +1,8 @@
1
1
  import { ReactiveState } from "../models.mjs";
2
-
3
2
  //#region src/helpers/value.d.ts
4
3
  declare function emitValue<Value>(state: ReactiveState<Value, never>): void;
5
4
  declare function equalArrays<Value>(state: ReactiveState<Value[], Value>, first: Value[], second: Value[]): boolean;
6
- declare function getValue<Value>(state: ReactiveState<Value, never>): Value;
5
+ declare function getSimpleValue<Value>(state: ReactiveState<Value, never>): Value;
6
+ declare function handleSimpleValue<Value>(state: ReactiveState<Value, Value>, origin: Value | (() => Value | Promise<Value>) | Promise<Value>, setValue: (state: ReactiveState<Value, Value>, value: Value) => void, onAfter?: () => void): void;
7
7
  //#endregion
8
- export { emitValue, equalArrays, getValue };
8
+ export { emitValue, equalArrays, getSimpleValue, handleSimpleValue };
@@ -1,9 +1,8 @@
1
1
  import { ACTIVE, BATCH } from "../constants.mjs";
2
2
  import { flushHandlers } from "../batch.mjs";
3
- import { round } from "@oscarpalmer/atoms/math";
4
3
  //#region src/helpers/value.ts
5
4
  function emitValue(state) {
6
- for (const computed of state.computeds) computed.effect.dirty = true;
5
+ for (const computed of state.computeds) computed.dirty = true;
7
6
  for (const effect of state.effects) BATCH.handlers.add(effect);
8
7
  for (const [, subscription] of state.subscriptions) BATCH.handlers.add(subscription);
9
8
  if (BATCH.depth === 0) flushHandlers();
@@ -13,7 +12,7 @@ function equalArrays(state, first, second) {
13
12
  if (length !== second.length) return false;
14
13
  let offset = 0;
15
14
  if (length >= 100) {
16
- offset = round(length / 10);
15
+ offset = Math.round(length / 10);
17
16
  offset = offset > 25 ? 25 : offset;
18
17
  for (let index = 0; index < offset; index += 1) if (!state.equal(first[index], second[index])) return false;
19
18
  }
@@ -21,10 +20,28 @@ function equalArrays(state, first, second) {
21
20
  for (let index = offset; index < length; index += 1) if (!state.equal(first[index], second[index])) return false;
22
21
  return true;
23
22
  }
24
- function getValue(state) {
23
+ function getSimpleValue(state) {
25
24
  if (ACTIVE.computed != null) state.computeds.add(ACTIVE.computed);
26
25
  if (ACTIVE.effect != null) state.effects.add(ACTIVE.effect);
27
26
  return state.value;
28
27
  }
28
+ function handleSimpleValue(state, origin, setValue, onAfter) {
29
+ try {
30
+ let actual = typeof origin === "function" ? origin() : origin;
31
+ if (actual instanceof Promise) {
32
+ state.promise = actual;
33
+ actual.then((value) => {
34
+ if (actual === state.promise) {
35
+ state.promise = void 0;
36
+ setValue(state, value);
37
+ }
38
+ }).catch(() => {
39
+ if (actual === state.promise) state.promise = void 0;
40
+ });
41
+ } else setValue(state, actual);
42
+ } catch {} finally {
43
+ onAfter?.();
44
+ }
45
+ }
29
46
  //#endregion
30
- export { emitValue, equalArrays, getValue };
47
+ export { emitValue, equalArrays, getSimpleValue, handleSimpleValue };
package/dist/index.d.mts CHANGED
@@ -1,10 +1,9 @@
1
1
  import { startBatch, stopBatch } from "./batch.mjs";
2
- import { Effect, effect } from "./effect.mjs";
3
- import { Reactive } from "./value/reactive.mjs";
4
- import { Computed, computed } from "./value/computed.mjs";
5
- import { Signal, signal } from "./value/signal.mjs";
6
- import { Unsubscribe } from "./models.mjs";
7
- import { ReactiveArray, array } from "./value/array.mjs";
8
- import { Store, store } from "./value/store.mjs";
2
+ import { Computed, Effect, ReactiveArray, ReactiveStore, Signal, Unsubscribe } from "./models.mjs";
3
+ import { effect } from "./effect.mjs";
9
4
  import { isArray, isComputed, isEffect, isReactive, isSignal } from "./helpers/is.mjs";
10
- export { type Computed, type Effect, type Reactive, type ReactiveArray, type Signal, type Store, type Unsubscribe, array, computed, effect, isArray, isComputed, isEffect, isReactive, isSignal, signal, startBatch, stopBatch, store };
5
+ import { array } from "./value/array.mjs";
6
+ import { computed } from "./value/computed.mjs";
7
+ import { signal } from "./value/signal.mjs";
8
+ import { store } from "./value/store.mjs";
9
+ export { type Computed, type Effect, type ReactiveArray, type ReactiveStore, type Signal, type Unsubscribe, array, computed, effect, isArray, isComputed, isEffect, isReactive, isSignal, signal, startBatch, stopBatch, store };
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { effect } from "./effect.mjs";
2
- import { isArray, isComputed, isEffect, isReactive, isSignal } from "./helpers/is.mjs";
3
2
  import { startBatch, stopBatch } from "./batch.mjs";
3
+ import { isArray, isComputed, isEffect, isReactive, isSignal } from "./helpers/is.mjs";
4
4
  import { computed } from "./value/computed.mjs";
5
5
  import { signal } from "./value/signal.mjs";
6
6
  import { array } from "./value/array.mjs";