Skip to content

Commit

Permalink
Добавил метод merge
Browse files Browse the repository at this point in the history
  • Loading branch information
LeMarck committed Nov 25, 2024
1 parent 115f79a commit aca8f4d
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 52 deletions.
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export * from "./event";
export * from "./effect";
export * from "./event";
export * from "./methods";
export * from "./store";
export * from "./utils";
export * from "./types.h";
35 changes: 35 additions & 0 deletions src/methods.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { createStore } from "./store";
import { combine, merge } from "./methods";
import { createEvent } from "./event";

describe("methods", () => {
it("should be create combine store", () => {
const $balance = createStore(0);
const $username = createStore("zerobias");
const watcherMock = jest.fn();

const $greeting = combine(
$balance,
$username,
(balance, username) => `Hello, ${username}. Your balance is ${balance}`,
);

$greeting.watch(watcherMock);
expect(watcherMock).toHaveBeenCalledWith("Hello, zerobias. Your balance is 0");
});

it("should be create new event that triggers upon any of the given units being triggered", () => {
const watcherMock = jest.fn();
const foo = createEvent<number>();
const bar = createEvent<number>();
const baz = merge(foo, bar);

baz.watch(watcherMock);

foo(10);
expect(watcherMock).toHaveBeenCalledWith(10);

baz(42);
expect(watcherMock).toHaveBeenCalledWith(42);
});
});
33 changes: 33 additions & 0 deletions src/methods.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { createEvent, type Event } from "./event";
import { createStore, type Store } from "./store";
import type { Unit } from "./types.h";

type States<S extends Store<unknown>[]> = {
[Key in keyof S]: S[Key] extends Store<infer U> ? U : never;
};

type CombineFn<S extends Store<unknown>[], NewStore> = (...states: States<S>) => NewStore;

export function combine<S extends Store<unknown>[], NewStore>(
...args: [...S, CombineFn<S, NewStore>]
): Store<NewStore> {
const stores = args.slice(0, -1) as S;
const fn = args[args.length - 1] as CombineFn<S, NewStore>;

const getStoreState = () => fn(...(stores.map((store) => store.getState()) as States<S>));

const updateStore = createEvent();
const newStore = createStore<NewStore>(getStoreState()).on(updateStore, () => getStoreState());

stores.forEach((store) => store.watch(() => updateStore()));

return newStore;
}

export function merge<T>(...units: Unit<T>[]): Event<T> {
const event = createEvent<T>();

units.forEach((unit) => unit.watch(event));

return event;
}
15 changes: 6 additions & 9 deletions src/store.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import type { Effect } from "./effect";
import { createEvent, type Event } from "./event";
import type { Unsubscribe } from "./types.h";

type Unit<T> = Effect<T, unknown> | Event<T> | Store<T>;
import { createEvent } from "./event";
import type { Unit, Unsubscribe } from "./types.h";

export interface Store<State> {
map<NewState>(fn: (state: State, lastState?: NewState) => NewState): Store<NewState>;
Expand All @@ -25,7 +22,7 @@ export interface Store<State> {

export function createStore<State>(defaultState: State): Store<State> {
const watchers: Set<(state: State) => void> = new Set();
const subscribers: Map<Unit<unknown>, () => void> = new Map();
const subscribers: Map<Unit<unknown>, Unsubscribe> = new Map();
const initialState = { ...{ defaultState } };

let state = defaultState;
Expand Down Expand Up @@ -54,10 +51,10 @@ export function createStore<State>(defaultState: State): Store<State> {
return $store;
},
off<Payload>(trigger: Unit<Payload>): void {
const subscriber = subscribers.get(trigger as Unit<unknown>);
const unsubscribe = subscribers.get(trigger as Unit<unknown>);

if (subscriber) {
subscriber();
if (unsubscribe) {
unsubscribe();
subscribers.delete(trigger as Unit<unknown>);
}
},
Expand Down
6 changes: 6 additions & 0 deletions src/types.h.ts
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
import type { Effect } from "./effect";
import type { Event } from "./event";
import type { Store } from "./store";

export type Unsubscribe = () => void;

export type Unit<T> = Effect<T, unknown> | Event<T> | Store<T>;
19 changes: 0 additions & 19 deletions src/utils.test.ts

This file was deleted.

22 changes: 0 additions & 22 deletions src/utils.ts

This file was deleted.

0 comments on commit aca8f4d

Please sign in to comment.