Skip to content

Commit 4990ea0

Browse files
committed
feat(signal): improve signal usage
1 parent 84c00d8 commit 4990ea0

File tree

3 files changed

+84
-70
lines changed

3 files changed

+84
-70
lines changed

src/context/dataContext.ts

Lines changed: 0 additions & 24 deletions
This file was deleted.

src/index.test.tsx

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,20 @@ describe("api", () => {
1010
this.payload = { id };
1111
}
1212
}
13-
const entity = createEntity<
14-
{ id: number; value: number },
15-
{ id: number },
16-
Increment
17-
>(() => ({
18-
mount: ({ parameter }) => ({ id: parameter.id, value: parameter.id }),
19-
reduce: ({ state, command, parameter }) => {
20-
if (
21-
command instanceof Increment &&
22-
command.payload.id === parameter.id
23-
) {
24-
return { id: state.id, value: state.value + 1 };
25-
}
26-
return state;
27-
},
28-
}));
13+
const entity = createEntity<{ id: number; value: number }, { id: number }>(
14+
() => ({
15+
mount: ({ parameter }) => ({ id: parameter.id, value: parameter.id }),
16+
reduce: ({ state, command, parameter }) => {
17+
if (
18+
command instanceof Increment &&
19+
command.payload.id === parameter.id
20+
) {
21+
return { id: state.id, value: state.value + 1 };
22+
}
23+
return state;
24+
},
25+
})
26+
);
2927

3028
const repository = createRepository();
3129
const branch = createBranch(repository);

src/index.ts

Lines changed: 70 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,44 @@
11
import type { ReadonlySignal, Signal } from "@preact/signals-core";
22
import { computed } from "@preact/signals-core";
33
import { signal } from "@preact/signals-core";
4-
import type { DataProvider, EntityHandler } from "./context/dataContext";
4+
5+
type EntityHandlerFactory<T, U> = () => EntityHandler<T, U>;
6+
7+
type EntityHandler<T, U> = {
8+
mount: (context: {
9+
parameter: U;
10+
state: T | null;
11+
merge: (events: unknown[]) => void;
12+
}) => T;
13+
reduce: (context: { command: unknown; parameter: U; state: T }) => T;
14+
};
15+
16+
type DataProvider = {
17+
getState: <T, U>(request: {
18+
entityHandler: EntityHandler<T, U>;
19+
parameter: U;
20+
// forceCacheRefresh: boolean;
21+
}) => Signal<T>;
22+
getEntityHandler: <T, U>(
23+
EntityHandlerFactory: EntityHandlerFactory<T, U>
24+
) => EntityHandler<T, U>;
25+
commands: unknown[];
26+
commit: (command: unknown[]) => void;
27+
merge: (command: unknown[]) => void;
28+
};
529

630
export function createRepository(): Signal<DataProvider> {
7-
const dataProviderState: {
8-
[entityHandlerIdentifier: symbol]: {
9-
[request: string]: { value: Signal<any>; index: number };
10-
};
11-
} = {};
31+
const dataProviderState = new Map<
32+
EntityHandler<any, any>,
33+
{ [request: string]: { value: Signal<any>; index: number } }
34+
>();
1235
const commands = signal([] as unknown[]);
1336

37+
const entityHandlers = new Map<
38+
EntityHandlerFactory<any, any>,
39+
EntityHandler<any, any>
40+
>();
41+
1442
const commit = (newCommands: unknown[]) => {
1543
commands.value = [...commands.value, ...newCommands];
1644
};
@@ -19,19 +47,27 @@ export function createRepository(): Signal<DataProvider> {
1947
throw new Error("not yet implemtend");
2048
};
2149

22-
const getState = <T, U, V>(request: {
23-
entityHandler: EntityHandler<T, U, V>;
24-
entityHandlerIdentifier: symbol;
50+
const getEntityHandler = function (
51+
entityHandlerFactory: EntityHandlerFactory<any, any>
52+
) {
53+
let entityHandler = entityHandlers.get(entityHandlerFactory);
54+
if (entityHandler === undefined) {
55+
entityHandler = entityHandlerFactory();
56+
entityHandlers.set(entityHandlerFactory, entityHandler);
57+
}
58+
return entityHandler;
59+
};
60+
61+
const getState = <T, U>(request: {
62+
entityHandler: EntityHandler<T, U>;
2563
parameter: U;
2664
// forceCacheRefresh: boolean;
2765
}): ReadonlySignal<T> => {
28-
let dataProviderStateValue =
29-
dataProviderState[request.entityHandlerIdentifier];
66+
let dataProviderStateValue = dataProviderState.get(request.entityHandler);
3067

3168
if (dataProviderStateValue === undefined) {
3269
dataProviderStateValue = {};
33-
dataProviderState[request.entityHandlerIdentifier] =
34-
dataProviderStateValue;
70+
dataProviderState.set(request.entityHandler, dataProviderStateValue);
3571
}
3672

3773
const serializedParameter = JSON.stringify(request.parameter); // @TODO improve serializer, stringify doesn always produce the same results in case of different orders
@@ -68,6 +104,7 @@ export function createRepository(): Signal<DataProvider> {
68104

69105
return computed(() => ({
70106
commands: commands.value,
107+
getEntityHandler,
71108
commit,
72109
merge,
73110
getState,
@@ -78,10 +115,12 @@ export function createBranch(
78115
dataProvider: Signal<DataProvider>
79116
): Signal<DataProvider> {
80117
const commands = signal([] as unknown[]);
118+
const getEntityHandler = dataProvider.value.getEntityHandler;
81119

82-
const dataProviderState: {
83-
[entityHandlerIdentifier: symbol]: { [request: string]: Signal<any> };
84-
} = {};
120+
const dataProviderState = new Map<
121+
EntityHandler<any, any>,
122+
{ [request: string]: Signal<any> }
123+
>();
85124

86125
const commit = (newCommands: unknown[]) => {
87126
commands.value = [...commands.value, ...newCommands];
@@ -91,19 +130,16 @@ export function createBranch(
91130
throw new Error("not yet implemtend");
92131
};
93132

94-
const getState = <T, U, V>(request: {
95-
entityHandler: EntityHandler<T, U, V>;
96-
entityHandlerIdentifier: symbol;
133+
const getState = <T, U>(request: {
134+
entityHandler: EntityHandler<T, U>;
97135
parameter: U;
98136
// forceCacheRefresh: boolean;
99137
}): ReadonlySignal<T> => {
100-
let dataProviderStateValue =
101-
dataProviderState[request.entityHandlerIdentifier];
138+
let dataProviderStateValue = dataProviderState.get(request.entityHandler);
102139

103140
if (dataProviderStateValue === undefined) {
104141
dataProviderStateValue = {};
105-
dataProviderState[request.entityHandlerIdentifier] =
106-
dataProviderStateValue;
142+
dataProviderState.set(request.entityHandler, dataProviderStateValue);
107143
}
108144

109145
const serializedParameter = JSON.stringify(request.parameter); // @TODO improve serializer, stringify doesn always produce the same results in case of different orders
@@ -126,25 +162,29 @@ export function createBranch(
126162

127163
return computed(() => ({
128164
commands: commands.value,
165+
getEntityHandler,
129166
commit,
130167
merge,
131168
getState,
132169
}));
133170
}
134171

135-
export function createEntity<T, U, V>(
136-
entityHandlerFactory: () => EntityHandler<T, U, V>
172+
export function createEntity<T, U>(
173+
entityHandlerFactory: () => EntityHandler<T, U>
137174
) {
138-
const entityHandler = entityHandlerFactory();
139-
const entityHandlerIdentifier = Symbol();
175+
return function (
176+
this: any,
177+
dataProvider: Signal<DataProvider>,
178+
parameter: U
179+
) {
180+
const entityHandler =
181+
dataProvider.value.getEntityHandler(entityHandlerFactory);
140182

141-
return (dataProvider: Signal<DataProvider>, parameter: U) => {
142183
return computed(
143184
() =>
144-
dataProvider.value.getState<T, U, V>({
185+
dataProvider.value.getState<T, U>({
145186
parameter,
146187
entityHandler,
147-
entityHandlerIdentifier,
148188
}).value
149189
);
150190
};

0 commit comments

Comments
 (0)