@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/runtimes/react.tsx
CHANGED
|
@@ -1,22 +1,34 @@
|
|
|
1
1
|
import { createContext, useContext, type ReactNode } from "react";
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
ContainerContract,
|
|
4
|
+
ContainerIdentifier,
|
|
5
|
+
} from "@/container/contract";
|
|
3
6
|
|
|
4
|
-
const ContainerContext = createContext<
|
|
7
|
+
const ContainerContext = createContext<ContainerContract | null>(null);
|
|
5
8
|
|
|
6
9
|
type ApplicationProviderProps = {
|
|
7
|
-
|
|
8
|
-
|
|
10
|
+
container: ContainerContract;
|
|
11
|
+
children?: ReactNode;
|
|
9
12
|
};
|
|
10
13
|
|
|
11
|
-
export function ApplicationProvider({
|
|
12
|
-
|
|
14
|
+
export function ApplicationProvider({
|
|
15
|
+
container,
|
|
16
|
+
children,
|
|
17
|
+
}: ApplicationProviderProps) {
|
|
18
|
+
return (
|
|
19
|
+
<ContainerContext.Provider value={container}>
|
|
20
|
+
{children}
|
|
21
|
+
</ContainerContext.Provider>
|
|
22
|
+
);
|
|
13
23
|
}
|
|
14
24
|
|
|
15
|
-
export function useService<T>(identifier:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
25
|
+
export function useService<T>(identifier: ContainerIdentifier<T>): T {
|
|
26
|
+
const container = useContext(ContainerContext);
|
|
27
|
+
if (!container) {
|
|
28
|
+
throw new Error(
|
|
29
|
+
"Application container is not available in React context.",
|
|
30
|
+
);
|
|
31
|
+
}
|
|
20
32
|
|
|
21
|
-
|
|
33
|
+
return container.make<T>(identifier);
|
|
22
34
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createContext, createComponent, useContext, type JSX } from "solid-js";
|
|
2
|
+
import type {
|
|
3
|
+
ContainerContract,
|
|
4
|
+
ContainerIdentifier,
|
|
5
|
+
} from "@/container/contract";
|
|
6
|
+
|
|
7
|
+
const ContainerContext = createContext<ContainerContract | null>(null);
|
|
8
|
+
|
|
9
|
+
type ApplicationProviderProps = {
|
|
10
|
+
container: ContainerContract;
|
|
11
|
+
children?: JSX.Element | (() => JSX.Element);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export function ApplicationProvider(props: ApplicationProviderProps) {
|
|
15
|
+
return createComponent(ContainerContext.Provider, {
|
|
16
|
+
value: props.container,
|
|
17
|
+
children: props.children as never,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function useService<T>(identifier: ContainerIdentifier<T>): T {
|
|
22
|
+
const container = useContext(ContainerContext);
|
|
23
|
+
if (!container) {
|
|
24
|
+
throw new Error(
|
|
25
|
+
"Application container is not available in Solid context.",
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return container.make<T>(identifier);
|
|
30
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { getContext, setContext } from "svelte";
|
|
2
|
+
import type {
|
|
3
|
+
ContainerContract,
|
|
4
|
+
ContainerIdentifier,
|
|
5
|
+
} from "@/container/contract";
|
|
6
|
+
|
|
7
|
+
export const containerKey: unique symbol = Symbol("application.container");
|
|
8
|
+
|
|
9
|
+
export function provideContainer(container: ContainerContract): void {
|
|
10
|
+
setContext(containerKey, container);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function useService<T>(identifier: ContainerIdentifier<T>): T {
|
|
14
|
+
const container =
|
|
15
|
+
getContext<ContainerContract | null>(containerKey) ?? null;
|
|
16
|
+
if (!container) {
|
|
17
|
+
throw new Error(
|
|
18
|
+
"Application container is not available in Svelte context.",
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return container.make<T>(identifier);
|
|
23
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { inject, type InjectionKey } from "vue";
|
|
2
|
+
import type {
|
|
3
|
+
ContainerContract,
|
|
4
|
+
ContainerIdentifier,
|
|
5
|
+
} from "@/container/contract";
|
|
6
|
+
|
|
7
|
+
export const containerKey: InjectionKey<ContainerContract> = Symbol(
|
|
8
|
+
"application.container",
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
export function useService<T>(identifier: ContainerIdentifier<T>): T {
|
|
12
|
+
const container = inject(containerKey, null);
|
|
13
|
+
if (!container) {
|
|
14
|
+
throw new Error(
|
|
15
|
+
"Application container is not available in Vue context.",
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return container.make<T>(identifier);
|
|
20
|
+
}
|
package/src/solid.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface Adapter {
|
|
2
|
+
get<T = unknown>(key: string): Promise<T | null>;
|
|
3
|
+
set<T = unknown>(key: string, value: T): Promise<void>;
|
|
4
|
+
has(key: string): Promise<boolean>;
|
|
5
|
+
delete(key: string): Promise<void>;
|
|
6
|
+
clear(): Promise<void>;
|
|
7
|
+
keys(): Promise<string[]>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type Contract = Adapter;
|
|
@@ -1,180 +1,194 @@
|
|
|
1
|
-
import MemoryStorageAdapter from "
|
|
2
|
-
import type {
|
|
1
|
+
import MemoryStorageAdapter from "@/storage/adapters/memory";
|
|
2
|
+
import type { Adapter } from "@/storage/adapters/contract";
|
|
3
3
|
|
|
4
4
|
type OpenFactory = Pick<IDBFactory, "open">;
|
|
5
5
|
|
|
6
|
-
export default class IndexedDbAdapter implements
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
protected req<T>(request: IDBRequest<T>): Promise<T> {
|
|
26
|
-
return new Promise<T>((resolve, reject) => {
|
|
27
|
-
request.onsuccess = () => resolve(request.result);
|
|
28
|
-
request.onerror = () => reject(request.error ?? new Error("IndexedDB request failed."));
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
protected openDb(): Promise<IDBDatabase> {
|
|
33
|
-
if (this.dbPromise) {
|
|
34
|
-
return this.dbPromise;
|
|
6
|
+
export default class IndexedDbAdapter implements Adapter {
|
|
7
|
+
protected fallback: Adapter;
|
|
8
|
+
protected name: string;
|
|
9
|
+
protected factory: OpenFactory | null;
|
|
10
|
+
protected dbPromise: Promise<IDBDatabase> | null;
|
|
11
|
+
|
|
12
|
+
constructor(
|
|
13
|
+
options: {
|
|
14
|
+
factory?: OpenFactory | null;
|
|
15
|
+
name?: string;
|
|
16
|
+
fallback?: Adapter;
|
|
17
|
+
} = {},
|
|
18
|
+
) {
|
|
19
|
+
this.factory = options.factory ?? globalThis.indexedDB ?? null;
|
|
20
|
+
this.name = options.name ?? "ioc-storage";
|
|
21
|
+
this.fallback = options.fallback ?? new MemoryStorageAdapter();
|
|
22
|
+
this.dbPromise = null;
|
|
35
23
|
}
|
|
36
24
|
|
|
37
|
-
|
|
38
|
-
|
|
25
|
+
protected req<T>(request: IDBRequest<T>): Promise<T> {
|
|
26
|
+
return new Promise<T>((resolve, reject) => {
|
|
27
|
+
request.onsuccess = () => resolve(request.result);
|
|
28
|
+
request.onerror = () =>
|
|
29
|
+
reject(request.error ?? new Error("IndexedDB request failed."));
|
|
30
|
+
});
|
|
39
31
|
}
|
|
40
32
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
reject(new Error("IndexedDB open request could not be created."));
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
request.onupgradeneeded = () => {
|
|
49
|
-
const db = request.result;
|
|
50
|
-
if (!db.objectStoreNames.contains("kv")) {
|
|
51
|
-
db.createObjectStore("kv");
|
|
33
|
+
protected openDb(): Promise<IDBDatabase> {
|
|
34
|
+
if (this.dbPromise) {
|
|
35
|
+
return this.dbPromise;
|
|
52
36
|
}
|
|
53
|
-
};
|
|
54
|
-
request.onsuccess = () => resolve(request.result);
|
|
55
|
-
request.onerror = () =>
|
|
56
|
-
reject(request.error ?? new Error("IndexedDB database could not be opened."));
|
|
57
|
-
});
|
|
58
37
|
|
|
59
|
-
|
|
60
|
-
|
|
38
|
+
if (!this.factory) {
|
|
39
|
+
return Promise.reject(new Error("IndexedDB is not available."));
|
|
40
|
+
}
|
|
61
41
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
42
|
+
this.dbPromise = new Promise<IDBDatabase>((resolve, reject) => {
|
|
43
|
+
const request = this.factory?.open(this.name, 1);
|
|
44
|
+
if (!request) {
|
|
45
|
+
reject(
|
|
46
|
+
new Error("IndexedDB open request could not be created."),
|
|
47
|
+
);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
request.onupgradeneeded = () => {
|
|
52
|
+
const db = request.result;
|
|
53
|
+
if (!db.objectStoreNames.contains("kv")) {
|
|
54
|
+
db.createObjectStore("kv");
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
request.onsuccess = () => resolve(request.result);
|
|
58
|
+
request.onerror = () =>
|
|
59
|
+
reject(
|
|
60
|
+
request.error ??
|
|
61
|
+
new Error("IndexedDB database could not be opened."),
|
|
62
|
+
);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
return this.dbPromise;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
protected async withStore<T>(
|
|
69
|
+
mode: IDBTransactionMode,
|
|
70
|
+
action: (store: IDBObjectStore) => Promise<T>,
|
|
71
|
+
): Promise<T> {
|
|
72
|
+
try {
|
|
73
|
+
const db = await this.openDb();
|
|
74
|
+
const tx = db.transaction("kv", mode);
|
|
75
|
+
const store = tx.objectStore("kv");
|
|
76
|
+
return await action(store);
|
|
77
|
+
} catch (_error) {
|
|
78
|
+
return actionFallback(this.fallback, mode, action);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async get<T = unknown>(key: string): Promise<T | null> {
|
|
83
|
+
return this.withStore("readonly", async (store) => {
|
|
84
|
+
const value = await this.req<unknown>(store.get(key));
|
|
85
|
+
return value === undefined ? null : (value as T);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async set<T = unknown>(key: string, value: T): Promise<void> {
|
|
90
|
+
await this.withStore("readwrite", async (store) => {
|
|
91
|
+
await this.req(store.put(value, key));
|
|
92
|
+
return undefined;
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async has(key: string): Promise<boolean> {
|
|
97
|
+
return this.withStore("readonly", async (store) => {
|
|
98
|
+
const count = await this.req<number>(store.count(key));
|
|
99
|
+
return count > 0;
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async delete(key: string): Promise<void> {
|
|
104
|
+
await this.withStore("readwrite", async (store) => {
|
|
105
|
+
await this.req(store.delete(key));
|
|
106
|
+
return undefined;
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async clear(): Promise<void> {
|
|
111
|
+
await this.withStore("readwrite", async (store) => {
|
|
112
|
+
await this.req(store.clear());
|
|
113
|
+
return undefined;
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async keys(): Promise<string[]> {
|
|
118
|
+
return this.withStore("readonly", async (store) => {
|
|
119
|
+
const keys = await this.req<Array<IDBValidKey>>(store.getAllKeys());
|
|
120
|
+
const normalized: string[] = [];
|
|
121
|
+
for (const key of keys) {
|
|
122
|
+
normalized.push(String(key));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return normalized;
|
|
126
|
+
});
|
|
73
127
|
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
async get<T = unknown>(key: string): Promise<T | null> {
|
|
77
|
-
return this.withStore("readonly", async (store) => {
|
|
78
|
-
const value = await this.req<unknown>(store.get(key));
|
|
79
|
-
return value === undefined ? null : (value as T);
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
async set<T = unknown>(key: string, value: T): Promise<void> {
|
|
84
|
-
await this.withStore("readwrite", async (store) => {
|
|
85
|
-
await this.req(store.put(value, key));
|
|
86
|
-
return undefined;
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
async has(key: string): Promise<boolean> {
|
|
91
|
-
return this.withStore("readonly", async (store) => {
|
|
92
|
-
const count = await this.req<number>(store.count(key));
|
|
93
|
-
return count > 0;
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
async delete(key: string): Promise<void> {
|
|
98
|
-
await this.withStore("readwrite", async (store) => {
|
|
99
|
-
await this.req(store.delete(key));
|
|
100
|
-
return undefined;
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
async clear(): Promise<void> {
|
|
105
|
-
await this.withStore("readwrite", async (store) => {
|
|
106
|
-
await this.req(store.clear());
|
|
107
|
-
return undefined;
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
async keys(): Promise<string[]> {
|
|
112
|
-
return this.withStore("readonly", async (store) => {
|
|
113
|
-
const keys = await this.req<Array<IDBValidKey>>(store.getAllKeys());
|
|
114
|
-
const normalized: string[] = [];
|
|
115
|
-
for (const key of keys) {
|
|
116
|
-
normalized.push(String(key));
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return normalized;
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
128
|
}
|
|
123
129
|
|
|
124
130
|
async function actionFallback<T>(
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
131
|
+
fallback: Adapter,
|
|
132
|
+
mode: IDBTransactionMode,
|
|
133
|
+
action: (store: IDBObjectStore) => Promise<T>,
|
|
128
134
|
): Promise<T> {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
135
|
+
// Keep call sites small: map IDB actions to the same short storage contract.
|
|
136
|
+
if (mode === "readonly") {
|
|
137
|
+
const store = createReadonlyProxy(fallback);
|
|
138
|
+
return action(store as unknown as IDBObjectStore);
|
|
139
|
+
}
|
|
134
140
|
|
|
135
|
-
|
|
136
|
-
|
|
141
|
+
const store = createReadWriteProxy(fallback);
|
|
142
|
+
return action(store as unknown as IDBObjectStore);
|
|
137
143
|
}
|
|
138
144
|
|
|
139
|
-
function createReadonlyProxy(fallback:
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
145
|
+
function createReadonlyProxy(fallback: Adapter): Partial<IDBObjectStore> {
|
|
146
|
+
return {
|
|
147
|
+
get: (key: IDBValidKey) =>
|
|
148
|
+
wrapPromiseRequest(fallback.get(String(key))),
|
|
149
|
+
count: (key?: IDBValidKey | IDBKeyRange) =>
|
|
150
|
+
wrapPromiseRequest(
|
|
151
|
+
fallback
|
|
152
|
+
.has(String(key as IDBValidKey))
|
|
153
|
+
.then((exists) => (exists ? 1 : 0)),
|
|
154
|
+
),
|
|
155
|
+
getAllKeys: () =>
|
|
156
|
+
wrapPromiseRequest(
|
|
157
|
+
fallback.keys().then((keys) => keys as Array<IDBValidKey>),
|
|
158
|
+
),
|
|
159
|
+
};
|
|
149
160
|
}
|
|
150
161
|
|
|
151
|
-
function createReadWriteProxy(fallback:
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
162
|
+
function createReadWriteProxy(fallback: Adapter): Partial<IDBObjectStore> {
|
|
163
|
+
return {
|
|
164
|
+
...createReadonlyProxy(fallback),
|
|
165
|
+
put: (value: unknown, key?: IDBValidKey) =>
|
|
166
|
+
wrapPromiseRequest(fallback.set(String(key as IDBValidKey), value)),
|
|
167
|
+
delete: (key: IDBValidKey | IDBKeyRange) =>
|
|
168
|
+
wrapPromiseRequest(fallback.delete(String(key as IDBValidKey))),
|
|
169
|
+
clear: () => wrapPromiseRequest(fallback.clear()),
|
|
170
|
+
};
|
|
160
171
|
}
|
|
161
172
|
|
|
162
173
|
function wrapPromiseRequest<T>(promise: Promise<T>): IDBRequest<T> {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
174
|
+
const request: Partial<IDBRequest<T>> = {
|
|
175
|
+
onsuccess: null,
|
|
176
|
+
onerror: null,
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
promise.then(
|
|
180
|
+
(result) => {
|
|
181
|
+
request.result = result;
|
|
182
|
+
request.onsuccess?.call(
|
|
183
|
+
request as IDBRequest<T>,
|
|
184
|
+
new Event("success"),
|
|
185
|
+
);
|
|
186
|
+
},
|
|
187
|
+
(error) => {
|
|
188
|
+
request.error = error as DOMException;
|
|
189
|
+
request.onerror?.call(request as IDBRequest<T>, new Event("error"));
|
|
190
|
+
},
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
return request as IDBRequest<T>;
|
|
180
194
|
}
|
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Adapter } from "@/storage/adapters/contract";
|
|
2
2
|
|
|
3
|
-
export default class LocalStorageAdapter implements
|
|
4
|
-
|
|
3
|
+
export default class LocalStorageAdapter implements Adapter {
|
|
4
|
+
protected storage: Storage;
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
async get<T = unknown>(key: string): Promise<T | null> {
|
|
11
|
-
const value = this.storage.getItem(key);
|
|
12
|
-
if (value === null) {
|
|
13
|
-
return null;
|
|
6
|
+
constructor(storage: Storage = window.localStorage) {
|
|
7
|
+
this.storage = storage;
|
|
14
8
|
}
|
|
15
9
|
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
async get<T = unknown>(key: string): Promise<T | null> {
|
|
11
|
+
const value = this.storage.getItem(key);
|
|
12
|
+
if (value === null) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
18
15
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
16
|
+
return JSON.parse(value) as T;
|
|
17
|
+
}
|
|
22
18
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
async set<T = unknown>(key: string, value: T): Promise<void> {
|
|
20
|
+
this.storage.setItem(key, JSON.stringify(value));
|
|
21
|
+
}
|
|
26
22
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
async has(key: string): Promise<boolean> {
|
|
24
|
+
return this.storage.getItem(key) !== null;
|
|
25
|
+
}
|
|
30
26
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
async delete(key: string): Promise<void> {
|
|
28
|
+
this.storage.removeItem(key);
|
|
29
|
+
}
|
|
34
30
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
for (let i = 0; i < this.storage.length; i += 1) {
|
|
38
|
-
const key = this.storage.key(i);
|
|
39
|
-
if (key !== null) {
|
|
40
|
-
keys.push(key);
|
|
41
|
-
}
|
|
31
|
+
async clear(): Promise<void> {
|
|
32
|
+
this.storage.clear();
|
|
42
33
|
}
|
|
43
34
|
|
|
44
|
-
|
|
45
|
-
|
|
35
|
+
async keys(): Promise<string[]> {
|
|
36
|
+
const keys: string[] = [];
|
|
37
|
+
for (let i = 0; i < this.storage.length; i += 1) {
|
|
38
|
+
const key = this.storage.key(i);
|
|
39
|
+
if (key !== null) {
|
|
40
|
+
keys.push(key);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return keys;
|
|
45
|
+
}
|
|
46
46
|
}
|
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Adapter } from "@/storage/adapters/contract";
|
|
2
2
|
|
|
3
|
-
export default class MemoryStorageAdapter implements
|
|
4
|
-
|
|
3
|
+
export default class MemoryStorageAdapter implements Adapter {
|
|
4
|
+
protected items = new Map<string, unknown>();
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
constructor() {}
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
async get<T = unknown>(key: string): Promise<T | null> {
|
|
9
|
+
if (!this.items.has(key)) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
return this.items.get(key) as T;
|
|
14
|
+
}
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
async set<T = unknown>(key: string, value: T): Promise<void> {
|
|
17
|
+
this.items.set(key, value);
|
|
18
|
+
}
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
async has(key: string): Promise<boolean> {
|
|
21
|
+
return this.items.has(key);
|
|
22
|
+
}
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
async delete(key: string): Promise<void> {
|
|
25
|
+
this.items.delete(key);
|
|
26
|
+
}
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
async clear(): Promise<void> {
|
|
29
|
+
this.items.clear();
|
|
30
|
+
}
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
async keys(): Promise<string[]> {
|
|
33
|
+
return Array.from(this.items.keys());
|
|
34
|
+
}
|
|
35
35
|
}
|