Skip to content

Commit 047331f

Browse files
committed
enhance(in-progress): Store result in own object
1 parent ea0a4dc commit 047331f

File tree

2 files changed

+115
-73
lines changed

2 files changed

+115
-73
lines changed

packages/normalizr/src/normalize/NormalizeDelegate.ts

Lines changed: 110 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -7,39 +7,39 @@ import type {
77
import { getCheckLoop } from './getCheckLoop.js';
88
import { POJODelegate } from '../delegate/Delegate.js';
99
import { INVALID } from '../denormalize/symbol.js';
10-
import { NormalizedSchema } from '../types.js';
10+
import type { NormalizedSchema } from '../types.js';
1111

1212
/** Full normalize() logic for POJO state */
1313
export class NormalizeDelegate
1414
extends POJODelegate
15-
implements INormalizeDelegate, NormalizedSchema<EntityTable, any>
15+
implements INormalizeDelegate
1616
{
17-
// declare readonly normalized: NormalizedSchema<E, R>;
18-
declare result: any;
19-
declare readonly entities: EntityTable;
20-
declare readonly indexes: {
21-
[entityKey: string]: {
22-
[indexName: string]: { [lookup: string]: string };
23-
};
24-
};
17+
declare readonly result: Normalized;
18+
// declare result: any;
19+
// declare readonly entities: EntityTable;
20+
// declare readonly indexes: {
21+
// [entityKey: string]: {
22+
// [indexName: string]: { [lookup: string]: string };
23+
// };
24+
// };
2525

26-
declare readonly entitiesMeta: {
27-
[entityKey: string]: {
28-
[pk: string]: {
29-
date: number;
30-
expiresAt: number;
31-
fetchedAt: number;
32-
};
33-
};
34-
};
26+
// declare readonly entitiesMeta: {
27+
// [entityKey: string]: {
28+
// [pk: string]: {
29+
// date: number;
30+
// expiresAt: number;
31+
// fetchedAt: number;
32+
// };
33+
// };
34+
// };
3535

3636
declare readonly meta: { fetchedAt: number; date: number; expiresAt: number };
3737
declare checkLoop: (entityKey: string, pk: string, input: object) => boolean;
3838

39-
protected new = {
40-
entities: new Map<string, Map<string, any>>(),
41-
indexes: new Map<string, Map<string, any>>(),
42-
};
39+
// protected new = {
40+
// entities: new Map<string, Map<string, any>>(),
41+
// indexes: new Map<string, Map<string, any>>(),
42+
// };
4343

4444
constructor(
4545
state: {
@@ -58,47 +58,11 @@ export class NormalizeDelegate
5858
actionMeta: { fetchedAt: number; date: number; expiresAt: number },
5959
) {
6060
super(state);
61-
// this.normalized = NormalizedSchema<E, R> = {
62-
// result: '' as any,
63-
// entities: { ...state.entities },
64-
// indexes: { ...state.indexes },
65-
// entitiesMeta: { ...state.entitiesMeta },
66-
// };
67-
this.entities = { ...state.entities };
68-
this.indexes = { ...state.indexes };
69-
this.entitiesMeta = { ...state.entitiesMeta };
61+
this.result = new Normalized(state);
7062
this.meta = actionMeta;
7163
this.checkLoop = getCheckLoop();
7264
}
7365

74-
protected getNewEntity(key: string, pk: string) {
75-
return this.getNewEntities(key).get(pk);
76-
}
77-
78-
protected getNewEntities(key: string): Map<string, any> {
79-
// first time we come across this type of entity
80-
if (!this.new.entities.has(key)) {
81-
this.new.entities.set(key, new Map());
82-
// we will be editing these, so we need to clone them first
83-
this.entities[key] = {
84-
...this.entities[key],
85-
};
86-
this.entitiesMeta[key] = {
87-
...this.entitiesMeta[key],
88-
};
89-
}
90-
91-
return this.new.entities.get(key) as Map<string, any>;
92-
}
93-
94-
protected getNewIndexes(key: string): Map<string, any> {
95-
if (!this.new.indexes.has(key)) {
96-
this.new.indexes.set(key, new Map());
97-
this.indexes[key] = { ...this.indexes[key] };
98-
}
99-
return this.new.indexes.get(key) as Map<string, any>;
100-
}
101-
10266
/** Updates an entity using merge lifecycles when it has previously been set */
10367
mergeEntity(
10468
schema: Mergeable & { indexes?: any },
@@ -112,7 +76,7 @@ export class NormalizeDelegate
11276
let nextMeta = this.meta;
11377

11478
// if we already processed this entity during this normalization (in another nested place)
115-
let entity = this.getNewEntity(key, pk);
79+
let entity = this.result.getEntity(key, pk);
11680
if (entity) {
11781
nextEntity = schema.merge(entity, incomingEntity);
11882
} else {
@@ -147,7 +111,7 @@ export class NormalizeDelegate
147111
meta: { fetchedAt: number; date: number; expiresAt: number } = this.meta,
148112
) {
149113
const key = schema.key;
150-
const newEntities = this.getNewEntities(key);
114+
const newEntities = this.result.getEntities(key);
151115
const updateMeta = !newEntities.has(pk);
152116
newEntities.set(pk, entity);
153117

@@ -156,17 +120,17 @@ export class NormalizeDelegate
156120
handleIndexes(
157121
pk,
158122
schema.indexes,
159-
this.getNewIndexes(key),
160-
this.indexes[key],
123+
this.result.getIndexes(key),
124+
this.clone.indexes[key],
161125
entity,
162-
this.entities[key] as any,
126+
this.clone.entities[key] as any,
163127
);
164128
}
165129

166130
// set this after index updates so we know what indexes to remove from
167-
this._setEntity(key, pk, entity);
131+
this.result.setEntity(key, pk, entity);
168132

169-
if (updateMeta) this._setMeta(key, pk, meta);
133+
if (updateMeta) this.result.setMeta(key, pk, meta);
170134
}
171135

172136
/** Invalidates an entity, potentially triggering suspense */
@@ -175,20 +139,95 @@ export class NormalizeDelegate
175139
this.setEntity(schema, pk, INVALID);
176140
}
177141

178-
protected _setEntity(key: string, pk: string, entity: any) {
142+
getMeta(key: string, pk: string) {
143+
return this.result.entitiesMeta[key][pk];
144+
}
145+
}
146+
147+
class Normalized implements NormalizedSchema<EntityTable, any> {
148+
result: any = '';
149+
declare readonly entities: EntityTable;
150+
declare readonly indexes: {
151+
[entityKey: string]: {
152+
[indexName: string]: { [lookup: string]: string };
153+
};
154+
};
155+
156+
declare readonly entitiesMeta: {
157+
[entityKey: string]: {
158+
[pk: string]: {
159+
date: number;
160+
expiresAt: number;
161+
fetchedAt: number;
162+
};
163+
};
164+
};
165+
166+
protected new = {
167+
entities: new Map<string, Map<string, any>>(),
168+
indexes: new Map<string, Map<string, any>>(),
169+
};
170+
171+
constructor({
172+
entities,
173+
indexes,
174+
entitiesMeta,
175+
}: {
176+
entities: EntityTable;
177+
indexes: NormalizedIndex;
178+
entitiesMeta: {
179+
[entityKey: string]: {
180+
[pk: string]: {
181+
date: number;
182+
expiresAt: number;
183+
fetchedAt: number;
184+
};
185+
};
186+
};
187+
}) {
188+
this.entities = { ...entities };
189+
this.indexes = { ...indexes };
190+
this.entitiesMeta = { ...entitiesMeta };
191+
}
192+
193+
setEntity(key: string, pk: string, entity: any) {
179194
(this.entities[key] as any)[pk] = entity;
180195
}
181196

182-
protected _setMeta(
197+
setMeta(
183198
key: string,
184199
pk: string,
185200
meta: { fetchedAt: number; date: number; expiresAt: number },
186201
) {
187202
this.entitiesMeta[key][pk] = meta;
188203
}
189204

190-
getMeta(key: string, pk: string) {
191-
return this.entitiesMeta[key][pk];
205+
getEntity(key: string, pk: string) {
206+
return this.getEntities(key).get(pk);
207+
}
208+
209+
getEntities(key: string): Map<string, any> {
210+
// first time we come across this type of entity
211+
if (!this.new.entities.has(key)) {
212+
this.new.entities.set(key, new Map());
213+
// we will be editing these, so we need to clone them first
214+
this.entities[key] = {
215+
...this.entities[key],
216+
};
217+
this.entitiesMeta[key] = {
218+
...this.entitiesMeta[key],
219+
};
220+
}
221+
222+
return this.new.entities.get(key) as Map<string, any>;
223+
}
224+
225+
getIndexes(key: string): Map<string, any> {
226+
if (!this.new.indexes.has(key)) {
227+
this.new.indexes.set(key, new Map());
228+
this.indexes[key] = { ...this.indexes[key] };
229+
}
230+
return this.new.indexes.get(key) as Map<string, any>;
192231
}
193232
}
194233

packages/normalizr/src/normalize/normalize.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,16 @@ See https://dataclient.io/rest/api/RestEndpoint#parseResponse for more informati
7979
}
8080
}
8181

82+
// using cloned or original should not matter as merge checks against a Set to determine whether to merge or not
83+
// however, we should still write a test to specifially test merge detection
84+
// TODO: we need a test to validate that getEntities uses the old version of state and not the cloned one
8285
const delegate = new NormalizeDelegate(
8386
{ entities, indexes, entitiesMeta },
8487
meta,
8588
);
8689
const visit = getVisit(delegate);
87-
delegate.result = visit(schema, input, input, undefined, args);
88-
return delegate as any;
90+
delegate.result.result = visit(schema, input, input, undefined, args);
91+
return delegate.result as any as NormalizedSchema<E, R>;
8992
};
9093

9194
function expectedSchemaType(schema: Schema) {

0 commit comments

Comments
 (0)