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.
- package/README.md +1 -2
- package/dist/cjs/holosphere.cjs +1 -1
- package/dist/esm/holosphere.js +61 -58
- package/dist/{index-B6-8KAQm.js → index-BEkCLOwI.js} +2 -2
- package/dist/{index-B6-8KAQm.js.map → index-BEkCLOwI.js.map} +1 -1
- package/dist/{index-D2WstuZJ.js → index-BEvX6DxG.js} +2 -2
- package/dist/{index-D2WstuZJ.js.map → index-BEvX6DxG.js.map} +1 -1
- package/dist/{index--QsHG_gD.cjs → index-BGTOiJ2Y.cjs} +2 -2
- package/dist/{index--QsHG_gD.cjs.map → index-BGTOiJ2Y.cjs.map} +1 -1
- package/dist/{index-COpLk9gL.cjs → index-BH1woZXL.cjs} +2 -2
- package/dist/{index-COpLk9gL.cjs.map → index-BH1woZXL.cjs.map} +1 -1
- package/dist/{index-BHptWysv.js → index-Cvxov2jv.js} +2970 -7753
- package/dist/index-Cvxov2jv.js.map +1 -0
- package/dist/index-vTKI_BAX.cjs +29 -0
- package/dist/index-vTKI_BAX.cjs.map +1 -0
- package/dist/{indexeddb-storage-wKG4mICM.cjs → indexeddb-storage-BmnCNnSg.cjs} +2 -2
- package/dist/{indexeddb-storage-wKG4mICM.cjs.map → indexeddb-storage-BmnCNnSg.cjs.map} +1 -1
- package/dist/{indexeddb-storage-kQ53UHEE.js → indexeddb-storage-MIFisaPy.js} +2 -2
- package/dist/{indexeddb-storage-kQ53UHEE.js.map → indexeddb-storage-MIFisaPy.js.map} +1 -1
- package/dist/{memory-storage-CGC8xM2G.cjs → memory-storage-BJjK3F4r.cjs} +2 -2
- package/dist/{memory-storage-CGC8xM2G.cjs.map → memory-storage-BJjK3F4r.cjs.map} +1 -1
- package/dist/{memory-storage-DnXCSbBl.js → memory-storage-DhHXdKQ-.js} +2 -2
- package/dist/{memory-storage-DnXCSbBl.js.map → memory-storage-DhHXdKQ-.js.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 +145 -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,295 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview ActivityPub storage backend client adapter.
|
|
3
|
-
* Provides HTTP-based connectivity to an ActivityPub server for federated data storage
|
|
4
|
-
* and real-time subscriptions via Server-Sent Events.
|
|
5
|
-
* @module storage/backends/activitypub-backend
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { StorageBackend } from '../backend-interface.js';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* ActivityPub storage backend implementation.
|
|
12
|
-
* Client adapter for connecting to an ActivityPub server via HTTP API
|
|
13
|
-
* with SSE-based real-time subscriptions.
|
|
14
|
-
*
|
|
15
|
-
* @class ActivityPubBackend
|
|
16
|
-
* @extends StorageBackend
|
|
17
|
-
* @example
|
|
18
|
-
* const backend = await BackendFactory.create('activitypub', {
|
|
19
|
-
* serverUrl: 'https://ap.example.com',
|
|
20
|
-
* appName: 'myapp',
|
|
21
|
-
* apiKey: 'secret-key'
|
|
22
|
-
* });
|
|
23
|
-
*/
|
|
24
|
-
export class ActivityPubBackend extends StorageBackend {
|
|
25
|
-
/**
|
|
26
|
-
* Create a new ActivityPub backend instance.
|
|
27
|
-
* @param {Object} config - Backend configuration
|
|
28
|
-
* @param {string} config.serverUrl - ActivityPub server URL
|
|
29
|
-
* @param {string} [config.appName='holosphere'] - Application/actor name
|
|
30
|
-
* @param {string} [config.apiKey] - Optional API key for authentication
|
|
31
|
-
*/
|
|
32
|
-
constructor(config) {
|
|
33
|
-
super(config);
|
|
34
|
-
this.serverUrl = config.serverUrl;
|
|
35
|
-
this.actorName = config.appName || 'holosphere';
|
|
36
|
-
this.apiKey = config.apiKey;
|
|
37
|
-
this.actorId = null;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
async init() {
|
|
41
|
-
if (!this.serverUrl) {
|
|
42
|
-
throw new Error('ActivityPub backend requires serverUrl in config');
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Ensure server URL doesn't have trailing slash
|
|
46
|
-
this.serverUrl = this.serverUrl.replace(/\/$/, '');
|
|
47
|
-
|
|
48
|
-
// Try to fetch or create actor
|
|
49
|
-
try {
|
|
50
|
-
const response = await fetch(`${this.serverUrl}/actor/${this.actorName}`, {
|
|
51
|
-
headers: { 'Accept': 'application/activity+json' },
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
if (response.ok) {
|
|
55
|
-
const actor = await response.json();
|
|
56
|
-
this.actorId = actor.id;
|
|
57
|
-
this.publicKey = actor.publicKey?.id || actor.id;
|
|
58
|
-
} else {
|
|
59
|
-
// Try to create actor
|
|
60
|
-
await this._createActor();
|
|
61
|
-
}
|
|
62
|
-
} catch (error) {
|
|
63
|
-
// Server might not be running yet, try to create actor
|
|
64
|
-
await this._createActor();
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
async _createActor() {
|
|
69
|
-
try {
|
|
70
|
-
const response = await this._fetch(`${this.serverUrl}/api/actors`, {
|
|
71
|
-
method: 'POST',
|
|
72
|
-
headers: { 'Content-Type': 'application/json' },
|
|
73
|
-
body: JSON.stringify({
|
|
74
|
-
name: this.actorName,
|
|
75
|
-
apiKey: this.apiKey,
|
|
76
|
-
}),
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
if (response.ok) {
|
|
80
|
-
const result = await response.json();
|
|
81
|
-
this.actorId = result.id;
|
|
82
|
-
this.publicKey = result.publicKey || result.id;
|
|
83
|
-
} else {
|
|
84
|
-
throw new Error(`Failed to create actor: ${response.status}`);
|
|
85
|
-
}
|
|
86
|
-
} catch (error) {
|
|
87
|
-
// If server is not available, set placeholder values
|
|
88
|
-
this.actorId = `${this.serverUrl}/actor/${this.actorName}`;
|
|
89
|
-
this.publicKey = this.actorId;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
buildPath(appName, holonId, lensName, key = null) {
|
|
94
|
-
// Use same path format as other backends
|
|
95
|
-
const encodedHolon = encodeURIComponent(holonId);
|
|
96
|
-
const encodedLens = encodeURIComponent(lensName);
|
|
97
|
-
|
|
98
|
-
if (key) {
|
|
99
|
-
const encodedKey = encodeURIComponent(key);
|
|
100
|
-
return `${appName}/${encodedHolon}/${encodedLens}/${encodedKey}`;
|
|
101
|
-
}
|
|
102
|
-
return `${appName}/${encodedHolon}/${encodedLens}`;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
async write(path, data, options = {}) {
|
|
106
|
-
const response = await this._fetch(`${this.serverUrl}/api/data`, {
|
|
107
|
-
method: 'POST',
|
|
108
|
-
headers: { 'Content-Type': 'application/json' },
|
|
109
|
-
body: JSON.stringify({
|
|
110
|
-
path,
|
|
111
|
-
data,
|
|
112
|
-
actorName: this.actorName,
|
|
113
|
-
}),
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
return response.ok;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
async read(path, options = {}) {
|
|
120
|
-
const response = await this._fetch(`${this.serverUrl}/api/data/${path}`);
|
|
121
|
-
|
|
122
|
-
if (!response.ok) {
|
|
123
|
-
if (response.status === 404) return null;
|
|
124
|
-
throw new Error(`Read failed: ${response.status}`);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const data = await response.json();
|
|
128
|
-
return data._deleted ? null : data;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
async readAll(path, options = {}) {
|
|
132
|
-
const response = await this._fetch(`${this.serverUrl}/api/data/${path}`);
|
|
133
|
-
|
|
134
|
-
if (!response.ok) {
|
|
135
|
-
if (response.status === 404) return [];
|
|
136
|
-
throw new Error(`ReadAll failed: ${response.status}`);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const data = await response.json();
|
|
140
|
-
return Array.isArray(data) ? data.filter(item => !item._deleted) : [data];
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
async update(path, updates) {
|
|
144
|
-
// Read existing, merge, write back
|
|
145
|
-
const existing = await this.read(path);
|
|
146
|
-
if (!existing) return false;
|
|
147
|
-
|
|
148
|
-
const merged = { ...existing, ...updates };
|
|
149
|
-
return this.write(path, merged);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
async delete(path) {
|
|
153
|
-
const response = await this._fetch(
|
|
154
|
-
`${this.serverUrl}/api/data/${path}?actor=${this.actorName}`,
|
|
155
|
-
{ method: 'DELETE' }
|
|
156
|
-
);
|
|
157
|
-
|
|
158
|
-
return response.ok;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
async deleteAll(path) {
|
|
162
|
-
const items = await this.readAll(path);
|
|
163
|
-
let count = 0;
|
|
164
|
-
|
|
165
|
-
for (const item of items) {
|
|
166
|
-
if (item && item.id) {
|
|
167
|
-
await this.delete(`${path}/${item.id}`);
|
|
168
|
-
count++;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
return { success: true, count };
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
async subscribe(path, callback, options = {}) {
|
|
176
|
-
// Use Server-Sent Events for real-time updates
|
|
177
|
-
const url = `${this.serverUrl}/subscribe?path=${encodeURIComponent(path)}`;
|
|
178
|
-
|
|
179
|
-
// Use EventSource if available (browser) or polyfill
|
|
180
|
-
let eventSource;
|
|
181
|
-
|
|
182
|
-
if (typeof EventSource !== 'undefined') {
|
|
183
|
-
eventSource = new EventSource(url);
|
|
184
|
-
} else {
|
|
185
|
-
// In Node.js, we need to use a different approach
|
|
186
|
-
// For now, return a polling-based subscription
|
|
187
|
-
return this._pollSubscribe(path, callback, options);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
eventSource.addEventListener('update', (event) => {
|
|
191
|
-
try {
|
|
192
|
-
const { path: eventPath, data } = JSON.parse(event.data);
|
|
193
|
-
const key = eventPath.split('/').pop();
|
|
194
|
-
callback(data, key);
|
|
195
|
-
} catch (error) {
|
|
196
|
-
console.error('ActivityPub subscription error:', error);
|
|
197
|
-
}
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
eventSource.onerror = (error) => {
|
|
201
|
-
console.error('ActivityPub SSE error:', error);
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
return {
|
|
205
|
-
unsubscribe: () => eventSource.close(),
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
async _pollSubscribe(path, callback, options = {}) {
|
|
210
|
-
// Fallback polling for Node.js environments
|
|
211
|
-
const interval = options.pollInterval || 5000;
|
|
212
|
-
let lastTimestamp = Date.now();
|
|
213
|
-
let running = true;
|
|
214
|
-
|
|
215
|
-
const poll = async () => {
|
|
216
|
-
while (running) {
|
|
217
|
-
try {
|
|
218
|
-
const items = await this.readAll(path);
|
|
219
|
-
for (const item of items) {
|
|
220
|
-
if (item._meta?.timestamp > lastTimestamp) {
|
|
221
|
-
const key = item.id || item._meta?.path?.split('/').pop();
|
|
222
|
-
callback(item, key);
|
|
223
|
-
lastTimestamp = item._meta.timestamp;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
} catch (error) {
|
|
227
|
-
console.error('Polling error:', error);
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
await new Promise(resolve => setTimeout(resolve, interval));
|
|
231
|
-
}
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
// Start polling
|
|
235
|
-
poll();
|
|
236
|
-
|
|
237
|
-
return {
|
|
238
|
-
unsubscribe: () => { running = false; },
|
|
239
|
-
};
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
async exportData(pathPrefix = '') {
|
|
243
|
-
const items = await this.readAll(pathPrefix || this.actorName);
|
|
244
|
-
|
|
245
|
-
return items.map(item => ({
|
|
246
|
-
path: item._meta?.path || `${pathPrefix}/${item.id}`,
|
|
247
|
-
data: item,
|
|
248
|
-
timestamp: item._meta?.timestamp || Date.now(),
|
|
249
|
-
}));
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
async importData(records, options = {}) {
|
|
253
|
-
const results = { success: 0, failed: 0, errors: [] };
|
|
254
|
-
|
|
255
|
-
for (const record of records) {
|
|
256
|
-
try {
|
|
257
|
-
await this.write(record.path, record.data);
|
|
258
|
-
results.success++;
|
|
259
|
-
} catch (error) {
|
|
260
|
-
results.failed++;
|
|
261
|
-
results.errors.push({ path: record.path, error: error.message });
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
return results;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
async _fetch(url, options = {}) {
|
|
269
|
-
const headers = options.headers || {};
|
|
270
|
-
|
|
271
|
-
// Add authorization if we have an API key
|
|
272
|
-
if (this.apiKey) {
|
|
273
|
-
headers['Authorization'] = `Bearer ${this.apiKey}`;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
return fetch(url, { ...options, headers });
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
close() {
|
|
280
|
-
// Nothing to close for HTTP client
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
getStatus() {
|
|
284
|
-
return {
|
|
285
|
-
type: 'activitypub',
|
|
286
|
-
serverUrl: this.serverUrl,
|
|
287
|
-
actorId: this.actorId,
|
|
288
|
-
actorName: this.actorName,
|
|
289
|
-
publicKey: this.publicKey,
|
|
290
|
-
connected: true,
|
|
291
|
-
};
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
export default ActivityPubBackend;
|