Skip to content

Commit bc55180

Browse files
committed
Refactor code structure and improve type annotations
1 parent df44e9c commit bc55180

File tree

1 file changed

+128
-97
lines changed

1 file changed

+128
-97
lines changed

src/index.ts

Lines changed: 128 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,18 @@ import { computed, isReactive, reactive } from "vue";
33

44
export type unObject = Record<string, unknown>;
55

6-
const configurable = true,
7-
/**
8-
* Creates an array of node objects with parent and siblings
9-
*
10-
* @param {unObject[]} siblings - Array of sibling nodes
11-
* @param {unObject} [parent] - Parent node
12-
* @returns {{ node: unObject; parent: unObject; siblings: unObject }[]}
13-
* Array of objects containing node, parent, and siblings
14-
*/
15-
getItems = (siblings: unObject[], parent?: unObject) =>
16-
[...siblings].reverse().map((node) => ({ node, parent, siblings }));
6+
const configurable = true;
7+
8+
/**
9+
* Creates an array of node objects with parent and siblings
10+
*
11+
* @param {unObject[]} siblings - Array of sibling nodes
12+
* @param {unObject} [parent] - Parent node
13+
* @returns {{ node: unObject; parent: unObject; siblings: unObject }[]} Array
14+
* of objects containing node, parent, and siblings
15+
*/
16+
const getItems = (siblings: unObject[], parent?: unObject) =>
17+
[...siblings].reverse().map((node: unObject) => ({ node, parent, siblings }));
1718

1819
/**
1920
* Creates a flat representation of a JSON tree with helper functions to
@@ -70,9 +71,14 @@ export default (
7071
* @returns {number} Index of the node in its siblings array
7172
*/
7273
get(this: unObject): number {
73-
return (this[keySiblings] as unObject[]).findIndex(
74-
(sibling) => this[keyId] === sibling[keyId],
75-
);
74+
/**
75+
* Checks if the given sibling is the same as the current node
76+
*
77+
* @param {unObject} sibling - The sibling to compare
78+
* @returns {boolean} True if the sibling matches the current node
79+
*/
80+
const isSibling = (sibling: unObject) => this[keyId] === sibling[keyId];
81+
return (this[keySiblings] as unObject[]).findIndex(isSibling);
7682
},
7783
},
7884
[keyNext]: {
@@ -101,18 +107,25 @@ export default (
101107
},
102108
},
103109
};
110+
104111
/**
105112
* Generator function that traverses the tree and yields each node
106113
*
107114
* @param {unObject[]} nodes - Array of nodes to traverse
108115
* @yields {unObject} Each node in the tree
109-
* @returns {Generator<unObject>} Generator that yields nodes
110116
*/
111-
const getNodes = function* (nodes: unObject[]) {
117+
const genNodes = function* (nodes: unObject[]) {
112118
const stack = getItems(nodes);
113119
while (stack.length) {
114120
const { node, parent, siblings } = stack.pop() ?? {};
115121
if (node) {
122+
/**
123+
* Checks if a property key is not already defined in the node
124+
*
125+
* @param {string} key - The property key to check
126+
* @returns {boolean} True if the key is not in the node
127+
*/
128+
const isNotInNode = (key: string) => !(key in node);
116129
if (node[keyParent] !== parent)
117130
Object.defineProperty(node, keyParent, {
118131
configurable,
@@ -123,7 +136,7 @@ export default (
123136
configurable,
124137
value: siblings,
125138
});
126-
if (Object.keys(properties).some((key) => !(key in node)))
139+
if (Object.keys(properties).some(isNotInNode))
127140
Object.defineProperties(node, properties);
128141
yield node;
129142
stack.push(
@@ -132,93 +145,111 @@ export default (
132145
}
133146
}
134147
},
135-
nodes = computed(() => [
136-
...getNodes(isReactive(tree) ? tree : reactive(tree)),
137-
]),
138-
nodesMap = computed(() =>
139-
Object.fromEntries(
140-
nodes.value.map((node) => [node[keyId] as string, node]),
141-
),
142-
),
143148
/**
144-
* Function to run actions on nodes
149+
* Generates a flat array of nodes from the tree structure
145150
*
146-
* @param {string} pId - ID of the node to perform action on
147-
* @param {string} action - Action to perform (add, addChild, remove, up,
148-
* down, left, right)
149-
* @returns {string | undefined} ID of the affected node or undefined
151+
* @returns {unObject[]} Array of nodes in the tree
150152
*/
151-
run = (pId: string, action: string) => {
152-
const the = nodesMap.value[pId];
153-
if (the) {
154-
const [root] = nodes.value,
155-
index = the[keyIndex] as number,
156-
next = the[keyNext] as undefined | unObject,
157-
nextIndex = index + 1,
158-
parent = the[keyParent] as undefined | unObject,
159-
prev = the[keyPrev] as undefined | unObject,
160-
prevIndex = index - 1,
161-
siblings = the[keySiblings] as unObject[];
162-
switch (action) {
163-
case "add": {
164-
const id = uid();
165-
siblings.splice(nextIndex, 0, { [keyId]: id });
166-
return id;
167-
}
168-
case "addChild": {
169-
const id = uid();
170-
if (!Array.isArray(the[keyChildren])) the[keyChildren] = [];
171-
(the[keyChildren] as unObject[]).unshift({ [keyId]: id });
172-
return id;
153+
getNodes = () => [...genNodes(isReactive(tree) ? tree : reactive(tree))];
154+
155+
const nodes = computed(getNodes);
156+
157+
/**
158+
* Gets the entry (key-value pair) for a node using its ID
159+
*
160+
* @param {unObject} node - The node to create an entry for
161+
* @returns {[string, unObject]} A tuple with the node ID and the node object
162+
*/
163+
const getNodeEntry = (node: unObject) => [node[keyId] as string, node],
164+
/**
165+
* Creates a map of nodes with node IDs as keys
166+
*
167+
* @returns {Record<string, unObject>} Object mapping node IDs to node
168+
* objects
169+
*/
170+
getNodesMap = () => Object.fromEntries(nodes.value.map(getNodeEntry));
171+
172+
const nodesMap = computed(getNodesMap);
173+
174+
/**
175+
* Function to run actions on nodes
176+
*
177+
* @param {string} pId - ID of the node to perform action on
178+
* @param {string} action - Action to perform (add, addChild, remove, up,
179+
* down, left, right)
180+
* @returns {string | undefined} ID of the affected node or undefined
181+
*/
182+
const run = (pId: string, action: string) => {
183+
const the = nodesMap.value[pId];
184+
if (the) {
185+
const [root] = nodes.value,
186+
index = the[keyIndex] as number,
187+
next = the[keyNext] as undefined | unObject,
188+
nextIndex = index + 1,
189+
parent = the[keyParent] as undefined | unObject,
190+
prev = the[keyPrev] as undefined | unObject,
191+
prevIndex = index - 1,
192+
siblings = the[keySiblings] as unObject[];
193+
switch (action) {
194+
case "add": {
195+
const id = uid();
196+
siblings.splice(nextIndex, 0, { [keyId]: id });
197+
return id;
198+
}
199+
case "addChild": {
200+
const id = uid();
201+
if (!Array.isArray(the[keyChildren])) the[keyChildren] = [];
202+
(the[keyChildren] as unObject[]).unshift({ [keyId]: id });
203+
return id;
204+
}
205+
case "down":
206+
if (
207+
index < siblings.length - 1 &&
208+
siblings[index] &&
209+
siblings[nextIndex]
210+
)
211+
[siblings[index], siblings[nextIndex]] = [
212+
siblings[nextIndex],
213+
siblings[index],
214+
];
215+
break;
216+
case "left":
217+
if (parent?.[keyParent]) {
218+
(parent[keySiblings] as unObject[]).splice(
219+
(parent[keyIndex] as number) + 1,
220+
0,
221+
...siblings.splice(index, 1),
222+
);
223+
return parent[keyId] as string;
173224
}
174-
case "down":
175-
if (
176-
index < siblings.length - 1 &&
177-
siblings[index] &&
178-
siblings[nextIndex]
179-
)
180-
[siblings[index], siblings[nextIndex]] = [
181-
siblings[nextIndex],
182-
siblings[index],
183-
];
184-
break;
185-
case "left":
186-
if (parent?.[keyParent]) {
187-
(parent[keySiblings] as unObject[]).splice(
188-
(parent[keyIndex] as number) + 1,
189-
0,
190-
...siblings.splice(index, 1),
191-
);
192-
return parent[keyId] as string;
193-
}
194-
break;
195-
case "remove": {
196-
const id = (next?.[keyId] ??
197-
prev?.[keyId] ??
198-
parent?.[keyId] ??
199-
root?.[keyId]) as string | undefined;
200-
siblings.splice(index, 1);
225+
break;
226+
case "remove": {
227+
const id = (next?.[keyId] ??
228+
prev?.[keyId] ??
229+
parent?.[keyId] ??
230+
root?.[keyId]) as string | undefined;
231+
siblings.splice(index, 1);
232+
return id;
233+
}
234+
case "right":
235+
if (prev) {
236+
const children = (prev[keyChildren] ?? []) as unObject[],
237+
id = prev[keyId] as string;
238+
prev[keyChildren] = [...children, ...siblings.splice(index, 1)];
201239
return id;
202240
}
203-
case "right":
204-
if (prev) {
205-
const children = (prev[keyChildren] ?? []) as unObject[],
206-
id = prev[keyId] as string;
207-
prev[keyChildren] = [...children, ...siblings.splice(index, 1)];
208-
return id;
209-
}
210-
break;
211-
case "up":
212-
if (index && siblings[index] && siblings[prevIndex])
213-
[siblings[prevIndex], siblings[index]] = [
214-
siblings[index],
215-
siblings[prevIndex],
216-
];
217-
break;
218-
}
241+
break;
242+
case "up":
243+
if (index && siblings[index] && siblings[prevIndex])
244+
[siblings[prevIndex], siblings[index]] = [
245+
siblings[index],
246+
siblings[prevIndex],
247+
];
248+
break;
219249
}
220-
return;
221-
};
250+
}
251+
return;
252+
};
222253

223254
return {
224255
/**

0 commit comments

Comments
 (0)