-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathStateController.js
More file actions
118 lines (103 loc) · 3.3 KB
/
StateController.js
File metadata and controls
118 lines (103 loc) · 3.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
export default class StateController {
_state = {};
get state() {
return this._state;
}
set state(value) {
this._state = value;
}
_traversePath(path, current = this._state) {
const keys = path.split(".");
for (let i = 0; i < keys.length - 1; i++) {
const key = keys[i];
const nextKey = keys[i + 1];
if (!(key in current) || typeof current[key] !== "object" || current[key] === null) {
// Create array if nextKey is a number, else object
current[key] = !isNaN(Number(nextKey)) ? [] : {};
}
current = current[key];
}
return { current, lastKey: keys[keys.length - 1] };
}
getKey(key) {
const { current, lastKey } = this._traversePath(key, this._state);
// console.log("getKey", current, lastKey);
return current && lastKey in current ? current[lastKey] : undefined;
}
setKey(key, value) {
const { current, lastKey } = this._traversePath(key, this._state);
// console.log(current, lastKey);
current[lastKey] = value;
}
setState(updates) {
if (typeof updates !== "object" || updates === null) {
throw new Error("setState requires an object as argument");
}
for (const [key, value] of Object.entries(updates)) {
this.setKey(key, value);
}
}
getState() {
return this._state;
}
// Utility methods
hasKey(key) {
const { current, lastKey } = this._traversePath(key);
return current ? lastKey in current : false;
}
removeKey(key) {
const { current, lastKey } = this._traversePath(key);
if (current && lastKey) {
delete current[lastKey];
}
}
getKeys(key) {
const { current, lastKey } = this._traversePath(key);
if (!current || typeof current !== 'object' || current === null) {
return [];
}
return Object.keys(current[lastKey]);
}
getType(key) {
const value = this.getKey(key);
if (value === undefined) return "undefined";
if (value === null) return "null";
if (Array.isArray(value)) return "array";
return typeof value;
}
// Array operations
push(key, value) {
const { current, lastKey } = this._traversePath(key);
if (current === undefined || lastKey === null) return;
if (!Array.isArray(current[lastKey])) {
current[lastKey] = [];
}
current[lastKey].push(value);
return current[lastKey].length;
}
pop(key) {
const { current, lastKey } = this._traversePath(key);
if (current && lastKey && Array.isArray(current[lastKey])) {
return current[lastKey].pop();
}
return undefined;
}
length(key) {
const { current, lastKey } = this._traversePath(key);
if (current && lastKey && Array.isArray(current[lastKey])) {
return current[lastKey].length;
}
return 0;
}
// Object operations
merge(key, value) {
const { current, lastKey } = this._traversePath(key);
if (current === undefined || lastKey === null) return;
if (typeof value !== "object" || value === null) {
current[lastKey] = value;
} else {
current[lastKey] = { ...current[lastKey], ...value };
}
}
}
export { StateController };