offdex 1.0.7 → 3.0.0
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/LICENSE +21 -0
- package/README.md +88 -36
- package/dist/BlobStorage/class.d.ts +10 -0
- package/dist/BlobStorage/class.d.ts.map +1 -0
- package/dist/BlobStorage/class.js +169 -0
- package/dist/BlobStorage/class.js.map +1 -0
- package/dist/ObjectStorage/class.d.ts +10 -0
- package/dist/ObjectStorage/class.d.ts.map +1 -0
- package/dist/ObjectStorage/class.js +169 -0
- package/dist/ObjectStorage/class.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/package.json +40 -16
- package/src/ObjectStore/index.js +0 -241
- package/src/ObservableObject/index.js +0 -12
- package/src/ObservableValue/index.js +0 -58
- package/src/StorageQuery/index.js +0 -12
- package/src/index.d.ts +0 -54
- package/src/index.js +0 -7
- package/src/types.d.ts +0 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 offdex contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
# Offdex
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
IndexedDB-backed object storage for browsers and workers. Store
|
|
4
|
+
structured-clone JS values (objects, arrays, and primitives limited to
|
|
5
|
+
msgpack-compatible types) by key, read them back directly, and share data across
|
|
6
|
+
tabs and workers without schema migrations.
|
|
4
7
|
|
|
5
8
|
## Why use Offdex
|
|
6
9
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
|
|
10
|
-
-
|
|
10
|
+
- Simple `put/get/head/delete/list` API in browser contexts.
|
|
11
|
+
- Object storage for msgpack-safe structured-clone JS values: primitives,
|
|
12
|
+
arrays, plain objects, Date, and typed arrays.
|
|
13
|
+
- Single object store keyed by string; no migrations to manage.
|
|
14
|
+
- Data shared per origin across tabs and workers (instance per JavaScript realm).
|
|
15
|
+
- Offline persistence via IndexedDB.
|
|
16
|
+
- TypeScript-first.
|
|
17
|
+
- Singleton-only API: one shared `storage` instance per JavaScript realm (per thread).
|
|
11
18
|
|
|
12
19
|
## Install
|
|
13
20
|
|
|
@@ -18,51 +25,96 @@ npm install offdex
|
|
|
18
25
|
## Quick start
|
|
19
26
|
|
|
20
27
|
```js
|
|
21
|
-
import
|
|
28
|
+
import storage from "offdex";
|
|
22
29
|
|
|
23
|
-
|
|
24
|
-
id: crypto.randomUUID(), // UUIDv4 string
|
|
25
|
-
name: "Ada Lovelace",
|
|
26
|
-
role: "analyst",
|
|
27
|
-
};
|
|
30
|
+
await storage.put("profile:ada", { greeting: "hello from IndexedDB" });
|
|
28
31
|
|
|
29
|
-
await storage.
|
|
32
|
+
const object = await storage.get("profile:ada");
|
|
33
|
+
if (object) {
|
|
34
|
+
console.log(object);
|
|
35
|
+
}
|
|
30
36
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
await storage.delete(profile.id);
|
|
37
|
+
await storage.put("bytes", new Uint8Array([1, 2, 3]));
|
|
38
|
+
const bytes = await storage.get("bytes");
|
|
39
|
+
console.log(bytes instanceof Uint8Array, bytes);
|
|
35
40
|
```
|
|
36
41
|
|
|
37
42
|
## API
|
|
38
43
|
|
|
39
|
-
### `storage`
|
|
44
|
+
### `storage` (default export)
|
|
45
|
+
|
|
46
|
+
Singleton storage instance per JavaScript realm backed by the `offdex` database
|
|
47
|
+
and `blobs` object store. The underlying store is shared per origin across tabs
|
|
48
|
+
and workers.
|
|
49
|
+
|
|
50
|
+
### Methods
|
|
51
|
+
|
|
52
|
+
- `put(key, value, options?)` -> `Promise<void>`
|
|
53
|
+
- `get(key, options?)` -> `Promise<unknown | null>`
|
|
54
|
+
- `head(key)` -> `Promise<boolean>`
|
|
55
|
+
- `delete(key)` -> `Promise<void>`
|
|
56
|
+
- `list(options?)` -> `Promise<{ objects: { key: string }[] }>`
|
|
57
|
+
|
|
58
|
+
### Value requirements (msgpack-compatible)
|
|
40
59
|
|
|
41
|
-
-
|
|
60
|
+
- `value` must be a structured-clone JS value encodable by `@msgpack/msgpack`
|
|
61
|
+
with default options.
|
|
62
|
+
- Allowed: `null`/`undefined`, booleans, numbers, strings, arrays, plain
|
|
63
|
+
objects, `Date`, and `ArrayBufferView` (typed arrays/DataView).
|
|
64
|
+
- Not allowed: `BigInt`, `Map`, `Set`, `RegExp`, `Error`, `Blob`/`File`,
|
|
65
|
+
`ArrayBuffer`, functions, symbols, or circular references.
|
|
66
|
+
- `put` throws a `TypeError` if a value is not msgpack-compatible.
|
|
67
|
+
- MessagePack note: `undefined` decodes as `null`, and binary decodes as
|
|
68
|
+
`Uint8Array`.
|
|
42
69
|
|
|
43
|
-
|
|
70
|
+
## Compatibility notes
|
|
44
71
|
|
|
45
|
-
-
|
|
46
|
-
|
|
47
|
-
-
|
|
48
|
-
- `
|
|
49
|
-
- `
|
|
50
|
-
- `deleteAllMatches(queryOrFilter: StorageQuery | (object) => boolean): Promise<void>` — deletes objects that pass a query or predicate.
|
|
72
|
+
- Method names mirror Cloudflare R2 (`put/get/head/delete/list`), but return
|
|
73
|
+
values are simplified for direct value access.
|
|
74
|
+
- Offdex does not use MessagePack internally; it just validates compatibility.
|
|
75
|
+
- `options` arguments are accepted for signature compatibility but not used.
|
|
76
|
+
- `list` currently returns all keys; prefix/limit/cursor options are ignored.
|
|
51
77
|
|
|
52
|
-
|
|
78
|
+
## Build
|
|
53
79
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
80
|
+
```bash
|
|
81
|
+
npm run build
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Tests
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
npx playwright install
|
|
88
|
+
npm test
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Playwright runs Chromium, Firefox, WebKit, plus mobile emulation projects.
|
|
92
|
+
|
|
93
|
+
## Benchmarks
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
npx playwright install
|
|
97
|
+
npm run bench
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The benchmark runs in Chromium via Playwright and times a batch of msgpack-safe
|
|
101
|
+
`put/head/get/list/delete` operations.
|
|
102
|
+
|
|
103
|
+
```text
|
|
104
|
+
[bench] put 200 items: 148.6ms
|
|
105
|
+
[bench] head 200 items: 101.6ms
|
|
106
|
+
[bench] get 200 items: 100.3ms
|
|
107
|
+
[bench] list 200 items: 2.7ms
|
|
108
|
+
[bench] delete 200 items: 123.8ms
|
|
109
|
+
```
|
|
57
110
|
|
|
58
|
-
|
|
111
|
+
## Manual browser check
|
|
59
112
|
|
|
60
|
-
- `
|
|
61
|
-
|
|
62
|
-
- `OnSetHandler`, `OnDeleteHandler` — callback shapes used by `get`/`getAllMatches`.
|
|
113
|
+
- Run `npm run build`, open `in-browser-testing.html`, then use `storage` from
|
|
114
|
+
the console with msgpack-compatible structured-clone values.
|
|
63
115
|
|
|
64
116
|
## Notes
|
|
65
117
|
|
|
66
|
-
-
|
|
67
|
-
- Data is
|
|
68
|
-
|
|
118
|
+
- Requires `indexedDB` (modern browsers / worker runtimes).
|
|
119
|
+
- Data is scoped per origin; all tabs/workers on the same origin share the same
|
|
120
|
+
store.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { R2GetOptions, R2ListOptions, R2Objects, R2PutOptions } from "@cloudflare/workers-types";
|
|
2
|
+
export declare class BlobStorage {
|
|
3
|
+
#private;
|
|
4
|
+
put: (key: string, value: unknown, _options?: R2PutOptions) => Promise<void>;
|
|
5
|
+
head: (key: string) => Promise<boolean>;
|
|
6
|
+
get: (key: string, _options?: R2GetOptions) => Promise<unknown | null>;
|
|
7
|
+
delete: (key: string) => Promise<void>;
|
|
8
|
+
list: (_options?: R2ListOptions) => Promise<R2Objects>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=class.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"class.d.ts","sourceRoot":"","sources":["../../src/BlobStorage/class.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,YAAY,EACZ,aAAa,EACb,SAAS,EACT,YAAY,EACb,MAAM,2BAA2B,CAAC;AAInC,qBAAa,WAAW;;IAgItB,GAAG,GACD,KAAK,MAAM,EACX,OAAO,OAAO,EACd,WAAW,YAAY,KACtB,OAAO,CAAC,IAAI,CAAC,CAwBd;IAEF,IAAI,GAAU,KAAK,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC,CAc1C;IAEF,GAAG,GACD,KAAK,MAAM,EACX,WAAW,YAAY,KACtB,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAcxB;IAEF,MAAM,GAAU,KAAK,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC,CASzC;IAEF,IAAI,GAAU,WAAW,aAAa,KAAG,OAAO,CAAC,SAAS,CAAC,CAiBzD;CACH"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
var _a;
|
|
2
|
+
export class BlobStorage {
|
|
3
|
+
static #dbName = "offdex";
|
|
4
|
+
static #storeName = "blobs";
|
|
5
|
+
#dbPromise = _a.#open();
|
|
6
|
+
static #open() {
|
|
7
|
+
return new Promise((resolve, reject) => {
|
|
8
|
+
const request = indexedDB.open(_a.#dbName, 1);
|
|
9
|
+
request.onupgradeneeded = () => {
|
|
10
|
+
const db = request.result;
|
|
11
|
+
if (!db.objectStoreNames.contains(_a.#storeName)) {
|
|
12
|
+
db.createObjectStore(_a.#storeName, { keyPath: "key" });
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
request.onsuccess = () => resolve(request.result);
|
|
16
|
+
request.onerror = () => reject(request.error);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
static #throwMsgpackError(path, reason) {
|
|
20
|
+
throw new TypeError(`{offdex} BlobStorage.put: value at ${path} is not msgpack-compatible (${reason})`);
|
|
21
|
+
}
|
|
22
|
+
static #assertMsgpackCompatible(value, path, seen) {
|
|
23
|
+
if (value === null || value === undefined)
|
|
24
|
+
return;
|
|
25
|
+
const valueType = typeof value;
|
|
26
|
+
if (valueType === "string" ||
|
|
27
|
+
valueType === "boolean" ||
|
|
28
|
+
valueType === "number")
|
|
29
|
+
return;
|
|
30
|
+
if (valueType === "bigint") {
|
|
31
|
+
_a.#throwMsgpackError(path, "bigint is not supported without custom msgpack options");
|
|
32
|
+
}
|
|
33
|
+
if (valueType === "symbol") {
|
|
34
|
+
_a.#throwMsgpackError(path, "symbol values are not supported");
|
|
35
|
+
}
|
|
36
|
+
if (valueType === "function") {
|
|
37
|
+
_a.#throwMsgpackError(path, "functions are not supported");
|
|
38
|
+
}
|
|
39
|
+
if (value instanceof Date)
|
|
40
|
+
return;
|
|
41
|
+
if (ArrayBuffer.isView(value))
|
|
42
|
+
return;
|
|
43
|
+
if (value instanceof ArrayBuffer) {
|
|
44
|
+
_a.#throwMsgpackError(path, "ArrayBuffer is not supported; use Uint8Array instead");
|
|
45
|
+
}
|
|
46
|
+
if (typeof Blob === "function" && value instanceof Blob) {
|
|
47
|
+
_a.#throwMsgpackError(path, "Blob/File values are not supported; use Uint8Array instead");
|
|
48
|
+
}
|
|
49
|
+
if (typeof File === "function" && value instanceof File) {
|
|
50
|
+
_a.#throwMsgpackError(path, "Blob/File values are not supported; use Uint8Array instead");
|
|
51
|
+
}
|
|
52
|
+
if (value instanceof Map) {
|
|
53
|
+
_a.#throwMsgpackError(path, "Map is not supported");
|
|
54
|
+
}
|
|
55
|
+
if (value instanceof Set) {
|
|
56
|
+
_a.#throwMsgpackError(path, "Set is not supported");
|
|
57
|
+
}
|
|
58
|
+
if (value instanceof RegExp) {
|
|
59
|
+
_a.#throwMsgpackError(path, "RegExp is not supported");
|
|
60
|
+
}
|
|
61
|
+
if (value instanceof Error) {
|
|
62
|
+
_a.#throwMsgpackError(path, "Error is not supported");
|
|
63
|
+
}
|
|
64
|
+
if (Array.isArray(value)) {
|
|
65
|
+
if (seen.has(value)) {
|
|
66
|
+
_a.#throwMsgpackError(path, "circular references are not supported");
|
|
67
|
+
}
|
|
68
|
+
seen.add(value);
|
|
69
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
70
|
+
_a.#assertMsgpackCompatible(value[index], `${path}[${index}]`, seen);
|
|
71
|
+
}
|
|
72
|
+
seen.delete(value);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (value && typeof value === "object") {
|
|
76
|
+
const proto = Object.getPrototypeOf(value);
|
|
77
|
+
if (proto !== Object.prototype && proto !== null) {
|
|
78
|
+
_a.#throwMsgpackError(path, "only plain objects are supported");
|
|
79
|
+
}
|
|
80
|
+
if (Object.getOwnPropertySymbols(value).length > 0) {
|
|
81
|
+
_a.#throwMsgpackError(path, "symbol keys are not supported");
|
|
82
|
+
}
|
|
83
|
+
if (seen.has(value)) {
|
|
84
|
+
_a.#throwMsgpackError(path, "circular references are not supported");
|
|
85
|
+
}
|
|
86
|
+
seen.add(value);
|
|
87
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
88
|
+
_a.#assertMsgpackCompatible(entry, `${path}.${key}`, seen);
|
|
89
|
+
}
|
|
90
|
+
seen.delete(value);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
_a.#throwMsgpackError(path, "unsupported value type");
|
|
94
|
+
}
|
|
95
|
+
put = async (key, value, _options) => {
|
|
96
|
+
_a.#assertMsgpackCompatible(value, "$", new WeakSet());
|
|
97
|
+
const db = await this.#dbPromise;
|
|
98
|
+
await new Promise((resolve, reject) => {
|
|
99
|
+
const tx = db.transaction(_a.#storeName, "readwrite");
|
|
100
|
+
try {
|
|
101
|
+
tx.objectStore(_a.#storeName).put({
|
|
102
|
+
key: String(key),
|
|
103
|
+
value,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
108
|
+
reject(new TypeError(`{offdex} BlobStorage.put: value must be structured-cloneable (${message})`));
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
tx.oncomplete = () => resolve();
|
|
112
|
+
tx.onerror = () => reject(tx.error);
|
|
113
|
+
tx.onabort = () => reject(tx.error);
|
|
114
|
+
});
|
|
115
|
+
};
|
|
116
|
+
head = async (key) => {
|
|
117
|
+
const db = await this.#dbPromise;
|
|
118
|
+
const exists = await new Promise((resolve, reject) => {
|
|
119
|
+
const tx = db.transaction(_a.#storeName, "readonly");
|
|
120
|
+
const store = tx.objectStore(_a.#storeName);
|
|
121
|
+
const req = typeof store.getKey === "function" ? store.getKey(key) : store.get(key);
|
|
122
|
+
tx.oncomplete = () => resolve(req.result !== undefined);
|
|
123
|
+
tx.onerror = () => reject(tx.error);
|
|
124
|
+
tx.onabort = () => reject(tx.error);
|
|
125
|
+
});
|
|
126
|
+
return exists;
|
|
127
|
+
};
|
|
128
|
+
get = async (key, _options) => {
|
|
129
|
+
const db = await this.#dbPromise;
|
|
130
|
+
const row = await new Promise((resolve, reject) => {
|
|
131
|
+
const tx = db.transaction(_a.#storeName, "readonly");
|
|
132
|
+
const req = tx.objectStore(_a.#storeName).get(key);
|
|
133
|
+
tx.oncomplete = () => resolve(req.result);
|
|
134
|
+
tx.onerror = () => reject(tx.error);
|
|
135
|
+
tx.onabort = () => reject(tx.error);
|
|
136
|
+
});
|
|
137
|
+
if (!row)
|
|
138
|
+
return null;
|
|
139
|
+
return row.value;
|
|
140
|
+
};
|
|
141
|
+
delete = async (key) => {
|
|
142
|
+
const db = await this.#dbPromise;
|
|
143
|
+
await new Promise((resolve, reject) => {
|
|
144
|
+
const tx = db.transaction(_a.#storeName, "readwrite");
|
|
145
|
+
tx.objectStore(_a.#storeName).delete(key);
|
|
146
|
+
tx.oncomplete = () => resolve();
|
|
147
|
+
tx.onerror = () => reject(tx.error);
|
|
148
|
+
tx.onabort = () => reject(tx.error);
|
|
149
|
+
});
|
|
150
|
+
};
|
|
151
|
+
list = async (_options) => {
|
|
152
|
+
const db = await this.#dbPromise;
|
|
153
|
+
const keys = await new Promise((resolve, reject) => {
|
|
154
|
+
const tx = db.transaction(_a.#storeName, "readonly");
|
|
155
|
+
const req = tx.objectStore(_a.#storeName).getAllKeys();
|
|
156
|
+
tx.oncomplete = () => resolve(req.result);
|
|
157
|
+
tx.onerror = () => reject(tx.error);
|
|
158
|
+
tx.onabort = () => reject(tx.error);
|
|
159
|
+
});
|
|
160
|
+
return {
|
|
161
|
+
objects: keys.map((key) => ({ key })),
|
|
162
|
+
truncated: false,
|
|
163
|
+
delimitedPrefixes: [],
|
|
164
|
+
cursor: undefined,
|
|
165
|
+
};
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
_a = BlobStorage;
|
|
169
|
+
//# sourceMappingURL=class.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"class.js","sourceRoot":"","sources":["../../src/BlobStorage/class.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { R2GetOptions, R2ListOptions, R2Objects, R2PutOptions } from "@cloudflare/workers-types";
|
|
2
|
+
export declare class ObjectStorage {
|
|
3
|
+
#private;
|
|
4
|
+
put: (key: string, value: unknown, _options?: R2PutOptions) => Promise<void>;
|
|
5
|
+
head: (key: string) => Promise<boolean>;
|
|
6
|
+
get: (key: string, _options?: R2GetOptions) => Promise<unknown | null>;
|
|
7
|
+
delete: (key: string) => Promise<void>;
|
|
8
|
+
list: (_options?: R2ListOptions) => Promise<R2Objects>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=class.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"class.d.ts","sourceRoot":"","sources":["../../src/ObjectStorage/class.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,YAAY,EACZ,aAAa,EACb,SAAS,EACT,YAAY,EACb,MAAM,2BAA2B,CAAC;AAInC,qBAAa,aAAa;;IAsIxB,GAAG,GACD,KAAK,MAAM,EACX,OAAO,OAAO,EACd,WAAW,YAAY,KACtB,OAAO,CAAC,IAAI,CAAC,CAwBd;IAEF,IAAI,GAAU,KAAK,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC,CAc1C;IAEF,GAAG,GACD,KAAK,MAAM,EACX,WAAW,YAAY,KACtB,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAcxB;IAEF,MAAM,GAAU,KAAK,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC,CASzC;IAEF,IAAI,GAAU,WAAW,aAAa,KAAG,OAAO,CAAC,SAAS,CAAC,CAiBzD;CACH"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
var _a;
|
|
2
|
+
export class ObjectStorage {
|
|
3
|
+
static #dbName = "offdex";
|
|
4
|
+
static #storeName = "blobs";
|
|
5
|
+
#dbPromise = _a.#open();
|
|
6
|
+
static #open() {
|
|
7
|
+
return new Promise((resolve, reject) => {
|
|
8
|
+
const request = indexedDB.open(_a.#dbName, 1);
|
|
9
|
+
request.onupgradeneeded = () => {
|
|
10
|
+
const db = request.result;
|
|
11
|
+
if (!db.objectStoreNames.contains(_a.#storeName)) {
|
|
12
|
+
db.createObjectStore(_a.#storeName, { keyPath: "key" });
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
request.onsuccess = () => resolve(request.result);
|
|
16
|
+
request.onerror = () => reject(request.error);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
static #throwMsgpackError(path, reason) {
|
|
20
|
+
throw new TypeError(`{offdex} ObjectStorage.put: value at ${path} is not msgpack-compatible (${reason})`);
|
|
21
|
+
}
|
|
22
|
+
static #assertMsgpackCompatible(value, path, seen) {
|
|
23
|
+
if (value === null || value === undefined)
|
|
24
|
+
return;
|
|
25
|
+
const valueType = typeof value;
|
|
26
|
+
if (valueType === "string" ||
|
|
27
|
+
valueType === "boolean" ||
|
|
28
|
+
valueType === "number")
|
|
29
|
+
return;
|
|
30
|
+
if (valueType === "bigint") {
|
|
31
|
+
_a.#throwMsgpackError(path, "bigint is not supported without custom msgpack options");
|
|
32
|
+
}
|
|
33
|
+
if (valueType === "symbol") {
|
|
34
|
+
_a.#throwMsgpackError(path, "symbol values are not supported");
|
|
35
|
+
}
|
|
36
|
+
if (valueType === "function") {
|
|
37
|
+
_a.#throwMsgpackError(path, "functions are not supported");
|
|
38
|
+
}
|
|
39
|
+
if (value instanceof Date)
|
|
40
|
+
return;
|
|
41
|
+
if (ArrayBuffer.isView(value))
|
|
42
|
+
return;
|
|
43
|
+
if (value instanceof ArrayBuffer) {
|
|
44
|
+
_a.#throwMsgpackError(path, "ArrayBuffer is not supported; use Uint8Array instead");
|
|
45
|
+
}
|
|
46
|
+
if (typeof Blob === "function" && value instanceof Blob) {
|
|
47
|
+
_a.#throwMsgpackError(path, "Blob/File values are not supported; use Uint8Array instead");
|
|
48
|
+
}
|
|
49
|
+
if (typeof File === "function" && value instanceof File) {
|
|
50
|
+
_a.#throwMsgpackError(path, "Blob/File values are not supported; use Uint8Array instead");
|
|
51
|
+
}
|
|
52
|
+
if (value instanceof Map) {
|
|
53
|
+
_a.#throwMsgpackError(path, "Map is not supported");
|
|
54
|
+
}
|
|
55
|
+
if (value instanceof Set) {
|
|
56
|
+
_a.#throwMsgpackError(path, "Set is not supported");
|
|
57
|
+
}
|
|
58
|
+
if (value instanceof RegExp) {
|
|
59
|
+
_a.#throwMsgpackError(path, "RegExp is not supported");
|
|
60
|
+
}
|
|
61
|
+
if (value instanceof Error) {
|
|
62
|
+
_a.#throwMsgpackError(path, "Error is not supported");
|
|
63
|
+
}
|
|
64
|
+
if (Array.isArray(value)) {
|
|
65
|
+
if (seen.has(value)) {
|
|
66
|
+
_a.#throwMsgpackError(path, "circular references are not supported");
|
|
67
|
+
}
|
|
68
|
+
seen.add(value);
|
|
69
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
70
|
+
_a.#assertMsgpackCompatible(value[index], `${path}[${index}]`, seen);
|
|
71
|
+
}
|
|
72
|
+
seen.delete(value);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (value && typeof value === "object") {
|
|
76
|
+
const proto = Object.getPrototypeOf(value);
|
|
77
|
+
if (proto !== Object.prototype && proto !== null) {
|
|
78
|
+
_a.#throwMsgpackError(path, "only plain objects are supported");
|
|
79
|
+
}
|
|
80
|
+
if (Object.getOwnPropertySymbols(value).length > 0) {
|
|
81
|
+
_a.#throwMsgpackError(path, "symbol keys are not supported");
|
|
82
|
+
}
|
|
83
|
+
if (seen.has(value)) {
|
|
84
|
+
_a.#throwMsgpackError(path, "circular references are not supported");
|
|
85
|
+
}
|
|
86
|
+
seen.add(value);
|
|
87
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
88
|
+
_a.#assertMsgpackCompatible(entry, `${path}.${key}`, seen);
|
|
89
|
+
}
|
|
90
|
+
seen.delete(value);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
_a.#throwMsgpackError(path, "unsupported value type");
|
|
94
|
+
}
|
|
95
|
+
put = async (key, value, _options) => {
|
|
96
|
+
_a.#assertMsgpackCompatible(value, "$", new WeakSet());
|
|
97
|
+
const db = await this.#dbPromise;
|
|
98
|
+
await new Promise((resolve, reject) => {
|
|
99
|
+
const tx = db.transaction(_a.#storeName, "readwrite");
|
|
100
|
+
try {
|
|
101
|
+
tx.objectStore(_a.#storeName).put({
|
|
102
|
+
key: String(key),
|
|
103
|
+
value,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
108
|
+
reject(new TypeError(`{offdex} ObjectStorage.put: value must be structured-cloneable (${message})`));
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
tx.oncomplete = () => resolve();
|
|
112
|
+
tx.onerror = () => reject(tx.error);
|
|
113
|
+
tx.onabort = () => reject(tx.error);
|
|
114
|
+
});
|
|
115
|
+
};
|
|
116
|
+
head = async (key) => {
|
|
117
|
+
const db = await this.#dbPromise;
|
|
118
|
+
const exists = await new Promise((resolve, reject) => {
|
|
119
|
+
const tx = db.transaction(_a.#storeName, "readonly");
|
|
120
|
+
const store = tx.objectStore(_a.#storeName);
|
|
121
|
+
const req = typeof store.getKey === "function" ? store.getKey(key) : store.get(key);
|
|
122
|
+
tx.oncomplete = () => resolve(req.result !== undefined);
|
|
123
|
+
tx.onerror = () => reject(tx.error);
|
|
124
|
+
tx.onabort = () => reject(tx.error);
|
|
125
|
+
});
|
|
126
|
+
return exists;
|
|
127
|
+
};
|
|
128
|
+
get = async (key, _options) => {
|
|
129
|
+
const db = await this.#dbPromise;
|
|
130
|
+
const row = await new Promise((resolve, reject) => {
|
|
131
|
+
const tx = db.transaction(_a.#storeName, "readonly");
|
|
132
|
+
const req = tx.objectStore(_a.#storeName).get(key);
|
|
133
|
+
tx.oncomplete = () => resolve(req.result);
|
|
134
|
+
tx.onerror = () => reject(tx.error);
|
|
135
|
+
tx.onabort = () => reject(tx.error);
|
|
136
|
+
});
|
|
137
|
+
if (!row)
|
|
138
|
+
return null;
|
|
139
|
+
return row.value;
|
|
140
|
+
};
|
|
141
|
+
delete = async (key) => {
|
|
142
|
+
const db = await this.#dbPromise;
|
|
143
|
+
await new Promise((resolve, reject) => {
|
|
144
|
+
const tx = db.transaction(_a.#storeName, "readwrite");
|
|
145
|
+
tx.objectStore(_a.#storeName).delete(key);
|
|
146
|
+
tx.oncomplete = () => resolve();
|
|
147
|
+
tx.onerror = () => reject(tx.error);
|
|
148
|
+
tx.onabort = () => reject(tx.error);
|
|
149
|
+
});
|
|
150
|
+
};
|
|
151
|
+
list = async (_options) => {
|
|
152
|
+
const db = await this.#dbPromise;
|
|
153
|
+
const keys = await new Promise((resolve, reject) => {
|
|
154
|
+
const tx = db.transaction(_a.#storeName, "readonly");
|
|
155
|
+
const req = tx.objectStore(_a.#storeName).getAllKeys();
|
|
156
|
+
tx.oncomplete = () => resolve(req.result);
|
|
157
|
+
tx.onerror = () => reject(tx.error);
|
|
158
|
+
tx.onabort = () => reject(tx.error);
|
|
159
|
+
});
|
|
160
|
+
return {
|
|
161
|
+
objects: keys.map((key) => ({ key })),
|
|
162
|
+
truncated: false,
|
|
163
|
+
delimitedPrefixes: [],
|
|
164
|
+
cursor: undefined,
|
|
165
|
+
};
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
_a = ObjectStorage;
|
|
169
|
+
//# sourceMappingURL=class.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"class.js","sourceRoot":"","sources":["../../src/ObjectStorage/class.ts"],"names":[],"mappings":";AAUA,MAAM,OAAO,aAAa;IACxB,MAAM,CAAU,OAAO,GAAG,QAAQ,CAAC;IACnC,MAAM,CAAU,UAAU,GAAG,OAAO,CAAC;IAC5B,UAAU,GAAyB,EAAa,CAAC,KAAK,EAAE,CAAC;IAElE,MAAM,CAAC,KAAK;QACV,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,EAAa,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACzD,OAAO,CAAC,eAAe,GAAG,GAAG,EAAE;gBAC7B,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;gBAC1B,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,EAAa,CAAC,UAAU,CAAC,EAAE,CAAC;oBAC5D,EAAE,CAAC,iBAAiB,CAAC,EAAa,CAAC,UAAU,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;gBACrE,CAAC;YACH,CAAC,CAAC;YACF,OAAO,CAAC,SAAS,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAClD,OAAO,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,kBAAkB,CAAC,IAAY,EAAE,MAAc;QACpD,MAAM,IAAI,SAAS,CACjB,wCAAwC,IAAI,+BAA+B,MAAM,GAAG,CACrF,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,wBAAwB,CAC7B,KAAc,EACd,IAAY,EACZ,IAAqB;QAErB,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO;QAElD,MAAM,SAAS,GAAG,OAAO,KAAK,CAAC;QAC/B,IACE,SAAS,KAAK,QAAQ;YACtB,SAAS,KAAK,SAAS;YACvB,SAAS,KAAK,QAAQ;YAEtB,OAAO;QACT,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;YAC3B,EAAa,CAAC,kBAAkB,CAC9B,IAAI,EACJ,wDAAwD,CACzD,CAAC;QACJ,CAAC;QACD,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;YAC3B,EAAa,CAAC,kBAAkB,CAAC,IAAI,EAAE,iCAAiC,CAAC,CAAC;QAC5E,CAAC;QACD,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;YAC7B,EAAa,CAAC,kBAAkB,CAAC,IAAI,EAAE,6BAA6B,CAAC,CAAC;QACxE,CAAC;QAED,IAAI,KAAK,YAAY,IAAI;YAAE,OAAO;QAClC,IAAI,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC;YAAE,OAAO;QACtC,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;YACjC,EAAa,CAAC,kBAAkB,CAC9B,IAAI,EACJ,sDAAsD,CACvD,CAAC;QACJ,CAAC;QAED,IAAI,OAAO,IAAI,KAAK,UAAU,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;YACxD,EAAa,CAAC,kBAAkB,CAC9B,IAAI,EACJ,4DAA4D,CAC7D,CAAC;QACJ,CAAC;QACD,IAAI,OAAO,IAAI,KAAK,UAAU,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;YACxD,EAAa,CAAC,kBAAkB,CAC9B,IAAI,EACJ,4DAA4D,CAC7D,CAAC;QACJ,CAAC;QAED,IAAI,KAAK,YAAY,GAAG,EAAE,CAAC;YACzB,EAAa,CAAC,kBAAkB,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC;QACjE,CAAC;QACD,IAAI,KAAK,YAAY,GAAG,EAAE,CAAC;YACzB,EAAa,CAAC,kBAAkB,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC;QACjE,CAAC;QACD,IAAI,KAAK,YAAY,MAAM,EAAE,CAAC;YAC5B,EAAa,CAAC,kBAAkB,CAAC,IAAI,EAAE,yBAAyB,CAAC,CAAC;QACpE,CAAC;QACD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,EAAa,CAAC,kBAAkB,CAAC,IAAI,EAAE,wBAAwB,CAAC,CAAC;QACnE,CAAC;QAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBACpB,EAAa,CAAC,kBAAkB,CAC9B,IAAI,EACJ,uCAAuC,CACxC,CAAC;YACJ,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAChB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;gBACrD,EAAa,CAAC,wBAAwB,CACpC,KAAK,CAAC,KAAK,CAAC,EACZ,GAAG,IAAI,IAAI,KAAK,GAAG,EACnB,IAAI,CACL,CAAC;YACJ,CAAC;YACD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACnB,OAAO;QACT,CAAC;QAED,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YACvC,MAAM,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;YAC3C,IAAI,KAAK,KAAK,MAAM,CAAC,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACjD,EAAa,CAAC,kBAAkB,CAC9B,IAAI,EACJ,kCAAkC,CACnC,CAAC;YACJ,CAAC;YACD,IAAI,MAAM,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACnD,EAAa,CAAC,kBAAkB,CAAC,IAAI,EAAE,+BAA+B,CAAC,CAAC;YAC1E,CAAC;YACD,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBACpB,EAAa,CAAC,kBAAkB,CAC9B,IAAI,EACJ,uCAAuC,CACxC,CAAC;YACJ,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAChB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACjD,EAAa,CAAC,wBAAwB,CAAC,KAAK,EAAE,GAAG,IAAI,IAAI,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;YACxE,CAAC;YACD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACnB,OAAO;QACT,CAAC;QAED,EAAa,CAAC,kBAAkB,CAAC,IAAI,EAAE,wBAAwB,CAAC,CAAC;IACnE,CAAC;IAED,GAAG,GAAG,KAAK,EACT,GAAW,EACX,KAAc,EACd,QAAuB,EACR,EAAE;QACjB,EAAa,CAAC,wBAAwB,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,OAAO,EAAE,CAAC,CAAC;QAElE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC;QACjC,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC1C,MAAM,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,EAAa,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;YACjE,IAAI,CAAC;gBACH,EAAE,CAAC,WAAW,CAAC,EAAa,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC;oBAC3C,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC;oBAChB,KAAK;iBACQ,CAAC,CAAC;YACnB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACvE,MAAM,CACJ,IAAI,SAAS,CACX,mEAAmE,OAAO,GAAG,CAC9E,CACF,CAAC;gBACF,OAAO;YACT,CAAC;YACD,EAAE,CAAC,UAAU,GAAG,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;YAChC,EAAE,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;YACpC,EAAE,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,IAAI,GAAG,KAAK,EAAE,GAAW,EAAoB,EAAE;QAC7C,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC;QAEjC,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAAU,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC5D,MAAM,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,EAAa,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;YAChE,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,EAAa,CAAC,UAAU,CAAC,CAAC;YACvD,MAAM,GAAG,GACP,OAAO,KAAK,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC1E,EAAE,CAAC,UAAU,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;YACxD,EAAE,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;YACpC,EAAE,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IAEF,GAAG,GAAG,KAAK,EACT,GAAW,EACX,QAAuB,EACE,EAAE;QAC3B,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC;QAEjC,MAAM,GAAG,GAAG,MAAM,IAAI,OAAO,CAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACjE,MAAM,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,EAAa,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;YAChE,MAAM,GAAG,GAAG,EAAE,CAAC,WAAW,CAAC,EAAa,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC9D,EAAE,CAAC,UAAU,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,MAAyB,CAAC,CAAC;YAC7D,EAAE,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;YACpC,EAAE,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QAEtB,OAAO,GAAG,CAAC,KAAK,CAAC;IACnB,CAAC,CAAC;IAEF,MAAM,GAAG,KAAK,EAAE,GAAW,EAAiB,EAAE;QAC5C,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC;QACjC,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC1C,MAAM,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,EAAa,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;YACjE,EAAE,CAAC,WAAW,CAAC,EAAa,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACrD,EAAE,CAAC,UAAU,GAAG,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;YAChC,EAAE,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;YACpC,EAAE,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,IAAI,GAAG,KAAK,EAAE,QAAwB,EAAsB,EAAE;QAC5D,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC;QAEjC,MAAM,IAAI,GAAG,MAAM,IAAI,OAAO,CAAW,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC3D,MAAM,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,EAAa,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;YAChE,MAAM,GAAG,GAAG,EAAE,CAAC,WAAW,CAAC,EAAa,CAAC,UAAU,CAAC,CAAC,UAAU,EAAE,CAAC;YAClE,EAAE,CAAC,UAAU,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,MAAkB,CAAC,CAAC;YACtD,EAAE,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;YACpC,EAAE,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAe,CAAA,CAAC;YACjD,SAAS,EAAE,KAAK;YAChB,iBAAiB,EAAE,EAAE;YACrB,MAAM,EAAE,SAAS;SACL,CAAC;IACjB,CAAC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;;AAEzD,wBAAmC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEzD,eAAe,IAAI,aAAa,EAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,35 +1,59 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "offdex",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
|
+
"description": "IndexedDB-backed object storage for structured-clone JS values (msgpack-compatible) in browsers and workers.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"indexeddb",
|
|
7
|
-
"
|
|
7
|
+
"structured-clone",
|
|
8
|
+
"msgpack",
|
|
9
|
+
"binary",
|
|
10
|
+
"object",
|
|
8
11
|
"storage",
|
|
9
12
|
"browser-storage",
|
|
10
13
|
"web-storage",
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"shared"
|
|
14
|
+
"r2",
|
|
15
|
+
"cloudflare",
|
|
16
|
+
"bucket",
|
|
17
|
+
"offline",
|
|
18
|
+
"worker",
|
|
19
|
+
"persist"
|
|
18
20
|
],
|
|
19
21
|
"license": "MIT",
|
|
20
22
|
"type": "module",
|
|
21
|
-
"main": "
|
|
22
|
-
"types": "
|
|
23
|
+
"main": "dist/index.js",
|
|
24
|
+
"types": "dist/index.d.ts",
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/jortsupetterson/offdex.git"
|
|
28
|
+
},
|
|
29
|
+
"bugs": {
|
|
30
|
+
"url": "https://github.com/jortsupetterson/offdex/issues"
|
|
31
|
+
},
|
|
32
|
+
"homepage": "https://github.com/jortsupetterson/offdex#readme",
|
|
23
33
|
"exports": {
|
|
24
34
|
".": {
|
|
25
|
-
"types": "./
|
|
26
|
-
"import": "./
|
|
35
|
+
"types": "./dist/index.d.ts",
|
|
36
|
+
"import": "./dist/index.js"
|
|
27
37
|
},
|
|
28
38
|
"./package.json": "./package.json"
|
|
29
39
|
},
|
|
30
40
|
"files": [
|
|
31
|
-
"
|
|
41
|
+
"dist",
|
|
42
|
+
"LICENSE",
|
|
32
43
|
"README.md"
|
|
33
44
|
],
|
|
34
|
-
"sideEffects": false
|
|
45
|
+
"sideEffects": false,
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "tsc -p tsconfig.build.json",
|
|
48
|
+
"test": "npm run build && playwright test",
|
|
49
|
+
"bench": "npm run build && playwright test -c playwright.bench.config.ts",
|
|
50
|
+
"prepublishOnly": "npm run build"
|
|
51
|
+
},
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"@cloudflare/workers-types": "^4.20260101.0"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@playwright/test": "^1.57.0",
|
|
57
|
+
"typescript": "^5.9.3"
|
|
58
|
+
}
|
|
35
59
|
}
|
package/src/ObjectStore/index.js
DELETED
|
@@ -1,241 +0,0 @@
|
|
|
1
|
-
export class ObjectStore {
|
|
2
|
-
static #idb = "offdex";
|
|
3
|
-
static #store = "objects";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @returns {Promise<IDBDatabase>}
|
|
7
|
-
*/
|
|
8
|
-
static #open() {
|
|
9
|
-
return new Promise((resolve, reject) => {
|
|
10
|
-
const request = indexedDB.open(ObjectStore.#idb);
|
|
11
|
-
|
|
12
|
-
request.addEventListener("upgradeneeded", () => {
|
|
13
|
-
const db = request.result;
|
|
14
|
-
if (!db.objectStoreNames.contains(ObjectStore.#store)) {
|
|
15
|
-
db.createObjectStore(ObjectStore.#store, { keyPath: "id" });
|
|
16
|
-
}
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
request.addEventListener("success", () => {
|
|
20
|
-
resolve(request.result);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
request.addEventListener("error", () => {
|
|
24
|
-
reject(request.error);
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
constructor() {
|
|
30
|
-
this.instance = ObjectStore.#open();
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* @param {import("../types").StoredObject} object
|
|
35
|
-
* @returns {Promise<void>}
|
|
36
|
-
*/
|
|
37
|
-
async put(object) {
|
|
38
|
-
const db = await this.instance;
|
|
39
|
-
return new Promise((resolve, reject) => {
|
|
40
|
-
const transaction = db.transaction(ObjectStore.#store, "readwrite");
|
|
41
|
-
const store = transaction.objectStore(ObjectStore.#store);
|
|
42
|
-
store.put(object);
|
|
43
|
-
|
|
44
|
-
transaction.oncomplete = () => resolve();
|
|
45
|
-
transaction.onerror = () =>
|
|
46
|
-
reject(new Error(`{offdex} ObjectStore: ${transaction.error}`));
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* @param {import("../types").UUIDv4} id
|
|
52
|
-
* @param {(propertyName: string, oldValue: any, newValue: any) => void | boolean} [onSetEvent]
|
|
53
|
-
* @param {(propertyName: string, deletedValue: any) => void | boolean} [onDeleteEvent]
|
|
54
|
-
* @returns {Promise<import("../types").StoredObject | undefined>}
|
|
55
|
-
*/
|
|
56
|
-
async get(id, onSetEvent, onDeleteEvent) {
|
|
57
|
-
const db = await this.instance;
|
|
58
|
-
const objectStoreInstance = this;
|
|
59
|
-
|
|
60
|
-
return new Promise((resolve, reject) => {
|
|
61
|
-
const transaction = db.transaction(ObjectStore.#store, "readonly");
|
|
62
|
-
const store = transaction.objectStore(ObjectStore.#store);
|
|
63
|
-
const request = store.get(id);
|
|
64
|
-
|
|
65
|
-
transaction.oncomplete = () => {
|
|
66
|
-
if (!request.result) {
|
|
67
|
-
resolve(undefined);
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const target = request.result;
|
|
72
|
-
|
|
73
|
-
const handler = {
|
|
74
|
-
set(targetObject, propertyName, newValue) {
|
|
75
|
-
const oldValue = targetObject[propertyName];
|
|
76
|
-
if (onSetEvent) {
|
|
77
|
-
const shouldUpdate = onSetEvent(propertyName, oldValue, newValue);
|
|
78
|
-
if (shouldUpdate === false) return true;
|
|
79
|
-
}
|
|
80
|
-
targetObject[propertyName] = newValue;
|
|
81
|
-
void objectStoreInstance.put(targetObject);
|
|
82
|
-
return true;
|
|
83
|
-
},
|
|
84
|
-
deleteProperty(targetObject, propertyName) {
|
|
85
|
-
const deletedValue = targetObject[propertyName];
|
|
86
|
-
if (onDeleteEvent) {
|
|
87
|
-
const shouldDelete = onDeleteEvent(propertyName, deletedValue);
|
|
88
|
-
if (shouldDelete === false) return true;
|
|
89
|
-
}
|
|
90
|
-
delete targetObject[propertyName];
|
|
91
|
-
void objectStoreInstance.put(targetObject);
|
|
92
|
-
return true;
|
|
93
|
-
},
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
resolve(new Proxy(target, handler));
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
transaction.onerror = () =>
|
|
100
|
-
reject(new Error(`{offdex} ObjectStore: ${transaction.error}`));
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* @param {import("../types").UUIDv4} id
|
|
106
|
-
* @returns {Promise<void>}
|
|
107
|
-
*/
|
|
108
|
-
async delete(id) {
|
|
109
|
-
const db = await this.instance;
|
|
110
|
-
return new Promise((resolve, reject) => {
|
|
111
|
-
const transaction = db.transaction(ObjectStore.#store, "readwrite");
|
|
112
|
-
const store = transaction.objectStore(ObjectStore.#store);
|
|
113
|
-
store.delete(id);
|
|
114
|
-
transaction.oncomplete = () => resolve();
|
|
115
|
-
transaction.onerror = () =>
|
|
116
|
-
reject(new Error(`{offdex} ObjectStore: ${transaction.error}`));
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* @param {import("../types").StoredObject[]} objects
|
|
122
|
-
* @returns {Promise<void>}
|
|
123
|
-
*/
|
|
124
|
-
async putAll(objects) {
|
|
125
|
-
const db = await this.instance;
|
|
126
|
-
return new Promise((resolve, reject) => {
|
|
127
|
-
const transaction = db.transaction(ObjectStore.#store, "readwrite");
|
|
128
|
-
const store = transaction.objectStore(ObjectStore.#store);
|
|
129
|
-
|
|
130
|
-
for (const object of objects) {
|
|
131
|
-
store.put(object);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
transaction.oncomplete = () => resolve();
|
|
135
|
-
transaction.onerror = () =>
|
|
136
|
-
reject(new Error(`{offdex} ObjectStore.putAll: ${transaction.error}`));
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* @param {import("../StorageQuery/index.js").StorageQuery | ((object: import("../types").StoredObject) => boolean)} queryOrPredicate
|
|
142
|
-
* @param {(propertyName: string, oldValue: any, newValue: any) => void | boolean} [onSetEvent]
|
|
143
|
-
* @param {(propertyName: string, deletedValue: any) => void | boolean} [onDeleteEvent]
|
|
144
|
-
* @returns {Promise<import("../types").StoredObject[]>}
|
|
145
|
-
*/
|
|
146
|
-
async getAllMatches(queryOrPredicate, onSetEvent, onDeleteEvent) {
|
|
147
|
-
const db = await this.instance;
|
|
148
|
-
const objectStoreInstance = this;
|
|
149
|
-
|
|
150
|
-
const predicate =
|
|
151
|
-
typeof queryOrPredicate === "function"
|
|
152
|
-
? queryOrPredicate
|
|
153
|
-
: (object) => queryOrPredicate.matches(object);
|
|
154
|
-
|
|
155
|
-
return new Promise((resolve, reject) => {
|
|
156
|
-
const transaction = db.transaction(ObjectStore.#store, "readonly");
|
|
157
|
-
const store = transaction.objectStore(ObjectStore.#store);
|
|
158
|
-
const request = store.openCursor();
|
|
159
|
-
|
|
160
|
-
const results = [];
|
|
161
|
-
|
|
162
|
-
request.onsuccess = () => {
|
|
163
|
-
const cursor = request.result;
|
|
164
|
-
if (!cursor) return;
|
|
165
|
-
|
|
166
|
-
const value = cursor.value;
|
|
167
|
-
|
|
168
|
-
if (predicate(value)) {
|
|
169
|
-
const handler = {
|
|
170
|
-
set(targetObject, propertyName, newValue) {
|
|
171
|
-
const oldValue = targetObject[propertyName];
|
|
172
|
-
if (onSetEvent) {
|
|
173
|
-
const shouldUpdate = onSetEvent(
|
|
174
|
-
propertyName,
|
|
175
|
-
oldValue,
|
|
176
|
-
newValue
|
|
177
|
-
);
|
|
178
|
-
if (shouldUpdate === false) return true;
|
|
179
|
-
}
|
|
180
|
-
targetObject[propertyName] = newValue;
|
|
181
|
-
void objectStoreInstance.put(targetObject);
|
|
182
|
-
return true;
|
|
183
|
-
},
|
|
184
|
-
deleteProperty(targetObject, propertyName) {
|
|
185
|
-
const deletedValue = targetObject[propertyName];
|
|
186
|
-
if (onDeleteEvent) {
|
|
187
|
-
const shouldDelete = onDeleteEvent(propertyName, deletedValue);
|
|
188
|
-
if (shouldDelete === false) return true;
|
|
189
|
-
}
|
|
190
|
-
delete targetObject[propertyName];
|
|
191
|
-
void objectStoreInstance.put(targetObject);
|
|
192
|
-
return true;
|
|
193
|
-
},
|
|
194
|
-
};
|
|
195
|
-
|
|
196
|
-
results.push(new Proxy(value, handler));
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
cursor.continue();
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
transaction.oncomplete = () => resolve(results);
|
|
203
|
-
transaction.onerror = () =>
|
|
204
|
-
reject(new Error(`{offdex} ObjectStore: ${transaction.error}`));
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* @param {import("../StorageQuery/index.js").StorageQuery | ((object: import("../types").StoredObject) => boolean)} queryOrPredicate
|
|
210
|
-
* @returns {Promise<void>}
|
|
211
|
-
*/
|
|
212
|
-
async deleteAllMatches(queryOrPredicate) {
|
|
213
|
-
const db = await this.instance;
|
|
214
|
-
|
|
215
|
-
const predicate =
|
|
216
|
-
typeof queryOrPredicate === "function"
|
|
217
|
-
? queryOrPredicate
|
|
218
|
-
: (object) => queryOrPredicate.matches(object);
|
|
219
|
-
|
|
220
|
-
return new Promise((resolve, reject) => {
|
|
221
|
-
const transaction = db.transaction(ObjectStore.#store, "readwrite");
|
|
222
|
-
const store = transaction.objectStore(ObjectStore.#store);
|
|
223
|
-
const request = store.openCursor();
|
|
224
|
-
|
|
225
|
-
request.onsuccess = () => {
|
|
226
|
-
const cursor = request.result;
|
|
227
|
-
if (!cursor) return;
|
|
228
|
-
|
|
229
|
-
if (predicate(cursor.value)) {
|
|
230
|
-
cursor.delete();
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
cursor.continue();
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
transaction.oncomplete = () => resolve();
|
|
237
|
-
transaction.onerror = () =>
|
|
238
|
-
reject(new Error(`{offdex} ObjectStore: ${transaction.error}`));
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { ObservableValue } from "../ObservableValue/index.js";
|
|
2
|
-
|
|
3
|
-
export class ObservableObject {
|
|
4
|
-
/**
|
|
5
|
-
* @param {import("../types").StoredObject} object
|
|
6
|
-
*/
|
|
7
|
-
constructor(object) {
|
|
8
|
-
for (const key in object) {
|
|
9
|
-
this[key] = new ObservableValue(object[key]);
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
export class ObservableValue {
|
|
2
|
-
/**
|
|
3
|
-
* @param {any} value
|
|
4
|
-
* @param {any} [fallback]
|
|
5
|
-
*/
|
|
6
|
-
constructor(value, fallback = null) {
|
|
7
|
-
this.value = value;
|
|
8
|
-
this.fallback = fallback;
|
|
9
|
-
/** @type {Set<{ event: "set" | "reset"; callback: (value: any) => void }>} */
|
|
10
|
-
this.observers = new Set();
|
|
11
|
-
}
|
|
12
|
-
get() {
|
|
13
|
-
return this.value;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* @param {any} newValue
|
|
17
|
-
* @returns {void}
|
|
18
|
-
*/
|
|
19
|
-
set(newValue) {
|
|
20
|
-
if (newValue === this.value) return;
|
|
21
|
-
this.value = newValue;
|
|
22
|
-
const changeObservers = [...this.observers].filter(
|
|
23
|
-
(observer) => observer.event === "set"
|
|
24
|
-
);
|
|
25
|
-
for (const observer of changeObservers) {
|
|
26
|
-
observer.callback(newValue);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
reset() {
|
|
30
|
-
this.value = this.fallback;
|
|
31
|
-
const resetObservers = [...this.observers].filter(
|
|
32
|
-
(observer) => observer.event === "reset"
|
|
33
|
-
);
|
|
34
|
-
for (const observer of resetObservers) {
|
|
35
|
-
observer.callback(this.fallback);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* @param {"set" | "reset"} event
|
|
40
|
-
* @param {Function} callback
|
|
41
|
-
* @returns {() => void}
|
|
42
|
-
*/
|
|
43
|
-
observe(event, callback) {
|
|
44
|
-
if (event !== "set" && event !== "reset")
|
|
45
|
-
throw new Error(
|
|
46
|
-
"{offdex} ObservableValue: Supported `event` parameters are [set, reset]"
|
|
47
|
-
);
|
|
48
|
-
if (typeof callback !== "function")
|
|
49
|
-
throw new Error(
|
|
50
|
-
"{offdex} ObservableValue: Paramater `callback` must be of type function"
|
|
51
|
-
);
|
|
52
|
-
const observer = { event, callback };
|
|
53
|
-
this.observers.add(observer);
|
|
54
|
-
return () => {
|
|
55
|
-
this.observers.delete(observer);
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
}
|
package/src/index.d.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
export type UUIDv4 = `${string}-${string}-${string}-${string}-${string}`;
|
|
2
|
-
|
|
3
|
-
export type StoredObject = { id: UUIDv4 } & Record<string, unknown>;
|
|
4
|
-
|
|
5
|
-
export type OnSetHandler = (
|
|
6
|
-
propertyName: string,
|
|
7
|
-
oldValue: unknown,
|
|
8
|
-
newValue: unknown
|
|
9
|
-
) => void | boolean;
|
|
10
|
-
|
|
11
|
-
export type OnDeleteHandler = (
|
|
12
|
-
propertyName: string,
|
|
13
|
-
deletedValue: unknown
|
|
14
|
-
) => void | boolean;
|
|
15
|
-
|
|
16
|
-
export class StorageQuery {
|
|
17
|
-
constructor(args?: Record<string, unknown>);
|
|
18
|
-
args: Record<string, unknown>;
|
|
19
|
-
matches(object: StoredObject): boolean;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export class ObservableValue<T = unknown> {
|
|
23
|
-
constructor(value: T, fallback?: T);
|
|
24
|
-
get(): T;
|
|
25
|
-
set(newValue: T): void;
|
|
26
|
-
reset(): void;
|
|
27
|
-
observe(event: "set" | "reset", callback: (value: T) => void): () => void;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export class ObservableObject<T extends StoredObject = StoredObject> {
|
|
31
|
-
constructor(object: T);
|
|
32
|
-
[key: string]: ObservableValue<unknown>;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export class ObjectStore {
|
|
36
|
-
constructor();
|
|
37
|
-
put(object: StoredObject): Promise<void>;
|
|
38
|
-
get(
|
|
39
|
-
id: UUIDv4,
|
|
40
|
-
onSetEvent?: OnSetHandler,
|
|
41
|
-
onDeleteEvent?: OnDeleteHandler
|
|
42
|
-
): Promise<StoredObject | undefined>;
|
|
43
|
-
delete(id: UUIDv4): Promise<void>;
|
|
44
|
-
getAllMatches(
|
|
45
|
-
queryOrFilter: StorageQuery | ((object: StoredObject) => boolean),
|
|
46
|
-
onSetEvent?: OnSetHandler,
|
|
47
|
-
onDeleteEvent?: OnDeleteHandler
|
|
48
|
-
): Promise<StoredObject[]>;
|
|
49
|
-
deleteAllMatches(
|
|
50
|
-
queryOrFilter: StorageQuery | ((object: StoredObject) => boolean)
|
|
51
|
-
): Promise<void>;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export const storage: ObjectStore;
|
package/src/index.js
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { ObjectStore } from "./ObjectStore/index.js";
|
|
2
|
-
import { StorageQuery } from "./StorageQuery/index.js";
|
|
3
|
-
import { ObservableValue } from "./ObservableValue/index.js";
|
|
4
|
-
import { ObservableObject } from "./ObservableObject/index.js";
|
|
5
|
-
|
|
6
|
-
export { ObjectStore, StorageQuery, ObservableValue, ObservableObject };
|
|
7
|
-
export const storage = new ObjectStore();
|
package/src/types.d.ts
DELETED