@yaasl/core 0.8.0-alpha.0 → 0.8.0-alpha.1

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.
@@ -1,30 +1,30 @@
1
1
  import { SetStateAction } from "@yaasl/utils";
2
2
  import { Stateful } from "./Stateful";
3
3
  import { MiddlewareAtomCallback } from "../middleware/middleware";
4
- export interface AtomConfig<AtomValue> {
4
+ export interface AtomConfig<Value> {
5
5
  /** Value that will be returned if the atom is not defined in the store */
6
- defaultValue: AtomValue;
6
+ defaultValue: Value;
7
7
  /** Name of the atom. Must be unique among all atoms. */
8
8
  name?: string;
9
9
  /** Middleware that will be applied on the atom */
10
10
  middleware?: MiddlewareAtomCallback<any>[];
11
11
  }
12
- export declare class Atom<AtomValue = unknown> extends Stateful<AtomValue> {
13
- readonly defaultValue: AtomValue;
12
+ export declare class Atom<Value = unknown> extends Stateful<Value> {
13
+ readonly defaultValue: Value;
14
14
  readonly name: string;
15
15
  didInit: PromiseLike<void> | boolean;
16
- constructor({ defaultValue, name, middleware, }: AtomConfig<AtomValue>);
16
+ constructor({ defaultValue, name, middleware, }: AtomConfig<Value>);
17
17
  /** Set the value of the atom.
18
18
  *
19
19
  * @param next New value or function to create the
20
20
  * new value based off the previous value.
21
21
  */
22
- set(next: SetStateAction<AtomValue>): void;
22
+ set(next: SetStateAction<Value>): void;
23
23
  /** Resolve the value of a promise and set as atom value.
24
24
  *
25
25
  * @param promise Promise to unwrap
26
26
  */
27
- unwrap(promise: Promise<AtomValue>): Promise<AtomValue>;
27
+ unwrap(promise: Promise<Value>): Promise<Value>;
28
28
  }
29
29
  /** Creates an atom store.
30
30
  *
@@ -34,4 +34,4 @@ export declare class Atom<AtomValue = unknown> extends Stateful<AtomValue> {
34
34
  *
35
35
  * @returns An atom instance.
36
36
  **/
37
- export declare const atom: <AtomValue>(config: AtomConfig<AtomValue>) => Atom<AtomValue>;
37
+ export declare const atom: <Value>(config: AtomConfig<Value>) => Atom<Value>;
@@ -1,19 +1,45 @@
1
+ import { SetStateAction } from "@yaasl/utils";
2
+ import { Atom } from "./atom";
1
3
  import { Stateful } from "./Stateful";
2
- type Derivation<T> = (context: {
4
+ type GetterFn<Value> = (context: {
3
5
  get: <V>(dep: Stateful<V>) => V;
4
- }) => T;
5
- export declare class Derive<DerivedValue> extends Stateful<DerivedValue> {
6
- private readonly derivation;
7
- private dependencies;
8
- constructor(derivation: Derivation<DerivedValue>);
9
- private addDependency;
6
+ }) => Value;
7
+ type SetterFn<Value> = (context: {
8
+ value: Value;
9
+ set: <V>(dep: Atom<V> | SettableDerive<V>, next: SetStateAction<V>) => void;
10
+ }) => void;
11
+ export declare class Derive<Value> extends Stateful<Value> {
12
+ private readonly getter;
13
+ protected readonly getterDependencies: Set<Stateful<any>>;
14
+ constructor(getter: GetterFn<Value>);
15
+ private addGetDependency;
10
16
  private deriveUpdate;
11
17
  }
12
- /** Creates a value, derived from one or more atoms or other derived values.
18
+ export declare class SettableDerive<Value = unknown> extends Derive<Value> {
19
+ private readonly setter;
20
+ protected readonly setterDependencies: Set<Atom<any> | SettableDerive<any>>;
21
+ constructor(getter: GetterFn<Value>, setter: SetterFn<Value>);
22
+ /** Set the value of the derived atom.
23
+ *
24
+ * @param next New value or function to create the
25
+ * new value based off the previous value.
26
+ */
27
+ set(next: SetStateAction<Value>): void;
28
+ private addSetDependency;
29
+ private compareDependencies;
30
+ }
31
+ /** A derive atom that allows deriving and elevating values from and
32
+ * to one or multiple other stateful elements.
33
+ *
34
+ * **Note:**
35
+ * - `getter` and `setter` should not have any side effects
36
+ * - `getter` and `setter` must use the same atoms
13
37
  *
14
- * @param get Function to derive the new value.
38
+ * @param getter Function to derive a new value from other stateful elements.
39
+ * @param setter Function to elevate a new value to it's stateful dependents.
15
40
  *
16
- * @returns A derived instance.
41
+ * @returns A derive instance.
17
42
  **/
18
- export declare const derive: <DerivedValue>(get: Derivation<DerivedValue>) => Derive<DerivedValue>;
43
+ export declare function derive<Value>(getter: GetterFn<Value>): Derive<Value>;
44
+ export declare function derive<Value>(getter: GetterFn<Value>, setter: SetterFn<Value>): SettableDerive<Value>;
19
45
  export {};
@@ -1,32 +1,77 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.derive = exports.Derive = void 0;
3
+ exports.derive = exports.SettableDerive = exports.Derive = void 0;
4
+ const utils_1 = require("@yaasl/utils");
4
5
  const Stateful_1 = require("./Stateful");
5
6
  class Derive extends Stateful_1.Stateful {
6
- constructor(derivation) {
7
+ constructor(getter) {
7
8
  super(undefined);
8
- this.derivation = derivation;
9
+ this.getter = getter;
9
10
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
- this.dependencies = new Set();
11
- this.value = derivation({ get: dep => this.addDependency(dep) });
11
+ this.getterDependencies = new Set();
12
+ this.value = getter({ get: dep => this.addGetDependency(dep) });
12
13
  }
13
- addDependency(dependency) {
14
- if (!this.dependencies.has(dependency)) {
14
+ addGetDependency(dependency) {
15
+ if (!this.getterDependencies.has(dependency)) {
15
16
  dependency.subscribe(() => this.deriveUpdate());
16
- this.dependencies.add(dependency);
17
+ this.getterDependencies.add(dependency);
17
18
  }
18
19
  return dependency.get();
19
20
  }
20
21
  deriveUpdate() {
21
- this.update(this.derivation({ get: dep => this.addDependency(dep) }));
22
+ this.update(this.getter({ get: dep => this.addGetDependency(dep) }));
22
23
  }
23
24
  }
24
25
  exports.Derive = Derive;
25
- /** Creates a value, derived from one or more atoms or other derived values.
26
- *
27
- * @param get Function to derive the new value.
28
- *
29
- * @returns A derived instance.
30
- **/
31
- const derive = (get) => new Derive(get);
26
+ class SettableDerive extends Derive {
27
+ constructor(getter, setter) {
28
+ super(getter);
29
+ this.setter = setter;
30
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
31
+ this.setterDependencies = new Set();
32
+ setter({
33
+ value: this.get(),
34
+ set: dep => this.addSetDependency(dep),
35
+ });
36
+ if (!this.compareDependencies()) {
37
+ throw new Error((0, utils_1.consoleMessage)("The set and get dependencies of a derived atom do not match."));
38
+ }
39
+ }
40
+ /** Set the value of the derived atom.
41
+ *
42
+ * @param next New value or function to create the
43
+ * new value based off the previous value.
44
+ */
45
+ set(next) {
46
+ const value = next instanceof Function ? next(this.get()) : next;
47
+ this.setter({
48
+ value,
49
+ set: (atom, next) => {
50
+ const value = next instanceof Function ? next(atom.get()) : next;
51
+ atom.set(value);
52
+ },
53
+ });
54
+ }
55
+ addSetDependency(dependency) {
56
+ if (!this.setterDependencies.has(dependency)) {
57
+ this.setterDependencies.add(dependency);
58
+ }
59
+ }
60
+ compareDependencies() {
61
+ const { getterDependencies, setterDependencies } = this;
62
+ if (getterDependencies.size !== setterDependencies.size) {
63
+ return false;
64
+ }
65
+ return Array.from(setterDependencies).every(dependency => getterDependencies.has(dependency));
66
+ }
67
+ }
68
+ exports.SettableDerive = SettableDerive;
69
+ function derive(getter, setter) {
70
+ if (setter) {
71
+ return new SettableDerive(getter, setter);
72
+ }
73
+ else {
74
+ return new Derive(getter);
75
+ }
76
+ }
32
77
  exports.derive = derive;
@@ -1,27 +1,71 @@
1
+ import { consoleMessage } from "@yaasl/utils";
1
2
  import { Stateful } from "./Stateful";
2
3
  export class Derive extends Stateful {
3
- constructor(derivation) {
4
+ constructor(getter) {
4
5
  super(undefined);
5
- this.derivation = derivation;
6
+ this.getter = getter;
6
7
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
- this.dependencies = new Set();
8
- this.value = derivation({ get: dep => this.addDependency(dep) });
8
+ this.getterDependencies = new Set();
9
+ this.value = getter({ get: dep => this.addGetDependency(dep) });
9
10
  }
10
- addDependency(dependency) {
11
- if (!this.dependencies.has(dependency)) {
11
+ addGetDependency(dependency) {
12
+ if (!this.getterDependencies.has(dependency)) {
12
13
  dependency.subscribe(() => this.deriveUpdate());
13
- this.dependencies.add(dependency);
14
+ this.getterDependencies.add(dependency);
14
15
  }
15
16
  return dependency.get();
16
17
  }
17
18
  deriveUpdate() {
18
- this.update(this.derivation({ get: dep => this.addDependency(dep) }));
19
+ this.update(this.getter({ get: dep => this.addGetDependency(dep) }));
20
+ }
21
+ }
22
+ export class SettableDerive extends Derive {
23
+ constructor(getter, setter) {
24
+ super(getter);
25
+ this.setter = setter;
26
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
27
+ this.setterDependencies = new Set();
28
+ setter({
29
+ value: this.get(),
30
+ set: dep => this.addSetDependency(dep),
31
+ });
32
+ if (!this.compareDependencies()) {
33
+ throw new Error(consoleMessage("The set and get dependencies of a derived atom do not match."));
34
+ }
35
+ }
36
+ /** Set the value of the derived atom.
37
+ *
38
+ * @param next New value or function to create the
39
+ * new value based off the previous value.
40
+ */
41
+ set(next) {
42
+ const value = next instanceof Function ? next(this.get()) : next;
43
+ this.setter({
44
+ value,
45
+ set: (atom, next) => {
46
+ const value = next instanceof Function ? next(atom.get()) : next;
47
+ atom.set(value);
48
+ },
49
+ });
50
+ }
51
+ addSetDependency(dependency) {
52
+ if (!this.setterDependencies.has(dependency)) {
53
+ this.setterDependencies.add(dependency);
54
+ }
55
+ }
56
+ compareDependencies() {
57
+ const { getterDependencies, setterDependencies } = this;
58
+ if (getterDependencies.size !== setterDependencies.size) {
59
+ return false;
60
+ }
61
+ return Array.from(setterDependencies).every(dependency => getterDependencies.has(dependency));
62
+ }
63
+ }
64
+ export function derive(getter, setter) {
65
+ if (setter) {
66
+ return new SettableDerive(getter, setter);
67
+ }
68
+ else {
69
+ return new Derive(getter);
19
70
  }
20
71
  }
21
- /** Creates a value, derived from one or more atoms or other derived values.
22
- *
23
- * @param get Function to derive the new value.
24
- *
25
- * @returns A derived instance.
26
- **/
27
- export const derive = (get) => new Derive(get);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yaasl/core",
3
- "version": "0.8.0-alpha.0",
3
+ "version": "0.8.0-alpha.1",
4
4
  "description": "yet another atomic store library (vanilla-js)",
5
5
  "author": "PrettyCoffee",
6
6
  "license": "MIT",
@@ -38,7 +38,7 @@
38
38
  "validate": "run-s lint test build"
39
39
  },
40
40
  "dependencies": {
41
- "@yaasl/utils": "0.8.0-alpha.0"
41
+ "@yaasl/utils": "0.8.0-alpha.1"
42
42
  },
43
43
  "eslintConfig": {
44
44
  "extends": [