localspace 0.2.1 → 0.3.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 (60) hide show
  1. package/README.md +98 -12
  2. package/dist/core/plugin-manager.d.ts +48 -0
  3. package/dist/core/plugin-manager.d.ts.map +1 -0
  4. package/dist/core/plugin-manager.js +334 -0
  5. package/dist/drivers/indexeddb.d.ts.map +1 -1
  6. package/dist/drivers/indexeddb.js +398 -322
  7. package/dist/drivers/localstorage.d.ts.map +1 -1
  8. package/dist/drivers/localstorage.js +85 -65
  9. package/dist/errors.d.ts +26 -0
  10. package/dist/errors.d.ts.map +1 -0
  11. package/dist/errors.js +54 -0
  12. package/dist/index.cjs.js +1 -1
  13. package/dist/index.cjs.js.map +1 -1
  14. package/dist/index.d.ts +10 -2
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.esm.js +1 -1
  17. package/dist/index.esm.js.map +1 -1
  18. package/dist/index.js +9 -1
  19. package/dist/index.umd.js +1 -1
  20. package/dist/index.umd.js.map +1 -1
  21. package/dist/localspace.d.ts +17 -3
  22. package/dist/localspace.d.ts.map +1 -1
  23. package/dist/localspace.js +547 -241
  24. package/dist/plugins/compression.d.ts +16 -0
  25. package/dist/plugins/compression.d.ts.map +1 -0
  26. package/dist/plugins/compression.js +59 -0
  27. package/dist/plugins/encryption.d.ts +26 -0
  28. package/dist/plugins/encryption.d.ts.map +1 -0
  29. package/dist/plugins/encryption.js +136 -0
  30. package/dist/plugins/quota.d.ts +22 -0
  31. package/dist/plugins/quota.d.ts.map +1 -0
  32. package/dist/plugins/quota.js +162 -0
  33. package/dist/plugins/sync.d.ts +16 -0
  34. package/dist/plugins/sync.d.ts.map +1 -0
  35. package/dist/plugins/sync.js +182 -0
  36. package/dist/plugins/ttl.d.ts +14 -0
  37. package/dist/plugins/ttl.d.ts.map +1 -0
  38. package/dist/plugins/ttl.js +94 -0
  39. package/dist/types.d.ts +71 -1
  40. package/dist/types.d.ts.map +1 -1
  41. package/dist/types.js +1 -1
  42. package/dist/utils/helpers.d.ts.map +1 -1
  43. package/dist/utils/helpers.js +7 -8
  44. package/dist/utils/serializer.d.ts.map +1 -1
  45. package/dist/utils/serializer.js +40 -37
  46. package/package.json +12 -3
  47. package/src/core/plugin-manager.ts +522 -0
  48. package/src/drivers/indexeddb.ts +305 -120
  49. package/src/drivers/localstorage.ts +251 -152
  50. package/src/errors.ts +120 -0
  51. package/src/index.ts +27 -0
  52. package/src/localspace.ts +446 -26
  53. package/src/plugins/compression.ts +97 -0
  54. package/src/plugins/encryption.ts +254 -0
  55. package/src/plugins/quota.ts +244 -0
  56. package/src/plugins/sync.ts +267 -0
  57. package/src/plugins/ttl.ts +146 -0
  58. package/src/types.ts +122 -1
  59. package/src/utils/helpers.ts +8 -5
  60. package/src/utils/serializer.ts +30 -6
package/README.md CHANGED
@@ -54,23 +54,21 @@ localspace is built on a foundation designed for growth. Here's what's planned:
54
54
  - [x] Batch operations (`setItems()`, `getItems()`, `removeItems()`) for higher throughput
55
55
  - [x] Automatic write coalescing (3-10x faster rapid writes, enabled by default)
56
56
  - [x] Connection pooling, transaction batching, and warmup
57
+ - [x] **Improved error handling** - Structured error types with detailed context
57
58
 
58
59
  ### TODO
59
- - [ ] **Improved error handling** - Structured error types with detailed context
60
- - [ ] **Plugin system** - Middleware architecture for cross-cutting concerns
61
- - [ ] **Cache API driver** - Native browser caching with automatic HTTP semantics
60
+ - [x] **Plugin system** - Middleware architecture for cross-cutting concerns
62
61
  - [ ] **OPFS driver** - Origin Private File System for high-performance file storage
63
- - [ ] **Memory driver** - In-memory storage for testing and SSR
64
62
  - [ ] **Custom driver templates** - Documentation and examples for third-party drivers
65
63
  - [ ] **Node.js** - File system and SQLite adapters
66
64
  - [ ] **React Native** - AsyncStorage and SQLite drivers
67
65
  - [ ] **Electron** - Main and renderer process coordination
68
66
  - [ ] **Deno** - Native KV store integration
69
- - [ ] **TTL plugin** - Time-to-live expiration with automatic cleanup
70
- - [ ] **Encryption plugin** - Transparent encryption/decryption with Web Crypto API
71
- - [ ] **Compression plugin** - LZ-string or Brotli compression for large values
72
- - [ ] **Sync plugin** - Multi-tab synchronization with BroadcastChannel
73
- - [ ] **Quota plugin** - Automatic quota management and cleanup strategies
67
+ - [x] **TTL plugin** - Time-to-live expiration with automatic cleanup
68
+ - [x] **Encryption plugin** - Transparent encryption/decryption with Web Crypto API
69
+ - [x] **Compression plugin** - LZ-string or Brotli compression for large values
70
+ - [x] **Sync plugin** - Multi-tab synchronization with BroadcastChannel
71
+ - [x] **Quota plugin** - Automatic quota management and cleanup strategies
74
72
 
75
73
  ### 📊 Community Priorities
76
74
 
@@ -210,6 +208,14 @@ await Promise.all([
210
208
  coalesced.setItem('fast-2', 'b'),
211
209
  ]); // batched into one tx within the window
212
210
 
211
+ // These features work independently and can be combined
212
+ const optimized = localspace.createInstance({
213
+ coalesceWrites: true, // optimizes single-item writes (setItem/removeItem)
214
+ coalesceWindowMs: 8,
215
+ maxBatchSize: 200, // limits batch API chunk size (setItems/removeItems)
216
+ });
217
+ await optimized.setDriver([optimized.INDEXEDDB]);
218
+
213
219
  // Note: localStorage batches are not atomic—writes are applied one by one.
214
220
  // For critical flows, prefer IndexedDB or handle your own compensating logic.
215
221
  ```
@@ -275,6 +281,82 @@ await localspace.setItem('file', file);
275
281
  const restored = await localspace.getItem<Blob>('file');
276
282
  ```
277
283
 
284
+ ## Plugin System
285
+
286
+ localspace now ships with a first-class plugin engine. Attach middleware when creating an instance or call `use()` later; plugins can mutate payloads, observe driver context, and run async interceptors around every storage call.
287
+
288
+ ```ts
289
+ const store = localspace.createInstance({
290
+ name: 'secure-store',
291
+ storeName: 'primary',
292
+ plugins: [
293
+ ttlPlugin({ defaultTTL: 60_000 }),
294
+ encryptionPlugin({ key: '0123456789abcdef0123456789abcdef' }),
295
+ compressionPlugin({ threshold: 1024 }),
296
+ syncPlugin({ channelName: 'localspace-sync' }),
297
+ quotaPlugin({ maxSize: 5 * 1024 * 1024, evictionPolicy: 'lru' }),
298
+ ],
299
+ });
300
+ ```
301
+
302
+ ### Lifecycle and hooks
303
+
304
+ - **Registration** – supply `plugins` when calling `createInstance()` or chain `instance.use(plugin)` later. Each plugin can also expose `enabled` (boolean or function) and `priority` to control execution order.
305
+ - **Lifecycle events** – `onInit(context)` is invoked after `ready()`, and `onDestroy` lets you tear down timers or channels. Call `await instance.destroy()` when disposing of an instance to run every `onDestroy` hook (executed in reverse priority order). Context exposes the active driver, db info, config, and a shared `metadata` bag for cross-plugin coordination.
306
+ - **Interceptors** – hook into `beforeSet/afterSet`, `beforeGet/afterGet`, `beforeRemove/afterRemove`, plus batch-specific methods such as `beforeSetItems` or `beforeGetItems`. Hooks run sequentially: `before*` hooks execute from highest to lowest priority, while `after*` hooks unwind in reverse order so layered transformations (compression → encryption → TTL) remain invertible. Returning a value passes it to the next plugin, while throwing a `LocalSpaceError` aborts the operation.
307
+ - **Per-call state** – plugins can stash data on `context.operationState` (e.g., capture the original value in `beforeSet` and reuse it in `afterSet`). For batch operations, `context.operationState.isBatch` is `true` and `context.operationState.batchSize` provides the total count.
308
+ - **Error handling & init policy** – unexpected exceptions are reported through `plugin.onError`. Throw a `LocalSpaceError` if you need to stop the pipeline (quota violations, failed decryptions, etc.). If a plugin `onInit` throws, the default policy is fail-fast (propagate and abort init). Set `pluginInitPolicy: 'disable-and-continue'` in config to log and skip the failing plugin instead (use with care for critical plugins like encryption).
309
+
310
+ ### Plugin execution order
311
+
312
+ Plugins are sorted by `priority` (higher runs first in `before*`, last in `after*`). Default priorities:
313
+
314
+ | Plugin | Priority | Notes |
315
+ |--------|----------|-------|
316
+ | sync | -100 | Runs last in `afterSet` to broadcast original (untransformed) values |
317
+ | quota | -10 | Runs late so it measures final payload sizes |
318
+ | ttl, encryption, compression | 0 | Default; chain in registration order |
319
+
320
+ **Recommended order**: `[ttlPlugin, encryptionPlugin, compressionPlugin, syncPlugin, quotaPlugin]`
321
+
322
+ ### Built-in plugins
323
+
324
+ #### TTL plugin
325
+ Wraps values as `{ data, expiresAt }`, invalidates stale reads, and optionally runs background cleanup. Options:
326
+
327
+ - `defaultTTL` (ms) and `keyTTL` overrides
328
+ - `cleanupInterval` to periodically scan `iterate()` output
329
+ - `onExpire(key, value)` callback before removal
330
+
331
+ #### Encryption plugin
332
+ Encrypts serialized payloads using the Web Crypto API (AES-GCM by default) and decrypts transparently on reads.
333
+
334
+ - Provide a `key` (CryptoKey/ArrayBuffer/string) or `keyDerivation` block (PBKDF2)
335
+ - Customize `algorithm`, `ivLength`, `ivGenerator`, or `randomSource`
336
+ - Works in browsers and modern Node runtimes (pass your own `subtle` when needed)
337
+
338
+ #### Compression plugin
339
+ Runs LZ-string compression (or a custom codec) when payloads exceed a `threshold` and restores them on read.
340
+
341
+ - `threshold` (bytes) controls when compression kicks in
342
+ - Supply a custom `{ compress, decompress }` codec if you prefer pako/Brotli
343
+
344
+ #### Sync plugin
345
+ Keeps multiple tabs/processes in sync via `BroadcastChannel` (with `storage`-event fallback).
346
+
347
+ - `channelName` separates logical buses
348
+ - `syncKeys` lets you scope which keys broadcast
349
+ - `conflictStrategy` defaults to `last-write-wins`; provide `onConflict` (return `false` to drop remote writes) for merge logic
350
+
351
+ #### Quota plugin
352
+ Tracks approximate storage usage after every mutation and enforces limits.
353
+
354
+ - `maxSize` (bytes) and optional `useNavigatorEstimate` to read the browser’s quota
355
+ - `evictionPolicy: 'error' | 'lru'` (LRU removes least-recently-used keys automatically)
356
+ - `onQuotaExceeded(info)` fires before throwing so you can log/alert users
357
+
358
+ > Tip: place quota plugins last so they see the final payload size after other transformations (TTL, encryption, compression, etc.).
359
+
278
360
  ## Migration Guide
279
361
 
280
362
  ### Note differences from localForage before upgrading
@@ -316,10 +398,11 @@ localspace.setItem('key', 'value', (err, value) => {
316
398
  ```
317
399
 
318
400
  ## Performance notes
319
- - **Automatic write coalescing (enabled by default):** localspace automatically merges rapid single writes within an 8ms window into one transaction, giving you 3-10x performance improvement with zero code changes. This is enabled by default for IndexedDB. Set `coalesceWrites: false` if you need strict per-operation durability.
401
+ - **Automatic write coalescing (enabled by default):** localspace automatically merges rapid single writes (`setItem`/`removeItem`) within an 8ms window into one transaction, giving you 3-10x performance improvement with zero code changes. This is enabled by default for IndexedDB. Set `coalesceWrites: false` if you need strict per-operation durability.
402
+ - **Read-your-writes consistency with coalescing:** Pending coalesced writes are flushed before reads (`getItem`, `getItems`, `iterate`, `keys`, `length`, `key`) and destructive ops (`clear`, `dropInstance`), so immediate reads always observe the latest value. If you need eventual reads for speed, you can switch `coalesceReadConsistency` to `'eventual'`.
320
403
  - **Batch APIs outperform loops:** Playwright benchmark (`test/playwright/benchmark.spec.ts`) on 500 items x 256B showed `setItems()` ~6x faster and `getItems()` ~7.7x faster than per-item loops, with `removeItems()` ~2.8x faster (Chromium, relaxed durability).
321
404
  - **Transaction helpers:** `runTransaction()` lets you co-locate reads/writes in a single transaction for atomic migrations and to shorten lock time.
322
- - **Batch sizing:** Use `maxBatchSize` to split very large batches and keep transaction size in check.
405
+ - **Batch sizing:** Use `maxBatchSize` to split very large batch operations (`setItems`/`removeItems`/`getItems`) and keep transaction size in check. This works independently from `coalesceWrites`, which optimizes single-item operations.
323
406
  - **IndexedDB durability defaults:** Chrome 121+ uses relaxed durability by default; keep it for speed or set `durability: 'strict'` in `config` for migration-style writes.
324
407
  - **Storage Buckets (Chromium 122+):** supply a `bucket` option to isolate critical data and hint durability/persistence per bucket.
325
408
  - **Connection warmup:** IndexedDB instances pre-warm a transaction after init to reduce first-op latency (`prewarmTransactions` enabled by default; set to `false` to skip).
@@ -331,8 +414,11 @@ When `compatibilityMode` is off, driver setup methods also use Node-style callba
331
414
  ## Troubleshooting
332
415
  - **Wait for readiness:** Call `await localspace.ready()` before the first operation when you need to confirm driver selection.
333
416
  - **Inspect drivers:** Use `localspace.driver()` to confirm which driver is active in different environments.
334
- - **Handle quota errors:** Catch `DOMException` errors from `setItem` to inform users about storage limits.
417
+ - **Read structured errors:** Rejections surface as `LocalSpaceError` with a `code`, contextual `details` (driver, operation, key, attemptedDrivers), and the original `cause`. Branch on `error.code` instead of parsing strings.
418
+ - **Handle quota errors:** Check for `error.code === 'QUOTA_EXCEEDED'` (or inspect `error.cause`) from `setItem` to inform users about storage limits.
335
419
  - **Run unit tests:** The project ships with Vitest and Playwright suites covering API behavior; run `yarn test` to verify changes.
420
+ - **Collect Playwright coverage:** Run `yarn test:e2e:coverage` to re-build the bundle, execute the Playwright suite with Chromium V8 coverage enabled, and emit both text + HTML reports via `nyc` (open `coverage/index.html` after the run; raw JSON sits in `.nyc_output`).
421
+ - **Collect combined Vitest + Playwright coverage:** Run `yarn coverage:full` to clean previous artifacts, run `vitest --coverage`, stash its Istanbul JSON into `.nyc_output`, then execute the coverage-enabled Playwright suite and emit merged `nyc` reports.
336
422
 
337
423
  ## License
338
424
  [MIT](./LICENSE)
@@ -0,0 +1,48 @@
1
+ import type { BatchItems, BatchResponse, DbInfo, LocalSpaceConfig, LocalSpaceInstance, LocalSpacePlugin, PluginContext, PluginOperation } from '../types';
2
+ export declare class PluginAbortError extends Error {
3
+ constructor(message?: string);
4
+ }
5
+ type PluginHost = LocalSpaceInstance & {
6
+ _config: LocalSpaceConfig;
7
+ _dbInfo: DbInfo | null;
8
+ };
9
+ export declare class PluginManager {
10
+ private readonly host;
11
+ private readonly sharedMetadata;
12
+ private readonly pluginRegistry;
13
+ private readonly initialized;
14
+ private readonly initPromises;
15
+ private readonly destroyed;
16
+ private readonly disabled;
17
+ private orderCounter;
18
+ constructor(host: PluginHost, initialPlugins?: LocalSpacePlugin[]);
19
+ hasPlugins(): boolean;
20
+ registerPlugins(plugins: LocalSpacePlugin[]): void;
21
+ private sortPlugins;
22
+ private getActivePlugins;
23
+ ensureInitialized(): Promise<void>;
24
+ createContext(operation: PluginOperation | null): PluginContext;
25
+ beforeSet<T>(key: string, value: T, context: PluginContext): Promise<T>;
26
+ afterSet<T>(key: string, value: T, context: PluginContext): Promise<void>;
27
+ beforeGet(key: string, context: PluginContext): Promise<string>;
28
+ afterGet<T>(key: string, value: T | null, context: PluginContext): Promise<T | null>;
29
+ beforeRemove(key: string, context: PluginContext): Promise<string>;
30
+ afterRemove(key: string, context: PluginContext): Promise<void>;
31
+ beforeSetItems<T>(entries: BatchItems<T>, context: PluginContext): Promise<BatchItems<T>>;
32
+ afterSetItems<T>(entries: BatchResponse<T>, context: PluginContext): Promise<BatchResponse<T>>;
33
+ beforeGetItems(keys: string[], context: PluginContext): Promise<string[]>;
34
+ afterGetItems<T>(entries: BatchResponse<T>, context: PluginContext): Promise<BatchResponse<T>>;
35
+ beforeRemoveItems(keys: string[], context: PluginContext): Promise<string[]>;
36
+ afterRemoveItems(keys: string[], context: PluginContext): Promise<void>;
37
+ destroy(): Promise<void>;
38
+ normalizeBatch<T>(items: BatchItems<T>): Array<{
39
+ key: string;
40
+ value: T;
41
+ }>;
42
+ private shouldPropagate;
43
+ private dispatchPluginError;
44
+ private invokeValueHook;
45
+ private invokeVoidHook;
46
+ }
47
+ export {};
48
+ //# sourceMappingURL=plugin-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-manager.d.ts","sourceRoot":"","sources":["../../src/core/plugin-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,334 @@
1
+ import { LocalSpaceError } from '../errors';
2
+ import { normalizeBatchEntries } from '../utils/helpers';
3
+ export class PluginAbortError extends Error {
4
+ constructor(message = 'Plugin aborted the operation') {
5
+ super(message);
6
+ this.name = 'PluginAbortError';
7
+ }
8
+ }
9
+ const sharedMetadataFor = () => Object.create(null);
10
+ export class PluginManager {
11
+ constructor(host, initialPlugins = []) {
12
+ Object.defineProperty(this, "host", {
13
+ enumerable: true,
14
+ configurable: true,
15
+ writable: true,
16
+ value: void 0
17
+ });
18
+ Object.defineProperty(this, "sharedMetadata", {
19
+ enumerable: true,
20
+ configurable: true,
21
+ writable: true,
22
+ value: sharedMetadataFor()
23
+ });
24
+ Object.defineProperty(this, "pluginRegistry", {
25
+ enumerable: true,
26
+ configurable: true,
27
+ writable: true,
28
+ value: []
29
+ });
30
+ Object.defineProperty(this, "initialized", {
31
+ enumerable: true,
32
+ configurable: true,
33
+ writable: true,
34
+ value: new WeakSet()
35
+ });
36
+ Object.defineProperty(this, "initPromises", {
37
+ enumerable: true,
38
+ configurable: true,
39
+ writable: true,
40
+ value: new WeakMap()
41
+ });
42
+ Object.defineProperty(this, "destroyed", {
43
+ enumerable: true,
44
+ configurable: true,
45
+ writable: true,
46
+ value: new WeakSet()
47
+ });
48
+ Object.defineProperty(this, "disabled", {
49
+ enumerable: true,
50
+ configurable: true,
51
+ writable: true,
52
+ value: new WeakSet()
53
+ });
54
+ Object.defineProperty(this, "orderCounter", {
55
+ enumerable: true,
56
+ configurable: true,
57
+ writable: true,
58
+ value: 0
59
+ });
60
+ this.host = host;
61
+ if (initialPlugins.length) {
62
+ this.registerPlugins(initialPlugins);
63
+ }
64
+ }
65
+ hasPlugins() {
66
+ return this.pluginRegistry.length > 0;
67
+ }
68
+ registerPlugins(plugins) {
69
+ for (const plugin of plugins) {
70
+ if (!plugin)
71
+ continue;
72
+ this.pluginRegistry.push({ plugin, order: this.orderCounter++ });
73
+ }
74
+ this.sortPlugins();
75
+ }
76
+ sortPlugins() {
77
+ this.pluginRegistry.sort((a, b) => {
78
+ const priorityA = a.plugin.priority ?? 0;
79
+ const priorityB = b.plugin.priority ?? 0;
80
+ if (priorityA === priorityB) {
81
+ return a.order - b.order;
82
+ }
83
+ return priorityB - priorityA;
84
+ });
85
+ }
86
+ getActivePlugins(options) {
87
+ const reverse = options?.reverse ?? false;
88
+ const plugins = this.pluginRegistry
89
+ .map((entry) => entry.plugin)
90
+ .filter((plugin) => {
91
+ if (this.disabled.has(plugin)) {
92
+ return false;
93
+ }
94
+ const enabled = plugin.enabled;
95
+ if (typeof enabled === 'function') {
96
+ try {
97
+ return !!enabled();
98
+ }
99
+ catch (error) {
100
+ console.warn(`Plugin "${plugin.name}" enabled() check failed`, error);
101
+ return false;
102
+ }
103
+ }
104
+ return enabled !== false;
105
+ });
106
+ return reverse ? plugins.slice().reverse() : plugins;
107
+ }
108
+ async ensureInitialized() {
109
+ for (const plugin of this.getActivePlugins()) {
110
+ if (this.initialized.has(plugin)) {
111
+ continue;
112
+ }
113
+ if (typeof plugin.onInit !== 'function') {
114
+ this.initialized.add(plugin);
115
+ continue;
116
+ }
117
+ const pendingInit = this.initPromises.get(plugin);
118
+ if (pendingInit) {
119
+ await pendingInit;
120
+ continue;
121
+ }
122
+ const context = this.createContext(null);
123
+ const initPromise = (async () => {
124
+ try {
125
+ await plugin.onInit(context);
126
+ this.initialized.add(plugin);
127
+ }
128
+ catch (error) {
129
+ await this.dispatchPluginError(plugin, error, 'init', 'lifecycle', undefined, context);
130
+ const policy = this.host._config.pluginInitPolicy ?? 'fail';
131
+ if (policy === 'disable-and-continue') {
132
+ this.disabled.add(plugin);
133
+ return;
134
+ }
135
+ throw error;
136
+ }
137
+ finally {
138
+ this.initPromises.delete(plugin);
139
+ }
140
+ })();
141
+ this.initPromises.set(plugin, initPromise);
142
+ await initPromise;
143
+ }
144
+ }
145
+ createContext(operation) {
146
+ return {
147
+ instance: this.host,
148
+ driver: this.host.driver ? this.host.driver() : null,
149
+ dbInfo: this.host._dbInfo ?? null,
150
+ config: this.host._config,
151
+ metadata: this.sharedMetadata,
152
+ operation,
153
+ operationState: Object.create(null),
154
+ };
155
+ }
156
+ async beforeSet(key, value, context) {
157
+ let current = value;
158
+ for (const plugin of this.getActivePlugins()) {
159
+ if (!plugin.beforeSet)
160
+ continue;
161
+ current = await this.invokeValueHook(plugin, () => plugin.beforeSet(key, current, context), 'before', 'setItem', key, context, current);
162
+ }
163
+ return current;
164
+ }
165
+ async afterSet(key, value, context) {
166
+ for (const plugin of this.getActivePlugins({ reverse: true })) {
167
+ if (!plugin.afterSet)
168
+ continue;
169
+ await this.invokeVoidHook(plugin, () => plugin.afterSet(key, value, context), 'after', 'setItem', key, context);
170
+ }
171
+ }
172
+ async beforeGet(key, context) {
173
+ let currentKey = key;
174
+ for (const plugin of this.getActivePlugins()) {
175
+ if (!plugin.beforeGet)
176
+ continue;
177
+ currentKey = await this.invokeValueHook(plugin, () => plugin.beforeGet(currentKey, context), 'before', 'getItem', currentKey, context, currentKey);
178
+ }
179
+ return currentKey;
180
+ }
181
+ async afterGet(key, value, context) {
182
+ let currentValue = value;
183
+ for (const plugin of this.getActivePlugins({ reverse: true })) {
184
+ if (!plugin.afterGet)
185
+ continue;
186
+ currentValue = await this.invokeValueHook(plugin, () => plugin.afterGet(key, currentValue, context), 'after', 'getItem', key, context, currentValue);
187
+ }
188
+ return currentValue;
189
+ }
190
+ async beforeRemove(key, context) {
191
+ let currentKey = key;
192
+ for (const plugin of this.getActivePlugins()) {
193
+ if (!plugin.beforeRemove)
194
+ continue;
195
+ currentKey = await this.invokeValueHook(plugin, () => plugin.beforeRemove(currentKey, context), 'before', 'removeItem', currentKey, context, currentKey);
196
+ }
197
+ return currentKey;
198
+ }
199
+ async afterRemove(key, context) {
200
+ for (const plugin of this.getActivePlugins({ reverse: true })) {
201
+ if (!plugin.afterRemove)
202
+ continue;
203
+ await this.invokeVoidHook(plugin, () => plugin.afterRemove(key, context), 'after', 'removeItem', key, context);
204
+ }
205
+ }
206
+ async beforeSetItems(entries, context) {
207
+ let current = entries;
208
+ for (const plugin of this.getActivePlugins()) {
209
+ if (!plugin.beforeSetItems)
210
+ continue;
211
+ current = await this.invokeValueHook(plugin, () => plugin.beforeSetItems(current, context), 'before', 'setItems', undefined, context, current);
212
+ }
213
+ return current;
214
+ }
215
+ async afterSetItems(entries, context) {
216
+ let current = entries;
217
+ for (const plugin of this.getActivePlugins({ reverse: true })) {
218
+ if (!plugin.afterSetItems)
219
+ continue;
220
+ current = await this.invokeValueHook(plugin, () => plugin.afterSetItems(current, context), 'after', 'setItems', undefined, context, current);
221
+ }
222
+ return current;
223
+ }
224
+ async beforeGetItems(keys, context) {
225
+ let currentKeys = keys;
226
+ for (const plugin of this.getActivePlugins()) {
227
+ if (!plugin.beforeGetItems)
228
+ continue;
229
+ currentKeys = await this.invokeValueHook(plugin, () => plugin.beforeGetItems(currentKeys, context), 'before', 'getItems', undefined, context, currentKeys);
230
+ }
231
+ return currentKeys;
232
+ }
233
+ async afterGetItems(entries, context) {
234
+ let current = entries;
235
+ for (const plugin of this.getActivePlugins({ reverse: true })) {
236
+ if (!plugin.afterGetItems)
237
+ continue;
238
+ current = await this.invokeValueHook(plugin, () => plugin.afterGetItems(current, context), 'after', 'getItems', undefined, context, current);
239
+ }
240
+ return current;
241
+ }
242
+ async beforeRemoveItems(keys, context) {
243
+ let currentKeys = keys;
244
+ for (const plugin of this.getActivePlugins()) {
245
+ if (!plugin.beforeRemoveItems)
246
+ continue;
247
+ currentKeys = await this.invokeValueHook(plugin, () => plugin.beforeRemoveItems(currentKeys, context), 'before', 'removeItems', undefined, context, currentKeys);
248
+ }
249
+ return currentKeys;
250
+ }
251
+ async afterRemoveItems(keys, context) {
252
+ for (const plugin of this.getActivePlugins({ reverse: true })) {
253
+ if (!plugin.afterRemoveItems)
254
+ continue;
255
+ await this.invokeVoidHook(plugin, () => plugin.afterRemoveItems(keys, context), 'after', 'removeItems', undefined, context);
256
+ }
257
+ }
258
+ async destroy() {
259
+ const plugins = this.pluginRegistry
260
+ .map((entry) => entry.plugin)
261
+ .slice()
262
+ .reverse();
263
+ for (const plugin of plugins) {
264
+ if (this.destroyed.has(plugin) || this.disabled.has(plugin)) {
265
+ continue;
266
+ }
267
+ if (typeof plugin.onDestroy !== 'function') {
268
+ this.destroyed.add(plugin);
269
+ continue;
270
+ }
271
+ const context = this.createContext(null);
272
+ try {
273
+ await plugin.onDestroy(context);
274
+ }
275
+ catch (error) {
276
+ await this.dispatchPluginError(plugin, error, 'destroy', 'lifecycle', undefined, context);
277
+ }
278
+ finally {
279
+ this.destroyed.add(plugin);
280
+ }
281
+ }
282
+ }
283
+ normalizeBatch(items) {
284
+ return normalizeBatchEntries(items);
285
+ }
286
+ shouldPropagate(error) {
287
+ return (error instanceof LocalSpaceError || error instanceof PluginAbortError);
288
+ }
289
+ async dispatchPluginError(plugin, error, stage, operation, key, context) {
290
+ const info = {
291
+ plugin: plugin.name,
292
+ operation,
293
+ stage,
294
+ key,
295
+ context,
296
+ error,
297
+ };
298
+ if (typeof plugin.onError === 'function') {
299
+ try {
300
+ await plugin.onError(error, info);
301
+ return;
302
+ }
303
+ catch (hookError) {
304
+ console.error(`Plugin onError handler failed for "${plugin.name}"`, hookError);
305
+ }
306
+ }
307
+ console.warn(`Plugin "${plugin.name}" error during ${operation}`, error);
308
+ }
309
+ async invokeValueHook(plugin, executor, stage, operation, key, context, fallback) {
310
+ try {
311
+ const result = await executor();
312
+ return (typeof result === 'undefined' ? fallback : result);
313
+ }
314
+ catch (error) {
315
+ if (this.shouldPropagate(error)) {
316
+ throw error;
317
+ }
318
+ await this.dispatchPluginError(plugin, error, stage, operation, key, context);
319
+ return fallback;
320
+ }
321
+ }
322
+ async invokeVoidHook(plugin, executor, stage, operation, key, context) {
323
+ try {
324
+ await executor();
325
+ }
326
+ catch (error) {
327
+ if (this.shouldPropagate(error)) {
328
+ throw error;
329
+ }
330
+ await this.dispatchPluginError(plugin, error, stage, operation, key, context);
331
+ }
332
+ }
333
+ }
334
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLW1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29yZS9wbHVnaW4tbWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFZQSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQzVDLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRXpELE1BQU0sT0FBTyxnQkFBaUIsU0FBUSxLQUFLO0lBQ3pDLFlBQVksT0FBTyxHQUFHLDhCQUE4QjtRQUNsRCxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDZixJQUFJLENBQUMsSUFBSSxHQUFHLGtCQUFrQixDQUFDO0lBQ2pDLENBQUM7Q0FDRjtBQVlELE1BQU0saUJBQWlCLEdBQUcsR0FBNEIsRUFBRSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7QUFFN0UsTUFBTSxPQUFPLGFBQWE7SUFxQnhCLFlBQVksSUFBZ0IsRUFBRSxpQkFBcUMsRUFBRTtRQXBCcEQ7Ozs7O1dBQWlCO1FBRWpCOzs7O21CQUNmLGlCQUFpQixFQUFFO1dBQUM7UUFFTDs7OzttQkFBcUMsRUFBRTtXQUFDO1FBRXhDOzs7O21CQUFjLElBQUksT0FBTyxFQUFvQjtXQUFDO1FBRTlDOzs7O21CQUFlLElBQUksT0FBTyxFQUd4QztXQUFDO1FBRWE7Ozs7bUJBQVksSUFBSSxPQUFPLEVBQW9CO1dBQUM7UUFFNUM7Ozs7bUJBQVcsSUFBSSxPQUFPLEVBQW9CO1dBQUM7UUFFcEQ7Ozs7bUJBQWUsQ0FBQztXQUFDO1FBR3ZCLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ2pCLElBQUksY0FBYyxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQzFCLElBQUksQ0FBQyxlQUFlLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDdkMsQ0FBQztJQUNILENBQUM7SUFFRCxVQUFVO1FBQ1IsT0FBTyxJQUFJLENBQUMsY0FBYyxDQUFD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R0FBRyxFQUNILE9BQU8sQ0FDUixDQUFDO1FBQ0osQ0FBQztJQUNILENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHtcbiAgQmF0Y2hJdGVtcyxcbiAgQmF0Y2hSZXNwb25zZSxcbiAgRGJJbmZvLFxuICBMb2NhbFNwYWNlQ29uZmlnLFxuICBMb2NhbFNwYWNlSW5zdGFuY2UsXG4gIExvY2FsU3BhY2VQbHVnaW4sXG4gIFBsdWdpbkNvbnRleHQsXG4gIFBsdWdpbkVycm9ySW5mbyxcbiAgUGx1Z2luT3BlcmF0aW9uLFxuICBQbHVnaW5TdGFnZSxcbn0gZnJvbSAnLi4vdHlwZXMnO1xuaW1wb3J0IHsgTG9jYWxTcGFjZUVycm9yIH0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7IG5vcm1hbGl6ZUJhdGNoRW50cmllcyB9IGZyb20gJy4uL3V0aWxzL2hlbHBlcnMnO1xuXG5leHBvcnQgY2xhc3MgUGx1Z2luQWJvcnRFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgY29uc3RydWN0b3IobWVzc2FnZSA9ICdQbHVnaW4gYWJvcnRlZCB0aGUgb3BlcmF0aW9uJykge1xuICAgIHN1cGVyKG1lc3NhZ2UpO1xuICAgIHRoaXMubmFtZSA9ICdQbHVnaW5BYm9ydEVycm9yJztcbiAgfVxufVxuXG50eXBlIFBsdWdpbkhvc3QgPSBMb2NhbFNwYWNlSW5zdGFuY2UgJiB7XG4gIF9jb25maWc6IExvY2FsU3BhY2VDb25maWc7XG4gIF9kYkluZm86IERiSW5mbyB8IG51bGw7XG59O1xuXG50eXBlIFJlZ2lzdGVyZWRQbHVnaW4gPSB7XG4gIHBsdWdpbjogTG9jYWxTcGFjZVBsdWdpbjtcbiAgb3JkZXI6IG51bWJlcjtcbn07XG5cbmNvbnN0IHNoYXJlZE1ldGFkYXRhRm9yID0gKCk6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0+IE9iamVjdC5jcmVhdGUobnVsbCk7XG5cbmV4cG9ydCBjbGFzcyBQbHVnaW5NYW5hZ2VyIHtcbiAgcHJpdmF0ZSByZWFkb25seSBob3N0OiBQbHVnaW5Ib3N0O1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgc2hhcmVkTWV0YWRhdGE6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID1cbiAgICBzaGFyZWRNZXRhZGF0YUZvcigpO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgcGx1Z2luUmVnaXN0cnk6IFJlZ2lzdGVyZWRQbHVnaW5bXSA9IFtdO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgaW5pdGlhbGl6ZWQgPSBuZXcgV2Vha1NldDxMb2NhbFNwYWNlUGx1Z2luPigpO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgaW5pdFByb21pc2VzID0gbmV3IFdlYWtNYXA8XG4gICAgTG9jYWxTcGFjZVBsdWdpbixcbiAgICBQcm9taXNlPHZvaWQ+XG4gID4oKTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGRlc3Ryb3llZCA9IG5ldyBXZWFrU2V0PExvY2FsU3BhY2VQbHVnaW4+KCk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBkaXNhYmxlZCA9IG5ldyBXZWFrU2V0PExvY2FsU3BhY2VQbHVnaW4+KCk7XG5cbiAgcHJpdmF0ZSBvcmRlckNvdW50ZXIgPSAwO1xuXG4gIGNvbnN0cnVjdG9yKGhvc3Q6IFBsdWdpbkhvc3QsIGluaXRpYWxQbHVnaW5zOiBMb2NhbFNwYWNlUGx1Z2luW10gPSBbXSkge1xuICAgIHRoaXMuaG9zdCA9IGhvc3Q7XG4gICAgaWYgKGluaXRpYWxQbHVnaW5zLmxlbmd0aCkge1xuICAgICAgdGhpcy5yZWdpc3RlclBsdWdpbnMoaW5pdGlhbFBsdWdpbnMpO1xuICAgIH1cbiAgfVxuXG4gIGhhc1BsdWdpbnMoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMucGx1Z2luUmVnaXN0cnkubGVuZ3RoID4gMDtcbiAgfVxuXG4gIHJlZ2lzdGVyUGx1Z2lucyhwbHVnaW5zOiBMb2NhbFNwYWNlUGx1Z2luW10pOiB2b2lkIHtcbiAgICBmb3IgKGNvbnN0IHBsdWdpbiBvZiBwbHVnaW5zKSB7XG4gICAgICBpZiAoIXBsdWdpbikgY29udGludWU7XG4gICAgICB0aGlzLnBsdWdpblJlZ2lzdHJ5LnB1c2goeyBwbHVnaW4sIG9yZGVyOiB0aGlzLm9yZGVyQ291bnRlcisrIH0pO1xuICAgIH1cbiAgICB0aGlzLnNvcnRQbHVnaW5zKCk7XG4gIH1cblxuICBwcml2YXRlIHNvcnRQbHVnaW5zKCk6IHZvaWQge1xuICAgIHRoaXMucGx1Z2luUmVnaXN0cnkuc29ydCgoYSwgYikgPT4ge1xuICAgICAgY29uc3QgcHJpb3JpdHlBID0gYS5wbHVnaW4ucHJpb3JpdHkgPz8gMDtcbiAgICAgIGNvbnN0IHByaW9yaXR5QiA9IGIucGx1Z2luLnByaW9yaXR5ID8/IDA7XG4gICAgICBpZiAocHJpb3JpdHlBID09PSBwcmlvcml0eUIpIHtcbiAgICAgICAgcmV0dXJuIGEub3JkZXIgLSBiLm9yZGVyO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHByaW9yaXR5QiAtIHByaW9yaXR5QTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0QWN0aXZlUGx1Z2lucyhvcHRpb25zPzoge1xuICAgIHJldmVyc2U/OiBib29sZWFuO1xuICB9KTogTG9jYWxTcGFjZVBsdWdpbltdIHtcbiAgICBjb25zdCByZXZlcnNlID0gb3B0aW9ucz8ucmV2ZXJzZSA/PyBmYWxzZTtcbiAgICBjb25zdCBwbHVnaW5zID0gdGhpcy5wbHVnaW5SZWdpc3RyeVxuICAgICAgLm1hcCgoZW50cnkpID0+IGVudHJ5LnBsdWdpbilcbiAgICAgIC5maWx0ZXIoKHBsdWdpbikgPT4ge1xuICAgICAgICBpZiAodGhpcy5kaXNhYmxlZC5oYXMocGx1Z2luKSkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBlbmFibGVkID0gcGx1Z2luLmVuYWJsZWQ7XG4gICAgICAgIGlmICh0eXBlb2YgZW5hYmxlZCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICByZXR1cm4gISFlbmFibGVkKCk7XG4gICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAgICAgYFBsdWdpbiBcIiR7cGx1Z2luLm5hbWV9XCIgZW5hYmxlZCgpIGNoZWNrIGZhaWxlZGAsXG4gICAgICAgICAgICAgIGVycm9yXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZW5hYmxlZCAhPT0gZmFsc2U7XG4gICAgICB9KTtcbiAgICByZXR1cm4gcmV2ZXJzZSA/IHBsdWdpbnMuc2xpY2UoKS5yZXZlcnNlKCkgOiBwbHVnaW5zO1xuICB9XG5cbiAgYXN5bmMgZW5zdXJlSW5pdGlhbGl6ZWQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgZm9yIChjb25zdCBwbHVnaW4gb2YgdGhpcy5nZXRBY3RpdmVQbHVnaW5zKCkpIHtcbiAgICAgIGlmICh0aGlzLmluaXRpYWxpemVkLmhhcyhwbHVnaW4pKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAodHlwZW9mIHBsdWdpbi5vbkluaXQgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhpcy5pbml0aWFsaXplZC5hZGQocGx1Z2luKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHBlbmRpbmdJbml0ID0gdGhpcy5pbml0UHJvbWlzZXMuZ2V0KHBsdWdpbik7XG4gICAgICBpZiAocGVuZGluZ0luaXQpIHtcbiAgICAgICAgYXdhaXQgcGVuZGluZ0luaXQ7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBjb250ZXh0ID0gdGhpcy5jcmVhdGVDb250ZXh0KG51bGwpO1xuICAgICAgY29uc3QgaW5pdFByb21pc2UgPSAoYXN5bmMgKCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IHBsdWdpbi5vbkluaXQhKGNvbnRleHQpO1xuICAgICAgICAgIHRoaXMuaW5pdGlhbGl6ZWQuYWRkKHBsdWdpbik7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgYXdhaXQgdGhpcy5kaXNwYXRjaFBsdWdpbkVycm9yKFxuICAgICAgICAgICAgcGx1Z2luLFxuICAgICAgICAgICAgZXJyb3IsXG4gICAgICAgICAgICAnaW5pdCcsXG4gICAgICAgICAgICAnbGlmZWN5Y2xlJyxcbiAgICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGNvbnRleHRcbiAgICAgICAgICApO1xuICAgICAgICAgIGNvbnN0IHBvbGljeSA9IHRoaXMuaG9zdC5fY29uZmlnLnBsdWdpbkluaXRQb2xpY3kgPz8gJ2ZhaWwnO1xuICAgICAgICAgIGlmIChwb2xpY3kgPT09ICdkaXNhYmxlLWFuZC1jb250aW51ZScpIHtcbiAgICAgICAgICAgIHRoaXMuZGlzYWJsZWQuYWRkKHBsdWdpbik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgIHRoaXMuaW5pdFByb21pc2VzLmRlbGV0ZShwbHVnaW4pO1xuICAgICAgICB9XG4gICAgICB9KSgpO1xuXG4gICAgICB0aGlzLmluaXRQcm9taXNlcy5zZXQocGx1Z2luLCBpbml0UHJvbWlzZSk7XG4gICAgICBhd2FpdCBpbml0UHJvbWlzZTtcbiAgICB9XG4gIH1cblxuICBjcmVhdGVDb250ZXh0KG9wZXJhdGlvbjogUGx1Z2luT3BlcmF0aW9uIHwgbnVsbCk6IFBsdWdpbkNvbnRleHQge1xuICAgIHJldHVybiB7XG4gICAgICBpbnN0YW5jZTogdGhpcy5ob3N0LFxuICAgICAgZHJpdmVyOiB0aGlzLmhvc3QuZHJpdmVyID8gdGhpcy5ob3N0LmRyaXZlcigpIDogbnVsbCxcbiAgICAgIGRiSW5mbzogdGhpcy5ob3N0Ll9kYkluZm8gPz8gbnVsbCxcbiAgICAgIGNvbmZpZzogdGhpcy5ob3N0Ll9jb25maWcsXG4gICAgICBtZXRhZGF0YTogdGhpcy5zaGFyZWRNZXRhZGF0YSxcbiAgICAgIG9wZXJhdGlvbixcbiAgICAgIG9wZXJhdGlvblN0YXRlOiBPYmplY3QuY3JlYXRlKG51bGwpLFxuICAgIH07XG4gIH1cblxuICBhc3luYyBiZWZvcmVTZXQ8VD4oXG4gICAga2V5OiBzdHJpbmcsXG4gICAgdmFsdWU6IFQsXG4gICAgY29udGV4dDogUGx1Z2luQ29udGV4dFxuICApOiBQcm9taXNlPFQ+IHtcbiAgICBsZXQgY3VycmVudCA9IHZhbHVlO1xuICAgIGZvciAoY29uc3QgcGx1Z2luIG9mIHRoaXMuZ2V0QWN0aXZlUGx1Z2lucygpKSB7XG4gICAgICBpZiAoIXBsdWdpbi5iZWZvcmVTZXQpIGNvbnRpbnVlO1xuICAgICAgY3VycmVudCA9IGF3YWl0IHRoaXMuaW52b2tlVmFsdWVIb29rKFxuICAgICAgICBwbHVnaW4sXG4gICAgICAgICgpID0+IHBsdWdpbi5iZWZvcmVTZXQhKGtleSwgY3VycmVudCwgY29udGV4dCksXG4gICAgICAgICdiZWZvcmUnLFxuICAgICAgICAnc2V0SXRlbScsXG4gICAgICAgIGtleSxcbiAgICAgICAgY29udGV4dCxcbiAgICAgICAgY3VycmVudFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIGN1cnJlbnQ7XG4gIH1cblxuICBhc3luYyBhZnRlclNldDxUPihcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVCxcbiAgICBjb250ZXh0OiBQbHVnaW5Db250ZXh0XG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGZvciAoY29uc3QgcGx1Z2luIG9mIHRoaXMuZ2V0QWN0aXZlUGx1Z2lucyh7IHJldmVyc2U6IHRydWUgfSkpIHtcbiAgICAgIGlmICghcGx1Z2luLmFmdGVyU2V0KSBjb250aW51ZTtcbiAgICAgIGF3YWl0IHRoaXMuaW52b2tlVm9pZEhvb2soXG4gICAgICAgIHBsdWdpbixcbiAgICAgICAgKCkgPT4gcGx1Z2luLmFmdGVyU2V0IShrZXksIHZhbHVlLCBjb250ZXh0KSxcbiAgICAgICAgJ2FmdGVyJyxcbiAgICAgICAgJ3NldEl0ZW0nLFxuICAgICAgICBrZXksXG4gICAgICAgIGNvbnRleHRcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgYmVmb3JlR2V0KGtleTogc3RyaW5nLCBjb250ZXh0OiBQbHVnaW5Db250ZXh0KTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBsZXQgY3VycmVudEtleSA9IGtleTtcbiAgICBmb3IgKGNvbnN0IHBsdWdpbiBvZiB0aGlzLmdldEFjdGl2ZVBsdWdpbnMoKSkge1xuICAgICAgaWYgKCFwbHVnaW4uYmVmb3JlR2V0KSBjb250aW51ZTtcbiAgICAgIGN1cnJlbnRLZXkgPSBhd2FpdCB0aGlzLmludm9rZVZhbHVlSG9vayhcbiAgICAgICAgcGx1Z2luLFxuICAgICAgICAoKSA9PiBwbHVnaW4uYmVmb3JlR2V0IShjdXJyZW50S2V5LCBjb250ZXh0KSxcbiAgICAgICAgJ2JlZm9yZScsXG4gICAgICAgICdnZXRJdGVtJyxcbiAgICAgICAgY3VycmVudEtleSxcbiAgICAgICAgY29udGV4dCxcbiAgICAgICAgY3VycmVudEtleVxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIGN1cnJlbnRLZXk7XG4gIH1cblxuICBhc3luYyBhZnRlckdldDxUPihcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVCB8IG51bGwsXG4gICAgY29udGV4dDogUGx1Z2luQ29udGV4dFxuICApOiBQcm9taXNlPFQgfCBudWxsPiB7XG4gICAgbGV0IGN1cnJlbnRWYWx1ZTogVCB8IG51bGwgPSB2YWx1ZTtcbiAgICBmb3IgKGNvbnN0IHBsdWdpbiBvZiB0aGlzLmdldEFjdGl2ZVBsdWdpbnMoeyByZXZlcnNlOiB0cnVlIH0pKSB7XG4gICAgICBpZiAoIXBsdWdpbi5hZnRlckdldCkgY29udGludWU7XG4gICAgICBjdXJyZW50VmFsdWUgPSBhd2FpdCB0aGlzLmludm9rZVZhbHVlSG9vayhcbiAgICAgICAgcGx1Z2luLFxuICAgICAgICAoKSA9PiBwbHVnaW4uYWZ0ZXJHZXQhKGtleSwgY3VycmVudFZhbHVlLCBjb250ZXh0KSxcbiAgICAgICAgJ2FmdGVyJyxcbiAgICAgICAgJ2dldEl0ZW0nLFxuICAgICAgICBrZXksXG4gICAgICAgIGNvbnRleHQsXG4gICAgICAgIGN1cnJlbnRWYWx1ZVxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIGN1cnJlbnRWYWx1ZTtcbiAgfVxuXG4gIGFzeW5jIGJlZm9yZVJlbW92ZShrZXk6IHN0cmluZywgY29udGV4dDogUGx1Z2luQ29udGV4dCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgbGV0IGN1cnJlbnRLZXkgPSBrZXk7XG4gICAgZm9yIChjb25zdCBwbHVnaW4gb2YgdGhpcy5nZXRBY3RpdmVQbHVnaW5zKCkpIHtcbiAgICAgIGlmICghcGx1Z2luLmJlZm9yZVJlbW92ZSkgY29udGludWU7XG4gICAgICBjdXJyZW50S2V5ID0gYXdhaXQgdGhpcy5pbnZva2VWYWx1ZUhvb2soXG4gICAgICAgIHBsdWdpbixcbiAgICAgICAgKCkgPT4gcGx1Z2luLmJlZm9yZVJlbW92ZSEoY3VycmVudEtleSwgY29udGV4dCksXG4gICAgICAgICdiZWZvcmUnLFxuICAgICAgICAncmVtb3ZlSXRlbScsXG4gICAgICAgIGN1cnJlbnRLZXksXG4gICAgICAgIGNvbnRleHQsXG4gICAgICAgIGN1cnJlbnRLZXlcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBjdXJyZW50S2V5O1xuICB9XG5cbiAgYXN5bmMgYWZ0ZXJSZW1vdmUoa2V5OiBzdHJpbmcsIGNvbnRleHQ6IFBsdWdpbkNvbnRleHQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBmb3IgKGNvbnN0IHBsdWdpbiBvZiB0aGlzLmdldEFjdGl2ZVBsdWdpbnMoeyByZXZlcnNlOiB0cnVlIH0pKSB7XG4gICAgICBpZiAoIXBsdWdpbi5hZnRlclJlbW92ZSkgY29udGludWU7XG4gICAgICBhd2FpdCB0aGlzLmludm9rZVZvaWRIb29rKFxuICAgICAgICBwbHVnaW4sXG4gICAgICAgICgpID0+IHBsdWdpbi5hZnRlclJlbW92ZSEoa2V5LCBjb250ZXh0KSxcbiAgICAgICAgJ2FmdGVyJyxcbiAgICAgICAgJ3JlbW92ZUl0ZW0nLFxuICAgICAgICBrZXksXG4gICAgICAgIGNvbnRleHRcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgYmVmb3JlU2V0SXRlbXM8VD4oXG4gICAgZW50cmllczogQmF0Y2hJdGVtczxUPixcbiAgICBjb250ZXh0OiBQbHVnaW5Db250ZXh0XG4gICk6IFByb21pc2U8QmF0Y2hJdGVtczxUPj4ge1xuICAgIGxldCBjdXJyZW50ID0gZW50cmllcztcbiAgICBmb3IgKGNvbnN0IHBsdWdpbiBvZiB0aGlzLmdldEFjdGl2ZVBsdWdpbnMoKSkge1xuICAgICAgaWYgKCFwbHVnaW4uYmVmb3JlU2V0SXRlbXMpIGNvbnRpbnVlO1xuICAgICAgY3VycmVudCA9IGF3YWl0IHRoaXMuaW52b2tlVmFsdWVIb29rKFxuICAgICAgICBwbHVnaW4sXG4gICAgICAgICgpID0+IHBsdWdpbi5iZWZvcmVTZXRJdGVtcyEoY3VycmVudCwgY29udGV4dCksXG4gICAgICAgICdiZWZvcmUnLFxuICAgICAgICAnc2V0SXRlbXMnLFxuICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgIGNvbnRleHQsXG4gICAgICAgIGN1cnJlbnRcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBjdXJyZW50O1xuICB9XG5cbiAgYXN5bmMgYWZ0ZXJTZXRJdGVtczxUPihcbiAgICBlbnRyaWVzOiBCYXRjaFJlc3BvbnNlPFQ+LFxuICAgIGNvbnRleHQ6IFBsdWdpbkNvbnRleHRcbiAgKTogUHJvbWlzZTxCYXRjaFJlc3BvbnNlPFQ+PiB7XG4gICAgbGV0IGN1cnJlbnQgPSBlbnRyaWVzO1xuICAgIGZvciAoY29uc3QgcGx1Z2luIG9mIHRoaXMuZ2V0QWN0aXZlUGx1Z2lucyh7IHJldmVyc2U6IHRydWUgfSkpIHtcbiAgICAgIGlmICghcGx1Z2luLmFmdGVyU2V0SXRlbXMpIGNvbnRpbnVlO1xuICAgICAgY3VycmVudCA9IGF3YWl0IHRoaXMuaW52b2tlVmFsdWVIb29rKFxuICAgICAgICBwbHVnaW4sXG4gICAgICAgICgpID0+IHBsdWdpbi5hZnRlclNldEl0ZW1zIShjdXJyZW50LCBjb250ZXh0KSxcbiAgICAgICAgJ2FmdGVyJyxcbiAgICAgICAgJ3NldEl0ZW1zJyxcbiAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICBjb250ZXh0LFxuICAgICAgICBjdXJyZW50XG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gY3VycmVudDtcbiAgfVxuXG4gIGFzeW5jIGJlZm9yZUdldEl0ZW1zKFxuICAgIGtleXM6IHN0cmluZ1tdLFxuICAgIGNvbnRleHQ6IFBsdWdpbkNvbnRleHRcbiAgKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgIGxldCBjdXJyZW50S2V5cyA9IGtleXM7XG4gICAgZm9yIChjb25zdCBwbHVnaW4gb2YgdGhpcy5nZXRBY3RpdmVQbHVnaW5zKCkpIHtcbiAgICAgIGlmICghcGx1Z2luLmJlZm9yZUdldEl0ZW1zKSBjb250aW51ZTtcbiAgICAgIGN1cnJlbnRLZXlzID0gYXdhaXQgdGhpcy5pbnZva2VWYWx1ZUhvb2soXG4gICAgICAgIHBsdWdpbixcbiAgICAgICAgKCkgPT4gcGx1Z2luLmJlZm9yZUdldEl0ZW1zIShjdXJyZW50S2V5cywgY29udGV4dCksXG4gICAgICAgICdiZWZvcmUnLFxuICAgICAgICAnZ2V0SXRlbXMnLFxuICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgIGNvbnRleHQsXG4gICAgICAgIGN1cnJlbnRLZXlzXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gY3VycmVudEtleXM7XG4gIH1cblxuICBhc3luYyBhZnRlckdldEl0ZW1zPFQ+KFxuICAgIGVudHJpZXM6IEJhdGNoUmVzcG9uc2U8VD4sXG4gICAgY29udGV4dDogUGx1Z2luQ29udGV4dFxuICApOiBQcm9taXNlPEJhdGNoUmVzcG9uc2U8VD4+IHtcbiAgICBsZXQgY3VycmVudCA9IGVudHJpZXM7XG4gICAgZm9yIChjb25zdCBwbHVnaW4gb2YgdGhpcy5nZXRBY3RpdmVQbHVnaW5zKHsgcmV2ZXJzZTogdHJ1ZSB9KSkge1xuICAgICAgaWYgKCFwbHVnaW4uYWZ0ZXJHZXRJdGVtcykgY29udGludWU7XG4gICAgICBjdXJyZW50ID0gYXdhaXQgdGhpcy5pbnZva2VWYWx1ZUhvb2soXG4gICAgICAgIHBsdWdpbixcbiAgICAgICAgKCkgPT4gcGx1Z2luLmFmdGVyR2V0SXRlbXMhKGN1cnJlbnQsIGNvbnRleHQpLFxuICAgICAgICAnYWZ0ZXInLFxuICAgICAgICAnZ2V0SXRlbXMnLFxuICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgIGNvbnRleHQsXG4gICAgICAgIGN1cnJlbnRcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBjdXJyZW50O1xuICB9XG5cbiAgYXN5bmMgYmVmb3JlUmVtb3ZlSXRlbXMoXG4gICAga2V5czogc3RyaW5nW10sXG4gICAgY29udGV4dDogUGx1Z2luQ29udGV4dFxuICApOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgbGV0IGN1cnJlbnRLZXlzID0ga2V5cztcbiAgICBmb3IgKGNvbnN0IHBsdWdpbiBvZiB0aGlzLmdldEFjdGl2ZVBsdWdpbnMoKSkge1xuICAgICAgaWYgKCFwbHVnaW4uYmVmb3JlUmVtb3ZlSXRlbXMpIGNvbnRpbnVlO1xuICAgICAgY3VycmVudEtleXMgPSBhd2FpdCB0aGlzLmludm9rZVZhbHVlSG9vayhcbiAgICAgICAgcGx1Z2luLFxuICAgICAgICAoKSA9PiBwbHVnaW4uYmVmb3JlUmVtb3ZlSXRlbXMhKGN1cnJlbnRLZXlzLCBjb250ZXh0KSxcbiAgICAgICAgJ2JlZm9yZScsXG4gICAgICAgICdyZW1vdmVJdGVtcycsXG4gICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgY29udGV4dCxcbiAgICAgICAgY3VycmVudEtleXNcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBjdXJyZW50S2V5cztcbiAgfVxuXG4gIGFzeW5jIGFmdGVyUmVtb3ZlSXRlbXMoXG4gICAga2V5czogc3RyaW5nW10sXG4gICAgY29udGV4dDogUGx1Z2luQ29udGV4dFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBmb3IgKGNvbnN0IHBsdWdpbiBvZiB0aGlzLmdldEFjdGl2ZVBsdWdpbnMoeyByZXZlcnNlOiB0cnVlIH0pKSB7XG4gICAgICBpZiAoIXBsdWdpbi5hZnRlclJlbW92ZUl0ZW1zKSBjb250aW51ZTtcbiAgICAgIGF3YWl0IHRoaXMuaW52b2tlVm9pZEhvb2soXG4gICAgICAgIHBsdWdpbixcbiAgICAgICAgKCkgPT4gcGx1Z2luLmFmdGVyUmVtb3ZlSXRlbXMhKGtleXMsIGNvbnRleHQpLFxuICAgICAgICAnYWZ0ZXInLFxuICAgICAgICAncmVtb3ZlSXRlbXMnLFxuICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgIGNvbnRleHRcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgZGVzdHJveSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBwbHVnaW5zID0gdGhpcy5wbHVnaW5SZWdpc3RyeVxuICAgICAgLm1hcCgoZW50cnkpID0+IGVudHJ5LnBsdWdpbilcbiAgICAgIC5zbGljZSgpXG4gICAgICAucmV2ZXJzZSgpO1xuICAgIGZvciAoY29uc3QgcGx1Z2luIG9mIHBsdWdpbnMpIHtcbiAgICAgIGlmICh0aGlzLmRlc3Ryb3llZC5oYXMocGx1Z2luKSB8fCB0aGlzLmRpc2FibGVkLmhhcyhwbHVnaW4pKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgaWYgKHR5cGVvZiBwbHVnaW4ub25EZXN0cm95ICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRoaXMuZGVzdHJveWVkLmFkZChwbHVnaW4pO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGNvbnRleHQgPSB0aGlzLmNyZWF0ZUNvbnRleHQobnVsbCk7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBwbHVnaW4ub25EZXN0cm95KGNvbnRleHQpO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5kaXNwYXRjaFBsdWdpbkVycm9yKFxuICAgICAgICAgIHBsdWdpbixcbiAgICAgICAgICBlcnJvcixcbiAgICAgICAgICAnZGVzdHJveScsXG4gICAgICAgICAgJ2xpZmVjeWNsZScsXG4gICAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICAgIGNvbnRleHRcbiAgICAgICAgKTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIHRoaXMuZGVzdHJveWVkLmFkZChwbHVnaW4pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIG5vcm1hbGl6ZUJhdGNoPFQ+KGl0ZW1zOiBCYXRjaEl0ZW1zPFQ+KTogQXJyYXk8eyBrZXk6IHN0cmluZzsgdmFsdWU6IFQgfT4ge1xuICAgIHJldHVybiBub3JtYWxpemVCYXRjaEVudHJpZXMoaXRlbXMpO1xuICB9XG5cbiAgcHJpdmF0ZSBzaG91bGRQcm9wYWdhdGUoZXJyb3I6IHVua25vd24pOiBib29sZWFuIHtcbiAgICByZXR1cm4gKFxuICAgICAgZXJyb3IgaW5zdGFuY2VvZiBMb2NhbFNwYWNlRXJyb3IgfHwgZXJyb3IgaW5zdGFuY2VvZiBQbHVnaW5BYm9ydEVycm9yXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZGlzcGF0Y2hQbHVnaW5FcnJvcihcbiAgICBwbHVnaW46IExvY2FsU3BhY2VQbHVnaW4sXG4gICAgZXJyb3I6IHVua25vd24sXG4gICAgc3RhZ2U6IFBsdWdpblN0YWdlLFxuICAgIG9wZXJhdGlvbjogUGx1Z2luT3BlcmF0aW9uLFxuICAgIGtleTogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICAgIGNvbnRleHQ6IFBsdWdpbkNvbnRleHRcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgaW5mbzogUGx1Z2luRXJyb3JJbmZvID0ge1xuICAgICAgcGx1Z2luOiBwbHVnaW4ubmFtZSxcbiAgICAgIG9wZXJhdGlvbixcbiAgICAgIHN0YWdlLFxuICAgICAga2V5LFxuICAgICAgY29udGV4dCxcbiAgICAgIGVycm9yLFxuICAgIH07XG5cbiAgICBpZiAodHlwZW9mIHBsdWdpbi5vbkVycm9yID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBwbHVnaW4ub25FcnJvcihlcnJvciwgaW5mbyk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gY2F0Y2ggKGhvb2tFcnJvcikge1xuICAgICAgICBjb25zb2xlLmVycm9yKFxuICAgICAgICAgIGBQbHVnaW4gb25FcnJvciBoYW5kbGVyIGZhaWxlZCBmb3IgXCIke3BsdWdpbi5uYW1lfVwiYCxcbiAgICAgICAgICBob29rRXJyb3JcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zb2xlLndhcm4oYFBsdWdpbiBcIiR7cGx1Z2luLm5hbWV9XCIgZXJyb3IgZHVyaW5nICR7b3BlcmF0aW9ufWAsIGVycm9yKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaW52b2tlVmFsdWVIb29rPFQ+KFxuICAgIHBsdWdpbjogTG9jYWxTcGFjZVBsdWdpbixcbiAgICBleGVjdXRvcjogKCkgPT4gUHJvbWlzZTxUPiB8IFQsXG4gICAgc3RhZ2U6IFBsdWdpblN0YWdlLFxuICAgIG9wZXJhdGlvbjogUGx1Z2luT3BlcmF0aW9uLFxuICAgIGtleTogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICAgIGNvbnRleHQ6IFBsdWdpbkNvbnRleHQsXG4gICAgZmFsbGJhY2s6IFRcbiAgKTogUHJvbWlzZTxUPiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGV4ZWN1dG9yKCk7XG4gICAgICByZXR1cm4gKHR5cGVvZiByZXN1bHQgPT09ICd1bmRlZmluZWQnID8gZmFsbGJhY2sgOiByZXN1bHQpIGFzIFQ7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmICh0aGlzLnNob3VsZFByb3BhZ2F0ZShlcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9XG4gICAgICBhd2FpdCB0aGlzLmRpc3BhdGNoUGx1Z2luRXJyb3IoXG4gICAgICAgIHBsdWdpbixcbiAgICAgICAgZXJyb3IsXG4gICAgICAgIHN0YWdlLFxuICAgICAgICBvcGVyYXRpb24sXG4gICAgICAgIGtleSxcbiAgICAgICAgY29udGV4dFxuICAgICAgKTtcbiAgICAgIHJldHVybiBmYWxsYmFjaztcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGludm9rZVZvaWRIb29rKFxuICAgIHBsdWdpbjogTG9jYWxTcGFjZVBsdWdpbixcbiAgICBleGVjdXRvcjogKCkgPT4gUHJvbWlzZTx2b2lkPiB8IHZvaWQsXG4gICAgc3RhZ2U6IFBsdWdpblN0YWdlLFxuICAgIG9wZXJhdGlvbjogUGx1Z2luT3BlcmF0aW9uLFxuICAgIGtleTogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICAgIGNvbnRleHQ6IFBsdWdpbkNvbnRleHRcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGV4ZWN1dG9yKCk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmICh0aGlzLnNob3VsZFByb3BhZ2F0ZShlcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9XG4gICAgICBhd2FpdCB0aGlzLmRpc3BhdGNoUGx1Z2luRXJyb3IoXG4gICAgICAgIHBsdWdpbixcbiAgICAgICAgZXJyb3IsXG4gICAgICAgIHN0YWdlLFxuICAgICAgICBvcGVyYXRpb24sXG4gICAgICAgIGtleSxcbiAgICAgICAgY29udGV4dFxuICAgICAgKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==
@@ -1 +1 @@
1
- {"version":3,"file":"indexeddb.d.ts","sourceRoot":"","sources":["../../src/drivers/indexeddb.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,MAAM,EASP,MAAM,UAAU,CAAC;AAm9DlB,QAAA,MAAM,YAAY,EAAE,MAkBnB,CAAC;AAEF,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"indexeddb.d.ts","sourceRoot":"","sources":["../../src/drivers/indexeddb.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,MAAM,EASP,MAAM,UAAU,CAAC;AA4oElB,QAAA,MAAM,YAAY,EAAE,MAkBnB,CAAC;AAEF,eAAe,YAAY,CAAC"}