@yaasl/core 0.9.0 → 0.9.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.
@@ -1,6 +1,7 @@
1
1
  type Callback<Value> = (value: Value, previous: Value) => void;
2
2
  export declare class Stateful<Value = unknown> {
3
3
  protected value: Value;
4
+ /** Promise that resolves when the states initialization was finished. */
4
5
  didInit: PromiseLike<void> | boolean;
5
6
  private listeners;
6
7
  constructor(value: Value);
@@ -2,7 +2,7 @@ import { SetStateAction } from "@yaasl/utils";
2
2
  import { Actions, Reducers } from "./createActions";
3
3
  import { Stateful } from "./Stateful";
4
4
  import { EffectAtomCallback } from "../effects/createEffect";
5
- export interface AtomConfig<Value, R extends Reducers<Value> = {}> {
5
+ export interface AtomConfig<Value, R extends Reducers<Value> = Reducers<Value>> {
6
6
  /** Value that will be used initially. */
7
7
  defaultValue: Value;
8
8
  /** Name of the atom. Must be unique among all atoms. Defaults to "atom-{number}". */
@@ -12,9 +12,12 @@ export interface AtomConfig<Value, R extends Reducers<Value> = {}> {
12
12
  /** Reducers for custom actions to set the atom's value. */
13
13
  reducers?: R;
14
14
  }
15
- export declare class Atom<Value = unknown, R extends Reducers<Value> = {}> extends Stateful<Value> {
15
+ export declare class Atom<Value = unknown, R extends Reducers<Value> = Reducers<Value>> extends Stateful<Value> {
16
+ /** Default value of the atom. */
16
17
  readonly defaultValue: Value;
18
+ /** Identifier of the atom. */
17
19
  readonly name: string;
20
+ /** Actions that can be used to set the atom's value. */
18
21
  readonly actions: Actions<Value, R>;
19
22
  constructor({ defaultValue, name, effects, reducers, }: AtomConfig<Value, R>);
20
23
  /** Set the value of the atom.
@@ -32,11 +35,5 @@ export declare class Atom<Value = unknown, R extends Reducers<Value> = {}> exten
32
35
  * @param config.reducers Reducers for custom actions to set the atom's value.
33
36
  *
34
37
  * @returns An atom instance.
35
- * - `result.get`: Read the value of state.
36
- * - `result.subscribe`: Subscribe to value changes.
37
- * - `result.set`: Set the value of the atom.
38
- * - `result.actions`: All actions that were created with reducers.
39
- * - `result.didInit`: State of the atom's effects initialization process.
40
- * Will be a promise if the initialization is pending and `true` if finished.
41
38
  **/
42
- export declare const createAtom: <Value, R extends Reducers<Value> = {}>(config: AtomConfig<Value, R>) => Atom<Value, R>;
39
+ export declare const createAtom: <Value, R extends Reducers<Value> = Reducers<Value>>(config: AtomConfig<Value, R>) => Atom<Value, R>;
@@ -17,7 +17,7 @@ export declare class Derive<Value> extends Stateful<Value> {
17
17
  }
18
18
  export declare class SettableDerive<Value = unknown> extends Derive<Value> {
19
19
  private readonly setter;
20
- protected readonly setterDependencies: Set<Atom<any, {}> | SettableDerive<any>>;
20
+ protected readonly setterDependencies: Set<Atom<any, import("./createActions").Reducers<any>> | SettableDerive<any>>;
21
21
  constructor(getter: GetterFn<Value>, setter: SetterFn<Value>);
22
22
  /** Set the value of the derived atom.
23
23
  *
@@ -1,20 +1,33 @@
1
1
  import { Stateful } from "./Stateful";
2
- type Selectable = Record<string | number, unknown>;
3
- type DeepKeys<T> = T extends object ? {
4
- [K in keyof T]: `${Exclude<K, symbol>}${"" | `.${DeepKeys<T[K]>}`}`;
5
- }[keyof T] : never;
6
- type DeepValue<T, Path> = T extends Record<string | number, unknown> ? Path extends `${infer Current}.${infer Next}` ? DeepValue<T[Current], Next> : T[Path & string] : never;
7
- export declare class Selector<Path extends DeepKeys<State>, State extends Selectable> extends Stateful<DeepValue<State, Path>> {
8
- protected readonly parent: Stateful<State>;
9
- protected readonly path: Path;
10
- constructor(parent: Stateful<State>, path: Path);
2
+ type PathableState = Record<string | number, unknown>;
3
+ type DeepKeys<State> = State extends PathableState ? {
4
+ [K in keyof State]: `${Exclude<K, symbol>}${"" | `.${DeepKeys<State[K]>}`}`;
5
+ }[keyof State] : never;
6
+ type DeepValue<State, Path> = State extends PathableState ? Path extends `${infer Current}.${infer Next}` ? DeepValue<State[Current], Next> : State[Path & string] : never;
7
+ export declare class PathSelector<State, Path extends DeepKeys<State>> extends Stateful<DeepValue<State, Path>> {
8
+ constructor(atom: Stateful<State>, path: Path);
11
9
  }
12
- /** Creates a value, selected from any stateful value.
13
- *
14
- * @param parent The parent element to select a value from. The internal state must be an object.
15
- * @param path The path to the value you want to select.
16
- *
17
- * @returns A selector instance.
18
- **/
19
- export declare const createSelector: <Path extends DeepKeys<State>, State extends Selectable>(parent: Stateful<State>, path: Path) => Selector<Path, State>;
10
+ type InferValuesFromAtoms<Atoms extends readonly unknown[], States extends unknown[] = []> = Atoms extends [Stateful<infer Value>, ...infer Rest] ? InferValuesFromAtoms<Rest, [...States, Value]> : States;
11
+ export declare class CombinerSelector<State, Atoms extends [Stateful<any>, ...Stateful<any>[]]> extends Stateful<State> {
12
+ constructor(atoms: Atoms, combiner: (...res: InferValuesFromAtoms<Atoms>) => State);
13
+ }
14
+ interface CreateSelectorOverloads {
15
+ /** Creates a value, selected from one atom with an object value by using a key path.
16
+ *
17
+ * @param atom The atom to select a value from. The internal state must be an object.
18
+ * @param path The path to the value you want to select.
19
+ *
20
+ * @returns A PathSelector instance.
21
+ **/
22
+ <State, Path extends DeepKeys<State>>(atom: Stateful<State>, path: Path): PathSelector<State, Path>;
23
+ /** Creates a value, selected from one atom with an object value by using a key path.
24
+ *
25
+ * @param atoms Atoms you need to combine to receive the new value.
26
+ * @param combiner Combiner function to use the atom values and create a new value.
27
+ *
28
+ * @returns A CombinerSelector instance.
29
+ **/
30
+ <Atoms extends [Stateful<any>, ...Stateful<any>[]], CombinedState>(states: Atoms, combiner: (...res: InferValuesFromAtoms<Atoms>) => CombinedState): CombinerSelector<CombinedState, Atoms>;
31
+ }
32
+ export declare const createSelector: CreateSelectorOverloads;
20
33
  export {};
@@ -1,5 +1,5 @@
1
+ export * from "./config";
1
2
  export * from "./createAtom";
2
3
  export * from "./createDerived";
3
- export * from "./config";
4
4
  export * from "./createSelector";
5
5
  export * from "./Stateful";
@@ -4,6 +4,7 @@ exports.Stateful = void 0;
4
4
  class Stateful {
5
5
  constructor(value) {
6
6
  this.value = value;
7
+ /** Promise that resolves when the states initialization was finished. */
7
8
  this.didInit = false;
8
9
  this.listeners = new Set();
9
10
  }
@@ -37,12 +37,6 @@ exports.Atom = Atom;
37
37
  * @param config.reducers Reducers for custom actions to set the atom's value.
38
38
  *
39
39
  * @returns An atom instance.
40
- * - `result.get`: Read the value of state.
41
- * - `result.subscribe`: Subscribe to value changes.
42
- * - `result.set`: Set the value of the atom.
43
- * - `result.actions`: All actions that were created with reducers.
44
- * - `result.didInit`: State of the atom's effects initialization process.
45
- * Will be a promise if the initialization is pending and `true` if finished.
46
40
  **/
47
41
  const createAtom = (config) => new Atom(config);
48
42
  exports.createAtom = createAtom;
@@ -1,26 +1,46 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createSelector = exports.Selector = void 0;
3
+ exports.createSelector = exports.CombinerSelector = exports.PathSelector = void 0;
4
+ const utils_1 = require("@yaasl/utils");
4
5
  const Stateful_1 = require("./Stateful");
5
- const selectValue = (state, path) => path
6
+ const selectPath = (state, path) => path
6
7
  .split(".")
7
8
  .reduce((result, key) => result[key], state);
8
- class Selector extends Stateful_1.Stateful {
9
- constructor(parent, path) {
10
- super(selectValue(parent.get(), path));
11
- this.parent = parent;
12
- this.path = path;
13
- parent.subscribe(state => this.update(selectValue(state, path)));
14
- this.setDidInit(parent.didInit);
9
+ class PathSelector extends Stateful_1.Stateful {
10
+ constructor(atom, path) {
11
+ super(selectPath(atom.get(), path));
12
+ atom.subscribe(state => this.update(selectPath(state, path)));
13
+ this.setDidInit(atom.didInit);
15
14
  }
16
15
  }
17
- exports.Selector = Selector;
18
- /** Creates a value, selected from any stateful value.
19
- *
20
- * @param parent The parent element to select a value from. The internal state must be an object.
21
- * @param path The path to the value you want to select.
22
- *
23
- * @returns A selector instance.
24
- **/
25
- const createSelector = (parent, path) => new Selector(parent, path);
16
+ exports.PathSelector = PathSelector;
17
+ // -- Combiner selector
18
+ const allDidInit = (atoms) => {
19
+ const inits = atoms
20
+ .map(atom => atom.didInit)
21
+ .filter((didInit) => typeof didInit !== "boolean");
22
+ return inits.length === 0 ? true : Promise.all(inits).then(utils_1.toVoid);
23
+ };
24
+ class CombinerSelector extends Stateful_1.Stateful {
25
+ constructor(atoms, combiner) {
26
+ const selectState = () => {
27
+ const values = atoms.map(atom => atom.get());
28
+ return combiner(...values);
29
+ };
30
+ super(selectState());
31
+ atoms.forEach(atom => atom.subscribe(() => this.update(selectState())));
32
+ this.setDidInit(allDidInit(atoms));
33
+ }
34
+ }
35
+ exports.CombinerSelector = CombinerSelector;
36
+ const createSelector = (atoms, selector) => {
37
+ if (atoms instanceof Stateful_1.Stateful && typeof selector === "string") {
38
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
39
+ return new PathSelector(atoms, selector);
40
+ }
41
+ if (Array.isArray(atoms) && typeof selector === "function") {
42
+ return new CombinerSelector(atoms, selector);
43
+ }
44
+ throw new Error("Selector args do not match any overload");
45
+ };
26
46
  exports.createSelector = createSelector;
@@ -14,8 +14,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./config"), exports);
17
18
  __exportStar(require("./createAtom"), exports);
18
19
  __exportStar(require("./createDerived"), exports);
19
- __exportStar(require("./config"), exports);
20
20
  __exportStar(require("./createSelector"), exports);
21
21
  __exportStar(require("./Stateful"), exports);
@@ -1,6 +1,7 @@
1
1
  export class Stateful {
2
2
  constructor(value) {
3
3
  this.value = value;
4
+ /** Promise that resolves when the states initialization was finished. */
4
5
  this.didInit = false;
5
6
  this.listeners = new Set();
6
7
  }
@@ -33,11 +33,5 @@ export class Atom extends Stateful {
33
33
  * @param config.reducers Reducers for custom actions to set the atom's value.
34
34
  *
35
35
  * @returns An atom instance.
36
- * - `result.get`: Read the value of state.
37
- * - `result.subscribe`: Subscribe to value changes.
38
- * - `result.set`: Set the value of the atom.
39
- * - `result.actions`: All actions that were created with reducers.
40
- * - `result.didInit`: State of the atom's effects initialization process.
41
- * Will be a promise if the initialization is pending and `true` if finished.
42
36
  **/
43
37
  export const createAtom = (config) => new Atom(config);
@@ -1,21 +1,40 @@
1
+ import { toVoid } from "@yaasl/utils";
1
2
  import { Stateful } from "./Stateful";
2
- const selectValue = (state, path) => path
3
+ const selectPath = (state, path) => path
3
4
  .split(".")
4
5
  .reduce((result, key) => result[key], state);
5
- export class Selector extends Stateful {
6
- constructor(parent, path) {
7
- super(selectValue(parent.get(), path));
8
- this.parent = parent;
9
- this.path = path;
10
- parent.subscribe(state => this.update(selectValue(state, path)));
11
- this.setDidInit(parent.didInit);
6
+ export class PathSelector extends Stateful {
7
+ constructor(atom, path) {
8
+ super(selectPath(atom.get(), path));
9
+ atom.subscribe(state => this.update(selectPath(state, path)));
10
+ this.setDidInit(atom.didInit);
12
11
  }
13
12
  }
14
- /** Creates a value, selected from any stateful value.
15
- *
16
- * @param parent The parent element to select a value from. The internal state must be an object.
17
- * @param path The path to the value you want to select.
18
- *
19
- * @returns A selector instance.
20
- **/
21
- export const createSelector = (parent, path) => new Selector(parent, path);
13
+ // -- Combiner selector
14
+ const allDidInit = (atoms) => {
15
+ const inits = atoms
16
+ .map(atom => atom.didInit)
17
+ .filter((didInit) => typeof didInit !== "boolean");
18
+ return inits.length === 0 ? true : Promise.all(inits).then(toVoid);
19
+ };
20
+ export class CombinerSelector extends Stateful {
21
+ constructor(atoms, combiner) {
22
+ const selectState = () => {
23
+ const values = atoms.map(atom => atom.get());
24
+ return combiner(...values);
25
+ };
26
+ super(selectState());
27
+ atoms.forEach(atom => atom.subscribe(() => this.update(selectState())));
28
+ this.setDidInit(allDidInit(atoms));
29
+ }
30
+ }
31
+ export const createSelector = (atoms, selector) => {
32
+ if (atoms instanceof Stateful && typeof selector === "string") {
33
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
34
+ return new PathSelector(atoms, selector);
35
+ }
36
+ if (Array.isArray(atoms) && typeof selector === "function") {
37
+ return new CombinerSelector(atoms, selector);
38
+ }
39
+ throw new Error("Selector args do not match any overload");
40
+ };
@@ -1,5 +1,5 @@
1
+ export * from "./config";
1
2
  export * from "./createAtom";
2
3
  export * from "./createDerived";
3
- export * from "./config";
4
4
  export * from "./createSelector";
5
5
  export * from "./Stateful";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yaasl/core",
3
- "version": "0.9.0",
3
+ "version": "0.9.2",
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.9.0"
41
+ "@yaasl/utils": "0.9.2"
42
42
  },
43
43
  "eslintConfig": {
44
44
  "extends": [