@rozenite/storage-plugin 1.13.0 → 2.1.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.
Files changed (84) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +6 -1
  3. package/dist/devtools/assets/panel-BlDRXgVW.js +32 -0
  4. package/dist/devtools/assets/panel-DBweZnW5.css +1 -0
  5. package/dist/devtools/panel.html +2 -2
  6. package/dist/react-native/chunks/async-storage.require.cjs +1 -1
  7. package/dist/react-native/chunks/async-storage.require.js +8 -7
  8. package/dist/react-native/chunks/index.require.cjs +1 -1
  9. package/dist/react-native/chunks/index.require.js +70 -66
  10. package/dist/react-native/chunks/secure-storage.require.cjs +1 -1
  11. package/dist/react-native/chunks/secure-storage.require.js +17 -13
  12. package/dist/react-native/chunks/useRozeniteStoragePlugin.require.cjs +1 -1
  13. package/dist/react-native/chunks/useRozeniteStoragePlugin.require.js +863 -344
  14. package/dist/react-native/index.d.ts +166 -18
  15. package/dist/rozenite.json +1 -1
  16. package/dist/sdk/index.cjs +1 -1
  17. package/dist/sdk/index.d.ts +13 -5
  18. package/dist/sdk/index.js +21 -12
  19. package/package.json +35 -37
  20. package/react-native.ts +12 -22
  21. package/rozenite.config.ts +74 -0
  22. package/sdk.ts +1 -5
  23. package/src/react-native/__tests__/entry-preview-pagination.test.ts +234 -0
  24. package/src/react-native/__tests__/export-snapshot.test.ts +138 -0
  25. package/src/react-native/__tests__/full-entry-request.test.ts +143 -0
  26. package/src/react-native/__tests__/import.test.ts +174 -11
  27. package/src/react-native/__tests__/storage-discovery.test.ts +144 -0
  28. package/src/react-native/__tests__/storage-view.test.ts +172 -0
  29. package/src/react-native/__tests__/stress-verification.test.ts +140 -0
  30. package/src/react-native/__tests__/use-storage-agent-tools.test.ts +221 -0
  31. package/src/react-native/adapters/__tests__/mmkv.test.ts +20 -30
  32. package/src/react-native/adapters/async-storage.ts +8 -9
  33. package/src/react-native/adapters/index.ts +2 -8
  34. package/src/react-native/adapters/mmkv.ts +12 -24
  35. package/src/react-native/adapters/secure-storage.ts +4 -0
  36. package/src/react-native/entry-preview-pagination.ts +261 -0
  37. package/src/react-native/export-snapshot.ts +88 -0
  38. package/src/react-native/full-entry-request.ts +91 -0
  39. package/src/react-native/import.ts +179 -16
  40. package/src/react-native/storage-discovery.ts +92 -0
  41. package/src/react-native/storage-view.ts +47 -109
  42. package/src/react-native/useRozeniteStoragePlugin.ts +153 -129
  43. package/src/react-native/useStorageAgentTools.ts +196 -91
  44. package/src/shared/__tests__/entry-preview.test.ts +99 -0
  45. package/src/shared/__tests__/snapshot.test.ts +31 -32
  46. package/src/shared/agent-tools.ts +33 -38
  47. package/src/shared/entry-preview.ts +54 -0
  48. package/src/shared/messaging.ts +140 -21
  49. package/src/shared/snapshot.ts +12 -18
  50. package/src/shared/types.ts +21 -4
  51. package/src/ui/__tests__/binary-value-editor-state.test.ts +16 -13
  52. package/src/ui/__tests__/binary.test.ts +31 -33
  53. package/src/ui/__tests__/large-value-viewer-state.test.ts +21 -0
  54. package/src/ui/__tests__/large-value-viewer.test.tsx +54 -0
  55. package/src/ui/__tests__/panel.test.tsx +382 -0
  56. package/src/ui/__tests__/storage-groups.test.ts +88 -0
  57. package/src/ui/__tests__/type-conversion.test.ts +8 -24
  58. package/src/ui/__tests__/use-storage-entries.test.tsx +337 -0
  59. package/src/ui/add-entry-dialog.tsx +66 -117
  60. package/src/ui/binary-value-editor-state.ts +16 -25
  61. package/src/ui/binary-value-editor.tsx +59 -47
  62. package/src/ui/binary.ts +54 -15
  63. package/src/ui/edit-entry-dialog.tsx +68 -104
  64. package/src/ui/editor-switcher.tsx +9 -16
  65. package/src/ui/entry-detail-dialog.tsx +62 -181
  66. package/src/ui/format-value.tsx +25 -0
  67. package/src/ui/globals.css +1 -123
  68. package/src/ui/import-dialog.tsx +72 -109
  69. package/src/ui/large-value-viewer-state.ts +25 -0
  70. package/src/ui/large-value-viewer.tsx +65 -0
  71. package/src/ui/panel.tsx +649 -509
  72. package/src/ui/query-client.tsx +23 -0
  73. package/src/ui/storage-groups.ts +66 -0
  74. package/src/ui/type-conversion.ts +2 -5
  75. package/src/ui/typed-value-editor.tsx +15 -20
  76. package/src/ui/use-storage-entries.ts +192 -0
  77. package/src/ui/utils.ts +1 -4
  78. package/tsconfig.json +5 -1
  79. package/dist/devtools/assets/panel-Bm-SWF7d.js +0 -33
  80. package/dist/devtools/assets/panel-DIqI4WSp.css +0 -1
  81. package/postcss.config.js +0 -6
  82. package/src/ui/confirm-dialog.tsx +0 -100
  83. package/src/ui/editable-table.tsx +0 -300
  84. package/tailwind.config.ts +0 -94
@@ -1,143 +1,619 @@
1
- import { useRozeniteDevToolsClient as v } from "@rozenite/plugin-bridge";
2
- import { useCallback as A, useMemo as T, useEffect as P } from "react";
3
- import { g as R, s as M } from "./types.js";
4
- import { useRozenitePluginAgentTool as p } from "@rozenite/agent-bridge";
5
- import { defineAgentToolContract as g } from "@rozenite/agent-shared";
6
- const x = async (t, e, r) => {
7
- const o = t.find(
8
- (n) => n.target.adapterId === e.target.adapterId && n.target.storageId === e.target.storageId
1
+ import { useRozeniteDevToolsClient as V } from "@rozenite/plugin-bridge";
2
+ import { useMemo as z, useEffect as G } from "react";
3
+ import { s as $, D as N, g as B } from "./types.js";
4
+ import { useRozenitePluginAgentTool as I } from "@rozenite/agent-bridge";
5
+ import { defineAgentToolContract as b, definePaginatedAgentToolContract as Y, DEFAULT_PAGE_LIMIT as Q, MAX_PAGE_LIMIT as J } from "@rozenite/agent-shared";
6
+ const W = "@rozenite/storage-plugin", T = 1;
7
+ class p extends Error {
8
+ constructor(t, r) {
9
+ super(r), this.path = t;
10
+ }
11
+ }
12
+ const y = (e) => e === null ? "null" : Array.isArray(e) ? "array" : typeof e, X = (e) => typeof e == "object" && e !== null && !Array.isArray(e), S = (e, t) => {
13
+ if (!X(e))
14
+ throw new p(t, `Expected object, got ${y(e)}`);
15
+ return e;
16
+ }, f = (e, t) => {
17
+ if (typeof e != "string")
18
+ throw new p(t, `Expected string, got ${y(e)}`);
19
+ return e;
20
+ }, C = (e, t) => {
21
+ if (!Array.isArray(e))
22
+ throw new p(t, `Expected array, got ${y(e)}`);
23
+ return e;
24
+ }, K = (e, t) => {
25
+ if (typeof e != "string" || !N.includes(e))
26
+ throw new p(
27
+ t,
28
+ `Expected one of ${N.join(", ")}, got ${y(e)}`
29
+ );
30
+ return e;
31
+ }, H = (e, t) => {
32
+ const r = S(e, t);
33
+ return { supportedTypes: C(r.supportedTypes, `${t}.supportedTypes`).map(
34
+ (a, i) => K(a, `${t}.supportedTypes[${i}]`)
35
+ ) };
36
+ }, Z = (e) => {
37
+ const t = S(e, "storage");
38
+ return {
39
+ adapterId: f(t.adapterId, "storage.adapterId"),
40
+ storageId: f(t.storageId, "storage.storageId"),
41
+ adapterName: f(t.adapterName, "storage.adapterName"),
42
+ storageName: f(t.storageName, "storage.storageName"),
43
+ capabilities: H(t.capabilities, "storage.capabilities")
44
+ };
45
+ }, ee = (e, t) => {
46
+ const r = S(e, t), o = f(r.key, `${t}.key`), n = K(r.type, `${t}.type`), a = `${t}.value`;
47
+ switch (n) {
48
+ case "string": {
49
+ const i = r.value;
50
+ if (typeof i != "string")
51
+ throw new p(
52
+ a,
53
+ `Expected string for type "string", got ${y(i)}`
54
+ );
55
+ return { key: o, type: "string", value: i };
56
+ }
57
+ case "number": {
58
+ const i = r.value;
59
+ if (typeof i != "number" || !Number.isFinite(i))
60
+ throw new p(
61
+ a,
62
+ `Expected finite number for type "number", got ${y(i)}`
63
+ );
64
+ return { key: o, type: "number", value: i };
65
+ }
66
+ case "boolean": {
67
+ const i = r.value;
68
+ if (typeof i != "boolean")
69
+ throw new p(
70
+ a,
71
+ `Expected boolean for type "boolean", got ${y(i)}`
72
+ );
73
+ return { key: o, type: "boolean", value: i };
74
+ }
75
+ case "buffer": {
76
+ const i = r.value;
77
+ if (!Array.isArray(i))
78
+ throw new p(
79
+ a,
80
+ `Expected number[] for type "buffer", got ${y(i)}`
81
+ );
82
+ const s = i.map((c, d) => {
83
+ if (typeof c != "number" || !Number.isInteger(c) || c < 0 || c > 255)
84
+ throw new p(
85
+ `${a}[${d}]`,
86
+ `Expected uint8 (integer 0-255), got ${y(c)}`
87
+ );
88
+ return c;
89
+ });
90
+ return { key: o, type: "buffer", value: s };
91
+ }
92
+ }
93
+ }, te = (e) => {
94
+ try {
95
+ const t = S(e, "$"), r = t.version;
96
+ if (r !== T)
97
+ throw new p(
98
+ "version",
99
+ `Unsupported snapshot version: ${y(r)} (this build supports version ${T})`
100
+ );
101
+ const o = f(t.plugin, "plugin"), n = f(t.createdAt, "createdAt"), a = Z(t.storage), s = C(t.entries, "entries").map((c, d) => ee(c, `entries[${d}]`));
102
+ return {
103
+ ok: !0,
104
+ snapshot: {
105
+ version: T,
106
+ plugin: o,
107
+ createdAt: n,
108
+ storage: a,
109
+ entries: s
110
+ }
111
+ };
112
+ } catch (t) {
113
+ if (t instanceof p)
114
+ return { ok: !1, error: { path: t.path, message: t.message } };
115
+ throw t;
116
+ }
117
+ }, re = (e) => ({
118
+ version: 1,
119
+ plugin: W,
120
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
121
+ storage: {
122
+ adapterId: e.target.adapterId,
123
+ storageId: e.target.storageId,
124
+ adapterName: e.adapterName,
125
+ storageName: e.storageName,
126
+ capabilities: e.capabilities
127
+ },
128
+ entries: e.entries
129
+ }), se = (e, t) => {
130
+ const r = [], o = [], n = [], a = [], i = [];
131
+ for (const [c, d] of e.entries.entries()) {
132
+ if (!$(t.capabilities, d.type)) {
133
+ a.push({ key: d.key, type: d.type });
134
+ continue;
135
+ }
136
+ if (t.isBlacklisted(d.key)) {
137
+ n.push({ key: d.key, reason: "blacklist" });
138
+ continue;
139
+ }
140
+ t.entryKeys.has(d.key) ? o.push(d.key) : r.push(d.key), i.push(c), t.entryKeys.add(d.key);
141
+ }
142
+ const s = e.storage.adapterId !== t.target.adapterId || e.storage.storageId !== t.target.storageId;
143
+ return {
144
+ newKeys: r,
145
+ overwriteKeys: o,
146
+ skippedKeys: n,
147
+ unsupportedTypes: a,
148
+ acceptedEntryIndexes: i,
149
+ metadataMismatch: s
150
+ };
151
+ }, ne = (e, t) => e.adapterId === t.adapterId && e.storageId === t.storageId, R = (e) => typeof e == "object" && e != null && !Array.isArray(e) && typeof e.adapterId == "string" && e.adapterId.trim().length > 0 && typeof e.storageId == "string" && e.storageId.trim().length > 0, M = (e) => typeof e == "object" && e != null && !Array.isArray(e) && typeof e.requestId == "string" ? e.requestId : "", oe = (e) => {
152
+ if (typeof e != "object" || e == null || Array.isArray(e))
153
+ return !1;
154
+ const t = e;
155
+ return typeof t.key != "string" ? !1 : t.type === "string" ? typeof t.value == "string" : t.type === "number" ? typeof t.value == "number" : t.type === "boolean" ? typeof t.value == "boolean" : t.type === "buffer" && Array.isArray(t.value) && t.value.every(
156
+ (r) => typeof r == "number" && Number.isInteger(r) && r >= 0 && r <= 255
9
157
  );
10
- if (!o) {
158
+ }, O = (e, t) => e.blacklist ? (e.blacklist.lastIndex = 0, e.blacklist.test(t)) : !1, U = (e, t) => e.find((r) => ne(r.target, t)), ae = async (e, t) => {
159
+ const r = M(t), o = t, n = te(o.snapshot);
160
+ if (typeof o != "object" || o == null || o.type !== "preview-import" || typeof o.requestId != "string" || o.requestId.trim().length === 0 || !R(o.target) || !n.ok)
161
+ return {
162
+ type: "storage-request-error",
163
+ requestId: r,
164
+ code: "INVALID_REQUEST",
165
+ message: "Import preview requests require a valid target, request ID, and snapshot."
166
+ };
167
+ const a = U(e, o.target);
168
+ if (!a)
169
+ return {
170
+ type: "storage-request-error",
171
+ requestId: r,
172
+ code: "TARGET_NOT_FOUND",
173
+ message: "The requested storage target was not found."
174
+ };
175
+ try {
176
+ const i = new Set(await a.getAllKeys());
177
+ return {
178
+ type: "import-preview",
179
+ requestId: r,
180
+ target: a.target,
181
+ preview: se(n.snapshot, {
182
+ target: a.target,
183
+ capabilities: a.capabilities,
184
+ entryKeys: i,
185
+ isBlacklisted: (s) => O(a, s)
186
+ })
187
+ };
188
+ } catch {
189
+ return {
190
+ type: "storage-request-error",
191
+ requestId: r,
192
+ code: "READ_FAILED",
193
+ message: "Failed to inspect the requested storage for import."
194
+ };
195
+ }
196
+ }, ie = async (e, t, r) => {
197
+ const o = M(t), n = t;
198
+ if (typeof n != "object" || n == null || n.type !== "import-entries" || typeof n.requestId != "string" || n.requestId.trim().length === 0 || !R(n.target) || !Array.isArray(n.entries) || !n.entries.every(oe)) {
11
199
  r({
12
200
  type: "import-result",
13
- target: e.target,
201
+ requestId: o,
202
+ target: R(n.target) ? n.target : { adapterId: "", storageId: "" },
14
203
  ok: !1,
15
204
  written: 0,
16
- total: e.entries.length,
205
+ total: 0,
206
+ error: "Import requests require a valid target, request ID, and entries."
207
+ });
208
+ return;
209
+ }
210
+ const a = U(e, n.target);
211
+ if (!a) {
212
+ r({
213
+ type: "import-result",
214
+ requestId: n.requestId,
215
+ target: n.target,
216
+ ok: !1,
217
+ written: 0,
218
+ total: n.entries.length,
17
219
  error: "Target storage not found"
18
220
  });
19
221
  return;
20
222
  }
21
- for (let n = 0; n < e.entries.length; n++) {
22
- const s = e.entries[n];
223
+ const i = n.entries.filter(
224
+ (s) => $(a.capabilities, s.type) && !O(a, s.key)
225
+ );
226
+ for (let s = 0; s < i.length; s++) {
227
+ const c = i[s];
23
228
  try {
24
- await o.set(s);
25
- } catch (i) {
229
+ await a.set(c);
230
+ } catch (d) {
231
+ if (s > 0) {
232
+ const g = (await a.getAllKeys()).length;
233
+ r({
234
+ type: "storage-invalidated",
235
+ target: n.target,
236
+ operation: "import",
237
+ entryCount: g
238
+ });
239
+ }
26
240
  r({
27
241
  type: "import-result",
28
- target: e.target,
242
+ requestId: n.requestId,
243
+ target: n.target,
29
244
  ok: !1,
30
- written: n,
31
- total: e.entries.length,
32
- failedKey: s.key,
33
- error: i instanceof Error ? i.message : String(i)
245
+ written: s,
246
+ total: i.length,
247
+ failedKey: c.key,
248
+ error: d instanceof Error ? d.message : String(d)
34
249
  });
35
250
  return;
36
251
  }
37
252
  r({
38
- type: "set-entry",
39
- target: e.target,
40
- entry: s
253
+ type: "import-progress",
254
+ requestId: n.requestId,
255
+ target: n.target,
256
+ written: s + 1,
257
+ total: i.length
258
+ });
259
+ }
260
+ if (i.length > 0) {
261
+ const s = (await a.getAllKeys()).length;
262
+ r({
263
+ type: "storage-invalidated",
264
+ target: n.target,
265
+ operation: "import",
266
+ entryCount: s
41
267
  });
42
268
  }
43
269
  r({
44
270
  type: "import-result",
45
- target: e.target,
271
+ requestId: n.requestId,
272
+ target: n.target,
46
273
  ok: !0,
47
- written: e.entries.length,
48
- total: e.entries.length
274
+ written: i.length,
275
+ total: i.length
276
+ });
277
+ }, ce = (e) => typeof e == "object" && e != null && !Array.isArray(e) && typeof e.requestId == "string" ? e.requestId : "", de = (e) => typeof e == "object" && e != null && !Array.isArray(e) && e.type === "discover-storages" && typeof e.requestId == "string" && e.requestId.trim().length > 0, ge = async (e) => ({
278
+ target: e.target,
279
+ adapterName: e.adapterName,
280
+ storageName: e.storageName,
281
+ entryCount: (await e.getAllKeys()).length,
282
+ capabilities: e.capabilities,
283
+ supportsSubscriptions: e.supportsSubscriptions
284
+ }), pe = (e) => {
285
+ const t = /* @__PURE__ */ new Set();
286
+ return e.some(({ target: r }) => {
287
+ const o = `${r.adapterId}:${r.storageId}`;
288
+ return t.has(o) ? !0 : (t.add(o), !1);
49
289
  });
50
- }, N = 1500, m = (t) => t.kind === "async", w = (t) => t.type === "buffer" ? `${t.type}:${t.value.join(",")}` : `${t.type}:${String(t.value)}`, K = (t) => new Map(t.map((e) => [e.key, e])), I = (t, e) => t.shouldFilterKey?.(e) ? !0 : t.blacklist ? (t.blacklist.lastIndex = 0, t.blacklist.test(e)) : !1, z = (t, e, r) => {
51
- if (!M(t, e))
290
+ }, ue = async (e, t) => {
291
+ const r = ce(t);
292
+ if (!de(t))
293
+ return {
294
+ type: "storage-request-error",
295
+ requestId: r,
296
+ code: "INVALID_REQUEST",
297
+ message: "Storage discovery requires a non-empty request ID."
298
+ };
299
+ try {
300
+ if (pe(e))
301
+ return {
302
+ type: "storage-request-error",
303
+ requestId: r,
304
+ code: "INVALID_REQUEST",
305
+ message: "Configured storages must have unique targets."
306
+ };
307
+ const o = await Promise.all(e.map(ge));
308
+ return { type: "storage-descriptors", requestId: r, storages: o };
309
+ } catch {
310
+ return {
311
+ type: "storage-request-error",
312
+ requestId: r,
313
+ code: "READ_FAILED",
314
+ message: "Failed to discover configured storages."
315
+ };
316
+ }
317
+ }, ye = 256, k = 16, le = (e) => e.toString(16).toUpperCase().padStart(2, "0"), fe = (e) => {
318
+ let t = "", r = 0;
319
+ for (const o of e) {
320
+ if (r === ye)
321
+ return { preview: t, isTruncated: !0 };
322
+ t += o, r += 1;
323
+ }
324
+ return { preview: t, isTruncated: !1 };
325
+ }, Ie = (e) => {
326
+ if (e.type === "string")
327
+ return {
328
+ key: e.key,
329
+ type: e.type,
330
+ ...fe(e.value),
331
+ // JavaScript strings expose their length in UTF-16 code units.
332
+ valueSize: e.value.length
333
+ };
334
+ if (e.type === "buffer") {
335
+ const r = e.value.slice(0, k);
336
+ return {
337
+ key: e.key,
338
+ type: e.type,
339
+ preview: r.map(le).join(" "),
340
+ valueSize: e.value.length,
341
+ isTruncated: e.value.length > k
342
+ };
343
+ }
344
+ const t = String(e.value);
345
+ return {
346
+ key: e.key,
347
+ type: e.type,
348
+ preview: t,
349
+ valueSize: t.length,
350
+ isTruncated: !1
351
+ };
352
+ }, me = 100, he = 4, we = (e) => typeof e == "object" && e != null && !Array.isArray(e) && typeof e.requestId == "string" ? e.requestId : "", L = (e) => typeof e == "object" && e != null && !Array.isArray(e) && typeof e.adapterId == "string" && e.adapterId.trim().length > 0 && typeof e.storageId == "string" && e.storageId.trim().length > 0, be = (e) => (e ?? "").trim().toLowerCase(), Ee = (e) => {
353
+ if (typeof e != "object" || e == null || Array.isArray(e) || e.type !== "list-entry-previews" || typeof e.requestId != "string" || e.requestId.trim().length === 0 || !L(e.target) || e.search !== void 0 && typeof e.search != "string" || e.cursor !== void 0 && typeof e.cursor != "string" || !Number.isFinite(e.limit) || !Number.isInteger(e.limit) || e.limit < 1)
354
+ return;
355
+ const t = e.keySortDirection;
356
+ if (t !== void 0 && t !== "ascending" && t !== "descending")
357
+ return;
358
+ const r = e;
359
+ return {
360
+ ...r,
361
+ search: be(r.search),
362
+ keySortDirection: t ?? "ascending",
363
+ limit: Math.min(r.limit, me)
364
+ };
365
+ }, D = (e) => btoa(encodeURIComponent(JSON.stringify(e))), Ae = (e) => {
366
+ try {
367
+ const t = JSON.parse(decodeURIComponent(atob(e)));
368
+ return typeof t != "object" || t == null || Array.isArray(t) || t.version !== 1 || !L(t.target) || typeof t.search != "string" || t.keySortDirection !== "ascending" && t.keySortDirection !== "descending" || typeof t.boundaryKey != "string" || t.direction !== "next" && t.direction !== "previous" ? void 0 : t;
369
+ } catch {
370
+ return;
371
+ }
372
+ }, x = (e, t) => e.adapterId === t.adapterId && e.storageId === t.storageId, qe = (e, t) => e < t ? -1 : e > t ? 1 : 0, Se = async (e, t) => {
373
+ const r = new Array(t.length);
374
+ let o = 0;
375
+ const n = async () => {
376
+ for (; o < t.length; ) {
377
+ const a = o;
378
+ o += 1;
379
+ const i = await e.get(t[a]);
380
+ i && (r[a] = Ie(i));
381
+ }
382
+ };
383
+ return await Promise.all(
384
+ Array.from({ length: Math.min(he, t.length) }, n)
385
+ ), r.filter((a) => a != null);
386
+ }, ve = async (e, t) => {
387
+ const r = we(t), o = Ee(t);
388
+ if (!o)
389
+ return {
390
+ type: "storage-request-error",
391
+ requestId: r,
392
+ code: "INVALID_REQUEST",
393
+ message: "Entry preview requests require a valid target, request ID, and positive integer limit."
394
+ };
395
+ const n = e.find((i) => x(i.target, o.target));
396
+ if (!n)
397
+ return {
398
+ type: "storage-request-error",
399
+ requestId: r,
400
+ code: "TARGET_NOT_FOUND",
401
+ message: "The requested storage target was not found."
402
+ };
403
+ let a;
404
+ if (o.cursor !== void 0 && (a = Ae(o.cursor), !a || !x(a.target, o.target) || a.search !== o.search || a.keySortDirection !== o.keySortDirection))
405
+ return {
406
+ type: "storage-request-error",
407
+ requestId: r,
408
+ code: "INVALID_CURSOR",
409
+ message: "The entry preview cursor is invalid or belongs to a different query.",
410
+ resetPagination: !0
411
+ };
412
+ try {
413
+ const i = (await n.getAllKeys()).filter((l) => l.toLowerCase().includes(o.search)).sort(qe);
414
+ o.keySortDirection === "descending" && i.reverse();
415
+ let s = 0;
416
+ if (a) {
417
+ const l = i.indexOf(a.boundaryKey);
418
+ if (l === -1)
419
+ return {
420
+ type: "storage-request-error",
421
+ requestId: r,
422
+ code: "INVALID_CURSOR",
423
+ message: "The entry preview cursor is stale after storage changes.",
424
+ resetPagination: !0
425
+ };
426
+ s = a.direction === "next" ? l + 1 : Math.max(0, l - o.limit);
427
+ }
428
+ const c = i.slice(s, s + o.limit), d = await Se(n, c), g = s + c.length, u = {
429
+ version: 1,
430
+ target: o.target,
431
+ search: o.search,
432
+ keySortDirection: o.keySortDirection
433
+ };
434
+ return {
435
+ type: "entry-previews",
436
+ requestId: r,
437
+ target: o.target,
438
+ items: d,
439
+ ...g < i.length && c.length > 0 ? {
440
+ nextCursor: D({
441
+ ...u,
442
+ boundaryKey: c.at(-1),
443
+ direction: "next"
444
+ })
445
+ } : {},
446
+ ...s > 0 && c.length > 0 ? {
447
+ previousCursor: D({
448
+ ...u,
449
+ boundaryKey: c[0],
450
+ direction: "previous"
451
+ })
452
+ } : {}
453
+ };
454
+ } catch {
455
+ return {
456
+ type: "storage-request-error",
457
+ requestId: r,
458
+ code: "READ_FAILED",
459
+ message: "Failed to read entry previews from the requested storage."
460
+ };
461
+ }
462
+ }, Te = (e) => typeof e == "object" && e != null && !Array.isArray(e) && typeof e.requestId == "string" ? e.requestId : "", Re = (e) => typeof e == "object" && e != null && !Array.isArray(e) && typeof e.adapterId == "string" && e.adapterId.trim().length > 0 && typeof e.storageId == "string" && e.storageId.trim().length > 0, $e = (e, t) => e.adapterId === t.adapterId && e.storageId === t.storageId, Ne = (e) => typeof e == "object" && e != null && !Array.isArray(e) && e.type === "get-entry" && typeof e.requestId == "string" && e.requestId.trim().length > 0 && Re(e.target) && typeof e.key == "string", ke = async (e, t) => {
463
+ const r = Te(t);
464
+ if (!Ne(t))
465
+ return {
466
+ type: "storage-request-error",
467
+ requestId: r,
468
+ code: "INVALID_REQUEST",
469
+ message: "Full entry requests require a valid target, request ID, and string key."
470
+ };
471
+ const o = e.find((n) => $e(n.target, t.target));
472
+ if (!o)
473
+ return {
474
+ type: "storage-request-error",
475
+ requestId: r,
476
+ code: "TARGET_NOT_FOUND",
477
+ message: "The requested storage target was not found."
478
+ };
479
+ try {
480
+ const n = await o.get(t.key);
481
+ return n ? {
482
+ type: "entry",
483
+ requestId: r,
484
+ target: o.target,
485
+ entry: n
486
+ } : {
487
+ type: "storage-request-error",
488
+ requestId: r,
489
+ code: "ENTRY_NOT_FOUND",
490
+ message: "The requested storage entry was not found."
491
+ };
492
+ } catch {
493
+ return {
494
+ type: "storage-request-error",
495
+ requestId: r,
496
+ code: "READ_FAILED",
497
+ message: "Failed to read the requested storage entry."
498
+ };
499
+ }
500
+ }, De = (e) => typeof e == "object" && e != null && !Array.isArray(e) && typeof e.requestId == "string" ? e.requestId : "", xe = (e) => typeof e == "object" && e != null && !Array.isArray(e) && typeof e.adapterId == "string" && e.adapterId.trim().length > 0 && typeof e.storageId == "string" && e.storageId.trim().length > 0, _e = (e, t) => e.adapterId === t.adapterId && e.storageId === t.storageId, Pe = (e) => typeof e == "object" && e != null && !Array.isArray(e) && e.type === "export-snapshot" && typeof e.requestId == "string" && e.requestId.trim().length > 0 && xe(e.target), je = async (e, t) => {
501
+ const r = De(t);
502
+ if (!Pe(t))
503
+ return {
504
+ type: "storage-request-error",
505
+ requestId: r,
506
+ code: "INVALID_REQUEST",
507
+ message: "Export requests require a valid target and request ID."
508
+ };
509
+ const o = e.find((n) => _e(n.target, t.target));
510
+ if (!o)
511
+ return {
512
+ type: "storage-request-error",
513
+ requestId: r,
514
+ code: "TARGET_NOT_FOUND",
515
+ message: "The requested storage target was not found."
516
+ };
517
+ try {
518
+ const n = await o.getAllEntries();
519
+ return {
520
+ type: "export-snapshot-result",
521
+ requestId: r,
522
+ target: o.target,
523
+ snapshot: re({
524
+ target: o.target,
525
+ adapterName: o.adapterName,
526
+ storageName: o.storageName,
527
+ capabilities: o.capabilities,
528
+ entries: n
529
+ })
530
+ };
531
+ } catch {
532
+ return {
533
+ type: "storage-request-error",
534
+ requestId: r,
535
+ code: "READ_FAILED",
536
+ message: "Failed to export the requested storage."
537
+ };
538
+ }
539
+ }, v = (e) => e.kind === "async", q = (e, t) => e.shouldFilterKey?.(t) ? !0 : e.blacklist ? (e.blacklist.lastIndex = 0, e.blacklist.test(t)) : !1, Fe = (e, t, r) => {
540
+ if (!$(e, t))
52
541
  throw new Error(
53
- `Type "${e}" is not supported by storage "${r.storageId}" in adapter "${r.adapterId}".`
542
+ `Type "${t}" is not supported by storage "${r.storageId}" in adapter "${r.adapterId}".`
54
543
  );
55
- }, b = async (t) => (m(t), t.getAllKeys()), E = async (t, e) => (m(t), t.get(e)), j = async (t, e) => {
56
- if (m(t)) {
57
- await t.set(e);
544
+ }, _ = async (e) => (v(e), e.getAllKeys()), P = async (e, t) => (v(e), e.get(t)), Ce = async (e, t) => {
545
+ if (v(e)) {
546
+ await e.set(t);
58
547
  return;
59
548
  }
60
- t.set(e);
61
- }, F = async (t, e) => {
62
- if (m(t)) {
63
- await t.delete(e);
549
+ e.set(t);
550
+ }, Ke = async (e, t) => {
551
+ if (v(e)) {
552
+ await e.delete(t);
64
553
  return;
65
554
  }
66
- t.delete(e);
67
- }, S = async (t) => {
68
- const e = await t();
69
- return K(e);
70
- }, V = (t, e, r) => {
71
- e.forEach((o, n) => {
72
- const s = t.get(n);
73
- if (!s) {
74
- r.onSet(o);
75
- return;
76
- }
77
- w(s) !== w(o) && r.onSet(o);
78
- }), t.forEach((o, n) => {
79
- e.has(n) || r.onDelete(n);
80
- });
81
- }, _ = async (t, e) => {
82
- let r = await S(t);
83
- const o = setInterval(async () => {
84
- try {
85
- const n = await S(t);
86
- V(r, n, e), r = n;
87
- } catch {
88
- }
89
- }, N);
90
- return {
91
- remove: () => {
92
- clearInterval(o);
93
- }
94
- };
95
- }, D = (t, e) => {
96
- const r = e.storage, o = {
97
- adapterId: t.id,
98
- storageId: e.id
99
- }, n = async (i) => {
100
- if (!I(e, i))
101
- return E(r, i);
102
- }, s = async () => {
103
- const i = await b(r);
555
+ e.delete(t);
556
+ }, Me = async (e) => {
557
+ await e.clear();
558
+ }, Oe = (e, t) => {
559
+ const r = t.storage, o = r.subscribe, n = /* @__PURE__ */ new Set();
560
+ let a = !1;
561
+ const i = {
562
+ adapterId: e.id,
563
+ storageId: t.id
564
+ }, s = async (d) => {
565
+ if (!q(t, d))
566
+ return P(r, d);
567
+ }, c = async () => {
568
+ const d = await _(r);
104
569
  return (await Promise.all(
105
- i.filter((l) => !I(e, l)).map((l) => E(r, l))
106
- )).filter((l) => !!l);
570
+ d.filter((u) => !q(t, u)).map((u) => P(r, u))
571
+ )).filter((u) => !!u);
107
572
  };
108
573
  return {
109
- id: R(o),
110
- target: o,
111
- adapterName: t.name,
112
- storageName: e.name,
113
- capabilities: e.capabilities,
114
- blacklist: e.blacklist,
115
- get: n,
116
- set: async (i) => {
117
- z(e.capabilities, i.type, o), await j(r, i);
574
+ id: B(i),
575
+ target: i,
576
+ adapterName: e.name,
577
+ storageName: t.name,
578
+ capabilities: t.capabilities,
579
+ supportsSubscriptions: o != null,
580
+ blacklist: t.blacklist,
581
+ get: s,
582
+ set: async (d) => {
583
+ Fe(t.capabilities, d.type, i), n.add(d.key);
584
+ try {
585
+ await Ce(r, d);
586
+ } finally {
587
+ n.delete(d.key);
588
+ }
118
589
  },
119
- delete: async (i) => {
120
- await F(r, i);
590
+ delete: async (d) => {
591
+ n.add(d);
592
+ try {
593
+ await Ke(r, d);
594
+ } finally {
595
+ n.delete(d);
596
+ }
121
597
  },
122
- getAllKeys: async () => (await b(r)).filter((a) => !I(e, a)),
123
- getAllEntries: s,
124
- watch: async ({ onSet: i, onDelete: a }) => r.subscribe ? r.subscribe(async (l) => {
598
+ purge: async () => {
599
+ a = !0;
125
600
  try {
126
- const d = await n(l);
127
- if (!d) {
128
- a(l);
129
- return;
130
- }
131
- i(d);
132
- } catch {
601
+ await Me(r);
602
+ } finally {
603
+ a = !1;
133
604
  }
134
- }) : _(s, { onSet: i, onDelete: a })
605
+ },
606
+ getAllKeys: async () => (await _(r)).filter((g) => !q(t, g)),
607
+ getAllEntries: c,
608
+ ...o ? {
609
+ watch: async (d) => o((g) => {
610
+ !a && !n.has(g) && !q(t, g) && d(g);
611
+ })
612
+ } : {}
135
613
  };
136
- }, q = (t) => t.flatMap(
137
- (e) => e.storages.map(
138
- (r) => D(e, r)
139
- )
140
- ), f = {
614
+ }, Ue = (e) => e.flatMap(
615
+ (t) => t.storages.map((r) => Oe(t, r))
616
+ ), E = {
141
617
  adapterId: {
142
618
  type: "string",
143
619
  description: "Storage adapter ID. Required when multiple adapters are configured."
@@ -146,58 +622,67 @@ const x = async (t, e, r) => {
146
622
  type: "string",
147
623
  description: "Storage node ID within the adapter. Required when multiple storages are configured."
148
624
  }
149
- }, u = "@rozenite/storage-plugin", $ = [
625
+ }, m = "@rozenite/storage-plugin", j = [
150
626
  "string",
151
627
  "number",
152
628
  "boolean",
153
629
  "buffer"
154
- ], y = {
155
- listStorages: g({
630
+ ], h = {
631
+ listStorages: b({
156
632
  name: "list-storages",
157
- description: "List all storage adapters and their storage nodes currently available on the device, including supported entry types and entry counts.",
633
+ description: "List all storage adapters and their storage nodes currently available on the device, including supported entry types. Entry counts are omitted to avoid enumerating every storage.",
158
634
  inputSchema: { type: "object", properties: {} }
159
635
  }),
160
- listEntries: g({
636
+ listEntries: Y({
161
637
  name: "list-entries",
162
638
  description: "List keys in a storage. This call intentionally does not return entry values to keep responses token-efficient.",
163
639
  inputSchema: {
164
640
  type: "object",
165
641
  properties: {
166
- ...f,
167
- offset: {
642
+ ...E,
643
+ limit: {
168
644
  type: "number",
169
- description: "Pagination offset. Defaults to 0."
645
+ description: "Pagination size. Defaults to 20 and is capped at 100."
170
646
  },
171
- limit: {
647
+ cursor: {
648
+ type: "string",
649
+ description: "Opaque pagination cursor from a previous list-entries call."
650
+ },
651
+ offset: {
172
652
  type: "number",
173
- description: "Pagination size. Defaults to 100."
653
+ description: "Deprecated initial pagination offset. Must be a non-negative integer and cannot be combined with cursor."
174
654
  }
175
655
  }
656
+ },
657
+ pagination: {
658
+ kind: "cursor",
659
+ fields: ["key"],
660
+ defaultFields: ["key"]
176
661
  }
177
662
  }),
178
- readEntry: g({
663
+ readEntry: b({
179
664
  name: "read-entry",
180
665
  description: "Read a single storage entry value by key.",
181
666
  inputSchema: {
182
667
  type: "object",
183
668
  properties: {
184
- ...f,
669
+ ...E,
185
670
  key: { type: "string", description: "Entry key." }
186
671
  },
187
672
  required: ["key"]
188
673
  }
189
674
  }),
190
- createEntry: g({
675
+ createEntry: b({
191
676
  name: "create-entry",
192
677
  description: "Create a new storage entry. Fails if the key already exists.",
193
678
  inputSchema: {
194
679
  type: "object",
195
680
  properties: {
196
- ...f,
681
+ ...E,
197
682
  key: { type: "string", description: "Entry key." },
198
683
  type: {
199
684
  type: "string",
200
- enum: [...$],
685
+ enum: [...j],
201
686
  description: "Entry value type. Must be one of the supported types for the target storage (see list-storages)."
202
687
  },
203
688
  value: {
@@ -207,17 +692,17 @@ const x = async (t, e, r) => {
207
692
  required: ["key", "type", "value"]
208
693
  }
209
694
  }),
210
- editEntry: g({
695
+ editEntry: b({
211
696
  name: "edit-entry",
212
697
  description: "Edit an existing storage entry. Fails if the key does not exist.",
213
698
  inputSchema: {
214
699
  type: "object",
215
700
  properties: {
216
- ...f,
701
+ ...E,
217
702
  key: { type: "string", description: "Entry key." },
218
703
  type: {
219
704
  type: "string",
220
- enum: [...$],
705
+ enum: [...j],
221
706
  description: "Entry value type. Must be one of the supported types for the target storage (see list-storages)."
222
707
  },
223
708
  value: {
@@ -227,292 +712,326 @@ const x = async (t, e, r) => {
227
712
  required: ["key", "type", "value"]
228
713
  }
229
714
  }),
230
- removeEntry: g({
715
+ removeEntry: b({
231
716
  name: "remove-entry",
232
717
  description: "Remove a storage entry by key.",
233
718
  inputSchema: {
234
719
  type: "object",
235
720
  properties: {
236
- ...f,
721
+ ...E,
237
722
  key: { type: "string", description: "Entry key." }
238
723
  },
239
724
  required: ["key"]
240
725
  }
241
726
  })
242
- }, k = (t, e) => {
243
- if (t === "string") {
244
- if (typeof e != "string")
727
+ }, F = (e, t) => {
728
+ if (e === "string") {
729
+ if (typeof t != "string")
245
730
  throw new Error("Expected string value for type=string");
246
- return e;
731
+ return t;
247
732
  }
248
- if (t === "number") {
249
- if (typeof e != "number" || Number.isNaN(e))
733
+ if (e === "number") {
734
+ if (typeof t != "number" || Number.isNaN(t))
250
735
  throw new Error("Expected number value for type=number");
251
- return e;
736
+ return t;
252
737
  }
253
- if (t === "boolean") {
254
- if (typeof e != "boolean")
738
+ if (e === "boolean") {
739
+ if (typeof t != "boolean")
255
740
  throw new Error("Expected boolean value for type=boolean");
256
- return e;
741
+ return t;
257
742
  }
258
- if (!Array.isArray(e) || !e.every((r) => Number.isInteger(r)))
743
+ if (!Array.isArray(t) || !t.every((r) => Number.isInteger(r)))
259
744
  throw new Error("Expected number[] value for type=buffer");
260
- return e;
261
- }, h = (t) => `${t.target.adapterId}/${t.target.storageId}`, L = (t) => {
262
- const e = A(
263
- (r, o) => {
264
- if (t.length === 0)
265
- throw new Error("No storages are registered.");
266
- if (r !== void 0 || o !== void 0) {
267
- const n = t.find(
268
- (s) => (r === void 0 || s.target.adapterId === r) && (o === void 0 || s.target.storageId === o)
269
- );
270
- if (!n) {
271
- const s = [
272
- r && `adapterId="${r}"`,
273
- o && `storageId="${o}"`
274
- ].filter(Boolean).join(", ");
275
- throw new Error(
276
- `No storage matched ${s}. Available: ${t.map(h).join(", ")}`
277
- );
278
- }
279
- return n;
280
- }
281
- if (t.length > 1)
282
- throw new Error(
283
- `Multiple storages detected. Provide adapterId and/or storageId. Available: ${t.map(h).join(", ")}`
284
- );
285
- return t[0];
286
- },
287
- [t]
288
- );
289
- p({
290
- pluginId: u,
291
- tool: y.listStorages,
292
- handler: async () => ({
293
- storages: await Promise.all(
294
- t.map(async (r) => ({
295
- adapterId: r.target.adapterId,
296
- storageId: r.target.storageId,
297
- adapterName: r.adapterName,
298
- storageName: r.storageName,
299
- supportedTypes: r.capabilities.supportedTypes,
300
- entryCount: (await r.getAllKeys()).length
301
- }))
302
- )
303
- })
304
- }), p({
305
- pluginId: u,
306
- tool: y.listEntries,
307
- handler: async ({ adapterId: r, storageId: o, offset: n = 0, limit: s = 100 }) => {
308
- const i = e(r, o), a = await i.getAllKeys(), l = Math.max(0, Math.floor(n)), d = Math.max(1, Math.floor(s)), c = a.slice(l, l + d);
309
- return {
310
- adapterId: i.target.adapterId,
311
- storageId: i.target.storageId,
312
- total: a.length,
313
- offset: l,
314
- limit: d,
315
- keys: c
316
- };
745
+ return t;
746
+ }, w = (e) => `${e.target.adapterId}/${e.target.storageId}`, Le = (e, t) => e.adapterId === t.adapterId && e.storageId === t.storageId, Ve = (e) => btoa(encodeURIComponent(JSON.stringify(e))), ze = (e) => {
747
+ try {
748
+ const t = JSON.parse(decodeURIComponent(atob(e)));
749
+ if (typeof t != "object" || t == null || Array.isArray(t) || t.version !== 1 || typeof t.target?.adapterId != "string" || typeof t.target?.storageId != "string" || !Number.isSafeInteger(t.offset) || t.offset < 0)
750
+ throw new Error("Invalid cursor");
751
+ return t;
752
+ } catch {
753
+ throw new Error(
754
+ "Invalid cursor. Run list-entries again without a cursor to restart pagination."
755
+ );
756
+ }
757
+ }, Ge = (e) => typeof e != "number" || !Number.isFinite(e) || !Number.isInteger(e) || e < 1 ? Q : Math.min(e, J), Be = (e) => typeof e != "number" || !Number.isFinite(e) || !Number.isSafeInteger(e) || e < 0 ? 0 : e, A = (e, t, r) => {
758
+ if (e.length === 0)
759
+ throw new Error("No storages are registered.");
760
+ if (t !== void 0 || r !== void 0) {
761
+ const o = e.filter(
762
+ (a) => (t === void 0 || a.target.adapterId === t) && (r === void 0 || a.target.storageId === r)
763
+ ), n = [
764
+ t !== void 0 && `adapterId="${t}"`,
765
+ r !== void 0 && `storageId="${r}"`
766
+ ].filter(Boolean).join(", ");
767
+ if (o.length === 0)
768
+ throw new Error(
769
+ `No storage matched ${n}. Available: ${e.map(w).join(", ")}`
770
+ );
771
+ if (o.length > 1)
772
+ throw new Error(
773
+ `Multiple storages matched ${n}. Provide both adapterId and storageId. Available: ${o.map(w).join(", ")}`
774
+ );
775
+ return o[0];
776
+ }
777
+ if (e.length > 1)
778
+ throw new Error(
779
+ `Multiple storages detected. Provide adapterId and/or storageId. Available: ${e.map(w).join(", ")}`
780
+ );
781
+ return e[0];
782
+ }, Ye = async (e, t) => {
783
+ const r = Ge(t.limit);
784
+ if (t.cursor !== void 0 && t.offset !== void 0)
785
+ throw new Error("Provide either cursor or offset, not both.");
786
+ const o = t.cursor === void 0 ? void 0 : ze(t.cursor);
787
+ if (o && !Le(o.target, e.target))
788
+ throw new Error(
789
+ "Cursor does not match the requested storage. Run list-entries again without a cursor to restart pagination."
790
+ );
791
+ const n = await e.getAllKeys(), a = o?.offset ?? Be(t.offset), i = Math.min(a + r, n.length);
792
+ return {
793
+ adapterId: e.target.adapterId,
794
+ storageId: e.target.storageId,
795
+ total: n.length,
796
+ items: n.slice(a, i).map((s) => ({ key: s })),
797
+ page: {
798
+ limit: r,
799
+ hasMore: i < n.length,
800
+ ...i < n.length ? {
801
+ nextCursor: Ve({
802
+ version: 1,
803
+ target: e.target,
804
+ offset: i
805
+ })
806
+ } : {}
317
807
  }
318
- }), p({
319
- pluginId: u,
320
- tool: y.readEntry,
321
- handler: async ({ adapterId: r, storageId: o, key: n }) => {
322
- const s = e(r, o), i = await s.get(n);
323
- if (!i)
808
+ };
809
+ }, Qe = (e) => ({
810
+ listStorages: async () => ({
811
+ storages: e.map((t) => ({
812
+ adapterId: t.target.adapterId,
813
+ storageId: t.target.storageId,
814
+ adapterName: t.adapterName,
815
+ storageName: t.storageName,
816
+ supportedTypes: t.capabilities.supportedTypes
817
+ }))
818
+ }),
819
+ listEntries: async (t) => {
820
+ const r = A(e, t.adapterId, t.storageId);
821
+ return Ye(r, t);
822
+ },
823
+ readEntry: async ({
824
+ adapterId: t,
825
+ storageId: r,
826
+ key: o
827
+ }) => {
828
+ const n = A(e, t, r), a = await n.get(o);
829
+ if (!a)
830
+ throw new Error(`Key "${o}" not found in storage "${w(n)}".`);
831
+ return {
832
+ adapterId: n.target.adapterId,
833
+ storageId: n.target.storageId,
834
+ entry: a
835
+ };
836
+ }
837
+ }), Je = (e) => {
838
+ const t = Qe(e);
839
+ I({
840
+ pluginId: m,
841
+ tool: h.listStorages,
842
+ handler: t.listStorages
843
+ }), I({
844
+ pluginId: m,
845
+ tool: h.listEntries,
846
+ handler: t.listEntries
847
+ }), I({
848
+ pluginId: m,
849
+ tool: h.readEntry,
850
+ handler: t.readEntry
851
+ }), I({
852
+ pluginId: m,
853
+ tool: h.createEntry,
854
+ handler: async ({ adapterId: r, storageId: o, key: n, type: a, value: i }) => {
855
+ const s = A(e, r, o);
856
+ if (await s.get(n))
324
857
  throw new Error(
325
- `Key "${n}" not found in storage "${h(s)}".`
858
+ `Key "${n}" already exists in storage "${w(s)}". Use edit-entry instead.`
326
859
  );
327
- return {
860
+ const d = F(a, i);
861
+ return await s.set({ key: n, type: a, value: d }), {
328
862
  adapterId: s.target.adapterId,
329
863
  storageId: s.target.storageId,
330
- entry: i
331
- };
332
- }
333
- }), p({
334
- pluginId: u,
335
- tool: y.createEntry,
336
- handler: async ({ adapterId: r, storageId: o, key: n, type: s, value: i }) => {
337
- const a = e(r, o);
338
- if (await a.get(n))
339
- throw new Error(
340
- `Key "${n}" already exists in storage "${h(a)}". Use edit-entry instead.`
341
- );
342
- const d = k(s, i);
343
- return await a.set({ key: n, type: s, value: d }), {
344
- adapterId: a.target.adapterId,
345
- storageId: a.target.storageId,
346
864
  created: !0,
347
865
  key: n
348
866
  };
349
867
  }
350
- }), p({
351
- pluginId: u,
352
- tool: y.editEntry,
353
- handler: async ({ adapterId: r, storageId: o, key: n, type: s, value: i }) => {
354
- const a = e(r, o);
355
- if (!await a.get(n))
868
+ }), I({
869
+ pluginId: m,
870
+ tool: h.editEntry,
871
+ handler: async ({ adapterId: r, storageId: o, key: n, type: a, value: i }) => {
872
+ const s = A(e, r, o);
873
+ if (!await s.get(n))
356
874
  throw new Error(
357
- `Key "${n}" not found in storage "${h(a)}". Use create-entry instead.`
875
+ `Key "${n}" not found in storage "${w(s)}". Use create-entry instead.`
358
876
  );
359
- const d = k(s, i);
360
- return await a.set({ key: n, type: s, value: d }), {
361
- adapterId: a.target.adapterId,
362
- storageId: a.target.storageId,
877
+ const d = F(a, i);
878
+ return await s.set({ key: n, type: a, value: d }), {
879
+ adapterId: s.target.adapterId,
880
+ storageId: s.target.storageId,
363
881
  edited: !0,
364
882
  key: n
365
883
  };
366
884
  }
367
- }), p({
368
- pluginId: u,
369
- tool: y.removeEntry,
885
+ }), I({
886
+ pluginId: m,
887
+ tool: h.removeEntry,
370
888
  handler: async ({ adapterId: r, storageId: o, key: n }) => {
371
- const s = e(r, o), i = !!await s.get(n);
372
- return await s.delete(n), {
373
- adapterId: s.target.adapterId,
374
- storageId: s.target.storageId,
889
+ const a = A(e, r, o), i = !!await a.get(n);
890
+ return await a.delete(n), {
891
+ adapterId: a.target.adapterId,
892
+ storageId: a.target.storageId,
375
893
  removed: i,
376
894
  key: n
377
895
  };
378
896
  }
379
897
  });
380
- }, B = ({
381
- storages: t
382
- }) => {
383
- const e = T(() => q(t), [t]);
384
- L(e);
385
- const r = v({
898
+ }, tt = ({ storages: e }) => {
899
+ const t = z(() => Ue(e), [e]);
900
+ Je(t);
901
+ const r = V({
386
902
  pluginId: "@rozenite/storage-plugin"
387
903
  });
388
- return P(() => {
904
+ return G(() => {
389
905
  if (!r)
390
906
  return;
391
- const o = async (a) => {
392
- const l = a ? e.filter((d) => d.id === a) : e;
393
- for (const d of l)
394
- try {
395
- const c = await d.getAllEntries();
396
- r.send("snapshot", {
397
- type: "snapshot",
398
- target: d.target,
399
- adapterName: d.adapterName,
400
- storageName: d.storageName,
401
- capabilities: d.capabilities,
402
- blacklist: d.blacklist ? { source: d.blacklist.source, flags: d.blacklist.flags } : void 0,
403
- entries: c
404
- });
405
- } catch (c) {
406
- console.warn(
407
- `[Rozenite] Storage Plugin: Failed to snapshot ${d.target.adapterId}/${d.target.storageId}.`,
408
- c
409
- );
410
- }
907
+ const o = [];
908
+ let n = !1;
909
+ const a = async (s, c, d) => {
910
+ const g = t.find(
911
+ (l) => l.target.adapterId === s.adapterId && l.target.storageId === s.storageId
912
+ ), u = g ? (await g.getAllKeys()).length : 0;
913
+ r.send("storage-invalidated", {
914
+ type: "storage-invalidated",
915
+ target: s,
916
+ key: c,
917
+ operation: d,
918
+ entryCount: u
919
+ });
411
920
  };
412
- o();
413
- const n = [];
414
- let s = !1;
415
921
  Promise.all(
416
- e.map(async (a) => {
922
+ t.filter((s) => s.supportsSubscriptions && s.watch).map(async (s) => {
417
923
  try {
418
- const l = await a.watch({
419
- onSet: (d) => {
420
- r.send("set-entry", {
421
- type: "set-entry",
422
- target: a.target,
423
- entry: d
424
- });
425
- },
426
- onDelete: (d) => {
427
- r.send("delete-entry", {
428
- type: "delete-entry",
429
- target: a.target,
430
- key: d
431
- });
432
- }
924
+ const c = s.watch;
925
+ if (!c)
926
+ return;
927
+ const d = await c((g) => {
928
+ a(s.target, g);
433
929
  });
434
- if (s) {
435
- l.remove();
930
+ if (n) {
931
+ d.remove();
436
932
  return;
437
933
  }
438
- n.push(l);
439
- } catch (l) {
934
+ o.push(d);
935
+ } catch (c) {
440
936
  console.warn(
441
- `[Rozenite] Storage Plugin: Failed to attach watcher for ${a.target.adapterId}/${a.target.storageId}.`,
442
- l
937
+ `[Rozenite] Storage Plugin: Failed to attach watcher for ${s.target.adapterId}/${s.target.storageId}.`,
938
+ c
443
939
  );
444
940
  }
445
941
  })
446
942
  );
447
943
  const i = [
448
- r.onMessage(
449
- "set-entry",
450
- async ({ target: a, entry: l }) => {
451
- const d = e.find(
452
- (c) => c.target.adapterId === a.adapterId && c.target.storageId === a.storageId
944
+ r.onMessage("set-entry", async ({ target: s, entry: c }) => {
945
+ const d = t.find(
946
+ (g) => g.target.adapterId === s.adapterId && g.target.storageId === s.storageId
947
+ );
948
+ if (!d) {
949
+ console.warn(
950
+ `[Rozenite] Storage Plugin: Storage target not found for ${s.adapterId}/${s.storageId}`
453
951
  );
454
- if (!d) {
455
- console.warn(
456
- `[Rozenite] Storage Plugin: Storage target not found for ${a.adapterId}/${a.storageId}`
457
- );
458
- return;
459
- }
460
- try {
461
- await d.set(l);
462
- } catch (c) {
463
- console.warn(
464
- `[Rozenite] Storage Plugin: Failed to set entry in ${a.adapterId}/${a.storageId}.`,
465
- c
466
- );
467
- }
952
+ return;
468
953
  }
469
- ),
470
- r.onMessage(
471
- "delete-entry",
472
- async ({ target: a, key: l }) => {
473
- const d = e.find(
474
- (c) => c.target.adapterId === a.adapterId && c.target.storageId === a.storageId
954
+ try {
955
+ await d.set(c), await a(d.target, c.key, "set");
956
+ } catch (g) {
957
+ console.warn(
958
+ `[Rozenite] Storage Plugin: Failed to set entry in ${s.adapterId}/${s.storageId}.`,
959
+ g
475
960
  );
476
- if (!d) {
477
- console.warn(
478
- `[Rozenite] Storage Plugin: Storage target not found for ${a.adapterId}/${a.storageId}`
479
- );
480
- return;
481
- }
482
- try {
483
- await d.delete(l);
484
- } catch (c) {
485
- console.warn(
486
- `[Rozenite] Storage Plugin: Failed to delete entry in ${a.adapterId}/${a.storageId}.`,
487
- c
488
- );
489
- }
490
961
  }
491
- ),
492
- r.onMessage(
493
- "get-snapshot",
494
- async ({ target: a }) => {
495
- if (a === "all") {
496
- await o();
497
- return;
498
- }
499
- await o(`${a.adapterId}:${a.storageId}`);
962
+ }),
963
+ r.onMessage("delete-entry", async ({ target: s, key: c }) => {
964
+ const d = t.find(
965
+ (g) => g.target.adapterId === s.adapterId && g.target.storageId === s.storageId
966
+ );
967
+ if (!d) {
968
+ console.warn(
969
+ `[Rozenite] Storage Plugin: Storage target not found for ${s.adapterId}/${s.storageId}`
970
+ );
971
+ return;
500
972
  }
501
- ),
973
+ try {
974
+ await d.delete(c), await a(d.target, c, "delete");
975
+ } catch (g) {
976
+ console.warn(
977
+ `[Rozenite] Storage Plugin: Failed to delete entry in ${s.adapterId}/${s.storageId}.`,
978
+ g
979
+ );
980
+ }
981
+ }),
982
+ r.onMessage("purge-storage", async ({ target: s }) => {
983
+ const c = t.find(
984
+ (d) => d.target.adapterId === s.adapterId && d.target.storageId === s.storageId
985
+ );
986
+ if (!c) {
987
+ console.warn(
988
+ `[Rozenite] Storage Plugin: Storage target not found for ${s.adapterId}/${s.storageId}`
989
+ );
990
+ return;
991
+ }
992
+ try {
993
+ await c.purge(), await a(c.target, void 0, "purge");
994
+ } catch (d) {
995
+ console.warn(
996
+ `[Rozenite] Storage Plugin: Failed to purge storage in ${s.adapterId}/${s.storageId}.`,
997
+ d
998
+ );
999
+ }
1000
+ }),
1001
+ r.onMessage("discover-storages", async (s) => {
1002
+ const c = await ue(t, s);
1003
+ r.send(c.type, c);
1004
+ }),
502
1005
  r.onMessage(
503
- "import-entries",
504
- async (a) => {
505
- await x(e, a, (l) => {
506
- l.type === "set-entry" ? r.send("set-entry", l) : r.send("import-result", l);
507
- });
1006
+ "list-entry-previews",
1007
+ async (s) => {
1008
+ const c = await ve(t, s);
1009
+ r.send(c.type, c);
508
1010
  }
509
- )
1011
+ ),
1012
+ r.onMessage("get-entry", async (s) => {
1013
+ const c = await ke(t, s);
1014
+ r.send(c.type, c);
1015
+ }),
1016
+ r.onMessage("export-snapshot", async (s) => {
1017
+ const c = await je(t, s);
1018
+ r.send(c.type, c);
1019
+ }),
1020
+ r.onMessage("preview-import", async (s) => {
1021
+ const c = await ae(t, s);
1022
+ r.send(c.type, c);
1023
+ }),
1024
+ r.onMessage("import-entries", async (s) => {
1025
+ await ie(t, s, (c) => {
1026
+ r.send(c.type, c);
1027
+ });
1028
+ })
510
1029
  ];
511
- return () => {
512
- s = !0, n.forEach((a) => a.remove()), i.forEach((a) => a.remove());
1030
+ return r.send("device-ready", { type: "device-ready" }), () => {
1031
+ n = !0, o.forEach((s) => s.remove()), i.forEach((s) => s.remove());
513
1032
  };
514
- }, [r, e]), r;
1033
+ }, [r, t]), r;
515
1034
  };
516
1035
  export {
517
- B as useRozeniteStoragePlugin
1036
+ tt as useRozeniteStoragePlugin
518
1037
  };