/[sudobot]/branches/8.x/src/utils/objects.ts
ViewVC logotype

Contents of /branches/8.x/src/utils/objects.ts

Parent Directory Parent Directory | Revision Log Revision Log


Revision 577 - (show annotations)
Mon Jul 29 18:52:37 2024 UTC (8 months ago) by rakinar2
File MIME type: application/typescript
File size: 4262 byte(s)
chore: add old version archive branches (2.x to 9.x-dev)
1 /*
2 * This file is part of SudoBot.
3 *
4 * Copyright (C) 2021-2023 OSN Developers.
5 *
6 * SudoBot is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * SudoBot is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with SudoBot. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 type AccessOptions = {
21 noCreate?: boolean;
22 noModify?: boolean;
23 noArrayAccess?: boolean;
24 returnExists?: boolean;
25 };
26
27 const access = (object: object | unknown[], accessor: string, setter?: (value: unknown) => unknown, options?: AccessOptions) => {
28 const accessors = accessor.split(".");
29 let current: unknown = object;
30 let prevAccessor: string | undefined;
31
32 if (accessors.length === 0 || !accessor) {
33 return object;
34 }
35
36 for (const access of accessors) {
37 const last = access === accessors[accessors.length - 1];
38
39 if (current instanceof Object) {
40 if (!options?.noArrayAccess && /\[\d+\]$/.test(access)) {
41 const array = current[access.slice(0, access.indexOf("[")) as keyof typeof current] as unknown as Array<unknown>;
42
43 if (!Array.isArray(array)) {
44 throw new Error(`Cannot access index ${access} of non-array value (${prevAccessor ?? "root"})`);
45 }
46
47 const index = parseInt(access.match(/\d+/)![0]);
48
49 if (Number.isNaN(index)) {
50 throw new Error(`Invalid index ${index} (${prevAccessor ?? "root"})`);
51 }
52
53 current = array[index];
54
55 if (options?.returnExists && last) {
56 return index in array;
57 }
58
59 if (setter && last && (!options?.noModify || !(index in array)) && (!options?.noCreate || index < array.length)) {
60 array[index] = setter(current);
61 }
62 } else {
63 if (Array.isArray(current)) {
64 return options?.returnExists ? false : undefined;
65 }
66
67 const value = current[access as keyof typeof current];
68
69 if (options?.returnExists && last) {
70 return access in current;
71 }
72
73 if (setter && last && (!options?.noModify || !(access in current)) && (!options?.noCreate || access in current)) {
74 (current as Record<PropertyKey, unknown>)[access as PropertyKey] = setter(current);
75 }
76
77 current = value;
78 }
79 } else {
80 if (last) {
81 return options?.returnExists ? false : undefined;
82 }
83
84 return current;
85 }
86 }
87
88 return options?.returnExists ? true : current;
89 };
90
91 export const get = <V = unknown>(object: object | unknown[], accessor: string, options?: AccessOptions) =>
92 access(object, accessor, undefined, options) as V;
93 export const has = (object: object | unknown[], accessor: string, options?: AccessOptions) =>
94 access(object, accessor, undefined, { ...options, returnExists: true });
95 export const set = (object: object | unknown[], accessor: string, value: unknown, options?: AccessOptions) =>
96 access(object, accessor, () => value, options);
97
98 export const toDotted = (object: Record<string, unknown>, arrayAccess = false) => {
99 const result: Record<string, unknown> = {};
100
101 function recurse(current: Record<string, unknown>, path: string[] = []) {
102 for (const key in current) {
103 if (current[key] instanceof Object && (arrayAccess || !Array.isArray(current[key]))) {
104 recurse(current[key] as Record<string, unknown>, path.concat(key));
105 } else {
106 result[path.concat(key).join(".")] = current[key];
107 }
108 }
109 }
110
111 recurse(object);
112 return result;
113 };

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26