holosphere 2.0.0-alpha21 → 2.0.0-alpha23

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 (69) hide show
  1. package/README.md +1 -2
  2. package/dist/cjs/holosphere.cjs +1 -1
  3. package/dist/esm/holosphere.js +61 -58
  4. package/dist/{index-B6-8KAQm.js → index-BEkCLOwI.js} +2 -2
  5. package/dist/{index-B6-8KAQm.js.map → index-BEkCLOwI.js.map} +1 -1
  6. package/dist/{index-D2WstuZJ.js → index-BEvX6DxG.js} +2 -2
  7. package/dist/{index-D2WstuZJ.js.map → index-BEvX6DxG.js.map} +1 -1
  8. package/dist/{index--QsHG_gD.cjs → index-BGTOiJ2Y.cjs} +2 -2
  9. package/dist/{index--QsHG_gD.cjs.map → index-BGTOiJ2Y.cjs.map} +1 -1
  10. package/dist/{index-COpLk9gL.cjs → index-BH1woZXL.cjs} +2 -2
  11. package/dist/{index-COpLk9gL.cjs.map → index-BH1woZXL.cjs.map} +1 -1
  12. package/dist/{index-BHptWysv.js → index-Cvxov2jv.js} +2970 -7753
  13. package/dist/index-Cvxov2jv.js.map +1 -0
  14. package/dist/index-vTKI_BAX.cjs +29 -0
  15. package/dist/index-vTKI_BAX.cjs.map +1 -0
  16. package/dist/{indexeddb-storage-wKG4mICM.cjs → indexeddb-storage-BmnCNnSg.cjs} +2 -2
  17. package/dist/{indexeddb-storage-wKG4mICM.cjs.map → indexeddb-storage-BmnCNnSg.cjs.map} +1 -1
  18. package/dist/{indexeddb-storage-kQ53UHEE.js → indexeddb-storage-MIFisaPy.js} +2 -2
  19. package/dist/{indexeddb-storage-kQ53UHEE.js.map → indexeddb-storage-MIFisaPy.js.map} +1 -1
  20. package/dist/{memory-storage-CGC8xM2G.cjs → memory-storage-BJjK3F4r.cjs} +2 -2
  21. package/dist/{memory-storage-CGC8xM2G.cjs.map → memory-storage-BJjK3F4r.cjs.map} +1 -1
  22. package/dist/{memory-storage-DnXCSbBl.js → memory-storage-DhHXdKQ-.js} +2 -2
  23. package/dist/{memory-storage-DnXCSbBl.js.map → memory-storage-DhHXdKQ-.js.map} +1 -1
  24. package/examples/demo.html +2 -29
  25. package/package.json +3 -8
  26. package/src/content/social-protocols.js +3 -59
  27. package/src/core/holosphere.js +16 -554
  28. package/src/crypto/nostr-utils.js +98 -1
  29. package/src/crypto/secp256k1.js +4 -393
  30. package/src/federation/discovery.js +7 -75
  31. package/src/federation/handshake.js +69 -202
  32. package/src/federation/hologram.js +222 -298
  33. package/src/federation/index.js +2 -9
  34. package/src/federation/registry.js +67 -1257
  35. package/src/federation/request-card.js +21 -35
  36. package/src/hierarchical/upcast.js +4 -9
  37. package/src/index.js +145 -296
  38. package/src/lib/federation-methods.js +370 -909
  39. package/src/storage/global-tables.js +1 -1
  40. package/src/storage/nostr-wrapper.js +9 -5
  41. package/src/subscriptions/manager.js +1 -1
  42. package/types/index.d.ts +145 -37
  43. package/bin/holosphere-activitypub.js +0 -158
  44. package/dist/2019-BzVkRcax.js +0 -6680
  45. package/dist/2019-BzVkRcax.js.map +0 -1
  46. package/dist/2019-C1hPR_Os.cjs +0 -8
  47. package/dist/2019-C1hPR_Os.cjs.map +0 -1
  48. package/dist/browser-BcmACE3G.js +0 -3058
  49. package/dist/browser-BcmACE3G.js.map +0 -1
  50. package/dist/browser-DaqYUTcG.cjs +0 -2
  51. package/dist/browser-DaqYUTcG.cjs.map +0 -1
  52. package/dist/index-BHptWysv.js.map +0 -1
  53. package/dist/index-CDlhzxT2.cjs +0 -29
  54. package/dist/index-CDlhzxT2.cjs.map +0 -1
  55. package/src/federation/capabilities.js +0 -46
  56. package/src/storage/backend-factory.js +0 -130
  57. package/src/storage/backend-interface.js +0 -161
  58. package/src/storage/backends/activitypub/server.js +0 -675
  59. package/src/storage/backends/activitypub-backend.js +0 -295
  60. package/src/storage/backends/gundb-backend.js +0 -875
  61. package/src/storage/backends/nostr-backend.js +0 -251
  62. package/src/storage/gun-async.js +0 -341
  63. package/src/storage/gun-auth.js +0 -373
  64. package/src/storage/gun-federation.js +0 -785
  65. package/src/storage/gun-references.js +0 -209
  66. package/src/storage/gun-schema.js +0 -306
  67. package/src/storage/gun-wrapper.js +0 -642
  68. package/src/storage/migration.js +0 -351
  69. package/src/storage/unified-storage.js +0 -161
@@ -1,351 +0,0 @@
1
- /**
2
- * @fileoverview Migration tool for HoloSphere storage backends.
3
- * Enables data migration between different storage backends (Nostr, GunDB, ActivityPub)
4
- * with export/import functionality, direct migration, and validation.
5
- * @module storage/migration
6
- */
7
-
8
- import { BackendFactory } from './backend-factory.js';
9
-
10
- /**
11
- * Portable data bundle format
12
- * @typedef {Object} DataBundle
13
- * @property {string} version - Bundle format version
14
- * @property {string} exportedAt - ISO timestamp
15
- * @property {string} sourceType - Source backend type
16
- * @property {string} sourceKey - Source public key
17
- * @property {number} recordCount - Number of records
18
- * @property {Object[]} records - Array of data records
19
- */
20
-
21
- /**
22
- * Migration record format
23
- * @typedef {Object} MigrationRecord
24
- * @property {string} path - Storage path
25
- * @property {Object} data - Record data
26
- * @property {number} timestamp - Creation timestamp
27
- * @property {string} [author] - Author public key
28
- */
29
-
30
- /**
31
- * Migration results
32
- * @typedef {Object} MigrationResults
33
- * @property {number} success - Successfully migrated records
34
- * @property {number} failed - Failed records
35
- * @property {Object[]} errors - Error details
36
- */
37
-
38
- /**
39
- * Migration tool for transferring data between HoloSphere storage backends.
40
- * Supports export/import to portable format, direct migration, and validation.
41
- *
42
- * @class MigrationTool
43
- * @example
44
- * const tool = new MigrationTool();
45
- * await tool.setSource('nostr', { relays: ['wss://...'] });
46
- * await tool.setTarget('gundb', { peers: ['wss://...'] });
47
- * const results = await tool.migrate();
48
- */
49
- export class MigrationTool {
50
- /**
51
- * Create a new MigrationTool instance.
52
- */
53
- constructor() {
54
- /** @type {StorageBackend|null} */
55
- this.sourceBackend = null;
56
- /** @type {StorageBackend|null} */
57
- this.targetBackend = null;
58
- }
59
-
60
- /**
61
- * Configure source backend
62
- * @param {string} type - Backend type: 'nostr' | 'gundb' | 'activitypub'
63
- * @param {Object} config - Backend configuration
64
- * @returns {Promise<void>}
65
- */
66
- async setSource(type, config) {
67
- this.sourceBackend = await BackendFactory.create(type, config);
68
- }
69
-
70
- /**
71
- * Configure target backend
72
- * @param {string} type - Backend type: 'nostr' | 'gundb' | 'activitypub'
73
- * @param {Object} config - Backend configuration
74
- * @returns {Promise<void>}
75
- */
76
- async setTarget(type, config) {
77
- this.targetBackend = await BackendFactory.create(type, config);
78
- }
79
-
80
- /**
81
- * Use an existing backend instance as source
82
- * @param {StorageBackend} backend - Backend instance
83
- */
84
- useSourceBackend(backend) {
85
- this.sourceBackend = backend;
86
- }
87
-
88
- /**
89
- * Use an existing backend instance as target
90
- * @param {StorageBackend} backend - Backend instance
91
- */
92
- useTargetBackend(backend) {
93
- this.targetBackend = backend;
94
- }
95
-
96
- /**
97
- * Export data from source to portable format
98
- * @param {string} [pathPrefix] - Optional path prefix filter
99
- * @returns {Promise<DataBundle>} Exportable data bundle
100
- */
101
- async export(pathPrefix = '') {
102
- if (!this.sourceBackend) {
103
- throw new Error('Source backend not configured. Call setSource() first.');
104
- }
105
-
106
- console.log(`Exporting data from ${this.sourceBackend.getStatus().type}...`);
107
-
108
- const records = await this.sourceBackend.exportData(pathPrefix);
109
- const status = this.sourceBackend.getStatus();
110
-
111
- const bundle = {
112
- version: '1.0',
113
- exportedAt: new Date().toISOString(),
114
- sourceType: status.type,
115
- sourceKey: status.publicKey || 'unknown',
116
- pathPrefix: pathPrefix || '',
117
- recordCount: records.length,
118
- records,
119
- };
120
-
121
- console.log(`Exported ${records.length} records.`);
122
- return bundle;
123
- }
124
-
125
- /**
126
- * Import data to target backend
127
- * @param {DataBundle} bundle - Data bundle from export()
128
- * @param {Object} [options] - Import options
129
- * @param {boolean} [options.overwrite] - Overwrite existing data
130
- * @param {boolean} [options.dryRun] - Simulate without writing
131
- * @param {Function} [options.onProgress] - Progress callback (current, total)
132
- * @returns {Promise<MigrationResults>} Import results
133
- */
134
- async import(bundle, options = {}) {
135
- if (!this.targetBackend) {
136
- throw new Error('Target backend not configured. Call setTarget() first.');
137
- }
138
-
139
- if (!bundle || !bundle.records) {
140
- throw new Error('Invalid bundle format. Expected { version, records }');
141
- }
142
-
143
- console.log(`Importing ${bundle.recordCount} records to ${this.targetBackend.getStatus().type}...`);
144
-
145
- if (options.dryRun) {
146
- console.log('Dry run mode - no data will be written.');
147
- return {
148
- dryRun: true,
149
- wouldImport: bundle.recordCount,
150
- records: bundle.records.map(r => r.path),
151
- };
152
- }
153
-
154
- const results = await this.targetBackend.importData(bundle.records, options);
155
-
156
- if (options.onProgress) {
157
- options.onProgress(results.success + results.failed, bundle.recordCount);
158
- }
159
-
160
- console.log(`Import complete: ${results.success} succeeded, ${results.failed} failed.`);
161
- return results;
162
- }
163
-
164
- /**
165
- * Migrate data directly from source to target
166
- * @param {string} [pathPrefix] - Optional path prefix filter
167
- * @param {Object} [options] - Migration options
168
- * @param {boolean} [options.dryRun] - Simulate without writing
169
- * @param {Function} [options.onProgress] - Progress callback
170
- * @returns {Promise<Object>} Migration results
171
- */
172
- async migrate(pathPrefix = '', options = {}) {
173
- if (!this.sourceBackend || !this.targetBackend) {
174
- throw new Error('Both source and target backends must be configured.');
175
- }
176
-
177
- const sourceStatus = this.sourceBackend.getStatus();
178
- const targetStatus = this.targetBackend.getStatus();
179
-
180
- console.log(`\nMigrating data:`);
181
- console.log(` From: ${sourceStatus.type} (${sourceStatus.publicKey || 'unknown'})`);
182
- console.log(` To: ${targetStatus.type}`);
183
- console.log(` Filter: ${pathPrefix || '(all data)'}\n`);
184
-
185
- // Export from source
186
- const bundle = await this.export(pathPrefix);
187
-
188
- // Import to target
189
- const importResults = await this.import(bundle, options);
190
-
191
- return {
192
- sourceType: sourceStatus.type,
193
- targetType: targetStatus.type,
194
- pathPrefix,
195
- exportedCount: bundle.recordCount,
196
- ...importResults,
197
- };
198
- }
199
-
200
- /**
201
- * Validate data integrity after migration
202
- * @param {string} [pathPrefix] - Optional path prefix filter
203
- * @returns {Promise<Object>} Validation results
204
- */
205
- async validate(pathPrefix = '') {
206
- if (!this.sourceBackend || !this.targetBackend) {
207
- throw new Error('Both source and target backends must be configured.');
208
- }
209
-
210
- console.log('Validating migration...');
211
-
212
- const sourceData = await this.sourceBackend.exportData(pathPrefix);
213
- const targetData = await this.targetBackend.exportData(pathPrefix);
214
-
215
- const sourceMap = new Map(sourceData.map(r => [r.path, r]));
216
- const targetMap = new Map(targetData.map(r => [r.path, r]));
217
-
218
- const missing = [];
219
- const different = [];
220
- const extra = [];
221
-
222
- // Check for missing or different records
223
- for (const [path, sourceRecord] of sourceMap) {
224
- const targetRecord = targetMap.get(path);
225
-
226
- if (!targetRecord) {
227
- missing.push(path);
228
- } else {
229
- // Compare data (ignoring metadata that may differ)
230
- const sourceDataStr = JSON.stringify(this._normalizeForComparison(sourceRecord.data));
231
- const targetDataStr = JSON.stringify(this._normalizeForComparison(targetRecord.data));
232
-
233
- if (sourceDataStr !== targetDataStr) {
234
- different.push({
235
- path,
236
- source: sourceRecord.data,
237
- target: targetRecord.data,
238
- });
239
- }
240
- }
241
- }
242
-
243
- // Check for extra records in target
244
- for (const path of targetMap.keys()) {
245
- if (!sourceMap.has(path)) {
246
- extra.push(path);
247
- }
248
- }
249
-
250
- const valid = missing.length === 0 && different.length === 0;
251
-
252
- console.log(`Validation ${valid ? 'PASSED' : 'FAILED'}:`);
253
- console.log(` Source records: ${sourceData.length}`);
254
- console.log(` Target records: ${targetData.length}`);
255
- console.log(` Missing: ${missing.length}`);
256
- console.log(` Different: ${different.length}`);
257
- console.log(` Extra: ${extra.length}`);
258
-
259
- return {
260
- valid,
261
- sourceCount: sourceData.length,
262
- targetCount: targetData.length,
263
- missing,
264
- different,
265
- extra,
266
- };
267
- }
268
-
269
- /**
270
- * Normalize data for comparison (remove volatile metadata)
271
- * @private
272
- */
273
- _normalizeForComparison(data) {
274
- if (!data || typeof data !== 'object') return data;
275
-
276
- const normalized = { ...data };
277
-
278
- // Remove metadata that may legitimately differ
279
- delete normalized._meta;
280
- delete normalized._author;
281
- delete normalized._timestamp;
282
-
283
- return normalized;
284
- }
285
-
286
- /**
287
- * Export bundle to JSON file (for manual transfer)
288
- * @param {DataBundle} bundle - Data bundle
289
- * @param {string} filePath - Output file path
290
- */
291
- async exportToFile(bundle, filePath) {
292
- const fs = await import('fs/promises');
293
- await fs.writeFile(filePath, JSON.stringify(bundle, null, 2), 'utf-8');
294
- console.log(`Bundle exported to ${filePath}`);
295
- }
296
-
297
- /**
298
- * Import bundle from JSON file
299
- * @param {string} filePath - Input file path
300
- * @returns {Promise<DataBundle>} Loaded bundle
301
- */
302
- async importFromFile(filePath) {
303
- const fs = await import('fs/promises');
304
- const content = await fs.readFile(filePath, 'utf-8');
305
- const bundle = JSON.parse(content);
306
- console.log(`Bundle loaded from ${filePath}: ${bundle.recordCount} records`);
307
- return bundle;
308
- }
309
-
310
- /**
311
- * Close all backend connections
312
- */
313
- close() {
314
- if (this.sourceBackend) {
315
- this.sourceBackend.close();
316
- }
317
- if (this.targetBackend) {
318
- this.targetBackend.close();
319
- }
320
- }
321
- }
322
-
323
- /**
324
- * Quick migration function for common use cases
325
- * @param {Object} sourceConfig - Source backend config with 'type' field
326
- * @param {Object} targetConfig - Target backend config with 'type' field
327
- * @param {string} [pathPrefix] - Optional path filter
328
- * @param {Object} [options] - Migration options
329
- * @returns {Promise<Object>} Migration results
330
- */
331
- export async function quickMigrate(sourceConfig, targetConfig, pathPrefix = '', options = {}) {
332
- const tool = new MigrationTool();
333
-
334
- try {
335
- await tool.setSource(sourceConfig.type, sourceConfig);
336
- await tool.setTarget(targetConfig.type, targetConfig);
337
-
338
- const results = await tool.migrate(pathPrefix, options);
339
-
340
- if (!options.skipValidation) {
341
- const validation = await tool.validate(pathPrefix);
342
- results.validation = validation;
343
- }
344
-
345
- return results;
346
- } finally {
347
- tool.close();
348
- }
349
- }
350
-
351
- export default MigrationTool;
@@ -1,161 +0,0 @@
1
- /**
2
- * @fileoverview Unified Storage Adapter.
3
- *
4
- * Routes storage operations to the correct backend (Nostr or GunDB).
5
- * Provides a consistent API for reading, writing, updating, and deleting
6
- * data across different storage backends.
7
- *
8
- * @module storage/unified-storage
9
- */
10
-
11
- import * as nostrWrapper from './nostr-wrapper.js';
12
- import * as gunWrapper from './gun-wrapper.js';
13
-
14
- /**
15
- * Build path from components
16
- * @param {string} appName - Application namespace
17
- * @param {string} holonId - Holon identifier
18
- * @param {string} lensName - Lens name
19
- * @param {string} [key] - Optional data key
20
- * @returns {string} Constructed path
21
- */
22
- export function buildPath(appName, holonId, lensName, key = null) {
23
- // Both backends use the same path format
24
- return nostrWrapper.buildPath(appName, holonId, lensName, key);
25
- }
26
-
27
- /**
28
- * Write data to storage
29
- * @param {Object} client - Client instance (nostr client or gun-compatible client)
30
- * @param {string} path - Storage path
31
- * @param {Object} data - Data to write
32
- * @param {Object} [options={}] - Write options
33
- * @returns {Promise<boolean>} Success indicator
34
- */
35
- export async function write(client, path, data, options = {}) {
36
- // Check if this is a GunDB client with backend methods (preferred - has write cache)
37
- if (client.write && client.gun) {
38
- return client.write(path, data, options);
39
- }
40
- // Fallback to direct gunWrapper (no write cache)
41
- if (client.gun) {
42
- return gunWrapper.write(client.gun, path, data, options);
43
- }
44
- // Default to Nostr
45
- return nostrWrapper.write(client, path, data, options);
46
- }
47
-
48
- /**
49
- * Read data from storage
50
- * @param {Object} client - Client instance
51
- * @param {string} path - Storage path
52
- * @param {Object} [options] - Read options
53
- * @returns {Promise<Object|null>} Data or null
54
- */
55
- export async function read(client, path, options = {}) {
56
- // Check if this is a GunDB client with backend methods (preferred - has write cache)
57
- if (client.read && client.gun) {
58
- return client.read(path, options);
59
- }
60
- // Fallback to direct gunWrapper
61
- if (client.gun) {
62
- return gunWrapper.read(client.gun, path);
63
- }
64
- return nostrWrapper.read(client, path, options);
65
- }
66
-
67
- /**
68
- * Read all data under a path prefix
69
- * @param {Object} client - Client instance
70
- * @param {string} path - Path prefix
71
- * @param {Object} [options] - Query options
72
- * @returns {Promise<Object[]>} Array of data objects
73
- */
74
- export async function readAll(client, path, options = {}) {
75
- // Check if this is a GunDB client with backend methods (preferred - has write cache)
76
- if (client.readAll && client.gun) {
77
- return client.readAll(path, options);
78
- }
79
- // Fallback to direct gunWrapper
80
- if (client.gun) {
81
- return gunWrapper.readAll(client.gun, path);
82
- }
83
- return nostrWrapper.readAll(client, path, options);
84
- }
85
-
86
- /**
87
- * Update data (merge fields)
88
- * @param {Object} client - Client instance
89
- * @param {string} path - Storage path
90
- * @param {Object} updates - Fields to update
91
- * @returns {Promise<boolean>} Success indicator
92
- */
93
- export async function update(client, path, updates) {
94
- // Check if this is a GunDB client with backend methods (preferred - has write cache)
95
- if (client.update && client.gun) {
96
- return client.update(path, updates);
97
- }
98
- // Fallback to direct gunWrapper
99
- if (client.gun) {
100
- return gunWrapper.update(client.gun, path, updates);
101
- }
102
- return nostrWrapper.update(client, path, updates);
103
- }
104
-
105
- /**
106
- * Delete data at path
107
- * @param {Object} client - Client instance
108
- * @param {string} path - Storage path
109
- * @param {Object} [options] - Delete options
110
- * @param {string} [options.signingKey] - Private key for signing tombstones (hex format)
111
- * @param {string} [options.authorPubkey] - Public key of the data author
112
- * @returns {Promise<boolean>} Success indicator
113
- */
114
- export async function deleteData(client, path, options = {}) {
115
- // Check if this is a GunDB client with backend methods (preferred - has write cache)
116
- if (client.delete && client.gun) {
117
- return client.delete(path);
118
- }
119
- // Fallback to direct gunWrapper
120
- if (client.gun) {
121
- return gunWrapper.deleteData(client.gun, path);
122
- }
123
- return nostrWrapper.deleteData(client, path, options);
124
- }
125
-
126
- /**
127
- * Delete all data under path prefix
128
- * @param {Object} client - Client instance
129
- * @param {string} path - Path prefix
130
- * @param {Object} [options] - Delete options
131
- * @param {string} [options.signingKey] - Private key for signing tombstones (hex format)
132
- * @param {string} [options.authorPubkey] - Public key of the data author
133
- * @returns {Promise<Object>} Deletion results
134
- */
135
- export async function deleteAll(client, path, options = {}) {
136
- // Fallback to direct gunWrapper (deleteAll not typically in client interface)
137
- if (client.gun) {
138
- return gunWrapper.deleteAll(client.gun, path);
139
- }
140
- return nostrWrapper.deleteAll(client, path, options);
141
- }
142
-
143
- /**
144
- * Subscribe to data changes
145
- * @param {Object} client - Client instance
146
- * @param {string} path - Path or path prefix
147
- * @param {Function} callback - Called on changes
148
- * @param {Object} [options] - Subscription options
149
- * @returns {Object} Subscription with unsubscribe method
150
- */
151
- export function subscribe(client, path, callback, options = {}) {
152
- // Check if this is a GunDB client with backend methods
153
- if (client.subscribe && client.gun) {
154
- return client.subscribe(path, callback, options);
155
- }
156
- // Fallback to direct gunWrapper
157
- if (client.gun) {
158
- return gunWrapper.subscribe(client.gun, path, callback, options);
159
- }
160
- return nostrWrapper.subscribe(client, path, callback, options);
161
- }