@fjell/registry 4.4.7 → 4.4.10

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 (54) hide show
  1. package/README.md +81 -4
  2. package/dist/Registry.cjs +20 -1
  3. package/dist/Registry.js +20 -1
  4. package/dist/RegistryHub.cjs +17 -1
  5. package/dist/RegistryHub.js +17 -1
  6. package/dist/index.cjs +35 -0
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/types.d.ts +15 -0
  9. package/docs/README.md +74 -0
  10. package/docs/index.html +17 -0
  11. package/docs/memory-data/scaling-10-instances.json +206 -206
  12. package/docs/memory-data/scaling-100-instances.json +206 -206
  13. package/docs/memory-data/scaling-1000-instances.json +108 -108
  14. package/docs/memory-data/scaling-10000-instances.json +49 -49
  15. package/docs/memory-data/scaling-20-instances.json +208 -208
  16. package/docs/memory-data/scaling-200-instances.json +201 -201
  17. package/docs/memory-data/scaling-2000-instances.json +107 -107
  18. package/docs/memory-data/scaling-50-instances.json +206 -206
  19. package/docs/memory-data/scaling-500-instances.json +108 -108
  20. package/docs/memory-data/scaling-5000-instances.json +49 -49
  21. package/docs/memory-overhead.svg +17 -17
  22. package/docs/memory.md +111 -111
  23. package/docs/package.json +35 -0
  24. package/docs/public/README.md +623 -0
  25. package/docs/public/TIMING_NODE_OPTIMIZATION.md +207 -0
  26. package/docs/public/examples/coordinates-example.ts +253 -0
  27. package/docs/public/examples/multi-level-keys.ts +374 -0
  28. package/docs/public/examples/registry-hub-coordinates-example.ts +370 -0
  29. package/docs/public/examples/registry-hub-types.ts +437 -0
  30. package/docs/public/examples/simple-example.ts +250 -0
  31. package/docs/public/examples-README.md +222 -0
  32. package/docs/public/fjell-icon.svg +1 -0
  33. package/docs/public/icon.png +0 -0
  34. package/docs/public/icon2.png +0 -0
  35. package/docs/public/memory-overhead.svg +120 -0
  36. package/docs/public/memory.md +430 -0
  37. package/docs/public/pano.png +0 -0
  38. package/docs/public/pano2.png +0 -0
  39. package/docs/public/timing-range.svg +176 -0
  40. package/docs/public/timing.md +483 -0
  41. package/docs/src/App.css +1175 -0
  42. package/docs/src/App.test.tsx +50 -0
  43. package/docs/src/App.tsx +583 -0
  44. package/docs/src/index.css +40 -0
  45. package/docs/src/main.tsx +10 -0
  46. package/docs/src/test/setup.ts +1 -0
  47. package/docs/timing-range.svg +41 -41
  48. package/docs/timing.md +101 -101
  49. package/docs/tsconfig.node.json +13 -0
  50. package/docs/vitest.config.ts +14 -0
  51. package/examples/README.md +35 -0
  52. package/examples/coordinates-example.ts +253 -0
  53. package/examples/registry-hub-coordinates-example.ts +370 -0
  54. package/package.json +1 -1
@@ -0,0 +1,253 @@
1
+ /**
2
+ * Coordinates Discovery Example
3
+ *
4
+ * This example demonstrates how to use the getCoordinates() method to:
5
+ * - Discover all registered instances in a registry
6
+ * - Inspect coordinates and their scopes
7
+ * - Monitor registry state for debugging
8
+ * - Implement discovery mechanisms
9
+ *
10
+ * Run this example with: npx tsx examples/coordinates-example.ts
11
+ *
12
+ * Note: In a real application, import from the built package:
13
+ * import { createRegistry, createInstance } from '@fjell/registry';
14
+ */
15
+
16
+ // Import the actual registry functionality
17
+ import { createRegistry } from '../src/Registry';
18
+ import { createInstance } from '../src/Instance';
19
+
20
+ // ===== Service Examples =====
21
+
22
+ class DatabaseService {
23
+ constructor(private type: string, private environment: string) { }
24
+
25
+ connect() {
26
+ console.log(`Connected to ${this.type} database in ${this.environment}`);
27
+ }
28
+
29
+ getInfo() {
30
+ return `${this.type} (${this.environment})`;
31
+ }
32
+ }
33
+
34
+ class CacheService {
35
+ constructor(private type: string) { }
36
+
37
+ get(key: string) {
38
+ console.log(`Getting ${key} from ${this.type} cache`);
39
+ return `cached_${key}`;
40
+ }
41
+
42
+ getInfo() {
43
+ return this.type;
44
+ }
45
+ }
46
+
47
+ class LoggingService {
48
+ constructor(private level: string) { }
49
+
50
+ log(message: string) {
51
+ console.log(`[${this.level.toUpperCase()}] ${message}`);
52
+ }
53
+
54
+ getInfo() {
55
+ return `Logging at ${this.level} level`;
56
+ }
57
+ }
58
+
59
+ // ===== Main Example =====
60
+
61
+ async function runCoordinatesExample() {
62
+ console.log('🔍 Registry Coordinates Discovery Example\n');
63
+
64
+ // Step 1: Create a registry
65
+ console.log('1. Creating registry...');
66
+ const registry = createRegistry('services');
67
+ console.log(' ✅ Registry created\n');
68
+
69
+ // Step 2: Register multiple instances with different scopes
70
+ console.log('2. Registering instances with various configurations...\n');
71
+
72
+ // Database services for different environments
73
+ registry.createInstance(
74
+ ['database'],
75
+ ['production', 'postgres'],
76
+ (coordinate, context) => {
77
+ const service = new DatabaseService('PostgreSQL', 'production');
78
+ const instance = createInstance(context.registry, coordinate);
79
+ (instance as any).connect = service.connect.bind(service);
80
+ (instance as any).getInfo = service.getInfo.bind(service);
81
+ return instance;
82
+ }
83
+ );
84
+ console.log(' ✅ PostgreSQL database (production) registered');
85
+
86
+ registry.createInstance(
87
+ ['database'],
88
+ ['development', 'sqlite'],
89
+ (coordinate, context) => {
90
+ const service = new DatabaseService('SQLite', 'development');
91
+ const instance = createInstance(context.registry, coordinate);
92
+ (instance as any).connect = service.connect.bind(service);
93
+ (instance as any).getInfo = service.getInfo.bind(service);
94
+ return instance;
95
+ }
96
+ );
97
+ console.log(' ✅ SQLite database (development) registered');
98
+
99
+ // Cache services
100
+ registry.createInstance(
101
+ ['cache', 'redis'],
102
+ ['production'],
103
+ (coordinate, context) => {
104
+ const service = new CacheService('Redis');
105
+ const instance = createInstance(context.registry, coordinate);
106
+ (instance as any).get = service.get.bind(service);
107
+ (instance as any).getInfo = service.getInfo.bind(service);
108
+ return instance;
109
+ }
110
+ );
111
+ console.log(' ✅ Redis cache (production) registered');
112
+
113
+ registry.createInstance(
114
+ ['cache', 'memory'],
115
+ ['development', 'testing'],
116
+ (coordinate, context) => {
117
+ const service = new CacheService('In-Memory');
118
+ const instance = createInstance(context.registry, coordinate);
119
+ (instance as any).get = service.get.bind(service);
120
+ (instance as any).getInfo = service.getInfo.bind(service);
121
+ return instance;
122
+ }
123
+ );
124
+ console.log(' ✅ Memory cache (development/testing) registered');
125
+
126
+ // Logging services
127
+ registry.createInstance(
128
+ ['logging'],
129
+ ['production'],
130
+ (coordinate, context) => {
131
+ const service = new LoggingService('error');
132
+ const instance = createInstance(context.registry, coordinate);
133
+ (instance as any).log = service.log.bind(service);
134
+ (instance as any).getInfo = service.getInfo.bind(service);
135
+ return instance;
136
+ }
137
+ );
138
+ console.log(' ✅ Error logging (production) registered');
139
+
140
+ registry.createInstance(
141
+ ['logging'],
142
+ ['development'],
143
+ (coordinate, context) => {
144
+ const service = new LoggingService('debug');
145
+ const instance = createInstance(context.registry, coordinate);
146
+ (instance as any).log = service.log.bind(service);
147
+ (instance as any).getInfo = service.getInfo.bind(service);
148
+ return instance;
149
+ }
150
+ );
151
+ console.log(' ✅ Debug logging (development) registered\n');
152
+
153
+ // Step 3: Demonstrate getCoordinates functionality
154
+ console.log('3. Discovering all registered coordinates...\n');
155
+
156
+ const coordinates = registry.getCoordinates();
157
+ console.log(`📊 Total registered coordinates: ${coordinates.length}\n`);
158
+
159
+ // Display all coordinates with their details
160
+ console.log('📍 Registered Coordinates:');
161
+ console.log('─'.repeat(60));
162
+ coordinates.forEach((coord, index) => {
163
+ console.log(`${index + 1}. ${coord.toString()}`);
164
+ console.log(` Key Path: [${coord.kta.join(' → ')}]`);
165
+ console.log(` Scopes: ${coord.scopes.length > 0 ? coord.scopes.join(', ') : 'none'}`);
166
+ console.log('');
167
+ });
168
+
169
+ // Step 4: Demonstrate filtering and analysis
170
+ console.log('4. Analyzing coordinate patterns...\n');
171
+
172
+ // Group by environment
173
+ const byEnvironment = {
174
+ production: coordinates.filter(c => c.scopes.includes('production')),
175
+ development: coordinates.filter(c => c.scopes.includes('development')),
176
+ testing: coordinates.filter(c => c.scopes.includes('testing')),
177
+ unscoped: coordinates.filter(c => c.scopes.length === 0)
178
+ };
179
+
180
+ console.log('🏢 Coordinates by Environment:');
181
+ Object.entries(byEnvironment).forEach(([env, coords]) => {
182
+ if (coords.length > 0) {
183
+ console.log(` ${env}: ${coords.length} instance(s)`);
184
+ coords.forEach(coord => {
185
+ console.log(` - ${coord.kta.join('.')}`);
186
+ });
187
+ }
188
+ });
189
+
190
+ // Group by service type (first element of kta)
191
+ const byServiceType = coordinates.reduce((acc, coord) => {
192
+ const serviceType = coord.kta[0];
193
+ if (!acc[serviceType]) acc[serviceType] = [];
194
+ acc[serviceType].push(coord);
195
+ return acc;
196
+ }, {} as Record<string, typeof coordinates>);
197
+
198
+ console.log('\n🔧 Coordinates by Service Type:');
199
+ Object.entries(byServiceType).forEach(([type, coords]) => {
200
+ console.log(` ${type}: ${coords.length} instance(s)`);
201
+ coords.forEach(coord => {
202
+ const scopeInfo = coord.scopes.length > 0 ? ` (${coord.scopes.join(', ')})` : '';
203
+ console.log(` - ${coord.kta.join('.')}${scopeInfo}`);
204
+ });
205
+ });
206
+
207
+ // Step 5: Demonstrate practical usage scenarios
208
+ console.log('\n5. Practical usage scenarios...\n');
209
+
210
+ // Scenario 1: Health check - verify all expected services are registered
211
+ console.log('🏥 Health Check Example:');
212
+ const expectedServices = ['database', 'cache', 'logging'];
213
+ const registeredServices = [...new Set(coordinates.map(c => c.kta[0]))];
214
+
215
+ expectedServices.forEach(service => {
216
+ const isRegistered = registeredServices.includes(service);
217
+ console.log(` ${service}: ${isRegistered ? '✅ Registered' : '❌ Missing'}`);
218
+ });
219
+
220
+ // Scenario 2: Environment validation
221
+ console.log('\n🌍 Environment Validation:');
222
+ const productionServices = coordinates.filter(c => c.scopes.includes('production'));
223
+ const developmentServices = coordinates.filter(c => c.scopes.includes('development'));
224
+
225
+ console.log(` Production environment has ${productionServices.length} service(s) registered`);
226
+ console.log(` Development environment has ${developmentServices.length} service(s) registered`);
227
+
228
+ // Scenario 3: Discovery mechanism
229
+ console.log('\n🔍 Service Discovery Example:');
230
+ console.log(' Available cache services:');
231
+ coordinates
232
+ .filter(c => c.kta.includes('cache'))
233
+ .forEach(coord => {
234
+ console.log(` - ${coord.kta.join('.')} (${coord.scopes.join(', ') || 'any scope'})`);
235
+ });
236
+
237
+ console.log('\n✨ Coordinates discovery example completed!');
238
+
239
+ return {
240
+ totalCoordinates: coordinates.length,
241
+ coordinates: coordinates,
242
+ byEnvironment,
243
+ byServiceType
244
+ };
245
+ }
246
+
247
+ // Export for testing
248
+ export { runCoordinatesExample };
249
+
250
+ // Run the example if this file is executed directly
251
+ if (import.meta.url === `file://${process.argv[1]}`) {
252
+ runCoordinatesExample().catch(console.error);
253
+ }
@@ -0,0 +1,370 @@
1
+ /**
2
+ * RegistryHub Coordinates Discovery Example
3
+ *
4
+ * This example demonstrates how to use the getAllCoordinates() method on RegistryHub to:
5
+ * - Discover all registered instances across multiple registries
6
+ * - See which registry type contains each coordinate
7
+ * - Analyze cross-registry service architecture
8
+ * - Implement system-wide monitoring and discovery
9
+ * - Validate service deployment across different domains
10
+ *
11
+ * Run this example with: npx tsx examples/registry-hub-coordinates-example.ts
12
+ *
13
+ * Note: In a real application, import from the built package:
14
+ * import { createRegistryHub, createRegistry, createInstance } from '@fjell/registry';
15
+ */
16
+
17
+ // Import the actual registry functionality
18
+ import { createRegistryHub } from '../src/RegistryHub';
19
+ import { createRegistry } from '../src/Registry';
20
+ import { createInstance } from '../src/Instance';
21
+
22
+ // ===== Service Examples =====
23
+
24
+ class AuthService {
25
+ constructor(private provider: string, private environment: string) { }
26
+
27
+ authenticate(token: string) { // eslint-disable-line @typescript-eslint/no-unused-vars
28
+ console.log(`Authenticating with ${this.provider} in ${this.environment}`);
29
+ return { userId: 'user123', provider: this.provider };
30
+ }
31
+
32
+ getInfo() {
33
+ return `${this.provider} Auth (${this.environment})`;
34
+ }
35
+ }
36
+
37
+ class DataRepository {
38
+ constructor(private database: string, private table: string) { }
39
+
40
+ save(data: any) {
41
+ console.log(`Saving to ${this.database}.${this.table}:`, data);
42
+ return { id: 'saved123', database: this.database };
43
+ }
44
+
45
+ getInfo() {
46
+ return `${this.database} Repository for ${this.table}`;
47
+ }
48
+ }
49
+
50
+ class CacheStore {
51
+ constructor(private type: string, private ttl: number) { }
52
+
53
+ set(key: string, value: any) { // eslint-disable-line @typescript-eslint/no-unused-vars
54
+ console.log(`Caching ${key} in ${this.type} for ${this.ttl}s`);
55
+ return { cached: true, type: this.type };
56
+ }
57
+
58
+ getInfo() {
59
+ return `${this.type} Cache (TTL: ${this.ttl}s)`;
60
+ }
61
+ }
62
+
63
+ class IntegrationService {
64
+ constructor(private provider: string, private version: string) { }
65
+
66
+ call(endpoint: string, data: any) { // eslint-disable-line @typescript-eslint/no-unused-vars
67
+ console.log(`Calling ${this.provider} v${this.version} at ${endpoint}`);
68
+ return { success: true, provider: this.provider };
69
+ }
70
+
71
+ getInfo() {
72
+ return `${this.provider} Integration v${this.version}`;
73
+ }
74
+ }
75
+
76
+ // ===== Main Example =====
77
+
78
+ async function runRegistryHubCoordinatesExample() {
79
+ console.log('🌐 RegistryHub Coordinates Discovery Example\n');
80
+
81
+ // Step 1: Create RegistryHub and multiple registries
82
+ console.log('1. Creating RegistryHub and domain-specific registries...');
83
+ const hub = createRegistryHub();
84
+
85
+ const authRegistry = createRegistry('auth');
86
+ const dataRegistry = createRegistry('data');
87
+ const cacheRegistry = createRegistry('cache');
88
+ const integrationsRegistry = createRegistry('integrations');
89
+
90
+ console.log(' ✅ RegistryHub created');
91
+ console.log(' ✅ 4 domain registries created\n');
92
+
93
+ // Step 2: Register all registries in the hub
94
+ console.log('2. Registering registries in the hub...');
95
+ hub.registerRegistry(authRegistry);
96
+ hub.registerRegistry(dataRegistry);
97
+ hub.registerRegistry(cacheRegistry);
98
+ hub.registerRegistry(integrationsRegistry);
99
+
100
+ console.log(' ✅ All registries registered in hub');
101
+ console.log(` 📊 Registered registry types: ${hub.getRegisteredTypes().join(', ')}\n`);
102
+
103
+ // Step 3: Create instances across different registries and environments
104
+ console.log('3. Creating instances across multiple registries and environments...\n');
105
+
106
+ // Auth Registry - Different authentication providers
107
+ authRegistry.createInstance(
108
+ ['Auth', 'JWT'],
109
+ ['production', 'oauth'],
110
+ (coordinate, context) => {
111
+ const service = new AuthService('JWT', 'production');
112
+ const instance = createInstance(context.registry, coordinate);
113
+ (instance as any).authenticate = service.authenticate.bind(service);
114
+ (instance as any).getInfo = service.getInfo.bind(service);
115
+ return instance;
116
+ }
117
+ );
118
+ console.log(' ✅ JWT Auth (production) registered in auth registry');
119
+
120
+ authRegistry.createInstance(
121
+ ['Auth', 'SAML'],
122
+ ['production', 'enterprise'],
123
+ (coordinate, context) => {
124
+ const service = new AuthService('SAML', 'production');
125
+ const instance = createInstance(context.registry, coordinate);
126
+ (instance as any).authenticate = service.authenticate.bind(service);
127
+ (instance as any).getInfo = service.getInfo.bind(service);
128
+ return instance;
129
+ }
130
+ );
131
+ console.log(' ✅ SAML Auth (production) registered in auth registry');
132
+
133
+ authRegistry.createInstance(
134
+ ['Auth', 'Local'],
135
+ ['development', 'testing'],
136
+ (coordinate, context) => {
137
+ const service = new AuthService('Local', 'development');
138
+ const instance = createInstance(context.registry, coordinate);
139
+ (instance as any).authenticate = service.authenticate.bind(service);
140
+ (instance as any).getInfo = service.getInfo.bind(service);
141
+ return instance;
142
+ }
143
+ );
144
+ console.log(' ✅ Local Auth (development) registered in auth registry');
145
+
146
+ // Data Registry - Different databases and entities
147
+ dataRegistry.createInstance(
148
+ ['Repository', 'User'],
149
+ ['production', 'firestore'],
150
+ (coordinate, context) => {
151
+ const repo = new DataRepository('Firestore', 'users');
152
+ const instance = createInstance(context.registry, coordinate);
153
+ (instance as any).save = repo.save.bind(repo);
154
+ (instance as any).getInfo = repo.getInfo.bind(repo);
155
+ return instance;
156
+ }
157
+ );
158
+ console.log(' ✅ User Repository (Firestore/production) registered in data registry');
159
+
160
+ dataRegistry.createInstance(
161
+ ['Repository', 'User'],
162
+ ['development', 'postgresql'],
163
+ (coordinate, context) => {
164
+ const repo = new DataRepository('PostgreSQL', 'users');
165
+ const instance = createInstance(context.registry, coordinate);
166
+ (instance as any).save = repo.save.bind(repo);
167
+ (instance as any).getInfo = repo.getInfo.bind(repo);
168
+ return instance;
169
+ }
170
+ );
171
+ console.log(' ✅ User Repository (PostgreSQL/development) registered in data registry');
172
+
173
+ dataRegistry.createInstance(
174
+ ['Repository', 'Order'],
175
+ ['production', 'firestore'],
176
+ (coordinate, context) => {
177
+ const repo = new DataRepository('Firestore', 'orders');
178
+ const instance = createInstance(context.registry, coordinate);
179
+ (instance as any).save = repo.save.bind(repo);
180
+ (instance as any).getInfo = repo.getInfo.bind(repo);
181
+ return instance;
182
+ }
183
+ );
184
+ console.log(' ✅ Order Repository (Firestore/production) registered in data registry');
185
+
186
+ // Cache Registry - Different cache implementations
187
+ cacheRegistry.createInstance(
188
+ ['Cache', 'Session'],
189
+ ['production', 'redis'],
190
+ (coordinate, context) => {
191
+ const cache = new CacheStore('Redis', 3600);
192
+ const instance = createInstance(context.registry, coordinate);
193
+ (instance as any).set = cache.set.bind(cache);
194
+ (instance as any).getInfo = cache.getInfo.bind(cache);
195
+ return instance;
196
+ }
197
+ );
198
+ console.log(' ✅ Session Cache (Redis/production) registered in cache registry');
199
+
200
+ cacheRegistry.createInstance(
201
+ ['Cache', 'Query'],
202
+ ['production', 'memcached'],
203
+ (coordinate, context) => {
204
+ const cache = new CacheStore('Memcached', 1800);
205
+ const instance = createInstance(context.registry, coordinate);
206
+ (instance as any).set = cache.set.bind(cache);
207
+ (instance as any).getInfo = cache.getInfo.bind(cache);
208
+ return instance;
209
+ }
210
+ );
211
+ console.log(' ✅ Query Cache (Memcached/production) registered in cache registry');
212
+
213
+ cacheRegistry.createInstance(
214
+ ['Cache', 'Memory'],
215
+ ['development', 'local'],
216
+ (coordinate, context) => {
217
+ const cache = new CacheStore('In-Memory', 300);
218
+ const instance = createInstance(context.registry, coordinate);
219
+ (instance as any).set = cache.set.bind(cache);
220
+ (instance as any).getInfo = cache.getInfo.bind(cache);
221
+ return instance;
222
+ }
223
+ );
224
+ console.log(' ✅ Memory Cache (local/development) registered in cache registry');
225
+
226
+ // Integrations Registry - External service integrations
227
+ integrationsRegistry.createInstance(
228
+ ['Payment', 'Stripe'],
229
+ ['production', 'live'],
230
+ (coordinate, context) => {
231
+ const integration = new IntegrationService('Stripe', '2023-10');
232
+ const instance = createInstance(context.registry, coordinate);
233
+ (instance as any).call = integration.call.bind(integration);
234
+ (instance as any).getInfo = integration.getInfo.bind(integration);
235
+ return instance;
236
+ }
237
+ );
238
+ console.log(' ✅ Stripe Payment (production) registered in integrations registry');
239
+
240
+ integrationsRegistry.createInstance(
241
+ ['Email', 'SendGrid'],
242
+ ['production', 'v3'],
243
+ (coordinate, context) => {
244
+ const integration = new IntegrationService('SendGrid', '3.0');
245
+ const instance = createInstance(context.registry, coordinate);
246
+ (instance as any).call = integration.call.bind(integration);
247
+ (instance as any).getInfo = integration.getInfo.bind(integration);
248
+ return instance;
249
+ }
250
+ );
251
+ console.log(' ✅ SendGrid Email (production) registered in integrations registry');
252
+
253
+ // Step 4: Demonstrate getAllCoordinates functionality
254
+ console.log('\n4. Discovering all coordinates across the entire system...\n');
255
+
256
+ const allCoordinates = hub.getAllCoordinates();
257
+ console.log(`🔍 Total coordinates discovered: ${allCoordinates.length}`);
258
+ console.log(`📦 Across ${hub.getRegisteredTypes().length} registry types\n`);
259
+
260
+ // Display all coordinates grouped by registry type
261
+ console.log('📍 All Registered Coordinates by Registry Type:');
262
+ console.log('═'.repeat(80));
263
+
264
+ const coordinatesByRegistry = allCoordinates.reduce((acc, item) => {
265
+ if (!acc[item.registryType]) acc[item.registryType] = [];
266
+ acc[item.registryType].push(item);
267
+ return acc;
268
+ }, {} as Record<string, typeof allCoordinates>);
269
+
270
+ Object.entries(coordinatesByRegistry).forEach(([registryType, coords]) => {
271
+ console.log(`\n📋 ${registryType.toUpperCase()} REGISTRY (${coords.length} instances):`);
272
+ console.log('─'.repeat(60));
273
+ coords.forEach((item, index) => {
274
+ const coord = item.coordinate;
275
+ console.log(` ${index + 1}. ${coord.kta.join(' → ')}`);
276
+ console.log(` Scopes: ${coord.scopes.length > 0 ? coord.scopes.join(', ') : 'none'}`);
277
+ console.log(` Full: ${coord.toString()}`);
278
+ console.log('');
279
+ });
280
+ });
281
+
282
+ // Step 5: Demonstrate cross-registry analysis
283
+ console.log('5. Cross-Registry Architecture Analysis...\n');
284
+
285
+ // Environment analysis
286
+ const environments = ['production', 'development', 'testing'];
287
+ console.log('🌍 Environment Distribution:');
288
+ environments.forEach(env => {
289
+ const envCoords = allCoordinates.filter(c => c.coordinate.scopes.includes(env));
290
+ console.log(` ${env}: ${envCoords.length} service(s) across ${new Set(envCoords.map(c => c.registryType)).size} registry type(s)`);
291
+
292
+ const registryBreakdown = envCoords.reduce((acc, c) => {
293
+ acc[c.registryType] = (acc[c.registryType] || 0) + 1;
294
+ return acc;
295
+ }, {} as Record<string, number>);
296
+
297
+ Object.entries(registryBreakdown).forEach(([regType, count]) => {
298
+ console.log(` - ${regType}: ${count}`);
299
+ });
300
+ });
301
+
302
+ // Service type analysis
303
+ console.log('\n🔧 Service Architecture Overview:');
304
+ const serviceTypes = [...new Set(allCoordinates.map(c => c.coordinate.kta[0]))];
305
+ serviceTypes.forEach(serviceType => {
306
+ const serviceCoords = allCoordinates.filter(c => c.coordinate.kta[0] === serviceType);
307
+ const registries = [...new Set(serviceCoords.map(c => c.registryType))];
308
+ console.log(` ${serviceType}: ${serviceCoords.length} implementation(s) in ${registries.join(', ')} registr${registries.length === 1 ? 'y' : 'ies'}`);
309
+ });
310
+
311
+ // Step 6: Demonstrate practical usage scenarios
312
+ console.log('\n6. Practical Usage Scenarios...\n');
313
+
314
+ // Scenario 1: System health check
315
+ console.log('🏥 System Health Check:');
316
+ const criticalServices = ['Auth', 'Repository', 'Cache', 'Payment'];
317
+ criticalServices.forEach(service => {
318
+ const implementations = allCoordinates.filter(c => c.coordinate.kta.includes(service));
319
+ const status = implementations.length > 0 ? '✅ Available' : '❌ Missing';
320
+ const details = implementations.length > 0 ? `(${implementations.length} implementation(s))` : '';
321
+ console.log(` ${service}: ${status} ${details}`);
322
+ });
323
+
324
+ // Scenario 2: Production readiness check
325
+ console.log('\n🚀 Production Readiness Check:');
326
+ const productionCoords = allCoordinates.filter(c => c.coordinate.scopes.includes('production'));
327
+ const productionByRegistry = productionCoords.reduce((acc, c) => {
328
+ acc[c.registryType] = (acc[c.registryType] || 0) + 1;
329
+ return acc;
330
+ }, {} as Record<string, number>);
331
+
332
+ console.log(` Total production services: ${productionCoords.length}`);
333
+ Object.entries(productionByRegistry).forEach(([regType, count]) => {
334
+ console.log(` - ${regType}: ${count} production service(s)`);
335
+ });
336
+
337
+ // Scenario 3: Development environment completeness
338
+ console.log('\n💻 Development Environment Check:');
339
+ const devCoords = allCoordinates.filter(c => c.coordinate.scopes.includes('development'));
340
+ console.log(` Development services available: ${devCoords.length}`);
341
+
342
+ // Check if we have dev equivalents for production services
343
+ const prodServiceKeys = productionCoords.map(c => c.coordinate.kta.join('.'));
344
+ const devServiceKeys = devCoords.map(c => c.coordinate.kta.join('.'));
345
+
346
+ const missingDevServices = prodServiceKeys.filter(key => !devServiceKeys.includes(key));
347
+ if (missingDevServices.length > 0) {
348
+ console.log(' ⚠️ Missing development equivalents for:');
349
+ missingDevServices.forEach(service => console.log(` - ${service}`));
350
+ } else {
351
+ console.log(' ✅ All production services have development equivalents');
352
+ }
353
+
354
+ console.log('\n✨ RegistryHub coordinates discovery example completed!');
355
+
356
+ return {
357
+ totalCoordinates: allCoordinates.length,
358
+ coordinatesByRegistry,
359
+ registryTypes: hub.getRegisteredTypes(),
360
+ allCoordinates
361
+ };
362
+ }
363
+
364
+ // Export for testing
365
+ export { runRegistryHubCoordinatesExample };
366
+
367
+ // Run the example if this file is executed directly
368
+ if (import.meta.url === `file://${process.argv[1]}`) {
369
+ runRegistryHubCoordinatesExample().catch(console.error);
370
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fjell/registry",
3
- "version": "4.4.7",
3
+ "version": "4.4.10",
4
4
  "keywords": [
5
5
  "registry",
6
6
  "fjell"