@raubjo/architect-core 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +216 -0
- package/bun.lock +82 -1
- package/package.json +55 -6
- package/src/cache/cache.ts +2 -2
- package/src/cache/manager.ts +93 -83
- package/src/config/adapters/esm.ts +26 -0
- package/src/config/clone.ts +5 -5
- package/src/config/env.global.d.ts +2 -1
- package/src/config/env.ts +53 -55
- package/src/config/env_test.helpers.ts +58 -0
- package/src/config/repository.ts +180 -142
- package/src/container/adapters/builtin.ts +347 -0
- package/src/container/adapters/inversify.ts +123 -0
- package/src/container/contract.ts +58 -0
- package/src/container/runtime.ts +149 -0
- package/src/filesystem/adapters/local.ts +92 -83
- package/src/filesystem/adapters/local_test.helpers.ts +50 -0
- package/src/filesystem/filesystem.ts +11 -11
- package/src/foundation/application.ts +205 -175
- package/src/foundation/application_test.helpers.ts +31 -0
- package/src/index.ts +15 -6
- package/src/react.ts +2 -0
- package/src/renderers/adapters/react.tsx +35 -0
- package/src/renderers/adapters/solid.tsx +32 -0
- package/src/renderers/adapters/svelte.ts +70 -0
- package/src/renderers/adapters/vue.ts +28 -0
- package/src/renderers/contract.ts +15 -0
- package/src/runtimes/react.tsx +24 -12
- package/src/runtimes/solid.tsx +30 -0
- package/src/runtimes/svelte.ts +23 -0
- package/src/runtimes/vue.ts +20 -0
- package/src/solid.ts +2 -0
- package/src/storage/adapters/contract.ts +10 -0
- package/src/storage/adapters/indexed-db.ts +170 -156
- package/src/storage/adapters/local-storage.ts +34 -34
- package/src/storage/adapters/memory.ts +25 -25
- package/src/storage/manager.ts +65 -61
- package/src/storage/storage.ts +1 -8
- package/src/support/facades/cache.ts +40 -40
- package/src/support/facades/config.ts +78 -48
- package/src/support/facades/facade.ts +43 -28
- package/src/support/facades/storage.ts +41 -41
- package/src/support/service-provider.ts +11 -11
- package/src/support/str.ts +94 -90
- package/src/support/str_test.helpers.ts +26 -0
- package/src/svelte.ts +2 -0
- package/src/vue.ts +2 -0
- package/tsconfig.json +16 -0
- package/coverage/lcov.info +0 -1078
- package/src/config/app.ts +0 -5
- package/src/rendering/adapters/react.tsx +0 -27
- package/src/rendering/renderer.ts +0 -13
- package/src/support/providers/config-service-provider.ts +0 -19
- package/tests/application.test.ts +0 -236
- package/tests/cache-facade.test.ts +0 -45
- package/tests/cache.test.ts +0 -68
- package/tests/config-clone.test.ts +0 -31
- package/tests/config-env.test.ts +0 -88
- package/tests/config-facade.test.ts +0 -96
- package/tests/config-repository.test.ts +0 -124
- package/tests/facade-base.test.ts +0 -80
- package/tests/filesystem.test.ts +0 -81
- package/tests/runtime-react.test.tsx +0 -37
- package/tests/service-provider.test.ts +0 -23
- package/tests/storage-facade.test.ts +0 -46
- package/tests/storage.test.ts +0 -264
- package/tests/str.test.ts +0 -73
package/src/config/clone.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { ConfigItems } from "
|
|
1
|
+
import type { ConfigItems } from "@/config/repository";
|
|
2
2
|
|
|
3
3
|
export function cloneConfigItems(items: ConfigItems): ConfigItems {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
if (typeof structuredClone === "function") {
|
|
5
|
+
return structuredClone(items) as ConfigItems;
|
|
6
|
+
}
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
return JSON.parse(JSON.stringify(items)) as ConfigItems;
|
|
9
9
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
declare global {
|
|
2
|
-
|
|
2
|
+
function env(key: string): import("./env").EnvValue | undefined;
|
|
3
|
+
function env<T>(key: string, defaultValue: T): import("./env").EnvValue | T;
|
|
3
4
|
}
|
|
4
5
|
|
|
5
6
|
export {};
|
package/src/config/env.ts
CHANGED
|
@@ -1,79 +1,77 @@
|
|
|
1
|
-
type
|
|
1
|
+
export type EnvValue = string | number | boolean | null;
|
|
2
|
+
type EnvMap = Record<string, EnvValue | undefined>;
|
|
2
3
|
|
|
3
|
-
function normalizeEnvValue(value:
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
function normalizeEnvValue(value: EnvValue | undefined): EnvValue | undefined {
|
|
5
|
+
if (typeof value !== "string") {
|
|
6
|
+
return value;
|
|
7
|
+
}
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
const normalized = value.trim().toLowerCase();
|
|
10
|
+
if (normalized === "true" || normalized === "(true)") {
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
if (normalized === "false" || normalized === "(false)") {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
if (normalized === "null" || normalized === "(null)") {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
if (normalized === "empty" || normalized === "(empty)") {
|
|
23
|
+
return "";
|
|
24
|
+
}
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
return value;
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
function resolveProcessEnv(): EnvMap {
|
|
29
|
-
|
|
30
|
-
globalThis as { process?: { env?: EnvMap } }
|
|
31
|
-
).process;
|
|
30
|
+
const processValue = (globalThis as { process?: { env?: EnvMap } }).process;
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
if (!processValue?.env) {
|
|
33
|
+
return {};
|
|
34
|
+
}
|
|
36
35
|
|
|
37
|
-
|
|
36
|
+
return processValue.env;
|
|
38
37
|
}
|
|
39
38
|
|
|
40
39
|
function resolveImportMetaEnv(): EnvMap {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
const testEnv = (
|
|
41
|
+
globalThis as {
|
|
42
|
+
__iocImportMetaEnvForTests?: EnvMap;
|
|
43
|
+
}
|
|
44
|
+
).__iocImportMetaEnvForTests;
|
|
45
|
+
if (testEnv) {
|
|
46
|
+
return testEnv;
|
|
44
47
|
}
|
|
45
|
-
).__iocImportMetaEnvForTests;
|
|
46
|
-
if (testEnv) {
|
|
47
|
-
return testEnv;
|
|
48
|
-
}
|
|
49
48
|
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
const meta = import.meta as ImportMeta & { env?: EnvMap };
|
|
50
|
+
return meta.env ?? {};
|
|
52
51
|
}
|
|
53
52
|
|
|
54
|
-
export function env
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
53
|
+
export function env(key: string): EnvValue | undefined;
|
|
54
|
+
export function env<T>(key: string, defaultValue: T): EnvValue | T;
|
|
55
|
+
export function env<T>(
|
|
56
|
+
key: string,
|
|
57
|
+
defaultValue?: T,
|
|
58
|
+
): EnvValue | T | undefined {
|
|
59
|
+
const importMetaEnv = resolveImportMetaEnv();
|
|
60
|
+
if (key in importMetaEnv) {
|
|
61
|
+
return normalizeEnvValue(importMetaEnv[key]);
|
|
62
|
+
}
|
|
59
63
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
+
const processEnv = resolveProcessEnv();
|
|
65
|
+
if (key in processEnv) {
|
|
66
|
+
return normalizeEnvValue(processEnv[key]);
|
|
67
|
+
}
|
|
64
68
|
|
|
65
|
-
|
|
69
|
+
return defaultValue;
|
|
66
70
|
}
|
|
67
71
|
|
|
68
72
|
export function registerGlobalEnv(): void {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
+
const globalScope = globalThis as { env?: typeof env };
|
|
74
|
+
if (typeof globalScope.env !== "function") {
|
|
75
|
+
globalScope.env = env;
|
|
76
|
+
}
|
|
73
77
|
}
|
|
74
|
-
|
|
75
|
-
export const __envTesting = {
|
|
76
|
-
normalizeEnvValue,
|
|
77
|
-
resolveImportMetaEnv,
|
|
78
|
-
resolveProcessEnv,
|
|
79
|
-
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { EnvValue } from "./env";
|
|
2
|
+
|
|
3
|
+
type EnvMap = Record<string, EnvValue | undefined>;
|
|
4
|
+
|
|
5
|
+
function normalizeEnvValue(value: EnvValue | undefined): EnvValue | undefined {
|
|
6
|
+
if (typeof value !== "string") {
|
|
7
|
+
return value;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const normalized = value.trim().toLowerCase();
|
|
11
|
+
if (normalized === "true" || normalized === "(true)") {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (normalized === "false" || normalized === "(false)") {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (normalized === "null" || normalized === "(null)") {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (normalized === "empty" || normalized === "(empty)") {
|
|
24
|
+
return "";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function resolveProcessEnv(): EnvMap {
|
|
31
|
+
const processValue = (globalThis as { process?: { env?: EnvMap } }).process;
|
|
32
|
+
|
|
33
|
+
if (!processValue?.env) {
|
|
34
|
+
return {};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return processValue.env;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function resolveImportMetaEnv(): EnvMap {
|
|
41
|
+
const testEnv = (
|
|
42
|
+
globalThis as {
|
|
43
|
+
__iocImportMetaEnvForTests?: EnvMap;
|
|
44
|
+
}
|
|
45
|
+
).__iocImportMetaEnvForTests;
|
|
46
|
+
if (testEnv) {
|
|
47
|
+
return testEnv;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const meta = import.meta as ImportMeta & { env?: EnvMap };
|
|
51
|
+
return meta.env ?? {};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export const envTestingHelpers = {
|
|
55
|
+
normalizeEnvValue,
|
|
56
|
+
resolveImportMetaEnv,
|
|
57
|
+
resolveProcessEnv,
|
|
58
|
+
};
|
package/src/config/repository.ts
CHANGED
|
@@ -2,203 +2,241 @@ export type ConfigItems = Record<string, unknown>;
|
|
|
2
2
|
export type ConfigDefaults = Record<string | number, unknown>;
|
|
3
3
|
|
|
4
4
|
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
5
|
-
|
|
5
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
function resolveDefault<T>(defaultValue: T | (() => T)): T {
|
|
9
|
-
|
|
9
|
+
return typeof defaultValue === "function" ?
|
|
10
|
+
(defaultValue as () => T)()
|
|
11
|
+
: defaultValue;
|
|
10
12
|
}
|
|
11
13
|
|
|
12
|
-
function dataGet(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
function dataGet(
|
|
15
|
+
source: unknown,
|
|
16
|
+
path: string,
|
|
17
|
+
defaultValue: unknown = null,
|
|
18
|
+
): unknown {
|
|
19
|
+
if (!path) {
|
|
20
|
+
return source;
|
|
21
|
+
}
|
|
16
22
|
|
|
17
|
-
|
|
18
|
-
|
|
23
|
+
const segments = path.split(".");
|
|
24
|
+
let cursor: unknown = source;
|
|
19
25
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
for (const segment of segments) {
|
|
27
|
+
if (isPlainObject(cursor) && segment in cursor) {
|
|
28
|
+
cursor = cursor[segment];
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
25
31
|
|
|
26
|
-
|
|
27
|
-
|
|
32
|
+
return resolveDefault(defaultValue);
|
|
33
|
+
}
|
|
28
34
|
|
|
29
|
-
|
|
35
|
+
return cursor;
|
|
30
36
|
}
|
|
31
37
|
|
|
32
|
-
function dataSet(
|
|
33
|
-
|
|
34
|
-
|
|
38
|
+
function dataSet(
|
|
39
|
+
target: Record<string, unknown>,
|
|
40
|
+
path: string,
|
|
41
|
+
value: unknown,
|
|
42
|
+
): void {
|
|
43
|
+
const segments = path.split(".");
|
|
44
|
+
let cursor: Record<string, unknown> = target;
|
|
35
45
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
46
|
+
for (let i = 0; i < segments.length; i += 1) {
|
|
47
|
+
const segment = segments[i];
|
|
48
|
+
const isLast = i === segments.length - 1;
|
|
39
49
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
50
|
+
if (isLast) {
|
|
51
|
+
cursor[segment] = value;
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
44
54
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
55
|
+
if (!isPlainObject(cursor[segment])) {
|
|
56
|
+
cursor[segment] = {};
|
|
57
|
+
}
|
|
48
58
|
|
|
49
|
-
|
|
50
|
-
|
|
59
|
+
cursor = cursor[segment] as Record<string, unknown>;
|
|
60
|
+
}
|
|
51
61
|
}
|
|
52
62
|
|
|
53
63
|
function dataForget(target: Record<string, unknown>, path: string): void {
|
|
54
|
-
|
|
55
|
-
|
|
64
|
+
const segments = path.split(".");
|
|
65
|
+
let cursor: Record<string, unknown> = target;
|
|
56
66
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
67
|
+
for (let i = 0; i < segments.length; i += 1) {
|
|
68
|
+
const segment = segments[i];
|
|
69
|
+
const isLast = i === segments.length - 1;
|
|
60
70
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
71
|
+
if (isLast) {
|
|
72
|
+
delete cursor[segment];
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
65
75
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
76
|
+
if (!isPlainObject(cursor[segment])) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
69
79
|
|
|
70
|
-
|
|
71
|
-
|
|
80
|
+
cursor = cursor[segment] as Record<string, unknown>;
|
|
81
|
+
}
|
|
72
82
|
}
|
|
73
83
|
|
|
74
84
|
export default class ConfigRepository {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
constructor(items: ConfigItems = {}) {
|
|
78
|
-
this.items = items;
|
|
79
|
-
}
|
|
85
|
+
protected items: ConfigItems;
|
|
80
86
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
for (const configKey of keys) {
|
|
84
|
-
if (this.get(configKey) == null) {
|
|
85
|
-
return false;
|
|
86
|
-
}
|
|
87
|
+
constructor(items: ConfigItems = {}) {
|
|
88
|
+
this.items = items;
|
|
87
89
|
}
|
|
88
90
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
+
has(key: string | string[]): boolean {
|
|
92
|
+
const keys = Array.isArray(key) ? key : [key];
|
|
93
|
+
for (const configKey of keys) {
|
|
94
|
+
if (this.get(configKey) == null) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
91
98
|
|
|
92
|
-
|
|
93
|
-
key: string | string[],
|
|
94
|
-
defaultValue: T | (() => T) | null = null,
|
|
95
|
-
): T | Record<string, unknown> | null {
|
|
96
|
-
if (Array.isArray(key)) {
|
|
97
|
-
return this.getMany(key);
|
|
99
|
+
return true;
|
|
98
100
|
}
|
|
99
101
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
102
|
+
get<T = unknown>(
|
|
103
|
+
key: string,
|
|
104
|
+
defaultValue?: T | (() => T) | null,
|
|
105
|
+
): T | null;
|
|
106
|
+
get(key: string[]): Record<string, unknown>;
|
|
107
|
+
get<T = unknown>(
|
|
108
|
+
key: string | string[],
|
|
109
|
+
defaultValue: T | (() => T) | null = null,
|
|
110
|
+
): T | Record<string, unknown> | null {
|
|
111
|
+
if (Array.isArray(key)) {
|
|
112
|
+
return this.getMany(key);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return dataGet(this.items, key, defaultValue) as T | null;
|
|
112
116
|
}
|
|
113
117
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
118
|
+
getMany(keys: string[] | ConfigDefaults): Record<string, unknown> {
|
|
119
|
+
const results: Record<string, unknown> = {};
|
|
117
120
|
|
|
118
|
-
|
|
119
|
-
|
|
121
|
+
if (Array.isArray(keys)) {
|
|
122
|
+
for (const key of keys) {
|
|
123
|
+
results[key] = this.get(key);
|
|
124
|
+
}
|
|
120
125
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if (typeof value !== "string") {
|
|
124
|
-
throw new TypeError(`Configuration value [${key}] is not a string.`);
|
|
125
|
-
}
|
|
126
|
+
return results;
|
|
127
|
+
}
|
|
126
128
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
+
for (const [key, defaultValue] of Object.entries(keys)) {
|
|
130
|
+
results[key] = this.get(key, defaultValue);
|
|
131
|
+
}
|
|
129
132
|
|
|
130
|
-
|
|
131
|
-
const value = this.get<number>(key, defaultValue);
|
|
132
|
-
if (!Number.isInteger(value)) {
|
|
133
|
-
throw new TypeError(`Configuration value [${key}] is not an integer.`);
|
|
133
|
+
return results;
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
|
|
137
|
-
|
|
136
|
+
string(
|
|
137
|
+
key: string,
|
|
138
|
+
defaultValue: string | (() => string) | null = null,
|
|
139
|
+
): string {
|
|
140
|
+
const value = this.get<string>(key, defaultValue);
|
|
141
|
+
if (typeof value !== "string") {
|
|
142
|
+
throw new TypeError(
|
|
143
|
+
`Configuration value [${key}] is not a string.`,
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return value;
|
|
148
|
+
}
|
|
138
149
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
150
|
+
integer(
|
|
151
|
+
key: string,
|
|
152
|
+
defaultValue: number | (() => number) | null = null,
|
|
153
|
+
): number {
|
|
154
|
+
const value = this.get<number>(key, defaultValue);
|
|
155
|
+
if (typeof value !== "number" || !Number.isInteger(value)) {
|
|
156
|
+
throw new TypeError(
|
|
157
|
+
`Configuration value [${key}] is not an integer.`,
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return value;
|
|
143
162
|
}
|
|
144
163
|
|
|
145
|
-
|
|
146
|
-
|
|
164
|
+
float(
|
|
165
|
+
key: string,
|
|
166
|
+
defaultValue: number | (() => number) | null = null,
|
|
167
|
+
): number {
|
|
168
|
+
const value = this.get<number>(key, defaultValue);
|
|
169
|
+
if (typeof value !== "number" || Number.isNaN(value)) {
|
|
170
|
+
throw new TypeError(`Configuration value [${key}] is not a float.`);
|
|
171
|
+
}
|
|
147
172
|
|
|
148
|
-
|
|
149
|
-
const value = this.get<boolean>(key, defaultValue);
|
|
150
|
-
if (typeof value !== "boolean") {
|
|
151
|
-
throw new TypeError(`Configuration value [${key}] is not a boolean.`);
|
|
173
|
+
return value;
|
|
152
174
|
}
|
|
153
175
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
176
|
+
boolean(
|
|
177
|
+
key: string,
|
|
178
|
+
defaultValue: boolean | (() => boolean) | null = null,
|
|
179
|
+
): boolean {
|
|
180
|
+
const value = this.get<boolean>(key, defaultValue);
|
|
181
|
+
if (typeof value !== "boolean") {
|
|
182
|
+
throw new TypeError(
|
|
183
|
+
`Configuration value [${key}] is not a boolean.`,
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return value;
|
|
161
188
|
}
|
|
162
189
|
|
|
163
|
-
|
|
164
|
-
|
|
190
|
+
array<T = unknown>(
|
|
191
|
+
key: string,
|
|
192
|
+
defaultValue: T[] | (() => T[]) | null = null,
|
|
193
|
+
): T[] {
|
|
194
|
+
const value = this.get<T[]>(key, defaultValue);
|
|
195
|
+
if (!Array.isArray(value)) {
|
|
196
|
+
throw new TypeError(
|
|
197
|
+
`Configuration value [${key}] is not an array.`,
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return value;
|
|
202
|
+
}
|
|
165
203
|
|
|
166
|
-
|
|
167
|
-
|
|
204
|
+
set(key: string | ConfigItems, value: unknown = null): void {
|
|
205
|
+
const payload = isPlainObject(key) ? key : { [key]: value };
|
|
168
206
|
|
|
169
|
-
|
|
170
|
-
|
|
207
|
+
for (const [configKey, configValue] of Object.entries(payload)) {
|
|
208
|
+
dataSet(this.items, configKey, configValue);
|
|
209
|
+
}
|
|
171
210
|
}
|
|
172
|
-
}
|
|
173
211
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
212
|
+
prepend(key: string, value: unknown): void {
|
|
213
|
+
const values = this.array<unknown>(key, []);
|
|
214
|
+
this.set(key, [value, ...values]);
|
|
215
|
+
}
|
|
178
216
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
217
|
+
push(key: string, value: unknown): void {
|
|
218
|
+
const values = this.array<unknown>(key, []);
|
|
219
|
+
values.push(value);
|
|
220
|
+
this.set(key, values);
|
|
221
|
+
}
|
|
184
222
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
223
|
+
all(): ConfigItems {
|
|
224
|
+
return this.items;
|
|
225
|
+
}
|
|
188
226
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
227
|
+
offsetExists(key: string): boolean {
|
|
228
|
+
return this.has(key);
|
|
229
|
+
}
|
|
192
230
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
231
|
+
offsetGet<T = unknown>(key: string): T | null {
|
|
232
|
+
return this.get<T>(key) as T | null;
|
|
233
|
+
}
|
|
196
234
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
235
|
+
offsetSet(key: string, value: unknown): void {
|
|
236
|
+
this.set(key, value);
|
|
237
|
+
}
|
|
200
238
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
239
|
+
offsetUnset(key: string): void {
|
|
240
|
+
dataForget(this.items, key);
|
|
241
|
+
}
|
|
204
242
|
}
|