Skip to content

Commit 307a26c

Browse files
committed
move out applyEdit
1 parent 09ef6f1 commit 307a26c

File tree

2 files changed

+214
-206
lines changed

2 files changed

+214
-206
lines changed
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
import type {
2+
DataModelCollection,
3+
Edit,
4+
Relationship,
5+
StaticModel,
6+
} from '../services/data-model-storage';
7+
import { updateSchema } from '../utils/schema-traversal';
8+
import {
9+
isRelationshipInvolvingField,
10+
isSameFieldOrAncestor,
11+
} from '../utils/utils';
12+
13+
function renameFieldInRelationshipSide(
14+
side: Relationship['relationship'][0],
15+
edit: Extract<Edit, { type: 'RenameField' }>
16+
): Relationship['relationship'][0] {
17+
if (
18+
side.ns !== edit.ns ||
19+
!side.fields ||
20+
!isSameFieldOrAncestor(edit.field, side.fields)
21+
) {
22+
return side;
23+
}
24+
return {
25+
...side,
26+
fields: [
27+
...side.fields.slice(0, edit.field.length - 1),
28+
edit.newName,
29+
...side.fields.slice(edit.field.length),
30+
],
31+
};
32+
}
33+
34+
export function applyEdit(edit: Edit, model?: StaticModel): StaticModel {
35+
if (edit.type === 'SetModel') {
36+
return edit.model;
37+
}
38+
if (!model) {
39+
throw new Error('Editing a model that has not been initialized');
40+
}
41+
switch (edit.type) {
42+
case 'AddCollection': {
43+
const newCollection: DataModelCollection = {
44+
ns: edit.ns,
45+
jsonSchema: edit.initialSchema,
46+
displayPosition: edit.position,
47+
indexes: [],
48+
};
49+
return {
50+
...model,
51+
collections: [...model.collections, newCollection],
52+
};
53+
}
54+
case 'AddRelationship': {
55+
return {
56+
...model,
57+
relationships: [...model.relationships, edit.relationship],
58+
};
59+
}
60+
case 'RemoveRelationship': {
61+
return {
62+
...model,
63+
relationships: model.relationships.filter(
64+
(relationship) => relationship.id !== edit.relationshipId
65+
),
66+
};
67+
}
68+
case 'UpdateRelationship': {
69+
const existingRelationship = model.relationships.find((r) => {
70+
return r.id === edit.relationship.id;
71+
});
72+
if (!existingRelationship) {
73+
throw new Error('Can not update non-existent relationship');
74+
}
75+
return {
76+
...model,
77+
relationships: model.relationships.map((r) => {
78+
return r === existingRelationship ? edit.relationship : r;
79+
}),
80+
};
81+
}
82+
case 'MoveCollection': {
83+
return {
84+
...model,
85+
collections: model.collections.map((collection) => {
86+
if (collection.ns === edit.ns) {
87+
return {
88+
...collection,
89+
displayPosition: edit.newPosition,
90+
};
91+
}
92+
return collection;
93+
}),
94+
};
95+
}
96+
case 'RemoveCollection': {
97+
return {
98+
...model,
99+
// Remove any relationships involving the collection being removed.
100+
relationships: model.relationships.filter((r) => {
101+
return !(
102+
r.relationship[0].ns === edit.ns || r.relationship[1].ns === edit.ns
103+
);
104+
}),
105+
collections: model.collections.filter(
106+
(collection) => collection.ns !== edit.ns
107+
),
108+
};
109+
}
110+
case 'RenameCollection': {
111+
return {
112+
...model,
113+
// Update relationships to point to the renamed namespace.
114+
relationships: model.relationships.map((relationship) => {
115+
const [local, foreign] = relationship.relationship;
116+
117+
return {
118+
...relationship,
119+
relationship: [
120+
{
121+
...local,
122+
ns: local.ns === edit.fromNS ? edit.toNS : local.ns,
123+
},
124+
{
125+
...foreign,
126+
ns: foreign.ns === edit.fromNS ? edit.toNS : foreign.ns,
127+
},
128+
],
129+
};
130+
}),
131+
collections: model.collections.map((collection) => ({
132+
...collection,
133+
// Rename the collection.
134+
ns: collection.ns === edit.fromNS ? edit.toNS : collection.ns,
135+
})),
136+
};
137+
}
138+
case 'UpdateCollectionNote': {
139+
return {
140+
...model,
141+
collections: model.collections.map((collection) => {
142+
if (collection.ns === edit.ns) {
143+
return {
144+
...collection,
145+
note: edit.note,
146+
};
147+
}
148+
return collection;
149+
}),
150+
};
151+
}
152+
case 'RemoveField': {
153+
return {
154+
...model,
155+
// Remove any relationships involving the field being removed.
156+
relationships: model.relationships.filter(({ relationship }) => {
157+
return !isRelationshipInvolvingField(
158+
relationship,
159+
edit.ns,
160+
edit.field
161+
);
162+
}),
163+
collections: model.collections.map((collection) => {
164+
if (collection.ns !== edit.ns) return collection;
165+
return {
166+
...collection,
167+
jsonSchema: updateSchema({
168+
jsonSchema: collection.jsonSchema,
169+
fieldPath: edit.field,
170+
update: 'removeField',
171+
}),
172+
};
173+
}),
174+
};
175+
}
176+
case 'RenameField': {
177+
return {
178+
...model,
179+
// Update any relationships involving the field being renamed.
180+
relationships: model.relationships.map((r) => {
181+
if (
182+
!isRelationshipInvolvingField(r.relationship, edit.ns, edit.field)
183+
) {
184+
return r;
185+
}
186+
return {
187+
...r,
188+
relationship: [
189+
renameFieldInRelationshipSide(r.relationship[0], edit),
190+
renameFieldInRelationshipSide(r.relationship[1], edit),
191+
] as const,
192+
};
193+
}),
194+
collections: model.collections.map((collection) => {
195+
if (collection.ns !== edit.ns) return collection;
196+
return {
197+
...collection,
198+
jsonSchema: updateSchema({
199+
jsonSchema: collection.jsonSchema,
200+
fieldPath: edit.field,
201+
update: 'renameField',
202+
newFieldName: edit.newName,
203+
}),
204+
};
205+
}),
206+
};
207+
}
208+
default: {
209+
return model;
210+
}
211+
}
212+
}

0 commit comments

Comments
 (0)