@yaasl/core 0.9.0 → 0.9.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.
@@ -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,7 +12,7 @@ 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
16
  readonly defaultValue: Value;
17
17
  readonly name: string;
18
18
  readonly actions: Actions<Value, R>;
@@ -39,4 +39,4 @@ export declare class Atom<Value = unknown, R extends Reducers<Value> = {}> exten
39
39
  * - `result.didInit`: State of the atom's effects initialization process.
40
40
  * Will be a promise if the initialization is pending and `true` if finished.
41
41
  **/
42
- export declare const createAtom: <Value, R extends Reducers<Value> = {}>(config: AtomConfig<Value, R>) => Atom<Value, R>;
42
+ 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";
@@ -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,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.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.9.0"
41
+ "@yaasl/utils": "0.9.1"
42
42
  },
43
43
  "eslintConfig": {
44
44
  "extends": [