holosphere 2.0.0-alpha21 → 2.0.0-alpha22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -2
- package/dist/cjs/holosphere.cjs +1 -1
- package/dist/esm/holosphere.js +43 -41
- package/dist/{index-COpLk9gL.cjs → index-B4xe-N5-.cjs} +2 -2
- package/dist/{index-COpLk9gL.cjs.map → index-B4xe-N5-.cjs.map} +1 -1
- package/dist/{index-D2WstuZJ.js → index-Bug_CGNq.js} +2 -2
- package/dist/{index-D2WstuZJ.js.map → index-Bug_CGNq.js.map} +1 -1
- package/dist/index-CaCPzdlv.cjs +29 -0
- package/dist/index-CaCPzdlv.cjs.map +1 -0
- package/dist/{index-B6-8KAQm.js → index-D76zMgwU.js} +2 -2
- package/dist/{index-B6-8KAQm.js.map → index-D76zMgwU.js.map} +1 -1
- package/dist/{index--QsHG_gD.cjs → index-DuOuk96g.cjs} +2 -2
- package/dist/{index--QsHG_gD.cjs.map → index-DuOuk96g.cjs.map} +1 -1
- package/dist/{index-BHptWysv.js → index-bYHRpACA.js} +2951 -7736
- package/dist/index-bYHRpACA.js.map +1 -0
- package/dist/{indexeddb-storage-kQ53UHEE.js → indexeddb-storage-BrIwr42m.js} +2 -2
- package/dist/{indexeddb-storage-kQ53UHEE.js.map → indexeddb-storage-BrIwr42m.js.map} +1 -1
- package/dist/{indexeddb-storage-wKG4mICM.cjs → indexeddb-storage-CFWfkdX9.cjs} +2 -2
- package/dist/{indexeddb-storage-wKG4mICM.cjs.map → indexeddb-storage-CFWfkdX9.cjs.map} +1 -1
- package/dist/{memory-storage-DnXCSbBl.js → memory-storage-BDQRj-2j.js} +2 -2
- package/dist/{memory-storage-DnXCSbBl.js.map → memory-storage-BDQRj-2j.js.map} +1 -1
- package/dist/{memory-storage-CGC8xM2G.cjs → memory-storage-bkatDnuR.cjs} +2 -2
- package/dist/{memory-storage-CGC8xM2G.cjs.map → memory-storage-bkatDnuR.cjs.map} +1 -1
- package/examples/demo.html +2 -29
- package/package.json +3 -8
- package/src/content/social-protocols.js +3 -59
- package/src/core/holosphere.js +16 -554
- package/src/crypto/nostr-utils.js +98 -1
- package/src/crypto/secp256k1.js +4 -393
- package/src/federation/discovery.js +7 -75
- package/src/federation/handshake.js +69 -202
- package/src/federation/hologram.js +222 -298
- package/src/federation/index.js +2 -9
- package/src/federation/registry.js +67 -1257
- package/src/federation/request-card.js +21 -35
- package/src/hierarchical/upcast.js +4 -9
- package/src/index.js +142 -296
- package/src/lib/federation-methods.js +370 -909
- package/src/storage/global-tables.js +1 -1
- package/src/storage/nostr-wrapper.js +9 -5
- package/src/subscriptions/manager.js +1 -1
- package/types/index.d.ts +145 -37
- package/bin/holosphere-activitypub.js +0 -158
- package/dist/2019-BzVkRcax.js +0 -6680
- package/dist/2019-BzVkRcax.js.map +0 -1
- package/dist/2019-C1hPR_Os.cjs +0 -8
- package/dist/2019-C1hPR_Os.cjs.map +0 -1
- package/dist/browser-BcmACE3G.js +0 -3058
- package/dist/browser-BcmACE3G.js.map +0 -1
- package/dist/browser-DaqYUTcG.cjs +0 -2
- package/dist/browser-DaqYUTcG.cjs.map +0 -1
- package/dist/index-BHptWysv.js.map +0 -1
- package/dist/index-CDlhzxT2.cjs +0 -29
- package/dist/index-CDlhzxT2.cjs.map +0 -1
- package/src/federation/capabilities.js +0 -46
- package/src/storage/backend-factory.js +0 -130
- package/src/storage/backend-interface.js +0 -161
- package/src/storage/backends/activitypub/server.js +0 -675
- package/src/storage/backends/activitypub-backend.js +0 -295
- package/src/storage/backends/gundb-backend.js +0 -875
- package/src/storage/backends/nostr-backend.js +0 -251
- package/src/storage/gun-async.js +0 -341
- package/src/storage/gun-auth.js +0 -373
- package/src/storage/gun-federation.js +0 -785
- package/src/storage/gun-references.js +0 -209
- package/src/storage/gun-schema.js +0 -306
- package/src/storage/gun-wrapper.js +0 -642
- package/src/storage/migration.js +0 -351
- package/src/storage/unified-storage.js +0 -161
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { aV as PersistentStorage } from "./index-
|
|
1
|
+
import { aV as PersistentStorage } from "./index-bYHRpACA.js";
|
|
2
2
|
class IndexedDBStorage extends PersistentStorage {
|
|
3
3
|
/**
|
|
4
4
|
* Create a new IndexedDBStorage instance.
|
|
@@ -210,4 +210,4 @@ class IndexedDBStorage extends PersistentStorage {
|
|
|
210
210
|
export {
|
|
211
211
|
IndexedDBStorage
|
|
212
212
|
};
|
|
213
|
-
//# sourceMappingURL=indexeddb-storage-
|
|
213
|
+
//# sourceMappingURL=indexeddb-storage-BrIwr42m.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"indexeddb-storage-kQ53UHEE.js","sources":["../src/storage/indexeddb-storage.js"],"sourcesContent":["/**\n * @fileoverview IndexedDB storage adapter for browsers.\n *\n * Provides persistent storage with good performance using browser IndexedDB.\n * Uses B-tree indexes for efficient prefix queries.\n *\n * @module storage/indexeddb-storage\n */\n\nimport { PersistentStorage } from './persistent-storage.js';\n\n/**\n * IndexedDB storage adapter for browsers.\n *\n * Provides high-performance persistent storage using IndexedDB with efficient prefix queries.\n *\n * @class IndexedDBStorage\n * @extends PersistentStorage\n * @example\n * const storage = new IndexedDBStorage();\n * await storage.init('myapp');\n * await storage.put('key1', { id: 'event1', content: 'test' });\n */\nexport class IndexedDBStorage extends PersistentStorage {\n /**\n * Create a new IndexedDBStorage instance.\n */\n constructor() {\n super();\n /** @type {IDBDatabase|null} */\n this.db = null;\n /** @type {string} */\n this.dbName = '';\n /** @type {string} */\n this.storeName = 'events';\n }\n\n /**\n * Initialize storage with namespace.\n *\n * Creates or opens the IndexedDB database and object store.\n * Handles version conflicts by deleting and recreating the database if needed.\n *\n * @param {string} namespace - Storage namespace\n * @returns {Promise<void>}\n */\n async init(namespace) {\n this.dbName = `holosphere_${namespace}`;\n\n try {\n await this._openDatabase();\n } catch (error) {\n // Handle version conflict by deleting and recreating the database\n if (error.name === 'VersionError') {\n console.warn(`[IndexedDBStorage] Version conflict detected for ${this.dbName}, recreating database...`);\n await this._deleteDatabase();\n await this._openDatabase();\n } else {\n throw error;\n }\n }\n }\n\n /**\n * Open the IndexedDB database.\n *\n * @returns {Promise<void>}\n * @private\n */\n async _openDatabase() {\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(this.dbName, 1);\n\n request.onerror = () => reject(request.error);\n request.onsuccess = () => {\n this.db = request.result;\n resolve(undefined);\n };\n\n request.onupgradeneeded = (event) => {\n const target = /** @type {IDBOpenDBRequest} */ (event.target);\n const db = target.result;\n\n // Create object store if it doesn't exist\n if (!db.objectStoreNames.contains(this.storeName)) {\n const objectStore = db.createObjectStore(this.storeName, { keyPath: 'key' });\n // Create index for prefix queries\n objectStore.createIndex('key', 'key', { unique: false });\n }\n };\n });\n }\n\n /**\n * Delete the IndexedDB database.\n *\n * @returns {Promise<void>}\n * @private\n */\n async _deleteDatabase() {\n return new Promise((resolve, reject) => {\n const request = indexedDB.deleteDatabase(this.dbName);\n request.onsuccess = () => resolve(undefined);\n request.onerror = () => reject(request.error);\n request.onblocked = () => {\n console.warn(`[IndexedDBStorage] Database deletion blocked for ${this.dbName}`);\n // Still resolve - the next open attempt will handle it\n resolve(undefined);\n };\n });\n }\n\n /**\n * Store an event.\n *\n * @param {string} key - Storage key\n * @param {Object} event - Event data\n * @returns {Promise<void>}\n */\n async put(key, event) {\n return new Promise((resolve, reject) => {\n if (!this.db) {\n reject(new Error('Database not initialized'));\n return;\n }\n const transaction = this.db.transaction([this.storeName], 'readwrite');\n const objectStore = transaction.objectStore(this.storeName);\n\n const request = objectStore.put({ key, event, timestamp: Date.now() });\n\n request.onsuccess = () => resolve(undefined);\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Retrieve an event.\n *\n * @param {string} key - Storage key\n * @returns {Promise<Object|null>} Event data or null\n */\n async get(key) {\n return new Promise((resolve, reject) => {\n if (!this.db) {\n reject(new Error('Database not initialized'));\n return;\n }\n const transaction = this.db.transaction([this.storeName], 'readonly');\n const objectStore = transaction.objectStore(this.storeName);\n\n const request = objectStore.get(key);\n\n request.onsuccess = () => {\n const result = request.result;\n resolve(result ? result.event : null);\n };\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Retrieve all events matching a prefix.\n *\n * Uses IDBKeyRange for efficient B-tree index queries.\n *\n * @param {string} prefix - Key prefix to match\n * @returns {Promise<any[]>} Array of matching events\n */\n async getAll(prefix) {\n return new Promise((resolve, reject) => {\n if (!this.db) {\n reject(new Error('Database not initialized'));\n return;\n }\n const transaction = this.db.transaction([this.storeName], 'readonly');\n const objectStore = transaction.objectStore(this.storeName);\n\n /** @type {any[]} */\n const results = [];\n\n // Use IDBKeyRange for efficient prefix query instead of full table scan\n // This creates a range from \"prefix\" to \"prefix\\uffff\" (highest unicode char)\n // which efficiently uses the B-tree index\n let request;\n if (prefix) {\n const range = IDBKeyRange.bound(prefix, prefix + '\\uffff', false, false);\n request = objectStore.openCursor(range);\n } else {\n // No prefix = get all\n request = objectStore.openCursor();\n }\n\n request.onsuccess = (event) => {\n const target = /** @type {IDBRequest} */ (event.target);\n const cursor = target.result;\n if (cursor) {\n results.push(cursor.value.event);\n cursor.continue();\n } else {\n resolve(results);\n }\n };\n\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Delete an event.\n *\n * @param {string} key - Storage key\n * @returns {Promise<void>}\n */\n async delete(key) {\n return new Promise((resolve, reject) => {\n if (!this.db) {\n reject(new Error('Database not initialized'));\n return;\n }\n const transaction = this.db.transaction([this.storeName], 'readwrite');\n const objectStore = transaction.objectStore(this.storeName);\n\n const request = objectStore.delete(key);\n\n request.onsuccess = () => resolve(undefined);\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Clear all stored events.\n *\n * @returns {Promise<void>}\n */\n async clear() {\n return new Promise((resolve, reject) => {\n if (!this.db) {\n reject(new Error('Database not initialized'));\n return;\n }\n const transaction = this.db.transaction([this.storeName], 'readwrite');\n const objectStore = transaction.objectStore(this.storeName);\n\n const request = objectStore.clear();\n\n request.onsuccess = () => resolve(undefined);\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Close the database connection.\n *\n * @returns {Promise<void>}\n */\n async close() {\n if (this.db) {\n this.db.close();\n this.db = null;\n }\n }\n}\n"],"names":[],"mappings":";AAuBO,MAAM,yBAAyB,kBAAkB;AAAA;AAAA;AAAA;AAAA,EAItD,cAAc;AACZ,UAAK;AAEL,SAAK,KAAK;AAEV,SAAK,SAAS;AAEd,SAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,KAAK,WAAW;AACpB,SAAK,SAAS,cAAc,SAAS;AAErC,QAAI;AACF,YAAM,KAAK,cAAa;AAAA,IAC1B,SAAS,OAAO;AAEd,UAAI,MAAM,SAAS,gBAAgB;AACjC,gBAAQ,KAAK,oDAAoD,KAAK,MAAM,0BAA0B;AACtG,cAAM,KAAK,gBAAe;AAC1B,cAAM,KAAK,cAAa;AAAA,MAC1B,OAAO;AACL,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,gBAAgB;AACpB,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,YAAM,UAAU,UAAU,KAAK,KAAK,QAAQ,CAAC;AAE7C,cAAQ,UAAU,MAAM,OAAO,QAAQ,KAAK;AAC5C,cAAQ,YAAY,MAAM;AACxB,aAAK,KAAK,QAAQ;AAClB,gBAAQ,MAAS;AAAA,MACnB;AAEA,cAAQ,kBAAkB,CAAC,UAAU;AACnC,cAAM;AAAA;AAAA,UAA0C,MAAM;AAAA;AACtD,cAAM,KAAK,OAAO;AAGlB,YAAI,CAAC,GAAG,iBAAiB,SAAS,KAAK,SAAS,GAAG;AACjD,gBAAM,cAAc,GAAG,kBAAkB,KAAK,WAAW,EAAE,SAAS,OAAO;AAE3E,sBAAY,YAAY,OAAO,OAAO,EAAE,QAAQ,OAAO;AAAA,QACzD;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,kBAAkB;AACtB,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,YAAM,UAAU,UAAU,eAAe,KAAK,MAAM;AACpD,cAAQ,YAAY,MAAM,QAAQ,MAAS;AAC3C,cAAQ,UAAU,MAAM,OAAO,QAAQ,KAAK;AAC5C,cAAQ,YAAY,MAAM;AACxB,gBAAQ,KAAK,oDAAoD,KAAK,MAAM,EAAE;AAE9E,gBAAQ,MAAS;AAAA,MACnB;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,IAAI,KAAK,OAAO;AACpB,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAI,CAAC,KAAK,IAAI;AACZ,eAAO,IAAI,MAAM,0BAA0B,CAAC;AAC5C;AAAA,MACF;AACA,YAAM,cAAc,KAAK,GAAG,YAAY,CAAC,KAAK,SAAS,GAAG,WAAW;AACrE,YAAM,cAAc,YAAY,YAAY,KAAK,SAAS;AAE1D,YAAM,UAAU,YAAY,IAAI,EAAE,KAAK,OAAO,WAAW,KAAK,IAAG,GAAI;AAErE,cAAQ,YAAY,MAAM,QAAQ,MAAS;AAC3C,cAAQ,UAAU,MAAM,OAAO,QAAQ,KAAK;AAAA,IAC9C,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,IAAI,KAAK;AACb,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAI,CAAC,KAAK,IAAI;AACZ,eAAO,IAAI,MAAM,0BAA0B,CAAC;AAC5C;AAAA,MACF;AACA,YAAM,cAAc,KAAK,GAAG,YAAY,CAAC,KAAK,SAAS,GAAG,UAAU;AACpE,YAAM,cAAc,YAAY,YAAY,KAAK,SAAS;AAE1D,YAAM,UAAU,YAAY,IAAI,GAAG;AAEnC,cAAQ,YAAY,MAAM;AACxB,cAAM,SAAS,QAAQ;AACvB,gBAAQ,SAAS,OAAO,QAAQ,IAAI;AAAA,MACtC;AACA,cAAQ,UAAU,MAAM,OAAO,QAAQ,KAAK;AAAA,IAC9C,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,OAAO,QAAQ;AACnB,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAI,CAAC,KAAK,IAAI;AACZ,eAAO,IAAI,MAAM,0BAA0B,CAAC;AAC5C;AAAA,MACF;AACA,YAAM,cAAc,KAAK,GAAG,YAAY,CAAC,KAAK,SAAS,GAAG,UAAU;AACpE,YAAM,cAAc,YAAY,YAAY,KAAK,SAAS;AAG1D,YAAM,UAAU,CAAA;AAKhB,UAAI;AACJ,UAAI,QAAQ;AACV,cAAM,QAAQ,YAAY,MAAM,QAAQ,SAAS,KAAU,OAAO,KAAK;AACvE,kBAAU,YAAY,WAAW,KAAK;AAAA,MACxC,OAAO;AAEL,kBAAU,YAAY,WAAU;AAAA,MAClC;AAEA,cAAQ,YAAY,CAAC,UAAU;AAC7B,cAAM;AAAA;AAAA,UAAoC,MAAM;AAAA;AAChD,cAAM,SAAS,OAAO;AACtB,YAAI,QAAQ;AACV,kBAAQ,KAAK,OAAO,MAAM,KAAK;AAC/B,iBAAO,SAAQ;AAAA,QACjB,OAAO;AACL,kBAAQ,OAAO;AAAA,QACjB;AAAA,MACF;AAEA,cAAQ,UAAU,MAAM,OAAO,QAAQ,KAAK;AAAA,IAC9C,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,OAAO,KAAK;AAChB,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAI,CAAC,KAAK,IAAI;AACZ,eAAO,IAAI,MAAM,0BAA0B,CAAC;AAC5C;AAAA,MACF;AACA,YAAM,cAAc,KAAK,GAAG,YAAY,CAAC,KAAK,SAAS,GAAG,WAAW;AACrE,YAAM,cAAc,YAAY,YAAY,KAAK,SAAS;AAE1D,YAAM,UAAU,YAAY,OAAO,GAAG;AAEtC,cAAQ,YAAY,MAAM,QAAQ,MAAS;AAC3C,cAAQ,UAAU,MAAM,OAAO,QAAQ,KAAK;AAAA,IAC9C,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,QAAQ;AACZ,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAI,CAAC,KAAK,IAAI;AACZ,eAAO,IAAI,MAAM,0BAA0B,CAAC;AAC5C;AAAA,MACF;AACA,YAAM,cAAc,KAAK,GAAG,YAAY,CAAC,KAAK,SAAS,GAAG,WAAW;AACrE,YAAM,cAAc,YAAY,YAAY,KAAK,SAAS;AAE1D,YAAM,UAAU,YAAY,MAAK;AAEjC,cAAQ,YAAY,MAAM,QAAQ,MAAS;AAC3C,cAAQ,UAAU,MAAM,OAAO,QAAQ,KAAK;AAAA,IAC9C,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,QAAQ;AACZ,QAAI,KAAK,IAAI;AACX,WAAK,GAAG,MAAK;AACb,WAAK,KAAK;AAAA,IACZ;AAAA,EACF;AACF;"}
|
|
1
|
+
{"version":3,"file":"indexeddb-storage-BrIwr42m.js","sources":["../src/storage/indexeddb-storage.js"],"sourcesContent":["/**\n * @fileoverview IndexedDB storage adapter for browsers.\n *\n * Provides persistent storage with good performance using browser IndexedDB.\n * Uses B-tree indexes for efficient prefix queries.\n *\n * @module storage/indexeddb-storage\n */\n\nimport { PersistentStorage } from './persistent-storage.js';\n\n/**\n * IndexedDB storage adapter for browsers.\n *\n * Provides high-performance persistent storage using IndexedDB with efficient prefix queries.\n *\n * @class IndexedDBStorage\n * @extends PersistentStorage\n * @example\n * const storage = new IndexedDBStorage();\n * await storage.init('myapp');\n * await storage.put('key1', { id: 'event1', content: 'test' });\n */\nexport class IndexedDBStorage extends PersistentStorage {\n /**\n * Create a new IndexedDBStorage instance.\n */\n constructor() {\n super();\n /** @type {IDBDatabase|null} */\n this.db = null;\n /** @type {string} */\n this.dbName = '';\n /** @type {string} */\n this.storeName = 'events';\n }\n\n /**\n * Initialize storage with namespace.\n *\n * Creates or opens the IndexedDB database and object store.\n * Handles version conflicts by deleting and recreating the database if needed.\n *\n * @param {string} namespace - Storage namespace\n * @returns {Promise<void>}\n */\n async init(namespace) {\n this.dbName = `holosphere_${namespace}`;\n\n try {\n await this._openDatabase();\n } catch (error) {\n // Handle version conflict by deleting and recreating the database\n if (error.name === 'VersionError') {\n console.warn(`[IndexedDBStorage] Version conflict detected for ${this.dbName}, recreating database...`);\n await this._deleteDatabase();\n await this._openDatabase();\n } else {\n throw error;\n }\n }\n }\n\n /**\n * Open the IndexedDB database.\n *\n * @returns {Promise<void>}\n * @private\n */\n async _openDatabase() {\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(this.dbName, 1);\n\n request.onerror = () => reject(request.error);\n request.onsuccess = () => {\n this.db = request.result;\n resolve(undefined);\n };\n\n request.onupgradeneeded = (event) => {\n const target = /** @type {IDBOpenDBRequest} */ (event.target);\n const db = target.result;\n\n // Create object store if it doesn't exist\n if (!db.objectStoreNames.contains(this.storeName)) {\n const objectStore = db.createObjectStore(this.storeName, { keyPath: 'key' });\n // Create index for prefix queries\n objectStore.createIndex('key', 'key', { unique: false });\n }\n };\n });\n }\n\n /**\n * Delete the IndexedDB database.\n *\n * @returns {Promise<void>}\n * @private\n */\n async _deleteDatabase() {\n return new Promise((resolve, reject) => {\n const request = indexedDB.deleteDatabase(this.dbName);\n request.onsuccess = () => resolve(undefined);\n request.onerror = () => reject(request.error);\n request.onblocked = () => {\n console.warn(`[IndexedDBStorage] Database deletion blocked for ${this.dbName}`);\n // Still resolve - the next open attempt will handle it\n resolve(undefined);\n };\n });\n }\n\n /**\n * Store an event.\n *\n * @param {string} key - Storage key\n * @param {Object} event - Event data\n * @returns {Promise<void>}\n */\n async put(key, event) {\n return new Promise((resolve, reject) => {\n if (!this.db) {\n reject(new Error('Database not initialized'));\n return;\n }\n const transaction = this.db.transaction([this.storeName], 'readwrite');\n const objectStore = transaction.objectStore(this.storeName);\n\n const request = objectStore.put({ key, event, timestamp: Date.now() });\n\n request.onsuccess = () => resolve(undefined);\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Retrieve an event.\n *\n * @param {string} key - Storage key\n * @returns {Promise<Object|null>} Event data or null\n */\n async get(key) {\n return new Promise((resolve, reject) => {\n if (!this.db) {\n reject(new Error('Database not initialized'));\n return;\n }\n const transaction = this.db.transaction([this.storeName], 'readonly');\n const objectStore = transaction.objectStore(this.storeName);\n\n const request = objectStore.get(key);\n\n request.onsuccess = () => {\n const result = request.result;\n resolve(result ? result.event : null);\n };\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Retrieve all events matching a prefix.\n *\n * Uses IDBKeyRange for efficient B-tree index queries.\n *\n * @param {string} prefix - Key prefix to match\n * @returns {Promise<any[]>} Array of matching events\n */\n async getAll(prefix) {\n return new Promise((resolve, reject) => {\n if (!this.db) {\n reject(new Error('Database not initialized'));\n return;\n }\n const transaction = this.db.transaction([this.storeName], 'readonly');\n const objectStore = transaction.objectStore(this.storeName);\n\n /** @type {any[]} */\n const results = [];\n\n // Use IDBKeyRange for efficient prefix query instead of full table scan\n // This creates a range from \"prefix\" to \"prefix\\uffff\" (highest unicode char)\n // which efficiently uses the B-tree index\n let request;\n if (prefix) {\n const range = IDBKeyRange.bound(prefix, prefix + '\\uffff', false, false);\n request = objectStore.openCursor(range);\n } else {\n // No prefix = get all\n request = objectStore.openCursor();\n }\n\n request.onsuccess = (event) => {\n const target = /** @type {IDBRequest} */ (event.target);\n const cursor = target.result;\n if (cursor) {\n results.push(cursor.value.event);\n cursor.continue();\n } else {\n resolve(results);\n }\n };\n\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Delete an event.\n *\n * @param {string} key - Storage key\n * @returns {Promise<void>}\n */\n async delete(key) {\n return new Promise((resolve, reject) => {\n if (!this.db) {\n reject(new Error('Database not initialized'));\n return;\n }\n const transaction = this.db.transaction([this.storeName], 'readwrite');\n const objectStore = transaction.objectStore(this.storeName);\n\n const request = objectStore.delete(key);\n\n request.onsuccess = () => resolve(undefined);\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Clear all stored events.\n *\n * @returns {Promise<void>}\n */\n async clear() {\n return new Promise((resolve, reject) => {\n if (!this.db) {\n reject(new Error('Database not initialized'));\n return;\n }\n const transaction = this.db.transaction([this.storeName], 'readwrite');\n const objectStore = transaction.objectStore(this.storeName);\n\n const request = objectStore.clear();\n\n request.onsuccess = () => resolve(undefined);\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Close the database connection.\n *\n * @returns {Promise<void>}\n */\n async close() {\n if (this.db) {\n this.db.close();\n this.db = null;\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-
|
|
2
|
-
//# sourceMappingURL=indexeddb-storage-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-CaCPzdlv.cjs");class t extends e.PersistentStorage{constructor(){super(),this.db=null,this.dbName="",this.storeName="events"}async init(e){this.dbName=`holosphere_${e}`;try{await this._openDatabase()}catch(t){if("VersionError"!==t.name)throw t;console.warn(`[IndexedDBStorage] Version conflict detected for ${this.dbName}, recreating database...`),await this._deleteDatabase(),await this._openDatabase()}}async _openDatabase(){return new Promise((e,t)=>{const r=indexedDB.open(this.dbName,1);r.onerror=()=>t(r.error),r.onsuccess=()=>{this.db=r.result,e(void 0)},r.onupgradeneeded=e=>{const t=e.target.result;if(!t.objectStoreNames.contains(this.storeName)){t.createObjectStore(this.storeName,{keyPath:"key"}).createIndex("key","key",{unique:!1})}}})}async _deleteDatabase(){return new Promise((e,t)=>{const r=indexedDB.deleteDatabase(this.dbName);r.onsuccess=()=>e(void 0),r.onerror=()=>t(r.error),r.onblocked=()=>{console.warn(`[IndexedDBStorage] Database deletion blocked for ${this.dbName}`),e(void 0)}})}async put(e,t){return new Promise((r,s)=>{if(!this.db)return void s(new Error("Database not initialized"));const o=this.db.transaction([this.storeName],"readwrite").objectStore(this.storeName).put({key:e,event:t,timestamp:Date.now()});o.onsuccess=()=>r(void 0),o.onerror=()=>s(o.error)})}async get(e){return new Promise((t,r)=>{if(!this.db)return void r(new Error("Database not initialized"));const s=this.db.transaction([this.storeName],"readonly").objectStore(this.storeName).get(e);s.onsuccess=()=>{const e=s.result;t(e?e.event:null)},s.onerror=()=>r(s.error)})}async getAll(e){return new Promise((t,r)=>{if(!this.db)return void r(new Error("Database not initialized"));const s=this.db.transaction([this.storeName],"readonly").objectStore(this.storeName),o=[];let n;if(e){const t=IDBKeyRange.bound(e,e+"",!1,!1);n=s.openCursor(t)}else n=s.openCursor();n.onsuccess=e=>{const r=e.target.result;r?(o.push(r.value.event),r.continue()):t(o)},n.onerror=()=>r(n.error)})}async delete(e){return new Promise((t,r)=>{if(!this.db)return void r(new Error("Database not initialized"));const s=this.db.transaction([this.storeName],"readwrite").objectStore(this.storeName).delete(e);s.onsuccess=()=>t(void 0),s.onerror=()=>r(s.error)})}async clear(){return new Promise((e,t)=>{if(!this.db)return void t(new Error("Database not initialized"));const r=this.db.transaction([this.storeName],"readwrite").objectStore(this.storeName).clear();r.onsuccess=()=>e(void 0),r.onerror=()=>t(r.error)})}async close(){this.db&&(this.db.close(),this.db=null)}}exports.IndexedDBStorage=t;
|
|
2
|
+
//# sourceMappingURL=indexeddb-storage-CFWfkdX9.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"indexeddb-storage-wKG4mICM.cjs","sources":["../src/storage/indexeddb-storage.js"],"sourcesContent":["/**\n * @fileoverview IndexedDB storage adapter for browsers.\n *\n * Provides persistent storage with good performance using browser IndexedDB.\n * Uses B-tree indexes for efficient prefix queries.\n *\n * @module storage/indexeddb-storage\n */\n\nimport { PersistentStorage } from './persistent-storage.js';\n\n/**\n * IndexedDB storage adapter for browsers.\n *\n * Provides high-performance persistent storage using IndexedDB with efficient prefix queries.\n *\n * @class IndexedDBStorage\n * @extends PersistentStorage\n * @example\n * const storage = new IndexedDBStorage();\n * await storage.init('myapp');\n * await storage.put('key1', { id: 'event1', content: 'test' });\n */\nexport class IndexedDBStorage extends PersistentStorage {\n /**\n * Create a new IndexedDBStorage instance.\n */\n constructor() {\n super();\n /** @type {IDBDatabase|null} */\n this.db = null;\n /** @type {string} */\n this.dbName = '';\n /** @type {string} */\n this.storeName = 'events';\n }\n\n /**\n * Initialize storage with namespace.\n *\n * Creates or opens the IndexedDB database and object store.\n * Handles version conflicts by deleting and recreating the database if needed.\n *\n * @param {string} namespace - Storage namespace\n * @returns {Promise<void>}\n */\n async init(namespace) {\n this.dbName = `holosphere_${namespace}`;\n\n try {\n await this._openDatabase();\n } catch (error) {\n // Handle version conflict by deleting and recreating the database\n if (error.name === 'VersionError') {\n console.warn(`[IndexedDBStorage] Version conflict detected for ${this.dbName}, recreating database...`);\n await this._deleteDatabase();\n await this._openDatabase();\n } else {\n throw error;\n }\n }\n }\n\n /**\n * Open the IndexedDB database.\n *\n * @returns {Promise<void>}\n * @private\n */\n async _openDatabase() {\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(this.dbName, 1);\n\n request.onerror = () => reject(request.error);\n request.onsuccess = () => {\n this.db = request.result;\n resolve(undefined);\n };\n\n request.onupgradeneeded = (event) => {\n const target = /** @type {IDBOpenDBRequest} */ (event.target);\n const db = target.result;\n\n // Create object store if it doesn't exist\n if (!db.objectStoreNames.contains(this.storeName)) {\n const objectStore = db.createObjectStore(this.storeName, { keyPath: 'key' });\n // Create index for prefix queries\n objectStore.createIndex('key', 'key', { unique: false });\n }\n };\n });\n }\n\n /**\n * Delete the IndexedDB database.\n *\n * @returns {Promise<void>}\n * @private\n */\n async _deleteDatabase() {\n return new Promise((resolve, reject) => {\n const request = indexedDB.deleteDatabase(this.dbName);\n request.onsuccess = () => resolve(undefined);\n request.onerror = () => reject(request.error);\n request.onblocked = () => {\n console.warn(`[IndexedDBStorage] Database deletion blocked for ${this.dbName}`);\n // Still resolve - the next open attempt will handle it\n resolve(undefined);\n };\n });\n }\n\n /**\n * Store an event.\n *\n * @param {string} key - Storage key\n * @param {Object} event - Event data\n * @returns {Promise<void>}\n */\n async put(key, event) {\n return new Promise((resolve, reject) => {\n if (!this.db) {\n reject(new Error('Database not initialized'));\n return;\n }\n const transaction = this.db.transaction([this.storeName], 'readwrite');\n const objectStore = transaction.objectStore(this.storeName);\n\n const request = objectStore.put({ key, event, timestamp: Date.now() });\n\n request.onsuccess = () => resolve(undefined);\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Retrieve an event.\n *\n * @param {string} key - Storage key\n * @returns {Promise<Object|null>} Event data or null\n */\n async get(key) {\n return new Promise((resolve, reject) => {\n if (!this.db) {\n reject(new Error('Database not initialized'));\n return;\n }\n const transaction = this.db.transaction([this.storeName], 'readonly');\n const objectStore = transaction.objectStore(this.storeName);\n\n const request = objectStore.get(key);\n\n request.onsuccess = () => {\n const result = request.result;\n resolve(result ? result.event : null);\n };\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Retrieve all events matching a prefix.\n *\n * Uses IDBKeyRange for efficient B-tree index queries.\n *\n * @param {string} prefix - Key prefix to match\n * @returns {Promise<any[]>} Array of matching events\n */\n async getAll(prefix) {\n return new Promise((resolve, reject) => {\n if (!this.db) {\n reject(new Error('Database not initialized'));\n return;\n }\n const transaction = this.db.transaction([this.storeName], 'readonly');\n const objectStore = transaction.objectStore(this.storeName);\n\n /** @type {any[]} */\n const results = [];\n\n // Use IDBKeyRange for efficient prefix query instead of full table scan\n // This creates a range from \"prefix\" to \"prefix\\uffff\" (highest unicode char)\n // which efficiently uses the B-tree index\n let request;\n if (prefix) {\n const range = IDBKeyRange.bound(prefix, prefix + '\\uffff', false, false);\n request = objectStore.openCursor(range);\n } else {\n // No prefix = get all\n request = objectStore.openCursor();\n }\n\n request.onsuccess = (event) => {\n const target = /** @type {IDBRequest} */ (event.target);\n const cursor = target.result;\n if (cursor) {\n results.push(cursor.value.event);\n cursor.continue();\n } else {\n resolve(results);\n }\n };\n\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Delete an event.\n *\n * @param {string} key - Storage key\n * @returns {Promise<void>}\n */\n async delete(key) {\n return new Promise((resolve, reject) => {\n if (!this.db) {\n reject(new Error('Database not initialized'));\n return;\n }\n const transaction = this.db.transaction([this.storeName], 'readwrite');\n const objectStore = transaction.objectStore(this.storeName);\n\n const request = objectStore.delete(key);\n\n request.onsuccess = () => resolve(undefined);\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Clear all stored events.\n *\n * @returns {Promise<void>}\n */\n async clear() {\n return new Promise((resolve, reject) => {\n if (!this.db) {\n reject(new Error('Database not initialized'));\n return;\n }\n const transaction = this.db.transaction([this.storeName], 'readwrite');\n const objectStore = transaction.objectStore(this.storeName);\n\n const request = objectStore.clear();\n\n request.onsuccess = () => resolve(undefined);\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Close the database connection.\n *\n * @returns {Promise<void>}\n */\n async close() {\n if (this.db) {\n this.db.close();\n this.db = null;\n }\n }\n}\n"],"names":["IndexedDBStorage","PersistentStorage","constructor","super","this","db","dbName","storeName","init","namespace","_openDatabase","error","name","console","warn","_deleteDatabase","Promise","resolve","reject","request","indexedDB","open","onerror","onsuccess","result","onupgradeneeded","event","objectStoreNames","contains","createObjectStore","keyPath","createIndex","unique","deleteDatabase","onblocked","put","key","Error","transaction","objectStore","timestamp","Date","now","get","getAll","prefix","results","range","IDBKeyRange","bound","openCursor","cursor","push","value","continue","delete","clear","close"],"mappings":"wHAuBO,MAAMA,UAAyBC,EAAAA,kBAIpC,WAAAC,GACEC,QAEAC,KAAKC,GAAK,KAEVD,KAAKE,OAAS,GAEdF,KAAKG,UAAY,QACnB,CAWA,UAAMC,CAAKC,GACTL,KAAKE,OAAS,cAAcG,IAE5B,UACQL,KAAKM,eACb,OAASC,GAEP,GAAmB,iBAAfA,EAAMC,KAKR,MAAMD,EAJNE,QAAQC,KAAK,oDAAoDV,KAAKE,wCAChEF,KAAKW,wBACLX,KAAKM,eAIf,CACF,CAQA,mBAAMA,GACJ,OAAO,IAAIM,QAAQ,CAACC,EAASC,KAC3B,MAAMC,EAAUC,UAAUC,KAAKjB,KAAKE,OAAQ,GAE5Ca,EAAQG,QAAU,IAAMJ,EAAOC,EAAQR,OACvCQ,EAAQI,UAAY,KAClBnB,KAAKC,GAAKc,EAAQK,OAClBP,OAAQ,IAGVE,EAAQM,gBAAmBC,IACzB,MACMrB,EAD0CqB,EAAM,OACpCF,OAGlB,IAAKnB,EAAGsB,iBAAiBC,SAASxB,KAAKG,WAAY,CAC7BF,EAAGwB,kBAAkBzB,KAAKG,UAAW,CAAEuB,QAAS,QAExDC,YAAY,MAAO,MAAO,CAAEC,QAAQ,GAClD,IAGN,CAQA,qBAAMjB,GACJ,OAAO,IAAIC,QAAQ,CAACC,EAASC,KAC3B,MAAMC,EAAUC,UAAUa,eAAe7B,KAAKE,QAC9Ca,EAAQI,UAAY,IAAMN,OAAQ,GAClCE,EAAQG,QAAU,IAAMJ,EAAOC,EAAQR,OACvCQ,EAAQe,UAAY,KAClBrB,QAAQC,KAAK,oDAAoDV,KAAKE,UAEtEW,OAAQ,KAGd,CASA,SAAMkB,CAAIC,EAAKV,GACb,OAAO,IAAIV,QAAQ,CAACC,EAASC,KAC3B,IAAKd,KAAKC,GAER,YADAa,EAAO,IAAImB,MAAM,6BAGnB,MAGMlB,EAHcf,KAAKC,GAAGiC,YAAY,CAAClC,KAAKG,WAAY,aAC1BgC,YAAYnC,KAAKG,WAErB4B,IAAI,CAAEC,MAAKV,QAAOc,UAAWC,KAAKC,QAE9DvB,EAAQI,UAAY,IAAMN,OAAQ,GAClCE,EAAQG,QAAU,IAAMJ,EAAOC,EAAQR,QAE3C,CAQA,SAAMgC,CAAIP,GACR,OAAO,IAAIpB,QAAQ,CAACC,EAASC,KAC3B,IAAKd,KAAKC,GAER,YADAa,EAAO,IAAImB,MAAM,6BAGnB,MAGMlB,EAHcf,KAAKC,GAAGiC,YAAY,CAAClC,KAAKG,WAAY,YAC1BgC,YAAYnC,KAAKG,WAErBoC,IAAIP,GAEhCjB,EAAQI,UAAY,KAClB,MAAMC,EAASL,EAAQK,OACvBP,EAAQO,EAASA,EAAOE,MAAQ,OAElCP,EAAQG,QAAU,IAAMJ,EAAOC,EAAQR,QAE3C,CAUA,YAAMiC,CAAOC,GACX,OAAO,IAAI7B,QAAQ,CAACC,EAASC,KAC3B,IAAKd,KAAKC,GAER,YADAa,EAAO,IAAImB,MAAM,6BAGnB,MACME,EADcnC,KAAKC,GAAGiC,YAAY,CAAClC,KAAKG,WAAY,YAC1BgC,YAAYnC,KAAKG,WAG3CuC,EAAU,GAKhB,IAAI3B,EACJ,GAAI0B,EAAQ,CACV,MAAME,EAAQC,YAAYC,MAAMJ,EAAQA,EAAS,KAAU,GAAO,GAClE1B,EAAUoB,EAAYW,WAAWH,EACnC,MAEE5B,EAAUoB,EAAYW,aAGxB/B,EAAQI,UAAaG,IACnB,MACMyB,EADoCzB,EAAM,OAC1BF,OAClB2B,GACFL,EAAQM,KAAKD,EAAOE,MAAM3B,OAC1ByB,EAAOG,YAEPrC,EAAQ6B,IAIZ3B,EAAQG,QAAU,IAAMJ,EAAOC,EAAQR,QAE3C,CAQA,YAAM,CAAOyB,GACX,OAAO,IAAIpB,QAAQ,CAACC,EAASC,KAC3B,IAAKd,KAAKC,GAER,YADAa,EAAO,IAAImB,MAAM,6BAGnB,MAGMlB,EAHcf,KAAKC,GAAGiC,YAAY,CAAClC,KAAKG,WAAY,aAC1BgC,YAAYnC,KAAKG,WAErBgD,OAAOnB,GAEnCjB,EAAQI,UAAY,IAAMN,OAAQ,GAClCE,EAAQG,QAAU,IAAMJ,EAAOC,EAAQR,QAE3C,CAOA,WAAM6C,GACJ,OAAO,IAAIxC,QAAQ,CAACC,EAASC,KAC3B,IAAKd,KAAKC,GAER,YADAa,EAAO,IAAImB,MAAM,6BAGnB,MAGMlB,EAHcf,KAAKC,GAAGiC,YAAY,CAAClC,KAAKG,WAAY,aAC1BgC,YAAYnC,KAAKG,WAErBiD,QAE5BrC,EAAQI,UAAY,IAAMN,OAAQ,GAClCE,EAAQG,QAAU,IAAMJ,EAAOC,EAAQR,QAE3C,CAOA,WAAM8C,GACArD,KAAKC,KACPD,KAAKC,GAAGoD,QACRrD,KAAKC,GAAK,KAEd"}
|
|
1
|
+
{"version":3,"file":"indexeddb-storage-CFWfkdX9.cjs","sources":["../src/storage/indexeddb-storage.js"],"sourcesContent":["/**\n * @fileoverview IndexedDB storage adapter for browsers.\n *\n * Provides persistent storage with good performance using browser IndexedDB.\n * Uses B-tree indexes for efficient prefix queries.\n *\n * @module storage/indexeddb-storage\n */\n\nimport { PersistentStorage } from './persistent-storage.js';\n\n/**\n * IndexedDB storage adapter for browsers.\n *\n * Provides high-performance persistent storage using IndexedDB with efficient prefix queries.\n *\n * @class IndexedDBStorage\n * @extends PersistentStorage\n * @example\n * const storage = new IndexedDBStorage();\n * await storage.init('myapp');\n * await storage.put('key1', { id: 'event1', content: 'test' });\n */\nexport class IndexedDBStorage extends PersistentStorage {\n /**\n * Create a new IndexedDBStorage instance.\n */\n constructor() {\n super();\n /** @type {IDBDatabase|null} */\n this.db = null;\n /** @type {string} */\n this.dbName = '';\n /** @type {string} */\n this.storeName = 'events';\n }\n\n /**\n * Initialize storage with namespace.\n *\n * Creates or opens the IndexedDB database and object store.\n * Handles version conflicts by deleting and recreating the database if needed.\n *\n * @param {string} namespace - Storage namespace\n * @returns {Promise<void>}\n */\n async init(namespace) {\n this.dbName = `holosphere_${namespace}`;\n\n try {\n await this._openDatabase();\n } catch (error) {\n // Handle version conflict by deleting and recreating the database\n if (error.name === 'VersionError') {\n console.warn(`[IndexedDBStorage] Version conflict detected for ${this.dbName}, recreating database...`);\n await this._deleteDatabase();\n await this._openDatabase();\n } else {\n throw error;\n }\n }\n }\n\n /**\n * Open the IndexedDB database.\n *\n * @returns {Promise<void>}\n * @private\n */\n async _openDatabase() {\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(this.dbName, 1);\n\n request.onerror = () => reject(request.error);\n request.onsuccess = () => {\n this.db = request.result;\n resolve(undefined);\n };\n\n request.onupgradeneeded = (event) => {\n const target = /** @type {IDBOpenDBRequest} */ (event.target);\n const db = target.result;\n\n // Create object store if it doesn't exist\n if (!db.objectStoreNames.contains(this.storeName)) {\n const objectStore = db.createObjectStore(this.storeName, { keyPath: 'key' });\n // Create index for prefix queries\n objectStore.createIndex('key', 'key', { unique: false });\n }\n };\n });\n }\n\n /**\n * Delete the IndexedDB database.\n *\n * @returns {Promise<void>}\n * @private\n */\n async _deleteDatabase() {\n return new Promise((resolve, reject) => {\n const request = indexedDB.deleteDatabase(this.dbName);\n request.onsuccess = () => resolve(undefined);\n request.onerror = () => reject(request.error);\n request.onblocked = () => {\n console.warn(`[IndexedDBStorage] Database deletion blocked for ${this.dbName}`);\n // Still resolve - the next open attempt will handle it\n resolve(undefined);\n };\n });\n }\n\n /**\n * Store an event.\n *\n * @param {string} key - Storage key\n * @param {Object} event - Event data\n * @returns {Promise<void>}\n */\n async put(key, event) {\n return new Promise((resolve, reject) => {\n if (!this.db) {\n reject(new Error('Database not initialized'));\n return;\n }\n const transaction = this.db.transaction([this.storeName], 'readwrite');\n const objectStore = transaction.objectStore(this.storeName);\n\n const request = objectStore.put({ key, event, timestamp: Date.now() });\n\n request.onsuccess = () => resolve(undefined);\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Retrieve an event.\n *\n * @param {string} key - Storage key\n * @returns {Promise<Object|null>} Event data or null\n */\n async get(key) {\n return new Promise((resolve, reject) => {\n if (!this.db) {\n reject(new Error('Database not initialized'));\n return;\n }\n const transaction = this.db.transaction([this.storeName], 'readonly');\n const objectStore = transaction.objectStore(this.storeName);\n\n const request = objectStore.get(key);\n\n request.onsuccess = () => {\n const result = request.result;\n resolve(result ? result.event : null);\n };\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Retrieve all events matching a prefix.\n *\n * Uses IDBKeyRange for efficient B-tree index queries.\n *\n * @param {string} prefix - Key prefix to match\n * @returns {Promise<any[]>} Array of matching events\n */\n async getAll(prefix) {\n return new Promise((resolve, reject) => {\n if (!this.db) {\n reject(new Error('Database not initialized'));\n return;\n }\n const transaction = this.db.transaction([this.storeName], 'readonly');\n const objectStore = transaction.objectStore(this.storeName);\n\n /** @type {any[]} */\n const results = [];\n\n // Use IDBKeyRange for efficient prefix query instead of full table scan\n // This creates a range from \"prefix\" to \"prefix\\uffff\" (highest unicode char)\n // which efficiently uses the B-tree index\n let request;\n if (prefix) {\n const range = IDBKeyRange.bound(prefix, prefix + '\\uffff', false, false);\n request = objectStore.openCursor(range);\n } else {\n // No prefix = get all\n request = objectStore.openCursor();\n }\n\n request.onsuccess = (event) => {\n const target = /** @type {IDBRequest} */ (event.target);\n const cursor = target.result;\n if (cursor) {\n results.push(cursor.value.event);\n cursor.continue();\n } else {\n resolve(results);\n }\n };\n\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Delete an event.\n *\n * @param {string} key - Storage key\n * @returns {Promise<void>}\n */\n async delete(key) {\n return new Promise((resolve, reject) => {\n if (!this.db) {\n reject(new Error('Database not initialized'));\n return;\n }\n const transaction = this.db.transaction([this.storeName], 'readwrite');\n const objectStore = transaction.objectStore(this.storeName);\n\n const request = objectStore.delete(key);\n\n request.onsuccess = () => resolve(undefined);\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Clear all stored events.\n *\n * @returns {Promise<void>}\n */\n async clear() {\n return new Promise((resolve, reject) => {\n if (!this.db) {\n reject(new Error('Database not initialized'));\n return;\n }\n const transaction = this.db.transaction([this.storeName], 'readwrite');\n const objectStore = transaction.objectStore(this.storeName);\n\n const request = objectStore.clear();\n\n request.onsuccess = () => resolve(undefined);\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Close the database connection.\n *\n * @returns {Promise<void>}\n */\n async close() {\n if (this.db) {\n this.db.close();\n this.db = null;\n }\n }\n}\n"],"names":["IndexedDBStorage","PersistentStorage","constructor","super","this","db","dbName","storeName","init","namespace","_openDatabase","error","name","console","warn","_deleteDatabase","Promise","resolve","reject","request","indexedDB","open","onerror","onsuccess","result","onupgradeneeded","event","objectStoreNames","contains","createObjectStore","keyPath","createIndex","unique","deleteDatabase","onblocked","put","key","Error","transaction","objectStore","timestamp","Date","now","get","getAll","prefix","results","range","IDBKeyRange","bound","openCursor","cursor","push","value","continue","delete","clear","close"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { aV as PersistentStorage } from "./index-
|
|
1
|
+
import { aV as PersistentStorage } from "./index-bYHRpACA.js";
|
|
2
2
|
class MemoryStorage extends PersistentStorage {
|
|
3
3
|
/**
|
|
4
4
|
* Create a new MemoryStorage instance.
|
|
@@ -88,4 +88,4 @@ MemoryStorage._globalStore = null;
|
|
|
88
88
|
export {
|
|
89
89
|
MemoryStorage
|
|
90
90
|
};
|
|
91
|
-
//# sourceMappingURL=memory-storage-
|
|
91
|
+
//# sourceMappingURL=memory-storage-BDQRj-2j.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-storage-
|
|
1
|
+
{"version":3,"file":"memory-storage-BDQRj-2j.js","sources":["../src/storage/memory-storage.js"],"sourcesContent":["/**\n * @fileoverview Memory-only storage adapter (fallback, no actual persistence).\n *\n * Provides in-memory storage for testing or when persistent storage is unavailable.\n * Data is shared across instances with the same namespace but lost on process restart.\n *\n * @module storage/memory-storage\n */\n\nimport { PersistentStorage } from './persistent-storage.js';\n\n/**\n * Memory-only storage adapter.\n *\n * Stores data in memory with no persistence across restarts.\n * Uses a global store to share data across instances with same namespace.\n *\n * @class MemoryStorage\n * @extends PersistentStorage\n * @example\n * const storage = new MemoryStorage();\n * await storage.init('myapp');\n * await storage.put('key1', { id: 'event1' });\n */\nexport class MemoryStorage extends PersistentStorage {\n /**\n * Create a new MemoryStorage instance.\n */\n constructor() {\n super();\n this.data = new Map();\n this.namespace = null;\n }\n\n /**\n * Initialize storage with namespace.\n *\n * @param {string} namespace - Storage namespace\n * @returns {Promise<void>}\n */\n async init(namespace) {\n this.namespace = namespace;\n // Check if there's existing data for this namespace\n if (!MemoryStorage._globalStore) {\n MemoryStorage._globalStore = new Map();\n }\n if (!MemoryStorage._globalStore.has(namespace)) {\n MemoryStorage._globalStore.set(namespace, new Map());\n }\n this.data = MemoryStorage._globalStore.get(namespace);\n }\n\n /**\n * Store an event.\n *\n * @param {string} key - Storage key\n * @param {Object} event - Event data\n * @returns {Promise<void>}\n */\n async put(key, event) {\n this.data.set(key, JSON.parse(JSON.stringify(event))); // Deep clone\n }\n\n /**\n * Retrieve an event.\n *\n * @param {string} key - Storage key\n * @returns {Promise<Object|null>} Event data or null\n */\n async get(key) {\n const data = this.data.get(key);\n return data ? JSON.parse(JSON.stringify(data)) : null; // Deep clone\n }\n\n /**\n * Retrieve all events matching a prefix.\n *\n * @param {string} prefix - Key prefix to match\n * @returns {Promise<any[]>} Array of matching events\n */\n async getAll(prefix) {\n /** @type {any[]} */\n const results = [];\n for (const [key, value] of this.data.entries()) {\n if (key.startsWith(prefix)) {\n results.push(JSON.parse(JSON.stringify(value)));\n }\n }\n return results;\n }\n\n /**\n * Delete an event.\n *\n * @param {string} key - Storage key\n * @returns {Promise<void>}\n */\n async delete(key) {\n this.data.delete(key);\n }\n\n /**\n * Clear all stored events.\n *\n * @returns {Promise<void>}\n */\n async clear() {\n this.data.clear();\n }\n\n /**\n * Close storage (no-op for memory storage).\n *\n * @returns {Promise<void>}\n */\n async close() {\n // Nothing to close for memory storage\n }\n}\n\n/**\n * Global store shared across instances with same namespace.\n * @private\n */\nMemoryStorage._globalStore = null;\n"],"names":[],"mappings":";AAwBO,MAAM,sBAAsB,kBAAkB;AAAA;AAAA;AAAA;AAAA,EAInD,cAAc;AACZ,UAAK;AACL,SAAK,OAAO,oBAAI,IAAG;AACnB,SAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,KAAK,WAAW;AACpB,SAAK,YAAY;AAEjB,QAAI,CAAC,cAAc,cAAc;AAC/B,oBAAc,eAAe,oBAAI,IAAG;AAAA,IACtC;AACA,QAAI,CAAC,cAAc,aAAa,IAAI,SAAS,GAAG;AAC9C,oBAAc,aAAa,IAAI,WAAW,oBAAI,IAAG,CAAE;AAAA,IACrD;AACA,SAAK,OAAO,cAAc,aAAa,IAAI,SAAS;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,IAAI,KAAK,OAAO;AACpB,SAAK,KAAK,IAAI,KAAK,KAAK,MAAM,KAAK,UAAU,KAAK,CAAC,CAAC;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,IAAI,KAAK;AACb,UAAM,OAAO,KAAK,KAAK,IAAI,GAAG;AAC9B,WAAO,OAAO,KAAK,MAAM,KAAK,UAAU,IAAI,CAAC,IAAI;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,OAAO,QAAQ;AAEnB,UAAM,UAAU,CAAA;AAChB,eAAW,CAAC,KAAK,KAAK,KAAK,KAAK,KAAK,WAAW;AAC9C,UAAI,IAAI,WAAW,MAAM,GAAG;AAC1B,gBAAQ,KAAK,KAAK,MAAM,KAAK,UAAU,KAAK,CAAC,CAAC;AAAA,MAChD;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,OAAO,KAAK;AAChB,SAAK,KAAK,OAAO,GAAG;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,QAAQ;AACZ,SAAK,KAAK,MAAK;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,QAAQ;AAAA,EAEd;AACF;AAMA,cAAc,eAAe;"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./index-
|
|
2
|
-
//# sourceMappingURL=memory-storage-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./index-CaCPzdlv.cjs");class e extends t.PersistentStorage{constructor(){super(),this.data=new Map,this.namespace=null}async init(t){this.namespace=t,e._globalStore||(e._globalStore=new Map),e._globalStore.has(t)||e._globalStore.set(t,new Map),this.data=e._globalStore.get(t)}async put(t,e){this.data.set(t,JSON.parse(JSON.stringify(e)))}async get(t){const e=this.data.get(t);return e?JSON.parse(JSON.stringify(e)):null}async getAll(t){const e=[];for(const[s,a]of this.data.entries())s.startsWith(t)&&e.push(JSON.parse(JSON.stringify(a)));return e}async delete(t){this.data.delete(t)}async clear(){this.data.clear()}async close(){}}e._globalStore=null,exports.MemoryStorage=e;
|
|
2
|
+
//# sourceMappingURL=memory-storage-bkatDnuR.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-storage-
|
|
1
|
+
{"version":3,"file":"memory-storage-bkatDnuR.cjs","sources":["../src/storage/memory-storage.js"],"sourcesContent":["/**\n * @fileoverview Memory-only storage adapter (fallback, no actual persistence).\n *\n * Provides in-memory storage for testing or when persistent storage is unavailable.\n * Data is shared across instances with the same namespace but lost on process restart.\n *\n * @module storage/memory-storage\n */\n\nimport { PersistentStorage } from './persistent-storage.js';\n\n/**\n * Memory-only storage adapter.\n *\n * Stores data in memory with no persistence across restarts.\n * Uses a global store to share data across instances with same namespace.\n *\n * @class MemoryStorage\n * @extends PersistentStorage\n * @example\n * const storage = new MemoryStorage();\n * await storage.init('myapp');\n * await storage.put('key1', { id: 'event1' });\n */\nexport class MemoryStorage extends PersistentStorage {\n /**\n * Create a new MemoryStorage instance.\n */\n constructor() {\n super();\n this.data = new Map();\n this.namespace = null;\n }\n\n /**\n * Initialize storage with namespace.\n *\n * @param {string} namespace - Storage namespace\n * @returns {Promise<void>}\n */\n async init(namespace) {\n this.namespace = namespace;\n // Check if there's existing data for this namespace\n if (!MemoryStorage._globalStore) {\n MemoryStorage._globalStore = new Map();\n }\n if (!MemoryStorage._globalStore.has(namespace)) {\n MemoryStorage._globalStore.set(namespace, new Map());\n }\n this.data = MemoryStorage._globalStore.get(namespace);\n }\n\n /**\n * Store an event.\n *\n * @param {string} key - Storage key\n * @param {Object} event - Event data\n * @returns {Promise<void>}\n */\n async put(key, event) {\n this.data.set(key, JSON.parse(JSON.stringify(event))); // Deep clone\n }\n\n /**\n * Retrieve an event.\n *\n * @param {string} key - Storage key\n * @returns {Promise<Object|null>} Event data or null\n */\n async get(key) {\n const data = this.data.get(key);\n return data ? JSON.parse(JSON.stringify(data)) : null; // Deep clone\n }\n\n /**\n * Retrieve all events matching a prefix.\n *\n * @param {string} prefix - Key prefix to match\n * @returns {Promise<any[]>} Array of matching events\n */\n async getAll(prefix) {\n /** @type {any[]} */\n const results = [];\n for (const [key, value] of this.data.entries()) {\n if (key.startsWith(prefix)) {\n results.push(JSON.parse(JSON.stringify(value)));\n }\n }\n return results;\n }\n\n /**\n * Delete an event.\n *\n * @param {string} key - Storage key\n * @returns {Promise<void>}\n */\n async delete(key) {\n this.data.delete(key);\n }\n\n /**\n * Clear all stored events.\n *\n * @returns {Promise<void>}\n */\n async clear() {\n this.data.clear();\n }\n\n /**\n * Close storage (no-op for memory storage).\n *\n * @returns {Promise<void>}\n */\n async close() {\n // Nothing to close for memory storage\n }\n}\n\n/**\n * Global store shared across instances with same namespace.\n * @private\n */\nMemoryStorage._globalStore = null;\n"],"names":["MemoryStorage","PersistentStorage","constructor","super","this","data","Map","namespace","init","_globalStore","has","set","get","put","key","event","JSON","parse","stringify","getAll","prefix","results","value","entries","startsWith","push","delete","clear","close"],"mappings":"wHAwBO,MAAMA,UAAsBC,EAAAA,kBAIjC,WAAAC,GACEC,QACAC,KAAKC,SAAWC,IAChBF,KAAKG,UAAY,IACnB,CAQA,UAAMC,CAAKD,GACTH,KAAKG,UAAYA,EAEZP,EAAcS,eACjBT,EAAcS,iBAAmBH,KAE9BN,EAAcS,aAAaC,IAAIH,IAClCP,EAAcS,aAAaE,IAAIJ,EAAW,IAAID,KAEhDF,KAAKC,KAAOL,EAAcS,aAAaG,IAAIL,EAC7C,CASA,SAAMM,CAAIC,EAAKC,GACbX,KAAKC,KAAKM,IAAIG,EAAKE,KAAKC,MAAMD,KAAKE,UAAUH,IAC/C,CAQA,SAAMH,CAAIE,GACR,MAAMT,EAAOD,KAAKC,KAAKO,IAAIE,GAC3B,OAAOT,EAAOW,KAAKC,MAAMD,KAAKE,UAAUb,IAAS,IACnD,CAQA,YAAMc,CAAOC,GAEX,MAAMC,EAAU,GAChB,IAAA,MAAYP,EAAKQ,KAAUlB,KAAKC,KAAKkB,UAC/BT,EAAIU,WAAWJ,IACjBC,EAAQI,KAAKT,KAAKC,MAAMD,KAAKE,UAAUI,KAG3C,OAAOD,CACT,CAQA,YAAM,CAAOP,GACXV,KAAKC,KAAKqB,OAAOZ,EACnB,CAOA,WAAMa,GACJvB,KAAKC,KAAKsB,OACZ,CAOA,WAAMC,GAEN,EAOF5B,EAAcS,aAAe"}
|
package/examples/demo.html
CHANGED
|
@@ -418,7 +418,7 @@
|
|
|
418
418
|
</div>
|
|
419
419
|
<div class="feature-card">
|
|
420
420
|
<h4>📱 Social Protocols</h4>
|
|
421
|
-
<p>Native
|
|
421
|
+
<p>Native Nostr (NIP-01) social protocol support.</p>
|
|
422
422
|
</div>
|
|
423
423
|
<div class="feature-card">
|
|
424
424
|
<h4>🔐 Cryptography</h4>
|
|
@@ -618,7 +618,7 @@ const events = await hs.load(holon, 'events'); // User-friendly</code
|
|
|
618
618
|
<div id="social" class="tab-content">
|
|
619
619
|
<div class="demo-section">
|
|
620
620
|
<h3>Social Protocols</h3>
|
|
621
|
-
<p>Publish and query content using Nostr
|
|
621
|
+
<p>Publish and query content using the Nostr protocol.</p>
|
|
622
622
|
|
|
623
623
|
<div id="socialProtocolsBanner" class="status info">
|
|
624
624
|
<strong>🌐 Connected to Real Nostr Relays!</strong><br>
|
|
@@ -637,25 +637,12 @@ const events = await hs.load(holon, 'events'); // User-friendly</code
|
|
|
637
637
|
}</textarea>
|
|
638
638
|
<button onclick="publishNostr()">Publish Nostr Event</button>
|
|
639
639
|
|
|
640
|
-
<h4>Publish ActivityPub Object</h4>
|
|
641
|
-
<div class="input-group">
|
|
642
|
-
<input type="text" id="apHolon" placeholder="Holon ID">
|
|
643
|
-
</div>
|
|
644
|
-
<textarea id="apObject" placeholder="ActivityPub object (JSON)">{
|
|
645
|
-
"@context": "https://www.w3.org/ns/activitystreams",
|
|
646
|
-
"type": "Note",
|
|
647
|
-
"content": "Hello from the Fediverse!",
|
|
648
|
-
"to": ["https://www.w3.org/ns/activitystreams#Public"]
|
|
649
|
-
}</textarea>
|
|
650
|
-
<button onclick="publishActivityPub()">Publish ActivityPub</button>
|
|
651
|
-
|
|
652
640
|
<h4>Query Social Data</h4>
|
|
653
641
|
<div class="input-group">
|
|
654
642
|
<input type="text" id="socialHolon" placeholder="Holon ID">
|
|
655
643
|
<select id="socialProtocol">
|
|
656
644
|
<option value="">All Protocols</option>
|
|
657
645
|
<option value="nostr">Nostr Only</option>
|
|
658
|
-
<option value="activitypub">ActivityPub Only</option>
|
|
659
646
|
</select>
|
|
660
647
|
<button onclick="querySocial()">Query Social Data</button>
|
|
661
648
|
</div>
|
|
@@ -1129,20 +1116,6 @@ Created at: ${new Date(event.created_at * 1000).toISOString()}</pre>`;
|
|
|
1129
1116
|
}
|
|
1130
1117
|
};
|
|
1131
1118
|
|
|
1132
|
-
window.publishActivityPub = async function() {
|
|
1133
|
-
try {
|
|
1134
|
-
const holon = document.getElementById('apHolon').value;
|
|
1135
|
-
const object = JSON.parse(document.getElementById('apObject').value);
|
|
1136
|
-
|
|
1137
|
-
const result = await hs.publishActivityPub(object, holon);
|
|
1138
|
-
|
|
1139
|
-
const output = document.getElementById('socialResult');
|
|
1140
|
-
output.innerHTML = `<pre>ActivityPub object published: ${result}</pre>`;
|
|
1141
|
-
} catch (error) {
|
|
1142
|
-
showError('socialResult', error);
|
|
1143
|
-
}
|
|
1144
|
-
};
|
|
1145
|
-
|
|
1146
1119
|
window.querySocial = async function() {
|
|
1147
1120
|
try {
|
|
1148
1121
|
const holon = document.getElementById('socialHolon').value;
|
package/package.json
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "holosphere",
|
|
3
|
-
"version": "2.0.0-
|
|
3
|
+
"version": "2.0.0-alpha22",
|
|
4
4
|
"description": "Holonic geospatial communication infrastructure combining H3 hexagonal indexing with distributed P2P storage",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"bin": {
|
|
7
|
-
"holosphere-activitypub": "bin/holosphere-activitypub.js"
|
|
8
|
-
},
|
|
9
6
|
"main": "./dist/cjs/holosphere.cjs",
|
|
10
7
|
"module": "./dist/esm/holosphere.js",
|
|
11
8
|
"browser": "./dist/cdn/holosphere.min.js",
|
|
@@ -33,7 +30,7 @@
|
|
|
33
30
|
"keywords": [
|
|
34
31
|
"geospatial",
|
|
35
32
|
"h3",
|
|
36
|
-
"
|
|
33
|
+
"nostr",
|
|
37
34
|
"p2p",
|
|
38
35
|
"distributed",
|
|
39
36
|
"holonic",
|
|
@@ -60,15 +57,13 @@
|
|
|
60
57
|
"ajv": "^8.12.0",
|
|
61
58
|
"dotenv": "^17.2.3",
|
|
62
59
|
"ethers": "^6.13.4",
|
|
63
|
-
"express": "^4.21.0",
|
|
64
60
|
"h3-js": "^4.1.0",
|
|
65
61
|
"nostr-tools": "^2.17.0",
|
|
66
62
|
"openai": "^4.85.1",
|
|
67
63
|
"ws": "^8.18.3"
|
|
68
64
|
},
|
|
69
65
|
"optionalDependencies": {
|
|
70
|
-
"@nostr-dev-kit/ndk-cache-dexie": "^2.5.0"
|
|
71
|
-
"gun": "^0.2020.1241"
|
|
66
|
+
"@nostr-dev-kit/ndk-cache-dexie": "^2.5.0"
|
|
72
67
|
},
|
|
73
68
|
"devDependencies": {
|
|
74
69
|
"@vitest/coverage-v8": "^1.3.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview Social protocol adapters for Nostr (NIP-01)
|
|
3
|
-
* Provides validation, transformation, and filtering utilities for social content
|
|
2
|
+
* @fileoverview Social protocol adapters for Nostr (NIP-01).
|
|
3
|
+
* Provides validation, transformation, and filtering utilities for social content.
|
|
4
4
|
* @module content/social-protocols
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -59,36 +59,6 @@ export function validateNostrEvent(event, partial = true, throwOnError = false)
|
|
|
59
59
|
return true;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
/**
|
|
63
|
-
* Validate ActivityPub object format.
|
|
64
|
-
* Checks for required @context and type fields, optionally validates id field.
|
|
65
|
-
* @param {Object} object - ActivityPub object to validate
|
|
66
|
-
* @param {boolean} [throwOnError=false] - Throw ValidationError on failure instead of returning false
|
|
67
|
-
* @param {boolean} [requireId=false] - Require id field (default: false, will be auto-generated)
|
|
68
|
-
* @returns {boolean} True if valid, false otherwise (unless throwOnError is true)
|
|
69
|
-
* @throws {ValidationError} If validation fails and throwOnError is true
|
|
70
|
-
*/
|
|
71
|
-
export function validateActivityPubObject(object, throwOnError = false, requireId = false) {
|
|
72
|
-
if (!object || typeof object !== 'object') {
|
|
73
|
-
if (throwOnError) throw new ValidationError('ValidationError: Invalid ActivityPub object format');
|
|
74
|
-
return false;
|
|
75
|
-
}
|
|
76
|
-
if (!object['@context']) {
|
|
77
|
-
if (throwOnError) throw new ValidationError('ValidationError: Invalid ActivityPub object format - @context is required');
|
|
78
|
-
return false;
|
|
79
|
-
}
|
|
80
|
-
if (typeof object.type !== 'string') {
|
|
81
|
-
if (throwOnError) throw new ValidationError('ValidationError: Invalid ActivityPub object format - type must be a string');
|
|
82
|
-
return false;
|
|
83
|
-
}
|
|
84
|
-
// ID is optional - will be auto-generated if not provided
|
|
85
|
-
if (requireId && typeof object.id !== 'string') {
|
|
86
|
-
if (throwOnError) throw new ValidationError('ValidationError: Invalid ActivityPub object format - id must be a string');
|
|
87
|
-
return false;
|
|
88
|
-
}
|
|
89
|
-
return true;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
62
|
/**
|
|
93
63
|
* Transform Nostr event to HoloSphere storage format.
|
|
94
64
|
* Normalizes Nostr events and adds metadata for HoloSphere compatibility.
|
|
@@ -109,7 +79,6 @@ export function transformNostrEvent(event) {
|
|
|
109
79
|
sig, // Keep original field name for compatibility
|
|
110
80
|
created_at: event.created_at,
|
|
111
81
|
kind: event.kind,
|
|
112
|
-
// Gun doesn't support arrays, so serialize as JSON string
|
|
113
82
|
tags: JSON.stringify(event.tags),
|
|
114
83
|
content: event.content,
|
|
115
84
|
signature: sig, // Also include as signature for clarity
|
|
@@ -120,31 +89,6 @@ export function transformNostrEvent(event) {
|
|
|
120
89
|
};
|
|
121
90
|
}
|
|
122
91
|
|
|
123
|
-
/**
|
|
124
|
-
* Transform ActivityPub object to HoloSphere storage format.
|
|
125
|
-
* Normalizes ActivityPub objects and adds metadata for HoloSphere compatibility.
|
|
126
|
-
* @param {Object} object - ActivityPub object
|
|
127
|
-
* @returns {Object} HoloSphere data object with protocol metadata
|
|
128
|
-
*/
|
|
129
|
-
export function transformActivityPubObject(object) {
|
|
130
|
-
// Generate ID if not provided
|
|
131
|
-
const id = object.id || `ap-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
132
|
-
|
|
133
|
-
return {
|
|
134
|
-
id,
|
|
135
|
-
protocol: 'activitypub',
|
|
136
|
-
type: object.type,
|
|
137
|
-
actor: object.actor,
|
|
138
|
-
published: object.published,
|
|
139
|
-
content: object.content || object.name,
|
|
140
|
-
originalObject: { ...object, id }, // Add generated ID to original object
|
|
141
|
-
_meta: {
|
|
142
|
-
timestamp: object.published ? new Date(object.published).getTime() : Date.now(),
|
|
143
|
-
protocol: 'activitypub',
|
|
144
|
-
},
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
|
|
148
92
|
/**
|
|
149
93
|
* Filter social content by access level.
|
|
150
94
|
* Returns items matching the specified access level or all items if no level specified.
|
|
@@ -164,7 +108,7 @@ export function filterByAccessLevel(content, accessLevel) {
|
|
|
164
108
|
* Filter social content by protocol type.
|
|
165
109
|
* Returns items matching the specified protocol or all items if 'all' is specified.
|
|
166
110
|
* @param {Object[]} content - Array of social content items
|
|
167
|
-
* @param {string} protocol - Protocol to filter by ('nostr'
|
|
111
|
+
* @param {string} protocol - Protocol to filter by ('nostr' or 'all')
|
|
168
112
|
* @returns {Object[]} Filtered content array
|
|
169
113
|
*/
|
|
170
114
|
export function filterByProtocol(content, protocol) {
|