holosphere 1.1.6 → 1.1.7

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.
@@ -0,0 +1,380 @@
1
+ import HoloSphere from '../holosphere.js';
2
+ import * as environmentalApi from '../services/environmentalApi.js';
3
+ import * as h3 from 'h3-js';
4
+
5
+ /**
6
+ * Example script demonstrating how to save environmental data to HoloSphere
7
+ * This creates a structured dataset that can be federated across different holons
8
+ */
9
+ async function storeEnvironmentalData() {
10
+ // Initialize HoloSphere
11
+ const holosphere = new HoloSphere('environmental-data', true);
12
+
13
+ try {
14
+ // Define schemas for different environmental data types
15
+ await setupSchemas(holosphere);
16
+
17
+ // Example coordinates (Rome, Italy)
18
+ const lat = 41.9;
19
+ const lon = 12.5;
20
+ const countryCode = 'ITA';
21
+
22
+ // Get the H3 index for this location at different resolutions
23
+ const cityHolon = await holosphere.getHolon(lat, lon, 7); // City level
24
+ const regionHolon = await holosphere.getHolon(lat, lon, 5); // Region level
25
+ const countryHolon = await holosphere.getHolon(lat, lon, 3); // Country level
26
+
27
+ console.log(`Processing data for holons:
28
+ - City: ${cityHolon}
29
+ - Region: ${regionHolon}
30
+ - Country: ${countryHolon}`);
31
+
32
+ // Set up federation between different levels
33
+ await holosphere.federate(cityHolon, regionHolon);
34
+ await holosphere.federate(regionHolon, countryHolon);
35
+
36
+ // Fetch environmental data
37
+ console.log('Fetching environmental data...');
38
+
39
+ // Air quality data (city level)
40
+ let airQualityRecord;
41
+ const airQualityData = await environmentalApi.getAirQuality(lat, lon);
42
+ if (airQualityData) {
43
+ airQualityRecord = transformAirQualityData(airQualityData, cityHolon);
44
+ await holosphere.put(cityHolon, 'air-quality', airQualityRecord);
45
+ console.log('Stored air quality data in city holon');
46
+ }
47
+
48
+ // Carbon sequestration data (region level)
49
+ const carbonData = await environmentalApi.getCarbonSequestration(lat, lon);
50
+ if (carbonData) {
51
+ const carbonRecord = transformCarbonData(carbonData, regionHolon);
52
+ await holosphere.put(regionHolon, 'carbon-sequestration', carbonRecord);
53
+ console.log('Stored carbon sequestration data in region holon');
54
+ }
55
+
56
+ // Soil carbon data (region level)
57
+ const soilCarbonData = await environmentalApi.getSoilCarbon(lat, lon);
58
+ if (soilCarbonData) {
59
+ const soilCarbonRecord = transformSoilCarbonData(soilCarbonData, regionHolon);
60
+ await holosphere.put(regionHolon, 'soil-data', soilCarbonRecord);
61
+ console.log('Stored soil carbon data in region holon');
62
+ }
63
+
64
+ // Biodiversity data (country level)
65
+ const biodiversityData = await environmentalApi.getBiodiversityData(countryCode);
66
+ if (biodiversityData) {
67
+ const biodiversityRecord = transformBiodiversityData(biodiversityData, countryHolon);
68
+ await holosphere.put(countryHolon, 'biodiversity', biodiversityRecord);
69
+ console.log('Stored biodiversity data in country holon');
70
+ }
71
+
72
+ // Define and add the environmental metrics schema
73
+ const metricsSchema = {
74
+ type: 'object',
75
+ properties: {
76
+ id: { type: 'string' },
77
+ holon: { type: 'string' },
78
+ timestamp: { type: 'number' },
79
+ metrics: {
80
+ type: 'object',
81
+ properties: {
82
+ airQualityIndex: { type: 'number' },
83
+ carbonSequestration: { type: 'number' },
84
+ soilCarbon: { type: 'number' },
85
+ biodiversityCount: { type: 'number' }
86
+ }
87
+ }
88
+ },
89
+ required: ['id', 'holon', 'timestamp', 'metrics']
90
+ };
91
+ await holosphere.setSchema('environmental-metrics', metricsSchema);
92
+ console.log('Set schema for environmental metrics');
93
+
94
+ // Create initial empty metrics object
95
+ const metricsRecord = {
96
+ id: `env-metrics-${Date.now()}`,
97
+ holon: countryHolon,
98
+ timestamp: Date.now(),
99
+ metrics: {
100
+ airQualityIndex: 0,
101
+ carbonSequestration: 0,
102
+ soilCarbon: 0,
103
+ biodiversityCount: 0
104
+ }
105
+ };
106
+ await holosphere.put(countryHolon, 'environmental-metrics', metricsRecord);
107
+ console.log('Added initial environmental metrics record');
108
+
109
+ // Propagate data to create federation references
110
+ console.log('Setting up data federation...');
111
+
112
+ // Propagate air quality data up to region
113
+ if (airQualityRecord) {
114
+ await holosphere.propagate(cityHolon, 'air-quality', airQualityRecord, {
115
+ targetSpaces: [regionHolon]
116
+ });
117
+ console.log('Propagated air quality data to region holon');
118
+ }
119
+
120
+ // Aggregate environmental metrics at country level - manual approach since compute has issues
121
+ console.log('Manually updating environmental metrics...');
122
+ try {
123
+ // Get data from various sources
124
+ const airData = airQualityRecord || { airQualityIndex: 0 };
125
+ const carbonData = await holosphere.get(regionHolon, 'carbon-sequestration');
126
+ const soilData = await holosphere.get(regionHolon, 'soil-data');
127
+ const bioData = await holosphere.get(countryHolon, 'biodiversity');
128
+
129
+ // Update metrics manually
130
+ const updatedMetrics = {
131
+ id: metricsRecord.id,
132
+ holon: countryHolon,
133
+ timestamp: Date.now(),
134
+ metrics: {
135
+ airQualityIndex: airData.airQualityIndex || 0,
136
+ carbonSequestration: carbonData?.carbonSequestration || 0,
137
+ soilCarbon: soilData?.soilCarbon || 0,
138
+ biodiversityCount: bioData?.biodiversityCount || 0
139
+ }
140
+ };
141
+
142
+ await holosphere.put(countryHolon, 'environmental-metrics', updatedMetrics);
143
+ console.log('Updated environmental metrics at country level:', updatedMetrics);
144
+ } catch (updateError) {
145
+ console.error('Error updating environmental metrics:', updateError);
146
+ }
147
+
148
+ // Get and display the metrics directly instead of using getFederated
149
+ console.log('Retrieving environmental metrics...');
150
+ try {
151
+ const environmentalMetrics = await holosphere.get(countryHolon, 'environmental-metrics');
152
+ console.log('Environmental metrics:', environmentalMetrics);
153
+ } catch (getError) {
154
+ console.error('Error retrieving metrics:', getError);
155
+ }
156
+
157
+ } catch (error) {
158
+ console.error('Error storing environmental data:', error);
159
+ } finally {
160
+ // Close HoloSphere instance
161
+ await holosphere.close();
162
+ console.log('HoloSphere instance closed successfully');
163
+ }
164
+ }
165
+
166
+ /**
167
+ * Set up schemas for environmental data
168
+ */
169
+ async function setupSchemas(holosphere) {
170
+ // Air quality schema
171
+ const airQualitySchema = {
172
+ type: 'object',
173
+ properties: {
174
+ id: { type: 'string' },
175
+ holon: { type: 'string' },
176
+ timestamp: { type: 'number' },
177
+ coordinates: {
178
+ type: 'object',
179
+ properties: {
180
+ lat: { type: 'number' },
181
+ lon: { type: 'number' }
182
+ }
183
+ },
184
+ airQualityIndex: { type: 'number' },
185
+ pollutants: {
186
+ type: 'object',
187
+ properties: {
188
+ co: { type: 'number' },
189
+ no2: { type: 'number' },
190
+ o3: { type: 'number' },
191
+ pm2_5: { type: 'number' },
192
+ pm10: { type: 'number' },
193
+ so2: { type: 'number' }
194
+ }
195
+ }
196
+ },
197
+ required: ['id', 'holon', 'timestamp', 'coordinates', 'airQualityIndex']
198
+ };
199
+
200
+ // Carbon sequestration schema
201
+ const carbonSchema = {
202
+ type: 'object',
203
+ properties: {
204
+ id: { type: 'string' },
205
+ holon: { type: 'string' },
206
+ timestamp: { type: 'number' },
207
+ coordinates: {
208
+ type: 'object',
209
+ properties: {
210
+ lat: { type: 'number' },
211
+ lon: { type: 'number' }
212
+ }
213
+ },
214
+ carbonSequestration: { type: 'number' },
215
+ temperature: { type: 'number' },
216
+ precipitation: { type: 'number' }
217
+ },
218
+ required: ['id', 'holon', 'timestamp', 'coordinates', 'carbonSequestration']
219
+ };
220
+
221
+ // Soil carbon schema
222
+ const soilSchema = {
223
+ type: 'object',
224
+ properties: {
225
+ id: { type: 'string' },
226
+ holon: { type: 'string' },
227
+ timestamp: { type: 'number' },
228
+ coordinates: {
229
+ type: 'object',
230
+ properties: {
231
+ lat: { type: 'number' },
232
+ lon: { type: 'number' }
233
+ }
234
+ },
235
+ soilCarbon: { type: 'number' },
236
+ soilType: { type: 'string' },
237
+ soilDepth: { type: 'string' }
238
+ },
239
+ required: ['id', 'holon', 'timestamp', 'coordinates', 'soilCarbon']
240
+ };
241
+
242
+ // Biodiversity schema
243
+ const biodiversitySchema = {
244
+ type: 'object',
245
+ properties: {
246
+ id: { type: 'string' },
247
+ holon: { type: 'string' },
248
+ timestamp: { type: 'number' },
249
+ countryCode: { type: 'string' },
250
+ biodiversityCount: { type: 'number' },
251
+ species: {
252
+ type: 'array',
253
+ items: {
254
+ type: 'object',
255
+ properties: {
256
+ scientificName: { type: 'string' },
257
+ count: { type: 'number' }
258
+ }
259
+ }
260
+ }
261
+ },
262
+ required: ['id', 'holon', 'timestamp', 'countryCode', 'biodiversityCount']
263
+ };
264
+
265
+ // Set schemas
266
+ await holosphere.setSchema('air-quality', airQualitySchema);
267
+ await holosphere.setSchema('carbon-sequestration', carbonSchema);
268
+ await holosphere.setSchema('soil-data', soilSchema);
269
+ await holosphere.setSchema('biodiversity', biodiversitySchema);
270
+
271
+ console.log('Environmental data schemas set up successfully');
272
+ }
273
+
274
+ /**
275
+ * Transform air quality data from API into our schema
276
+ */
277
+ function transformAirQualityData(apiData, holon) {
278
+ const components = apiData.list?.[0]?.components || {};
279
+ const main = apiData.list?.[0]?.main || {};
280
+
281
+ return {
282
+ id: `air-quality-${Date.now()}`,
283
+ holon: holon,
284
+ timestamp: Date.now(),
285
+ coordinates: {
286
+ lat: apiData.coord?.lat || 0,
287
+ lon: apiData.coord?.lon || 0
288
+ },
289
+ airQualityIndex: main.aqi || 0,
290
+ pollutants: {
291
+ co: components.co || 0,
292
+ no2: components.no2 || 0,
293
+ o3: components.o3 || 0,
294
+ pm2_5: components.pm2_5 || 0,
295
+ pm10: components.pm10 || 0,
296
+ so2: components.so2 || 0
297
+ }
298
+ };
299
+ }
300
+
301
+ /**
302
+ * Transform carbon sequestration data from API into our schema
303
+ */
304
+ function transformCarbonData(apiData, holon) {
305
+ const parameters = apiData.properties?.parameter || {};
306
+ const temperature = parameters.T2M?.['20230701'] || 0;
307
+ const precipitation = parameters.PRECTOT?.['20230701'] || 0;
308
+
309
+ // Calculate a simplified carbon sequestration estimate
310
+ // (In a real app, use actual models based on temperature, precipitation, etc.)
311
+ const carbonSequestration = (temperature * 0.5) + (precipitation * 2);
312
+
313
+ return {
314
+ id: `carbon-seq-${Date.now()}`,
315
+ holon: holon,
316
+ timestamp: Date.now(),
317
+ coordinates: {
318
+ lat: apiData.geometry?.coordinates[1] || 0,
319
+ lon: apiData.geometry?.coordinates[0] || 0
320
+ },
321
+ carbonSequestration: carbonSequestration,
322
+ temperature: temperature,
323
+ precipitation: precipitation
324
+ };
325
+ }
326
+
327
+ /**
328
+ * Transform soil carbon data from API into our schema
329
+ */
330
+ function transformSoilCarbonData(apiData, holon) {
331
+ const properties = apiData.properties || {};
332
+ const soilCarbon = properties.soilGrids?.properties?.soc?.mean || 0;
333
+
334
+ return {
335
+ id: `soil-carbon-${Date.now()}`,
336
+ holon: holon,
337
+ timestamp: Date.now(),
338
+ coordinates: {
339
+ lat: apiData.geometry?.coordinates[1] || 0,
340
+ lon: apiData.geometry?.coordinates[0] || 0
341
+ },
342
+ soilCarbon: soilCarbon,
343
+ soilType: properties.soilType || 'Unknown',
344
+ soilDepth: '0-30cm'
345
+ };
346
+ }
347
+
348
+ /**
349
+ * Transform biodiversity data from API into our schema
350
+ */
351
+ function transformBiodiversityData(apiData, holon) {
352
+ const results = apiData.results || [];
353
+ const species = {};
354
+
355
+ // Count species occurrences
356
+ results.forEach(occurrence => {
357
+ const name = occurrence.scientificName || 'Unknown';
358
+ species[name] = (species[name] || 0) + 1;
359
+ });
360
+
361
+ // Convert to array format
362
+ const speciesArray = Object.keys(species).map(name => ({
363
+ scientificName: name,
364
+ count: species[name]
365
+ }));
366
+
367
+ return {
368
+ id: `biodiversity-${Date.now()}`,
369
+ holon: holon,
370
+ timestamp: Date.now(),
371
+ countryCode: results[0]?.countryCode || 'Unknown',
372
+ biodiversityCount: results.length,
373
+ species: speciesArray
374
+ };
375
+ }
376
+
377
+ // Execute the example
378
+ storeEnvironmentalData()
379
+ .then(() => console.log('Environmental data example completed'))
380
+ .catch(error => console.error('Error in environmental data example:', error));
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Organization Federation Example for HoloSphere
3
+ *
4
+ * This example demonstrates a real-world use case where a tech team creates tasks
5
+ * that are federated to the parent organization for visibility.
6
+ */
7
+
8
+ import HoloSphere from './holosphere.js';
9
+
10
+ async function organizationFederationExample() {
11
+ const holoSphere = new HoloSphere('organization-example');
12
+
13
+ try {
14
+ console.log('Starting Organization Federation Example...');
15
+
16
+ // Define our spaces/holons
17
+ const orgHolon = 'acme-organization';
18
+ const techTeamHolon = 'acme-tech-team';
19
+
20
+ // Step 1: Create federation relationship between tech team and organization
21
+ console.log('\nStep 1: Creating federation relationship...');
22
+
23
+ await holoSphere.federate(techTeamHolon, orgHolon);
24
+ console.log('Federation created between tech team and organization');
25
+
26
+ // Step 2: Set up bidirectional notification settings (critical!)
27
+ console.log('\nStep 2: Setting up bidirectional notification...');
28
+
29
+ // First set up tech team to notify organization
30
+ const techTeamFedSettings = await holoSphere.getGlobal('federation', techTeamHolon);
31
+ if (techTeamFedSettings) {
32
+ techTeamFedSettings.notify = techTeamFedSettings.notify || [];
33
+ if (!techTeamFedSettings.notify.includes(orgHolon)) {
34
+ techTeamFedSettings.notify.push(orgHolon);
35
+ await holoSphere.putGlobal('federation', techTeamFedSettings);
36
+ console.log('Tech team set to notify organization');
37
+ }
38
+ }
39
+
40
+ // Then set up organization to notify tech team (if needed)
41
+ const orgFedSettings = await holoSphere.getGlobal('federation', orgHolon);
42
+ if (orgFedSettings) {
43
+ orgFedSettings.notify = orgFedSettings.notify || [];
44
+ if (!orgFedSettings.notify.includes(techTeamHolon)) {
45
+ orgFedSettings.notify.push(techTeamHolon);
46
+ await holoSphere.putGlobal('federation', orgFedSettings);
47
+ console.log('Organization set to notify tech team');
48
+ }
49
+ }
50
+
51
+ // Step 3: Verify federation is set up properly
52
+ console.log('\nStep 3: Verifying federation setup...');
53
+
54
+ const techTeamFedInfo = await holoSphere.getFederation(techTeamHolon);
55
+ console.log('Tech team federation info:', techTeamFedInfo);
56
+
57
+ // Step 4: Create a task in the tech team holon
58
+ console.log('\nStep 4: Creating a task in the tech team holon...');
59
+
60
+ const task = {
61
+ id: 'task-123',
62
+ title: 'Implement new authentication system',
63
+ description: 'Replace the current auth system with OAuth2',
64
+ assignee: 'dev@example.com',
65
+ status: 'in_progress',
66
+ priority: 'high',
67
+ dueDate: '2023-12-31',
68
+ createdAt: new Date().toISOString(),
69
+ tags: ['security', 'infrastructure']
70
+ };
71
+
72
+ // Store the task in the tech team holon
73
+ await holoSphere.put(techTeamHolon, 'tasks', task);
74
+ console.log('Task created in tech team holon:', task.id);
75
+
76
+ // Step 5: Propagate the task to the organization holon
77
+ console.log('\nStep 5: Propagating task to organization holon...');
78
+
79
+ await holoSphere.propagate(techTeamHolon, 'tasks', task);
80
+ console.log('Task propagated to organization holon');
81
+
82
+ // Step 6: Allow time for propagation
83
+ console.log('\nStep 6: Waiting for propagation to complete...');
84
+ await new Promise(resolve => setTimeout(resolve, 1000));
85
+
86
+ // Step 7: Verify task in both holons
87
+ console.log('\nStep 7: Verifying task is in both holons...');
88
+
89
+ // Check tech team holon directly
90
+ const techTeamTask = await holoSphere.get(techTeamHolon, 'tasks', 'task-123');
91
+ console.log('Task in tech team holon:', techTeamTask ? 'Found' : 'Not found');
92
+ if (techTeamTask) console.log('Tech team task status:', techTeamTask.status);
93
+
94
+ // Check organization holon directly
95
+ const orgTask = await holoSphere.get(orgHolon, 'tasks', 'task-123');
96
+ console.log('Task in organization holon:', orgTask ? 'Found' : 'Not found');
97
+ if (orgTask) {
98
+ console.log('Organization task status:', orgTask.status);
99
+ console.log('Federation metadata:', orgTask.federation);
100
+ }
101
+
102
+ // Step 8: Use getFederated to view all tasks across holons
103
+ console.log('\nStep 8: Using getFederated to view all tasks...');
104
+
105
+ const allOrgTasks = await holoSphere.getFederated(orgHolon, 'tasks');
106
+ console.log(`Organization holon has access to ${allOrgTasks.length} tasks`);
107
+
108
+ const allTechTasks = await holoSphere.getFederated(techTeamHolon, 'tasks');
109
+ console.log(`Tech team holon has access to ${allTechTasks.length} tasks`);
110
+
111
+ // Step 9: Update the task in tech team and propagate the change
112
+ console.log('\nStep 9: Updating task in tech team holon...');
113
+
114
+ const updatedTask = {
115
+ ...task,
116
+ status: 'completed',
117
+ completedAt: new Date().toISOString()
118
+ };
119
+
120
+ await holoSphere.put(techTeamHolon, 'tasks', updatedTask);
121
+ await holoSphere.propagate(techTeamHolon, 'tasks', updatedTask);
122
+ console.log('Task updated and propagated');
123
+
124
+ // Step 10: Allow time for propagation
125
+ console.log('\nStep 10: Waiting for propagation to complete...');
126
+ await new Promise(resolve => setTimeout(resolve, 1000));
127
+
128
+ // Step 11: Verify updates in both holons
129
+ console.log('\nStep 11: Verifying updated task in both holons...');
130
+
131
+ const updatedTechTeamTask = await holoSphere.get(techTeamHolon, 'tasks', 'task-123');
132
+ console.log('Updated task in tech team holon status:', updatedTechTeamTask?.status);
133
+
134
+ const updatedOrgTask = await holoSphere.get(orgHolon, 'tasks', 'task-123');
135
+ console.log('Updated task in organization holon status:', updatedOrgTask?.status);
136
+
137
+ // Step 12: Clean up - remove federation
138
+ console.log('\nStep 12: Cleaning up - removing federation...');
139
+
140
+ await holoSphere.unfederate(techTeamHolon, orgHolon);
141
+ console.log('Federation removed between tech team and organization');
142
+
143
+ console.log('\nOrganization federation example completed successfully!');
144
+ } catch (error) {
145
+ console.error('Error in organization federation example:', error);
146
+ } finally {
147
+ // Always close the HoloSphere instance
148
+ await holoSphere.close();
149
+ console.log('HoloSphere instance closed');
150
+ }
151
+ }
152
+
153
+ // Run the example
154
+ organizationFederationExample().catch(console.error);
@@ -0,0 +1,147 @@
1
+ import HoloSphere from '../holosphere.js';
2
+ import * as h3 from 'h3-js';
3
+
4
+ /**
5
+ * Example demonstrating how to query environmental data from HoloSphere
6
+ * This shows how to access data across federated holons at different scales
7
+ */
8
+ async function queryEnvironmentalData() {
9
+ // Initialize HoloSphere with the same appname used to store the data
10
+ const holosphere = new HoloSphere('environmental-data');
11
+
12
+ try {
13
+ // Example coordinates (Rome, Italy)
14
+ const lat = 41.9;
15
+ const lon = 12.5;
16
+
17
+ // Get the holons at different resolutions
18
+ const cityHolon = await holosphere.getHolon(lat, lon, 7); // City level
19
+ const regionHolon = await holosphere.getHolon(lat, lon, 5); // Region level
20
+ const countryHolon = await holosphere.getHolon(lat, lon, 3); // Country level
21
+
22
+ console.log(`Querying environmental data for location (${lat}, ${lon})`);
23
+ console.log(` - City: ${cityHolon}`);
24
+ console.log(` - Region: ${regionHolon}`);
25
+ console.log(` - Country: ${countryHolon}`);
26
+
27
+ // Query 1: Get air quality data from the city level
28
+ console.log('\n=== CITY LEVEL: Air Quality Data ===');
29
+ const airQualityData = await holosphere.getAll(cityHolon, 'air-quality');
30
+ if (airQualityData.length > 0) {
31
+ const latest = airQualityData.sort((a, b) => b.timestamp - a.timestamp)[0];
32
+ console.log(`Latest Air Quality Index: ${latest.airQualityIndex}`);
33
+ console.log('Pollutant levels:');
34
+ Object.entries(latest.pollutants).forEach(([pollutant, value]) => {
35
+ console.log(` - ${pollutant}: ${value}`);
36
+ });
37
+ } else {
38
+ console.log('No air quality data available for this location');
39
+ }
40
+
41
+ // Query 2: Use federation to get soil data referenced at the region level
42
+ console.log('\n=== REGION LEVEL: Soil Carbon Data ===');
43
+ const soilData = await holosphere.getAll(regionHolon, 'soil-data');
44
+ if (soilData.length > 0) {
45
+ const latest = soilData.sort((a, b) => b.timestamp - a.timestamp)[0];
46
+ console.log(`Soil Carbon: ${latest.soilCarbon} g/kg`);
47
+ console.log(`Soil Type: ${latest.soilType}`);
48
+ console.log(`Soil Depth: ${latest.soilDepth}`);
49
+ } else {
50
+ console.log('No soil data available for this region');
51
+ }
52
+
53
+ // Query 3: Get carbon sequestration data at region level
54
+ console.log('\n=== REGION LEVEL: Carbon Sequestration ===');
55
+ const carbonData = await holosphere.getAll(regionHolon, 'carbon-sequestration');
56
+ if (carbonData.length > 0) {
57
+ const latest = carbonData.sort((a, b) => b.timestamp - a.timestamp)[0];
58
+ console.log(`Carbon Sequestration: ${latest.carbonSequestration} tons/hectare/year`);
59
+ console.log(`Temperature: ${latest.temperature}°C`);
60
+ console.log(`Precipitation: ${latest.precipitation} mm`);
61
+ } else {
62
+ console.log('No carbon sequestration data available for this region');
63
+ }
64
+
65
+ // Query 4: Get biodiversity data at country level
66
+ console.log('\n=== COUNTRY LEVEL: Biodiversity ===');
67
+ const biodiversityData = await holosphere.getAll(countryHolon, 'biodiversity');
68
+ if (biodiversityData.length > 0) {
69
+ const latest = biodiversityData.sort((a, b) => b.timestamp - a.timestamp)[0];
70
+ console.log(`Biodiversity Count: ${latest.biodiversityCount} species`);
71
+ console.log(`Country Code: ${latest.countryCode}`);
72
+ console.log(`Top 5 Species:`);
73
+
74
+ // Sort species by count and show top 5
75
+ const topSpecies = latest.species.sort((a, b) => b.count - a.count).slice(0, 5);
76
+ topSpecies.forEach((species, index) => {
77
+ console.log(` ${index + 1}. ${species.scientificName}: ${species.count} occurrences`);
78
+ });
79
+ } else {
80
+ console.log('No biodiversity data available for this country');
81
+ }
82
+
83
+ // Query 5: Get federated data across all levels
84
+ console.log('\n=== FEDERATED DATA: Environmental Metrics ===');
85
+ const federatedData = await holosphere.getFederated(countryHolon, 'environmental-metrics', {
86
+ resolveReferences: true,
87
+ aggregate: true,
88
+ idField: 'id'
89
+ });
90
+
91
+ if (federatedData.length > 0) {
92
+ console.log('Aggregated Environmental Metrics:');
93
+ federatedData.forEach(data => {
94
+ if (data.metrics) {
95
+ Object.entries(data.metrics).forEach(([metric, value]) => {
96
+ console.log(` - ${metric}: ${value}`);
97
+ });
98
+ } else {
99
+ console.log('No metrics available in federated data');
100
+ }
101
+ });
102
+ } else {
103
+ console.log('No federated environmental metrics available');
104
+ }
105
+
106
+ // Query 6: Get references to air quality data from the region level
107
+ // This demonstrates accessing data via federation references
108
+ console.log('\n=== FEDERATION REFERENCES: Air Quality Data from Region ===');
109
+ const airQualityRefs = await holosphere.getAll(regionHolon, 'air-quality');
110
+ if (airQualityRefs.length > 0) {
111
+ console.log(`Found ${airQualityRefs.length} air quality references in region`);
112
+
113
+ // Get the first reference and resolve it
114
+ const ref = airQualityRefs[0];
115
+ console.log('Reference details:');
116
+
117
+ if (ref.soul) {
118
+ console.log(` - Soul path: ${ref.soul}`);
119
+
120
+ // Resolve reference manually to show the process
121
+ const resolvedData = await holosphere.getNodeBySoul(ref.soul);
122
+ if (resolvedData) {
123
+ console.log('Successfully resolved reference to original air quality data:');
124
+ console.log(` - Air Quality Index: ${resolvedData.airQualityIndex}`);
125
+ console.log(` - Source Holon: ${resolvedData.holon}`);
126
+ } else {
127
+ console.log('Could not resolve reference - original data not found');
128
+ }
129
+ } else {
130
+ console.log('Not a soul reference:', ref);
131
+ }
132
+ } else {
133
+ console.log('No air quality references found at region level');
134
+ }
135
+
136
+ } catch (error) {
137
+ console.error('Error querying environmental data:', error);
138
+ } finally {
139
+ // Always close the HoloSphere instance
140
+ await holosphere.close();
141
+ }
142
+ }
143
+
144
+ // Execute the example
145
+ queryEnvironmentalData()
146
+ .then(() => console.log('\nEnvironmental data query example completed'))
147
+ .catch(error => console.error('Error in environmental data query example:', error));