protoobject 1.1.29 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/README.md +142 -2
  2. package/lib/cjs/browser.js +28 -0
  3. package/lib/cjs/browser.js.map +1 -0
  4. package/lib/cjs/classes/proto-object-crypto.js +133 -0
  5. package/lib/cjs/classes/proto-object-crypto.js.map +1 -0
  6. package/lib/cjs/classes/proto-object-fs.js +395 -0
  7. package/lib/cjs/classes/proto-object-fs.js.map +1 -0
  8. package/lib/cjs/classes/proto-object-sqlite.js +331 -0
  9. package/lib/cjs/classes/proto-object-sqlite.js.map +1 -0
  10. package/lib/cjs/classes/proto-object-stream.js +148 -0
  11. package/lib/cjs/classes/proto-object-stream.js.map +1 -0
  12. package/lib/cjs/classes/proto-object-tcp.js +322 -0
  13. package/lib/cjs/classes/proto-object-tcp.js.map +1 -0
  14. package/lib/cjs/classes/proto-object.js.map +1 -0
  15. package/lib/cjs/decorators/static-implements.js.map +1 -0
  16. package/lib/cjs/index.js +41 -0
  17. package/lib/cjs/index.js.map +1 -0
  18. package/lib/cjs/package.json +1 -0
  19. package/lib/{types → cjs/types}/any-object.js.map +1 -1
  20. package/lib/cjs/types/collection-transformer.js.map +1 -0
  21. package/lib/cjs/types/dynamic-methods.js.map +1 -0
  22. package/lib/cjs/types/record-transformer.js.map +1 -0
  23. package/lib/cjs/types/static-methods.js.map +1 -0
  24. package/lib/cjs/types/unknown-object.js.map +1 -0
  25. package/lib/cjs/types/validator-function.js.map +1 -0
  26. package/lib/cjs/utils/protoobject-browser-storage.js +672 -0
  27. package/lib/cjs/utils/protoobject-browser-storage.js.map +1 -0
  28. package/lib/cjs/utils/protoobject-factory.js.map +1 -0
  29. package/lib/cjs/utils/protoobject-localstorage.js +188 -0
  30. package/lib/cjs/utils/protoobject-localstorage.js.map +1 -0
  31. package/lib/esm/browser.js +20 -0
  32. package/lib/esm/browser.js.map +1 -0
  33. package/lib/esm/classes/proto-object-crypto.js +129 -0
  34. package/lib/esm/classes/proto-object-crypto.js.map +1 -0
  35. package/lib/esm/classes/proto-object-fs.js +391 -0
  36. package/lib/esm/classes/proto-object-fs.js.map +1 -0
  37. package/lib/esm/classes/proto-object-sqlite.js +328 -0
  38. package/lib/esm/classes/proto-object-sqlite.js.map +1 -0
  39. package/lib/esm/classes/proto-object-stream.js +144 -0
  40. package/lib/esm/classes/proto-object-stream.js.map +1 -0
  41. package/lib/esm/classes/proto-object-tcp.js +317 -0
  42. package/lib/esm/classes/proto-object-tcp.js.map +1 -0
  43. package/lib/esm/classes/proto-object.js +264 -0
  44. package/lib/esm/classes/proto-object.js.map +1 -0
  45. package/lib/esm/decorators/static-implements.js +12 -0
  46. package/lib/esm/decorators/static-implements.js.map +1 -0
  47. package/lib/esm/index.js +22 -0
  48. package/lib/esm/index.js.map +1 -0
  49. package/lib/esm/package.json +1 -0
  50. package/lib/esm/types/any-object.js +2 -0
  51. package/lib/esm/types/any-object.js.map +1 -0
  52. package/lib/esm/types/collection-transformer.js +3 -0
  53. package/lib/esm/types/collection-transformer.js.map +1 -0
  54. package/lib/esm/types/dynamic-methods.js +3 -0
  55. package/lib/esm/types/dynamic-methods.js.map +1 -0
  56. package/lib/esm/types/record-transformer.js +3 -0
  57. package/lib/esm/types/record-transformer.js.map +1 -0
  58. package/lib/esm/types/static-methods.js +4 -0
  59. package/lib/esm/types/static-methods.js.map +1 -0
  60. package/lib/esm/types/unknown-object.js +2 -0
  61. package/lib/esm/types/unknown-object.js.map +1 -0
  62. package/lib/esm/types/validator-function.js +3 -0
  63. package/lib/esm/types/validator-function.js.map +1 -0
  64. package/lib/esm/utils/protoobject-browser-storage.js +668 -0
  65. package/lib/esm/utils/protoobject-browser-storage.js.map +1 -0
  66. package/lib/esm/utils/protoobject-factory.js +32 -0
  67. package/lib/esm/utils/protoobject-factory.js.map +1 -0
  68. package/lib/esm/utils/protoobject-localstorage.js +184 -0
  69. package/lib/esm/utils/protoobject-localstorage.js.map +1 -0
  70. package/lib/types/browser.d.ts +18 -0
  71. package/lib/types/browser.d.ts.map +1 -0
  72. package/lib/types/classes/proto-object-crypto.d.ts +99 -0
  73. package/lib/types/classes/proto-object-crypto.d.ts.map +1 -0
  74. package/lib/types/classes/proto-object-fs.d.ts +107 -0
  75. package/lib/types/classes/proto-object-fs.d.ts.map +1 -0
  76. package/lib/types/classes/proto-object-sqlite.d.ts +98 -0
  77. package/lib/types/classes/proto-object-sqlite.d.ts.map +1 -0
  78. package/lib/types/classes/proto-object-stream.d.ts +38 -0
  79. package/lib/types/classes/proto-object-stream.d.ts.map +1 -0
  80. package/lib/types/classes/proto-object-tcp.d.ts +86 -0
  81. package/lib/types/classes/proto-object-tcp.d.ts.map +1 -0
  82. package/lib/{classes → types/classes}/proto-object.d.ts +1 -0
  83. package/lib/types/classes/proto-object.d.ts.map +1 -0
  84. package/lib/{decorators → types/decorators}/static-implements.d.ts +1 -0
  85. package/lib/types/decorators/static-implements.d.ts.map +1 -0
  86. package/lib/types/index.d.ts +24 -0
  87. package/lib/types/index.d.ts.map +1 -0
  88. package/lib/types/{any-object.d.ts → types/any-object.d.ts} +1 -0
  89. package/lib/types/types/any-object.d.ts.map +1 -0
  90. package/lib/types/{collection-transformer.d.ts → types/collection-transformer.d.ts} +1 -0
  91. package/lib/types/types/collection-transformer.d.ts.map +1 -0
  92. package/lib/types/{dynamic-methods.d.ts → types/dynamic-methods.d.ts} +1 -0
  93. package/lib/types/types/dynamic-methods.d.ts.map +1 -0
  94. package/lib/types/{record-transformer.d.ts → types/record-transformer.d.ts} +1 -0
  95. package/lib/types/types/record-transformer.d.ts.map +1 -0
  96. package/lib/types/{static-methods.d.ts → types/static-methods.d.ts} +1 -0
  97. package/lib/types/types/static-methods.d.ts.map +1 -0
  98. package/lib/types/{unknown-object.d.ts → types/unknown-object.d.ts} +1 -0
  99. package/lib/types/types/unknown-object.d.ts.map +1 -0
  100. package/lib/types/{validator-function.d.ts → types/validator-function.d.ts} +1 -0
  101. package/lib/types/types/validator-function.d.ts.map +1 -0
  102. package/lib/types/utils/protoobject-browser-storage.d.ts +118 -0
  103. package/lib/types/utils/protoobject-browser-storage.d.ts.map +1 -0
  104. package/lib/{utils → types/utils}/protoobject-factory.d.ts +1 -0
  105. package/lib/types/utils/protoobject-factory.d.ts.map +1 -0
  106. package/lib/types/utils/protoobject-localstorage.d.ts +69 -0
  107. package/lib/types/utils/protoobject-localstorage.d.ts.map +1 -0
  108. package/package.json +57 -6
  109. package/CHANGELOG.md +0 -186
  110. package/FUNDING.yml +0 -2
  111. package/ignoreUpdatesModules.json +0 -4
  112. package/lib/classes/proto-object.js.map +0 -1
  113. package/lib/decorators/static-implements.js.map +0 -1
  114. package/lib/index.d.ts +0 -14
  115. package/lib/index.js +0 -18
  116. package/lib/index.js.map +0 -1
  117. package/lib/types/collection-transformer.js.map +0 -1
  118. package/lib/types/dynamic-methods.js.map +0 -1
  119. package/lib/types/record-transformer.js.map +0 -1
  120. package/lib/types/static-methods.js.map +0 -1
  121. package/lib/types/unknown-object.js.map +0 -1
  122. package/lib/types/validator-function.js.map +0 -1
  123. package/lib/utils/protoobject-factory.js.map +0 -1
  124. /package/lib/{classes → cjs/classes}/proto-object.js +0 -0
  125. /package/lib/{decorators → cjs/decorators}/static-implements.js +0 -0
  126. /package/lib/{types → cjs/types}/any-object.js +0 -0
  127. /package/lib/{types → cjs/types}/collection-transformer.js +0 -0
  128. /package/lib/{types → cjs/types}/dynamic-methods.js +0 -0
  129. /package/lib/{types → cjs/types}/record-transformer.js +0 -0
  130. /package/lib/{types → cjs/types}/static-methods.js +0 -0
  131. /package/lib/{types → cjs/types}/unknown-object.js +0 -0
  132. /package/lib/{types → cjs/types}/validator-function.js +0 -0
  133. /package/lib/{utils → cjs/utils}/protoobject-factory.js +0 -0
@@ -0,0 +1,668 @@
1
+ /**
2
+ * Universal ProtoObject browser storage utility
3
+ * Supports localStorage, sessionStorage, IndexedDB, cookies, BroadcastChannel, and Web Workers
4
+ */
5
+ export class ProtoObjectBrowserStorage {
6
+ /**
7
+ * Save ProtoObject instance to browser storage
8
+ */
9
+ static async save(key, obj, options = { type: "local" }) {
10
+ try {
11
+ const json = obj.toJSON();
12
+ const serialized = JSON.stringify(json);
13
+ switch (options.type) {
14
+ case "local":
15
+ return this.saveToWebStorage(key, serialized, "localStorage");
16
+ case "session":
17
+ return this.saveToWebStorage(key, serialized, "sessionStorage");
18
+ case "indexeddb":
19
+ return await this.saveToIndexedDB(key, json, options);
20
+ case "cookies":
21
+ return this.saveToCookies(key, serialized, options);
22
+ case "broadcast":
23
+ return this.saveToBroadcast(key, json, options);
24
+ case "worker":
25
+ return await this.saveToWorker(key, json, options);
26
+ default:
27
+ console.error(`Unsupported storage type: ${options.type}`);
28
+ return false;
29
+ }
30
+ }
31
+ catch (error) {
32
+ console.error("ProtoObjectBrowserStorage.save error:", error);
33
+ return false;
34
+ }
35
+ }
36
+ /**
37
+ * Load ProtoObject instance from browser storage
38
+ */
39
+ static async load(key, ClassConstructor, options = { type: "local" }) {
40
+ try {
41
+ let data;
42
+ switch (options.type) {
43
+ case "local":
44
+ data = this.loadFromWebStorage(key, "localStorage");
45
+ break;
46
+ case "session":
47
+ data = this.loadFromWebStorage(key, "sessionStorage");
48
+ break;
49
+ case "indexeddb":
50
+ data = await this.loadFromIndexedDB(key, options);
51
+ break;
52
+ case "cookies":
53
+ data = this.loadFromCookies(key);
54
+ break;
55
+ case "broadcast":
56
+ data = this.loadFromBroadcast(key, options);
57
+ break;
58
+ case "worker":
59
+ data = await this.loadFromWorker(key, options);
60
+ break;
61
+ default:
62
+ console.error(`Unsupported storage type: ${options.type}`);
63
+ return undefined;
64
+ }
65
+ return data ? ClassConstructor.fromJSON(data) : undefined;
66
+ }
67
+ catch (error) {
68
+ console.error("ProtoObjectBrowserStorage.load error:", error);
69
+ return undefined;
70
+ }
71
+ }
72
+ /**
73
+ * Remove item from browser storage
74
+ */
75
+ static async remove(key, options = { type: "local" }) {
76
+ try {
77
+ switch (options.type) {
78
+ case "local":
79
+ return this.removeFromWebStorage(key, "localStorage");
80
+ case "session":
81
+ return this.removeFromWebStorage(key, "sessionStorage");
82
+ case "indexeddb":
83
+ return await this.removeFromIndexedDB(key, options);
84
+ case "cookies":
85
+ return this.removeFromCookies(key, options);
86
+ case "broadcast":
87
+ return this.removeFromBroadcast(key, options);
88
+ case "worker":
89
+ return await this.removeFromWorker(key, options);
90
+ default:
91
+ console.error(`Unsupported storage type: ${options.type}`);
92
+ return false;
93
+ }
94
+ }
95
+ catch (error) {
96
+ console.error("ProtoObjectBrowserStorage.remove error:", error);
97
+ return false;
98
+ }
99
+ }
100
+ /**
101
+ * Check if key exists in browser storage
102
+ */
103
+ static async exists(key, options = { type: "local" }) {
104
+ try {
105
+ switch (options.type) {
106
+ case "local":
107
+ return this.existsInWebStorage(key, "localStorage");
108
+ case "session":
109
+ return this.existsInWebStorage(key, "sessionStorage");
110
+ case "indexeddb":
111
+ return await this.existsInIndexedDB(key, options);
112
+ case "cookies":
113
+ return this.existsInCookies(key);
114
+ case "broadcast":
115
+ return this.existsInBroadcast(key, options);
116
+ case "worker":
117
+ return await this.existsInWorker(key, options);
118
+ default:
119
+ console.error(`Unsupported storage type: ${options.type}`);
120
+ return false;
121
+ }
122
+ }
123
+ catch (error) {
124
+ console.error("ProtoObjectBrowserStorage.exists error:", error);
125
+ return false;
126
+ }
127
+ }
128
+ /**
129
+ * Get all keys with optional prefix filter
130
+ */
131
+ static async getKeys(prefix, options = { type: "local" }) {
132
+ try {
133
+ switch (options.type) {
134
+ case "local":
135
+ return this.getKeysFromWebStorage(prefix, "localStorage");
136
+ case "session":
137
+ return this.getKeysFromWebStorage(prefix, "sessionStorage");
138
+ case "indexeddb":
139
+ return await this.getKeysFromIndexedDB(prefix, options);
140
+ case "cookies":
141
+ return this.getKeysFromCookies(prefix);
142
+ case "broadcast":
143
+ return this.getKeysFromBroadcast(prefix, options);
144
+ case "worker":
145
+ return await this.getKeysFromWorker(prefix, options);
146
+ default:
147
+ console.error(`Unsupported storage type: ${options.type}`);
148
+ return [];
149
+ }
150
+ }
151
+ catch (error) {
152
+ console.error("ProtoObjectBrowserStorage.getKeys error:", error);
153
+ return [];
154
+ }
155
+ }
156
+ /**
157
+ * Clear storage with optional prefix filter
158
+ */
159
+ static async clear(prefix, options = { type: "local" }) {
160
+ try {
161
+ const keys = await this.getKeys(prefix, options);
162
+ let removed = 0;
163
+ for (const key of keys) {
164
+ if (await this.remove(key, options)) {
165
+ removed += 1;
166
+ }
167
+ }
168
+ return removed;
169
+ }
170
+ catch (error) {
171
+ console.error("ProtoObjectBrowserStorage.clear error:", error);
172
+ return 0;
173
+ }
174
+ }
175
+ // Private methods for Web Storage (localStorage/sessionStorage)
176
+ static saveToWebStorage(key, serialized, storageType) {
177
+ if (typeof window === "undefined" || !window[storageType]) {
178
+ return false;
179
+ }
180
+ window[storageType].setItem(key, serialized);
181
+ return true;
182
+ }
183
+ static loadFromWebStorage(key, storageType) {
184
+ if (typeof window === "undefined" || !window[storageType]) {
185
+ return undefined;
186
+ }
187
+ const serialized = window[storageType].getItem(key);
188
+ return serialized ? JSON.parse(serialized) : undefined;
189
+ }
190
+ static removeFromWebStorage(key, storageType) {
191
+ if (typeof window === "undefined" || !window[storageType]) {
192
+ return false;
193
+ }
194
+ window[storageType].removeItem(key);
195
+ return true;
196
+ }
197
+ static existsInWebStorage(key, storageType) {
198
+ if (typeof window === "undefined" || !window[storageType]) {
199
+ return false;
200
+ }
201
+ return window[storageType].getItem(key) !== null;
202
+ }
203
+ static getKeysFromWebStorage(prefix, storageType) {
204
+ if (typeof window === "undefined" || !window[storageType]) {
205
+ return [];
206
+ }
207
+ const keys = [];
208
+ const storage = window[storageType];
209
+ for (let i = 0; i < storage.length; i++) {
210
+ const key = storage.key(i);
211
+ if (key && (!prefix || key.startsWith(prefix))) {
212
+ keys.push(key);
213
+ }
214
+ }
215
+ return keys;
216
+ }
217
+ // Private methods for IndexedDB
218
+ static async getIndexedDB(options) {
219
+ if (typeof window === "undefined" || !window.indexedDB) {
220
+ return undefined;
221
+ }
222
+ const dbName = options.dbName || "ProtoObjectDB";
223
+ if (this.idbDatabases.has(dbName)) {
224
+ return this.idbDatabases.get(dbName);
225
+ }
226
+ return new Promise((resolve, reject) => {
227
+ const request = indexedDB.open(dbName, 1);
228
+ request.onerror = () => reject(request.error);
229
+ request.onsuccess = () => {
230
+ const db = request.result;
231
+ this.idbDatabases.set(dbName, db);
232
+ resolve(db);
233
+ };
234
+ request.onupgradeneeded = () => {
235
+ const db = request.result;
236
+ const storeName = options.storeName || "objects";
237
+ if (!db.objectStoreNames.contains(storeName)) {
238
+ db.createObjectStore(storeName);
239
+ }
240
+ };
241
+ });
242
+ }
243
+ static async saveToIndexedDB(key, data, options) {
244
+ const db = await this.getIndexedDB(options);
245
+ if (!db)
246
+ return false;
247
+ return new Promise((resolve) => {
248
+ const transaction = db.transaction([options.storeName || "objects"], "readwrite");
249
+ const store = transaction.objectStore(options.storeName || "objects");
250
+ const request = store.put(data, key);
251
+ request.onsuccess = () => resolve(true);
252
+ request.onerror = () => resolve(false);
253
+ });
254
+ }
255
+ static async loadFromIndexedDB(key, options) {
256
+ const db = await this.getIndexedDB(options);
257
+ if (!db)
258
+ return undefined;
259
+ return new Promise((resolve) => {
260
+ const transaction = db.transaction([options.storeName || "objects"], "readonly");
261
+ const store = transaction.objectStore(options.storeName || "objects");
262
+ const request = store.get(key);
263
+ request.onsuccess = () => resolve(request.result || undefined);
264
+ request.onerror = () => resolve(undefined);
265
+ });
266
+ }
267
+ static async removeFromIndexedDB(key, options) {
268
+ const db = await this.getIndexedDB(options);
269
+ if (!db)
270
+ return false;
271
+ return new Promise((resolve) => {
272
+ const transaction = db.transaction([options.storeName || "objects"], "readwrite");
273
+ const store = transaction.objectStore(options.storeName || "objects");
274
+ const request = store.delete(key);
275
+ request.onsuccess = () => resolve(true);
276
+ request.onerror = () => resolve(false);
277
+ });
278
+ }
279
+ static async existsInIndexedDB(key, options) {
280
+ const data = await this.loadFromIndexedDB(key, options);
281
+ return data !== undefined;
282
+ }
283
+ static async getKeysFromIndexedDB(prefix, options) {
284
+ const db = await this.getIndexedDB(options);
285
+ if (!db)
286
+ return [];
287
+ return new Promise((resolve) => {
288
+ const transaction = db.transaction([options.storeName || "objects"], "readonly");
289
+ const store = transaction.objectStore(options.storeName || "objects");
290
+ const request = store.getAllKeys();
291
+ request.onsuccess = () => {
292
+ const keys = request.result
293
+ .map((key) => String(key))
294
+ .filter((key) => !prefix || key.startsWith(prefix));
295
+ resolve(keys);
296
+ };
297
+ request.onerror = () => resolve([]);
298
+ });
299
+ }
300
+ // Private methods for Cookies
301
+ static saveToCookies(key, serialized, options) {
302
+ if (typeof document === "undefined") {
303
+ return false;
304
+ }
305
+ try {
306
+ const maxAge = options.maxAge || 31536000; // 1 year default
307
+ const domain = options.domain ? `; domain=${options.domain}` : "";
308
+ const path = `; path=${options.path || "/"}`;
309
+ document.cookie = `${encodeURIComponent(key)}=${encodeURIComponent(serialized)}; max-age=${maxAge}${domain}${path}`;
310
+ return true;
311
+ }
312
+ catch {
313
+ return false;
314
+ }
315
+ }
316
+ static loadFromCookies(key) {
317
+ if (typeof document === "undefined") {
318
+ return undefined;
319
+ }
320
+ try {
321
+ const encodedKey = encodeURIComponent(key);
322
+ const cookies = document.cookie.split(";");
323
+ for (const cookie of cookies) {
324
+ const [cookieKey, cookieValue] = cookie.trim().split("=");
325
+ if (cookieKey === encodedKey && cookieValue) {
326
+ const decoded = decodeURIComponent(cookieValue);
327
+ return JSON.parse(decoded);
328
+ }
329
+ }
330
+ return undefined;
331
+ }
332
+ catch {
333
+ return undefined;
334
+ }
335
+ }
336
+ static removeFromCookies(key, options) {
337
+ if (typeof document === "undefined") {
338
+ return false;
339
+ }
340
+ try {
341
+ const domain = options.domain ? `; domain=${options.domain}` : "";
342
+ const path = `; path=${options.path || "/"}`;
343
+ document.cookie = `${encodeURIComponent(key)}=; expires=Thu, 01 Jan 1970 00:00:00 GMT${domain}${path}`;
344
+ return true;
345
+ }
346
+ catch {
347
+ return false;
348
+ }
349
+ }
350
+ static existsInCookies(key) {
351
+ return this.loadFromCookies(key) !== undefined;
352
+ }
353
+ static getKeysFromCookies(prefix) {
354
+ if (typeof document === "undefined") {
355
+ return [];
356
+ }
357
+ try {
358
+ const keys = [];
359
+ const cookies = document.cookie.split(";");
360
+ for (const cookie of cookies) {
361
+ const [cookieKey] = cookie.trim().split("=");
362
+ if (cookieKey) {
363
+ const decoded = decodeURIComponent(cookieKey);
364
+ if (!prefix || decoded.startsWith(prefix)) {
365
+ keys.push(decoded);
366
+ }
367
+ }
368
+ }
369
+ return keys;
370
+ }
371
+ catch {
372
+ return [];
373
+ }
374
+ }
375
+ // Private methods for BroadcastChannel
376
+ static getBroadcastChannel(options) {
377
+ if (typeof window === "undefined" || !window.BroadcastChannel) {
378
+ return undefined;
379
+ }
380
+ const channelName = options.channelName || "protoobject-channel";
381
+ if (!this.channels.has(channelName)) {
382
+ this.channels.set(channelName, new BroadcastChannel(channelName));
383
+ }
384
+ return this.channels.get(channelName);
385
+ }
386
+ static saveToBroadcast(key, data, options) {
387
+ const channel = this.getBroadcastChannel(options);
388
+ if (!channel)
389
+ return false;
390
+ try {
391
+ channel.postMessage({ type: "save", key, data });
392
+ return true;
393
+ }
394
+ catch {
395
+ return false;
396
+ }
397
+ }
398
+ static loadFromBroadcast(key, options) {
399
+ const channel = this.getBroadcastChannel(options);
400
+ if (!channel)
401
+ return undefined;
402
+ // BroadcastChannel is async by nature, this is a synchronous fallback
403
+ // In real usage, you'd typically listen for messages
404
+ try {
405
+ channel.postMessage({ type: "load", key });
406
+ return undefined; // Would need async implementation for real usage
407
+ }
408
+ catch {
409
+ return undefined;
410
+ }
411
+ }
412
+ static removeFromBroadcast(key, options) {
413
+ const channel = this.getBroadcastChannel(options);
414
+ if (!channel)
415
+ return false;
416
+ try {
417
+ channel.postMessage({ type: "remove", key });
418
+ return true;
419
+ }
420
+ catch {
421
+ return false;
422
+ }
423
+ }
424
+ static existsInBroadcast(key, options) {
425
+ const channel = this.getBroadcastChannel(options);
426
+ if (!channel)
427
+ return false;
428
+ try {
429
+ channel.postMessage({ type: "exists", key });
430
+ return false; // Would need async implementation for real usage
431
+ }
432
+ catch {
433
+ return false;
434
+ }
435
+ }
436
+ static getKeysFromBroadcast(prefix, options) {
437
+ const channel = this.getBroadcastChannel(options);
438
+ if (!channel)
439
+ return [];
440
+ try {
441
+ channel.postMessage({ type: "getKeys", prefix });
442
+ return []; // Would need async implementation for real usage
443
+ }
444
+ catch {
445
+ return [];
446
+ }
447
+ }
448
+ // Private methods for Web Worker
449
+ static getWorker(options) {
450
+ if (typeof window === "undefined" ||
451
+ !window.Worker ||
452
+ !options.workerScript) {
453
+ return undefined;
454
+ }
455
+ if (!this.workers.has(options.workerScript)) {
456
+ try {
457
+ const worker = new Worker(options.workerScript);
458
+ this.workers.set(options.workerScript, worker);
459
+ }
460
+ catch {
461
+ return undefined;
462
+ }
463
+ }
464
+ return this.workers.get(options.workerScript);
465
+ }
466
+ static async saveToWorker(key, data, options) {
467
+ const worker = this.getWorker(options);
468
+ if (!worker)
469
+ return false;
470
+ return new Promise((resolve) => {
471
+ const messageId = Date.now().toString();
472
+ const handleMessage = (event) => {
473
+ if (event.data.id === messageId) {
474
+ worker.removeEventListener("message", handleMessage);
475
+ resolve(event.data.success || false);
476
+ }
477
+ };
478
+ worker.addEventListener("message", handleMessage);
479
+ worker.postMessage({ id: messageId, type: "save", key, data });
480
+ // Timeout after 5 seconds
481
+ setTimeout(() => {
482
+ worker.removeEventListener("message", handleMessage);
483
+ resolve(false);
484
+ }, 5000);
485
+ });
486
+ }
487
+ static async loadFromWorker(key, options) {
488
+ const worker = this.getWorker(options);
489
+ if (!worker)
490
+ return undefined;
491
+ return new Promise((resolve) => {
492
+ const messageId = Date.now().toString();
493
+ const handleMessage = (event) => {
494
+ if (event.data.id === messageId) {
495
+ worker.removeEventListener("message", handleMessage);
496
+ resolve(event.data.data || undefined);
497
+ }
498
+ };
499
+ worker.addEventListener("message", handleMessage);
500
+ worker.postMessage({ id: messageId, type: "load", key });
501
+ // Timeout after 5 seconds
502
+ setTimeout(() => {
503
+ worker.removeEventListener("message", handleMessage);
504
+ resolve(undefined);
505
+ }, 5000);
506
+ });
507
+ }
508
+ static async removeFromWorker(key, options) {
509
+ const worker = this.getWorker(options);
510
+ if (!worker)
511
+ return false;
512
+ return new Promise((resolve) => {
513
+ const messageId = Date.now().toString();
514
+ const handleMessage = (event) => {
515
+ if (event.data.id === messageId) {
516
+ worker.removeEventListener("message", handleMessage);
517
+ resolve(event.data.success || false);
518
+ }
519
+ };
520
+ worker.addEventListener("message", handleMessage);
521
+ worker.postMessage({ id: messageId, type: "remove", key });
522
+ // Timeout after 5 seconds
523
+ setTimeout(() => {
524
+ worker.removeEventListener("message", handleMessage);
525
+ resolve(false);
526
+ }, 5000);
527
+ });
528
+ }
529
+ static async existsInWorker(key, options) {
530
+ const worker = this.getWorker(options);
531
+ if (!worker)
532
+ return false;
533
+ return new Promise((resolve) => {
534
+ const messageId = Date.now().toString();
535
+ const handleMessage = (event) => {
536
+ if (event.data.id === messageId) {
537
+ worker.removeEventListener("message", handleMessage);
538
+ resolve(event.data.exists || false);
539
+ }
540
+ };
541
+ worker.addEventListener("message", handleMessage);
542
+ worker.postMessage({ id: messageId, type: "exists", key });
543
+ // Timeout after 5 seconds
544
+ setTimeout(() => {
545
+ worker.removeEventListener("message", handleMessage);
546
+ resolve(false);
547
+ }, 5000);
548
+ });
549
+ }
550
+ static async getKeysFromWorker(prefix, options) {
551
+ const worker = this.getWorker(options);
552
+ if (!worker)
553
+ return [];
554
+ return new Promise((resolve) => {
555
+ const messageId = Date.now().toString();
556
+ const handleMessage = (event) => {
557
+ if (event.data.id === messageId) {
558
+ worker.removeEventListener("message", handleMessage);
559
+ resolve(event.data.keys || []);
560
+ }
561
+ };
562
+ worker.addEventListener("message", handleMessage);
563
+ worker.postMessage({ id: messageId, type: "getKeys", prefix });
564
+ // Timeout after 5 seconds
565
+ setTimeout(() => {
566
+ worker.removeEventListener("message", handleMessage);
567
+ resolve([]);
568
+ }, 5000);
569
+ });
570
+ }
571
+ /**
572
+ * Array operations
573
+ */
574
+ static async saveArray(key, objects, options = { type: "local" }) {
575
+ try {
576
+ const jsonArray = objects.map((obj) => obj.toJSON());
577
+ const serialized = JSON.stringify({ array: jsonArray });
578
+ switch (options.type) {
579
+ case "local":
580
+ return this.saveToWebStorage(key, serialized, "localStorage");
581
+ case "session":
582
+ return this.saveToWebStorage(key, serialized, "sessionStorage");
583
+ case "indexeddb":
584
+ return await this.saveToIndexedDB(key, { array: jsonArray }, options);
585
+ case "cookies":
586
+ return this.saveToCookies(key, serialized, options);
587
+ case "broadcast":
588
+ return this.saveToBroadcast(key, { array: jsonArray }, options);
589
+ case "worker":
590
+ return await this.saveToWorker(key, { array: jsonArray }, options);
591
+ default:
592
+ console.error(`Unsupported storage type: ${options.type}`);
593
+ return false;
594
+ }
595
+ }
596
+ catch (error) {
597
+ console.error("ProtoObjectBrowserStorage.saveArray error:", error);
598
+ return false;
599
+ }
600
+ }
601
+ static async loadArray(key, ClassConstructor, options = { type: "local" }) {
602
+ try {
603
+ let data;
604
+ switch (options.type) {
605
+ case "local":
606
+ data = this.loadFromWebStorage(key, "localStorage");
607
+ break;
608
+ case "session":
609
+ data = this.loadFromWebStorage(key, "sessionStorage");
610
+ break;
611
+ case "indexeddb":
612
+ data = await this.loadFromIndexedDB(key, options);
613
+ break;
614
+ case "cookies":
615
+ data = this.loadFromCookies(key);
616
+ break;
617
+ case "broadcast":
618
+ data = this.loadFromBroadcast(key, options);
619
+ break;
620
+ case "worker":
621
+ data = await this.loadFromWorker(key, options);
622
+ break;
623
+ default:
624
+ console.error(`Unsupported storage type: ${options.type}`);
625
+ return undefined;
626
+ }
627
+ if (!data || !Array.isArray(data.array)) {
628
+ return undefined;
629
+ }
630
+ return data.array.map((json) => ClassConstructor.fromJSON(json));
631
+ }
632
+ catch (error) {
633
+ console.error("ProtoObjectBrowserStorage.loadArray error:", error);
634
+ return undefined;
635
+ }
636
+ }
637
+ /**
638
+ * Utility method to check storage support
639
+ */
640
+ static getStorageSupport() {
641
+ return {
642
+ local: typeof window !== "undefined" && !!window.localStorage,
643
+ session: typeof window !== "undefined" && !!window.sessionStorage,
644
+ indexeddb: typeof window !== "undefined" && !!window.indexedDB,
645
+ cookies: typeof document !== "undefined",
646
+ broadcast: typeof window !== "undefined" && !!window.BroadcastChannel,
647
+ worker: typeof window !== "undefined" && !!window.Worker,
648
+ };
649
+ }
650
+ /**
651
+ * Cleanup method to close connections
652
+ */
653
+ static cleanup() {
654
+ // Close IndexedDB connections
655
+ this.idbDatabases.forEach((db) => db.close());
656
+ this.idbDatabases.clear();
657
+ // Close BroadcastChannels
658
+ this.channels.forEach((channel) => channel.close());
659
+ this.channels.clear();
660
+ // Terminate workers
661
+ this.workers.forEach((worker) => worker.terminate());
662
+ this.workers.clear();
663
+ }
664
+ }
665
+ ProtoObjectBrowserStorage.workers = new Map();
666
+ ProtoObjectBrowserStorage.channels = new Map();
667
+ ProtoObjectBrowserStorage.idbDatabases = new Map();
668
+ //# sourceMappingURL=protoobject-browser-storage.js.map