forked from techniq/layerstack
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathget.ts
More file actions
109 lines (94 loc) · 2.33 KB
/
get.ts
File metadata and controls
109 lines (94 loc) · 2.33 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
/**
* Parse a path string (with optional bracket notation) into an array of path segments.
* Supports both dot notation (a.b.c) and bracket notation (a[0].b, a["key"])
*/
function parsePath(path: string): (string | number)[] {
if (path === '') {
return [''];
}
const segments: (string | number)[] = [];
let current = '';
let i = 0;
while (i < path.length) {
const char = path[i];
if (char === '.') {
if (current) {
segments.push(current);
current = '';
}
i++;
continue;
}
if (char === '[') {
if (current) {
segments.push(current);
current = '';
}
i++;
// Check for quoted key
if (path[i] === '"' || path[i] === "'") {
const quote = path[i];
i++;
let key = '';
while (i < path.length && path[i] !== quote) {
key += path[i];
i++;
}
segments.push(key);
i += 2; // skip closing quote and opening bracket
continue;
}
// Numeric index
let index = '';
while (i < path.length && path[i] !== ']') {
index += path[i];
i++;
}
segments.push(parseInt(index, 10));
i++; // skip closing bracket
continue;
}
current += char;
i++;
}
if (current) {
segments.push(current);
}
return segments;
}
/**
* See: https://github.com/angus-c/just/blob/d8c5dd18941062d8db7e9310ecc8f53fd607df54/packages/object-safe-get/index.mjs#L33C1-L61C2
*/
export function get<T = any>(
obj: any,
propsArg: string | number | symbol | (string | number | symbol)[],
defaultValue?: T
): T {
if (!obj) {
return defaultValue as T;
}
let props: (string | number | symbol)[];
if (Array.isArray(propsArg)) {
props = propsArg.slice(0);
} else if (typeof propsArg === 'string') {
props = parsePath(propsArg);
} else if (typeof propsArg === 'symbol') {
props = [propsArg];
} else if (typeof propsArg === 'number') {
props = [propsArg];
} else {
throw new Error('props arg must be an array, a string, a number or a symbol');
}
let result: any = obj;
while (props.length) {
const prop = props.shift()!;
if (!result) {
return defaultValue as T;
}
result = result[prop];
if (result === undefined) {
return defaultValue as T;
}
}
return result;
}