holosphere 1.1.20 → 2.0.0-alpha1

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 (147) hide show
  1. package/.env.example +36 -0
  2. package/.eslintrc.json +16 -0
  3. package/.prettierrc.json +7 -0
  4. package/LICENSE +162 -38
  5. package/README.md +483 -367
  6. package/bin/holosphere-activitypub.js +158 -0
  7. package/cleanup-test-data.js +204 -0
  8. package/examples/demo.html +1333 -0
  9. package/examples/example-bot.js +197 -0
  10. package/package.json +47 -87
  11. package/scripts/check-bundle-size.js +54 -0
  12. package/scripts/check-quest-ids.js +77 -0
  13. package/scripts/import-holons.js +578 -0
  14. package/scripts/publish-to-relay.js +101 -0
  15. package/scripts/read-example.js +186 -0
  16. package/scripts/relay-diagnostic.js +59 -0
  17. package/scripts/relay-example.js +179 -0
  18. package/scripts/resync-to-relay.js +245 -0
  19. package/scripts/revert-import.js +196 -0
  20. package/scripts/test-hybrid-mode.js +108 -0
  21. package/scripts/test-local-storage.js +63 -0
  22. package/scripts/test-nostr-direct.js +55 -0
  23. package/scripts/test-read-data.js +45 -0
  24. package/scripts/test-write-read.js +63 -0
  25. package/scripts/verify-import.js +95 -0
  26. package/scripts/verify-relay-data.js +139 -0
  27. package/src/ai/aggregation.js +319 -0
  28. package/src/ai/breakdown.js +511 -0
  29. package/src/ai/classifier.js +217 -0
  30. package/src/ai/council.js +228 -0
  31. package/src/ai/embeddings.js +279 -0
  32. package/src/ai/federation-ai.js +324 -0
  33. package/src/ai/h3-ai.js +955 -0
  34. package/src/ai/index.js +112 -0
  35. package/src/ai/json-ops.js +225 -0
  36. package/src/ai/llm-service.js +205 -0
  37. package/src/ai/nl-query.js +223 -0
  38. package/src/ai/relationships.js +353 -0
  39. package/src/ai/schema-extractor.js +218 -0
  40. package/src/ai/spatial.js +293 -0
  41. package/src/ai/tts.js +194 -0
  42. package/src/content/social-protocols.js +168 -0
  43. package/src/core/holosphere.js +273 -0
  44. package/src/crypto/secp256k1.js +259 -0
  45. package/src/federation/discovery.js +334 -0
  46. package/src/federation/hologram.js +1042 -0
  47. package/src/federation/registry.js +386 -0
  48. package/src/hierarchical/upcast.js +110 -0
  49. package/src/index.js +2669 -0
  50. package/src/schema/validator.js +91 -0
  51. package/src/spatial/h3-operations.js +110 -0
  52. package/src/storage/backend-factory.js +125 -0
  53. package/src/storage/backend-interface.js +142 -0
  54. package/src/storage/backends/activitypub/server.js +653 -0
  55. package/src/storage/backends/activitypub-backend.js +272 -0
  56. package/src/storage/backends/gundb-backend.js +233 -0
  57. package/src/storage/backends/nostr-backend.js +136 -0
  58. package/src/storage/filesystem-storage-browser.js +41 -0
  59. package/src/storage/filesystem-storage.js +138 -0
  60. package/src/storage/global-tables.js +81 -0
  61. package/src/storage/gun-async.js +281 -0
  62. package/src/storage/gun-wrapper.js +221 -0
  63. package/src/storage/indexeddb-storage.js +122 -0
  64. package/src/storage/key-storage-simple.js +76 -0
  65. package/src/storage/key-storage.js +136 -0
  66. package/src/storage/memory-storage.js +59 -0
  67. package/src/storage/migration.js +338 -0
  68. package/src/storage/nostr-async.js +811 -0
  69. package/src/storage/nostr-client.js +939 -0
  70. package/src/storage/nostr-wrapper.js +211 -0
  71. package/src/storage/outbox-queue.js +208 -0
  72. package/src/storage/persistent-storage.js +109 -0
  73. package/src/storage/sync-service.js +164 -0
  74. package/src/subscriptions/manager.js +142 -0
  75. package/test-ai-real-api.js +202 -0
  76. package/tests/unit/ai/aggregation.test.js +295 -0
  77. package/tests/unit/ai/breakdown.test.js +446 -0
  78. package/tests/unit/ai/classifier.test.js +294 -0
  79. package/tests/unit/ai/council.test.js +262 -0
  80. package/tests/unit/ai/embeddings.test.js +384 -0
  81. package/tests/unit/ai/federation-ai.test.js +344 -0
  82. package/tests/unit/ai/h3-ai.test.js +458 -0
  83. package/tests/unit/ai/index.test.js +304 -0
  84. package/tests/unit/ai/json-ops.test.js +307 -0
  85. package/tests/unit/ai/llm-service.test.js +390 -0
  86. package/tests/unit/ai/nl-query.test.js +383 -0
  87. package/tests/unit/ai/relationships.test.js +311 -0
  88. package/tests/unit/ai/schema-extractor.test.js +384 -0
  89. package/tests/unit/ai/spatial.test.js +279 -0
  90. package/tests/unit/ai/tts.test.js +279 -0
  91. package/tests/unit/content.test.js +332 -0
  92. package/tests/unit/contract/core.test.js +88 -0
  93. package/tests/unit/contract/crypto.test.js +198 -0
  94. package/tests/unit/contract/data.test.js +223 -0
  95. package/tests/unit/contract/federation.test.js +181 -0
  96. package/tests/unit/contract/hierarchical.test.js +113 -0
  97. package/tests/unit/contract/schema.test.js +114 -0
  98. package/tests/unit/contract/social.test.js +217 -0
  99. package/tests/unit/contract/spatial.test.js +110 -0
  100. package/tests/unit/contract/subscriptions.test.js +128 -0
  101. package/tests/unit/contract/utils.test.js +159 -0
  102. package/tests/unit/core.test.js +152 -0
  103. package/tests/unit/crypto.test.js +328 -0
  104. package/tests/unit/federation.test.js +234 -0
  105. package/tests/unit/gun-async.test.js +252 -0
  106. package/tests/unit/hierarchical.test.js +399 -0
  107. package/tests/unit/integration/scenario-01-geographic-storage.test.js +74 -0
  108. package/tests/unit/integration/scenario-02-federation.test.js +76 -0
  109. package/tests/unit/integration/scenario-03-subscriptions.test.js +102 -0
  110. package/tests/unit/integration/scenario-04-validation.test.js +129 -0
  111. package/tests/unit/integration/scenario-05-hierarchy.test.js +125 -0
  112. package/tests/unit/integration/scenario-06-social.test.js +135 -0
  113. package/tests/unit/integration/scenario-07-persistence.test.js +130 -0
  114. package/tests/unit/integration/scenario-08-authorization.test.js +161 -0
  115. package/tests/unit/integration/scenario-09-cross-dimensional.test.js +139 -0
  116. package/tests/unit/integration/scenario-10-cross-holosphere-capabilities.test.js +357 -0
  117. package/tests/unit/integration/scenario-11-cross-holosphere-federation.test.js +410 -0
  118. package/tests/unit/integration/scenario-12-capability-federated-read.test.js +719 -0
  119. package/tests/unit/performance/benchmark.test.js +85 -0
  120. package/tests/unit/schema.test.js +213 -0
  121. package/tests/unit/spatial.test.js +158 -0
  122. package/tests/unit/storage.test.js +195 -0
  123. package/tests/unit/subscriptions.test.js +328 -0
  124. package/tests/unit/test-data-permanence-debug.js +197 -0
  125. package/tests/unit/test-data-permanence.js +340 -0
  126. package/tests/unit/test-key-persistence-fixed.js +148 -0
  127. package/tests/unit/test-key-persistence.js +172 -0
  128. package/tests/unit/test-relay-permanence.js +376 -0
  129. package/tests/unit/test-second-node.js +95 -0
  130. package/tests/unit/test-simple-write.js +89 -0
  131. package/vite.config.js +49 -0
  132. package/vitest.config.js +20 -0
  133. package/FEDERATION.md +0 -213
  134. package/compute.js +0 -298
  135. package/content.js +0 -980
  136. package/federation.js +0 -1234
  137. package/global.js +0 -736
  138. package/hexlib.js +0 -335
  139. package/hologram.js +0 -183
  140. package/holosphere-bundle.esm.js +0 -33256
  141. package/holosphere-bundle.js +0 -33287
  142. package/holosphere-bundle.min.js +0 -39
  143. package/holosphere.d.ts +0 -601
  144. package/holosphere.js +0 -719
  145. package/node.js +0 -246
  146. package/schema.js +0 -139
  147. package/utils.js +0 -302
@@ -0,0 +1,338 @@
1
+ /**
2
+ * Migration Tool for HoloSphere Storage Backends
3
+ *
4
+ * Enables data migration between different storage backends:
5
+ * - Export data from any backend to a portable format
6
+ * - Import data to any backend from the portable format
7
+ * - Direct migration between backends
8
+ * - Validation of migrated data
9
+ */
10
+
11
+ import { BackendFactory } from './backend-factory.js';
12
+
13
+ /**
14
+ * Portable data bundle format
15
+ * @typedef {Object} DataBundle
16
+ * @property {string} version - Bundle format version
17
+ * @property {string} exportedAt - ISO timestamp
18
+ * @property {string} sourceType - Source backend type
19
+ * @property {string} sourceKey - Source public key
20
+ * @property {number} recordCount - Number of records
21
+ * @property {Object[]} records - Array of data records
22
+ */
23
+
24
+ /**
25
+ * Migration record format
26
+ * @typedef {Object} MigrationRecord
27
+ * @property {string} path - Storage path
28
+ * @property {Object} data - Record data
29
+ * @property {number} timestamp - Creation timestamp
30
+ * @property {string} [author] - Author public key
31
+ */
32
+
33
+ /**
34
+ * Migration results
35
+ * @typedef {Object} MigrationResults
36
+ * @property {number} success - Successfully migrated records
37
+ * @property {number} failed - Failed records
38
+ * @property {Object[]} errors - Error details
39
+ */
40
+
41
+ export class MigrationTool {
42
+ constructor() {
43
+ this.sourceBackend = null;
44
+ this.targetBackend = null;
45
+ }
46
+
47
+ /**
48
+ * Configure source backend
49
+ * @param {string} type - Backend type: 'nostr' | 'gundb' | 'activitypub'
50
+ * @param {Object} config - Backend configuration
51
+ * @returns {Promise<void>}
52
+ */
53
+ async setSource(type, config) {
54
+ this.sourceBackend = await BackendFactory.create(type, config);
55
+ }
56
+
57
+ /**
58
+ * Configure target backend
59
+ * @param {string} type - Backend type: 'nostr' | 'gundb' | 'activitypub'
60
+ * @param {Object} config - Backend configuration
61
+ * @returns {Promise<void>}
62
+ */
63
+ async setTarget(type, config) {
64
+ this.targetBackend = await BackendFactory.create(type, config);
65
+ }
66
+
67
+ /**
68
+ * Use an existing backend instance as source
69
+ * @param {StorageBackend} backend - Backend instance
70
+ */
71
+ useSourceBackend(backend) {
72
+ this.sourceBackend = backend;
73
+ }
74
+
75
+ /**
76
+ * Use an existing backend instance as target
77
+ * @param {StorageBackend} backend - Backend instance
78
+ */
79
+ useTargetBackend(backend) {
80
+ this.targetBackend = backend;
81
+ }
82
+
83
+ /**
84
+ * Export data from source to portable format
85
+ * @param {string} [pathPrefix] - Optional path prefix filter
86
+ * @returns {Promise<DataBundle>} Exportable data bundle
87
+ */
88
+ async export(pathPrefix = '') {
89
+ if (!this.sourceBackend) {
90
+ throw new Error('Source backend not configured. Call setSource() first.');
91
+ }
92
+
93
+ console.log(`Exporting data from ${this.sourceBackend.getStatus().type}...`);
94
+
95
+ const records = await this.sourceBackend.exportData(pathPrefix);
96
+ const status = this.sourceBackend.getStatus();
97
+
98
+ const bundle = {
99
+ version: '1.0',
100
+ exportedAt: new Date().toISOString(),
101
+ sourceType: status.type,
102
+ sourceKey: status.publicKey || 'unknown',
103
+ pathPrefix: pathPrefix || '',
104
+ recordCount: records.length,
105
+ records,
106
+ };
107
+
108
+ console.log(`Exported ${records.length} records.`);
109
+ return bundle;
110
+ }
111
+
112
+ /**
113
+ * Import data to target backend
114
+ * @param {DataBundle} bundle - Data bundle from export()
115
+ * @param {Object} [options] - Import options
116
+ * @param {boolean} [options.overwrite] - Overwrite existing data
117
+ * @param {boolean} [options.dryRun] - Simulate without writing
118
+ * @param {Function} [options.onProgress] - Progress callback (current, total)
119
+ * @returns {Promise<MigrationResults>} Import results
120
+ */
121
+ async import(bundle, options = {}) {
122
+ if (!this.targetBackend) {
123
+ throw new Error('Target backend not configured. Call setTarget() first.');
124
+ }
125
+
126
+ if (!bundle || !bundle.records) {
127
+ throw new Error('Invalid bundle format. Expected { version, records }');
128
+ }
129
+
130
+ console.log(`Importing ${bundle.recordCount} records to ${this.targetBackend.getStatus().type}...`);
131
+
132
+ if (options.dryRun) {
133
+ console.log('Dry run mode - no data will be written.');
134
+ return {
135
+ dryRun: true,
136
+ wouldImport: bundle.recordCount,
137
+ records: bundle.records.map(r => r.path),
138
+ };
139
+ }
140
+
141
+ const results = await this.targetBackend.importData(bundle.records, options);
142
+
143
+ if (options.onProgress) {
144
+ options.onProgress(results.success + results.failed, bundle.recordCount);
145
+ }
146
+
147
+ console.log(`Import complete: ${results.success} succeeded, ${results.failed} failed.`);
148
+ return results;
149
+ }
150
+
151
+ /**
152
+ * Migrate data directly from source to target
153
+ * @param {string} [pathPrefix] - Optional path prefix filter
154
+ * @param {Object} [options] - Migration options
155
+ * @param {boolean} [options.dryRun] - Simulate without writing
156
+ * @param {Function} [options.onProgress] - Progress callback
157
+ * @returns {Promise<Object>} Migration results
158
+ */
159
+ async migrate(pathPrefix = '', options = {}) {
160
+ if (!this.sourceBackend || !this.targetBackend) {
161
+ throw new Error('Both source and target backends must be configured.');
162
+ }
163
+
164
+ const sourceStatus = this.sourceBackend.getStatus();
165
+ const targetStatus = this.targetBackend.getStatus();
166
+
167
+ console.log(`\nMigrating data:`);
168
+ console.log(` From: ${sourceStatus.type} (${sourceStatus.publicKey || 'unknown'})`);
169
+ console.log(` To: ${targetStatus.type}`);
170
+ console.log(` Filter: ${pathPrefix || '(all data)'}\n`);
171
+
172
+ // Export from source
173
+ const bundle = await this.export(pathPrefix);
174
+
175
+ // Import to target
176
+ const importResults = await this.import(bundle, options);
177
+
178
+ return {
179
+ sourceType: sourceStatus.type,
180
+ targetType: targetStatus.type,
181
+ pathPrefix,
182
+ exportedCount: bundle.recordCount,
183
+ ...importResults,
184
+ };
185
+ }
186
+
187
+ /**
188
+ * Validate data integrity after migration
189
+ * @param {string} [pathPrefix] - Optional path prefix filter
190
+ * @returns {Promise<Object>} Validation results
191
+ */
192
+ async validate(pathPrefix = '') {
193
+ if (!this.sourceBackend || !this.targetBackend) {
194
+ throw new Error('Both source and target backends must be configured.');
195
+ }
196
+
197
+ console.log('Validating migration...');
198
+
199
+ const sourceData = await this.sourceBackend.exportData(pathPrefix);
200
+ const targetData = await this.targetBackend.exportData(pathPrefix);
201
+
202
+ const sourceMap = new Map(sourceData.map(r => [r.path, r]));
203
+ const targetMap = new Map(targetData.map(r => [r.path, r]));
204
+
205
+ const missing = [];
206
+ const different = [];
207
+ const extra = [];
208
+
209
+ // Check for missing or different records
210
+ for (const [path, sourceRecord] of sourceMap) {
211
+ const targetRecord = targetMap.get(path);
212
+
213
+ if (!targetRecord) {
214
+ missing.push(path);
215
+ } else {
216
+ // Compare data (ignoring metadata that may differ)
217
+ const sourceDataStr = JSON.stringify(this._normalizeForComparison(sourceRecord.data));
218
+ const targetDataStr = JSON.stringify(this._normalizeForComparison(targetRecord.data));
219
+
220
+ if (sourceDataStr !== targetDataStr) {
221
+ different.push({
222
+ path,
223
+ source: sourceRecord.data,
224
+ target: targetRecord.data,
225
+ });
226
+ }
227
+ }
228
+ }
229
+
230
+ // Check for extra records in target
231
+ for (const path of targetMap.keys()) {
232
+ if (!sourceMap.has(path)) {
233
+ extra.push(path);
234
+ }
235
+ }
236
+
237
+ const valid = missing.length === 0 && different.length === 0;
238
+
239
+ console.log(`Validation ${valid ? 'PASSED' : 'FAILED'}:`);
240
+ console.log(` Source records: ${sourceData.length}`);
241
+ console.log(` Target records: ${targetData.length}`);
242
+ console.log(` Missing: ${missing.length}`);
243
+ console.log(` Different: ${different.length}`);
244
+ console.log(` Extra: ${extra.length}`);
245
+
246
+ return {
247
+ valid,
248
+ sourceCount: sourceData.length,
249
+ targetCount: targetData.length,
250
+ missing,
251
+ different,
252
+ extra,
253
+ };
254
+ }
255
+
256
+ /**
257
+ * Normalize data for comparison (remove volatile metadata)
258
+ * @private
259
+ */
260
+ _normalizeForComparison(data) {
261
+ if (!data || typeof data !== 'object') return data;
262
+
263
+ const normalized = { ...data };
264
+
265
+ // Remove metadata that may legitimately differ
266
+ delete normalized._meta;
267
+ delete normalized._author;
268
+ delete normalized._timestamp;
269
+
270
+ return normalized;
271
+ }
272
+
273
+ /**
274
+ * Export bundle to JSON file (for manual transfer)
275
+ * @param {DataBundle} bundle - Data bundle
276
+ * @param {string} filePath - Output file path
277
+ */
278
+ async exportToFile(bundle, filePath) {
279
+ const fs = await import('fs/promises');
280
+ await fs.writeFile(filePath, JSON.stringify(bundle, null, 2), 'utf-8');
281
+ console.log(`Bundle exported to ${filePath}`);
282
+ }
283
+
284
+ /**
285
+ * Import bundle from JSON file
286
+ * @param {string} filePath - Input file path
287
+ * @returns {Promise<DataBundle>} Loaded bundle
288
+ */
289
+ async importFromFile(filePath) {
290
+ const fs = await import('fs/promises');
291
+ const content = await fs.readFile(filePath, 'utf-8');
292
+ const bundle = JSON.parse(content);
293
+ console.log(`Bundle loaded from ${filePath}: ${bundle.recordCount} records`);
294
+ return bundle;
295
+ }
296
+
297
+ /**
298
+ * Close all backend connections
299
+ */
300
+ close() {
301
+ if (this.sourceBackend) {
302
+ this.sourceBackend.close();
303
+ }
304
+ if (this.targetBackend) {
305
+ this.targetBackend.close();
306
+ }
307
+ }
308
+ }
309
+
310
+ /**
311
+ * Quick migration function for common use cases
312
+ * @param {Object} sourceConfig - Source backend config with 'type' field
313
+ * @param {Object} targetConfig - Target backend config with 'type' field
314
+ * @param {string} [pathPrefix] - Optional path filter
315
+ * @param {Object} [options] - Migration options
316
+ * @returns {Promise<Object>} Migration results
317
+ */
318
+ export async function quickMigrate(sourceConfig, targetConfig, pathPrefix = '', options = {}) {
319
+ const tool = new MigrationTool();
320
+
321
+ try {
322
+ await tool.setSource(sourceConfig.type, sourceConfig);
323
+ await tool.setTarget(targetConfig.type, targetConfig);
324
+
325
+ const results = await tool.migrate(pathPrefix, options);
326
+
327
+ if (!options.skipValidation) {
328
+ const validation = await tool.validate(pathPrefix);
329
+ results.validation = validation;
330
+ }
331
+
332
+ return results;
333
+ } finally {
334
+ tool.close();
335
+ }
336
+ }
337
+
338
+ export default MigrationTool;