holosphere 1.1.4 → 1.1.6

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/FEDERATION.md ADDED
@@ -0,0 +1,265 @@
1
+ # HoloSphere Federation
2
+
3
+ This document explains how to use the federation functionality in HoloSphere, which allows different spaces to share data with each other.
4
+
5
+ ## What is Federation?
6
+
7
+ Federation in HoloSphere allows different spaces (data stores) to connect and share data with each other. This enables:
8
+
9
+ - Creating networks of connected spaces
10
+ - Propagating data across these networks
11
+ - Subscribing to changes in federated spaces
12
+
13
+ Federation can be either public (no authentication required) or private (password-protected).
14
+
15
+ ## Core Federation Functions
16
+
17
+ ### Creating a Federation
18
+
19
+ To create a federation between two spaces:
20
+
21
+ ```javascript
22
+ // Public federation (no passwords)
23
+ await holoSphere.federate('space1', 'space2');
24
+
25
+ // Private federation (with passwords)
26
+ await holoSphere.federate('space1', 'space2', 'password1', 'password2');
27
+ ```
28
+
29
+ ### Setting Up Bidirectional Notification (Important!)
30
+
31
+ After creating a federation, you need to set up the notification settings for proper bidirectional data propagation:
32
+
33
+ ```javascript
34
+ // 1. Get federation settings for first space
35
+ const fedSettings1 = await holoSphere.getGlobal('federation', 'space1');
36
+ if (fedSettings1) {
37
+ // 2. Configure notify settings
38
+ fedSettings1.notify = fedSettings1.notify || [];
39
+ if (!fedSettings1.notify.includes('space2')) {
40
+ fedSettings1.notify.push('space2');
41
+ }
42
+ // 3. Save updated settings
43
+ await holoSphere.putGlobal('federation', fedSettings1);
44
+ }
45
+
46
+ // Repeat for the second space
47
+ const fedSettings2 = await holoSphere.getGlobal('federation', 'space2');
48
+ if (fedSettings2) {
49
+ fedSettings2.notify = fedSettings2.notify || [];
50
+ if (!fedSettings2.notify.includes('space1')) {
51
+ fedSettings2.notify.push('space1');
52
+ }
53
+ await holoSphere.putGlobal('federation', fedSettings2);
54
+ }
55
+ ```
56
+
57
+ ### Getting Federation Information
58
+
59
+ To retrieve information about a space's federation:
60
+
61
+ ```javascript
62
+ // Public space
63
+ const fedInfo = await holoSphere.getFederation('space1');
64
+
65
+ // Private space
66
+ const fedInfo = await holoSphere.getFederation('space1', 'password1');
67
+ ```
68
+
69
+ The returned object contains:
70
+ - `id`: The space ID
71
+ - `name`: The space name
72
+ - `federation`: Array of space IDs that this space is federated with
73
+ - `notify`: Array of space IDs that this space will propagate data to
74
+
75
+ ### Propagating Data to Federated Spaces
76
+
77
+ To propagate data to all federated spaces:
78
+
79
+ ```javascript
80
+ const data = { id: 'item1', value: 42 };
81
+
82
+ // 1. Store data locally first
83
+ await holoSphere.put('space1', 'items', data);
84
+
85
+ // 2. Explicitly propagate to federated spaces
86
+ await holoSphere.propagateToFederation('space1', 'items', data);
87
+
88
+ // 3. (Optional) Add a short delay to ensure propagation completes
89
+ await new Promise(resolve => setTimeout(resolve, 1000));
90
+ ```
91
+
92
+ ### Accessing Data Across Federated Spaces
93
+
94
+ There are multiple ways to access data across federated spaces:
95
+
96
+ #### Method 1: Using getFederated (Recommended)
97
+
98
+ This retrieves data from both the local space and all federated spaces:
99
+
100
+ ```javascript
101
+ // Get all items from local and federated spaces
102
+ const allItems = await holoSphere.getFederated('space2', 'items');
103
+
104
+ // Find a specific item by ID
105
+ const item1 = allItems.find(item => item.id === 'item1');
106
+ ```
107
+
108
+ #### Method 2: Direct Access
109
+
110
+ After propagation, data may also be accessible directly:
111
+
112
+ ```javascript
113
+ // Attempt to get item1 from space2 directly
114
+ const item1FromSpace2 = await holoSphere.get('space2', 'items', 'item1');
115
+ ```
116
+
117
+ ### Subscribing to Federation Changes
118
+
119
+ To subscribe to changes in a federation:
120
+
121
+ ```javascript
122
+ // Subscribe
123
+ const subscription = await holoSphere.subscribeFederation('space1', null, (data, originSpace, lens) => {
124
+ console.log(`Received data from ${originSpace}/${lens}:`, data);
125
+ });
126
+
127
+ // Later, unsubscribe
128
+ subscription.unsubscribe();
129
+ ```
130
+
131
+ ### Removing a Federation
132
+
133
+ To remove a federation between two spaces:
134
+
135
+ ```javascript
136
+ // Public federation
137
+ await holoSphere.unfederate('space1', 'space2');
138
+
139
+ // Private federation
140
+ await holoSphere.unfederate('space1', 'space2', 'password1', 'password2');
141
+ ```
142
+
143
+ ## Complete Example
144
+
145
+ Here's a complete example showing the proper way to set up and use federation:
146
+
147
+ ```javascript
148
+ import HoloSphere from './holosphere.js';
149
+
150
+ async function federationExample() {
151
+ const holoSphere = new HoloSphere('example-app');
152
+
153
+ try {
154
+ const space1 = 'public-space1';
155
+ const space2 = 'public-space2';
156
+
157
+ // Step 1: Create federation
158
+ await holoSphere.federate(space1, space2);
159
+
160
+ // Step 2: Set up bidirectional notify settings (critical!)
161
+ const fedSettings1 = await holoSphere.getGlobal('federation', space1);
162
+ if (fedSettings1) {
163
+ fedSettings1.notify = fedSettings1.notify || [];
164
+ if (!fedSettings1.notify.includes(space2)) {
165
+ fedSettings1.notify.push(space2);
166
+ await holoSphere.putGlobal('federation', fedSettings1);
167
+ }
168
+ }
169
+
170
+ const fedSettings2 = await holoSphere.getGlobal('federation', space2);
171
+ if (fedSettings2) {
172
+ fedSettings2.notify = fedSettings2.notify || [];
173
+ if (!fedSettings2.notify.includes(space1)) {
174
+ fedSettings2.notify.push(space1);
175
+ await holoSphere.putGlobal('federation', fedSettings2);
176
+ }
177
+ }
178
+
179
+ // Step 3: Verify federation is set up properly
180
+ const updatedFedInfo = await holoSphere.getFederation(space1);
181
+ console.log(`Federation info for ${space1}:`, updatedFedInfo);
182
+
183
+ // Step 4: Store data in space1
184
+ const item = {
185
+ id: 'item1',
186
+ title: 'Federation Test',
187
+ value: 42
188
+ };
189
+ await holoSphere.put(space1, 'items', item);
190
+
191
+ // Step 5: Propagate to federation
192
+ await holoSphere.propagateToFederation(space1, 'items', item);
193
+
194
+ // Step 6: Allow time for propagation
195
+ await new Promise(resolve => setTimeout(resolve, 1000));
196
+
197
+ // Step 7: Access data from both spaces
198
+ const itemFromSpace1 = await holoSphere.get(space1, 'items', 'item1');
199
+ console.log('Item from space1:', itemFromSpace1);
200
+
201
+ // Step 8: Access federated data
202
+ // Method 1: Using getFederated
203
+ const federatedData = await holoSphere.getFederated(space2, 'items');
204
+ const itemFromFederation = federatedData.find(item => item.id === 'item1');
205
+ console.log('Item from federation:', itemFromFederation);
206
+
207
+ // Method 2: Direct access (if propagation worked correctly)
208
+ const directAccess = await holoSphere.get(space2, 'items', 'item1');
209
+ console.log('Direct access from space2:', directAccess);
210
+
211
+ // Step 9: Clean up
212
+ await holoSphere.unfederate(space1, space2);
213
+ } finally {
214
+ // Always close the HoloSphere instance
215
+ await holoSphere.close();
216
+ }
217
+ }
218
+
219
+ federationExample().catch(console.error);
220
+ ```
221
+
222
+ ## Running the Tests
223
+
224
+ HoloSphere includes test scripts to verify federation functionality:
225
+
226
+ ### Public Federation Tests
227
+
228
+ Run the public federation tests with:
229
+
230
+ ```bash
231
+ node test-federation.js
232
+ ```
233
+
234
+ This tests:
235
+ - Creating public federations
236
+ - Storing and retrieving data
237
+ - Propagating data to federated spaces
238
+ - Subscribing to federation changes
239
+ - Removing federations
240
+
241
+ ## Troubleshooting
242
+
243
+ ### Common Issues
244
+
245
+ 1. **Missing Notify Settings**: The most common issue is not properly configuring notify settings. Always ensure both spaces have each other in their notify arrays.
246
+
247
+ 2. **No Explicit Propagation**: Data doesn't automatically propagate between spaces. You must explicitly call `propagateToFederation()` after storing data.
248
+
249
+ 3. **Authentication Errors**: When working with private federations, ensure passwords are correct and consistent.
250
+
251
+ 4. **Timing Issues**: Data propagation is asynchronous. Add small delays (500-1000ms) between operations to allow propagation to complete.
252
+
253
+ 5. **Missing Federation Metadata**: After propagation, federated items should have a `federation` property containing the origin space and timestamp.
254
+
255
+ ### Best Practices
256
+
257
+ 1. **Verify Federation Setup**: After creating a federation, always check the federation info to ensure it includes both the federation relationship and notify settings.
258
+
259
+ 2. **Error Handling**: Wrap federation operations in try/catch blocks and handle errors gracefully.
260
+
261
+ 3. **Bidirectional Setup**: For proper data sharing, both spaces need notify settings pointing to each other.
262
+
263
+ 4. **Propagation Timing**: Allow sufficient time for propagation operations to complete before attempting to access data.
264
+
265
+ 5. **Cleanup**: Always close the HoloSphere instance when done to prevent resource leaks.
@@ -0,0 +1,5 @@
1
+ module.exports = {
2
+ presets: [
3
+ ['@babel/preset-env', {targets: {node: 'current'}}],
4
+ ],
5
+ };