@fjell/registry 4.4.52 ā 4.4.53
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/package.json +4 -4
- package/API.md +0 -62
- package/GETTING_STARTED.md +0 -69
- package/build.js +0 -38
- package/docs/README.md +0 -74
- package/docs/TIMING_NODE_OPTIMIZATION.md +0 -207
- package/docs/TIMING_README.md +0 -170
- package/docs/docs.config.ts +0 -114
- package/docs/index.html +0 -26
- package/docs/package-lock.json +0 -5129
- package/docs/package.json +0 -34
- package/docs/public/404.html +0 -53
- package/docs/public/GETTING_STARTED.md +0 -69
- package/docs/public/README.md +0 -623
- package/docs/public/TIMING_NODE_OPTIMIZATION.md +0 -207
- package/docs/public/api.md +0 -62
- package/docs/public/client-api-overview.md +0 -137
- package/docs/public/configuration.md +0 -759
- package/docs/public/error-handling/README.md +0 -356
- package/docs/public/error-handling/network-errors.md +0 -485
- package/docs/public/examples/coordinates-example.ts +0 -253
- package/docs/public/examples/multi-level-keys.ts +0 -374
- package/docs/public/examples/registry-hub-coordinates-example.ts +0 -370
- package/docs/public/examples/registry-hub-types.ts +0 -437
- package/docs/public/examples/simple-example.ts +0 -250
- package/docs/public/examples-README.md +0 -241
- package/docs/public/fjell-icon.svg +0 -1
- package/docs/public/icon.png +0 -0
- package/docs/public/icon2.png +0 -0
- package/docs/public/memory-overhead.svg +0 -120
- package/docs/public/memory.md +0 -430
- package/docs/public/operations/README.md +0 -121
- package/docs/public/operations/all.md +0 -325
- package/docs/public/operations/create.md +0 -415
- package/docs/public/operations/get.md +0 -389
- package/docs/public/package.json +0 -63
- package/docs/public/pano.png +0 -0
- package/docs/public/pano2.png +0 -0
- package/docs/public/timing-range.svg +0 -176
- package/docs/public/timing.md +0 -483
- package/docs/timing-range.svg +0 -174
- package/docs/vitest.config.ts +0 -14
- package/examples/README.md +0 -241
- package/examples/coordinates-example.ts +0 -253
- package/examples/multi-level-keys.ts +0 -382
- package/examples/registry-hub-coordinates-example.ts +0 -370
- package/examples/registry-hub-types.ts +0 -437
- package/examples/registry-statistics-example.ts +0 -264
- package/examples/simple-example.ts +0 -250
- package/tsconfig.docs.json +0 -28
- package/vitest.config.ts +0 -22
|
@@ -1,264 +0,0 @@
|
|
|
1
|
-
import { createRegistry, Instance } from '../src';
|
|
2
|
-
import { ServiceClient } from '../src/RegistryStats';
|
|
3
|
-
|
|
4
|
-
export async function runRegistryStatisticsExample() {
|
|
5
|
-
// Example demonstrating Registry statistics tracking with scopes
|
|
6
|
-
console.log('=== Registry Statistics Tracking with Scopes Example ===\n');
|
|
7
|
-
|
|
8
|
-
// Create a registry
|
|
9
|
-
const registry = createRegistry('services');
|
|
10
|
-
|
|
11
|
-
// Create some mock instances for different environments
|
|
12
|
-
const authProdService: Instance<'auth'> = {
|
|
13
|
-
coordinate: { kta: ['auth'], scopes: ['production'] } as any,
|
|
14
|
-
registry: registry as any,
|
|
15
|
-
} as any;
|
|
16
|
-
|
|
17
|
-
const authDevService: Instance<'auth'> = {
|
|
18
|
-
coordinate: { kta: ['auth'], scopes: ['development'] } as any,
|
|
19
|
-
registry: registry as any,
|
|
20
|
-
} as any;
|
|
21
|
-
|
|
22
|
-
const userProdService: Instance<'user'> = {
|
|
23
|
-
coordinate: { kta: ['user'], scopes: ['production', 'sql'] } as any,
|
|
24
|
-
registry: registry as any,
|
|
25
|
-
} as any;
|
|
26
|
-
|
|
27
|
-
const userDevService: Instance<'user'> = {
|
|
28
|
-
coordinate: { kta: ['user'], scopes: ['development', 'nosql'] } as any,
|
|
29
|
-
registry: registry as any,
|
|
30
|
-
} as any;
|
|
31
|
-
|
|
32
|
-
const cacheService: Instance<'cache', 'redis'> = {
|
|
33
|
-
coordinate: { kta: ['cache', 'redis'], scopes: [] } as any,
|
|
34
|
-
registry: registry as any,
|
|
35
|
-
} as any;
|
|
36
|
-
|
|
37
|
-
// Register the services with different scopes
|
|
38
|
-
registry.register(['auth'], authProdService, { scopes: ['production'] });
|
|
39
|
-
registry.register(['auth'], authDevService, { scopes: ['development'] });
|
|
40
|
-
registry.register(['user'], userProdService, { scopes: ['production', 'sql'] });
|
|
41
|
-
registry.register(['user'], userDevService, { scopes: ['development', 'nosql'] });
|
|
42
|
-
registry.register(['cache', 'redis'], cacheService); // No scopes
|
|
43
|
-
|
|
44
|
-
// Check initial statistics
|
|
45
|
-
let stats = registry.getStatistics();
|
|
46
|
-
console.log('Initial statistics:');
|
|
47
|
-
console.log(`Total get calls: ${stats.totalGetCalls}`);
|
|
48
|
-
console.log(`Coordinate call records: ${stats.coordinateCallRecords.length} entries`);
|
|
49
|
-
console.log('');
|
|
50
|
-
|
|
51
|
-
// Use the services with different scope combinations and clients
|
|
52
|
-
console.log('Making service calls with different scopes and clients...');
|
|
53
|
-
|
|
54
|
-
// Application calls (direct calls from the application)
|
|
55
|
-
registry.get(['auth'], { scopes: ['production'], client: 'MyWebApp' });
|
|
56
|
-
registry.get(['auth'], { scopes: ['development'], client: 'MyWebApp' });
|
|
57
|
-
registry.get(['auth'], { scopes: ['production'], client: 'MyWebApp' }); // Same app, second call
|
|
58
|
-
|
|
59
|
-
// Service-to-service calls (simulated by specifying service clients)
|
|
60
|
-
const orderServiceClient: ServiceClient = {
|
|
61
|
-
registryType: 'services',
|
|
62
|
-
coordinate: { kta: ['order'], scopes: ['business'] }
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
const paymentServiceClient: ServiceClient = {
|
|
66
|
-
registryType: 'services',
|
|
67
|
-
coordinate: { kta: ['payment'], scopes: ['stripe'] }
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
registry.get(['user'], { scopes: ['production', 'sql'], client: orderServiceClient });
|
|
71
|
-
registry.get(['user'], { scopes: ['sql', 'production'], client: orderServiceClient }); // Same service, scope order normalized
|
|
72
|
-
registry.get(['user'], { scopes: ['development', 'nosql'], client: paymentServiceClient });
|
|
73
|
-
|
|
74
|
-
// Mixed calls - some with no client specified
|
|
75
|
-
registry.get(['cache', 'redis']); // No client specified
|
|
76
|
-
registry.get(['cache', 'redis'], { client: 'CacheUtility' }); // Application client
|
|
77
|
-
|
|
78
|
-
// More service-to-service calls
|
|
79
|
-
registry.get(['auth'], { scopes: ['production'], client: orderServiceClient });
|
|
80
|
-
registry.get(['cache', 'redis'], { client: paymentServiceClient });
|
|
81
|
-
|
|
82
|
-
// Check updated statistics
|
|
83
|
-
stats = registry.getStatistics();
|
|
84
|
-
console.log('\nStatistics after service calls:');
|
|
85
|
-
console.log(`Total get calls: ${stats.totalGetCalls}`);
|
|
86
|
-
console.log('\nClient Summary:');
|
|
87
|
-
console.log(` Service-to-service calls: ${stats.clientSummary.serviceCalls}`);
|
|
88
|
-
console.log(` Application calls: ${stats.clientSummary.applicationCalls}`);
|
|
89
|
-
console.log(` Unidentified calls: ${stats.clientSummary.unidentifiedCalls}`);
|
|
90
|
-
console.log('\nDetailed coordinate call records:');
|
|
91
|
-
|
|
92
|
-
// Display statistics for each coordinate/scope combination with client breakdown
|
|
93
|
-
stats.coordinateCallRecords.forEach((record, index) => {
|
|
94
|
-
const ktaDisplay = record.kta.join(' ā ');
|
|
95
|
-
const scopesDisplay = record.scopes.length > 0 ? record.scopes.join(', ') : 'no scopes';
|
|
96
|
-
console.log(` ${index + 1}. ${ktaDisplay} [${scopesDisplay}]: ${record.count} calls`);
|
|
97
|
-
|
|
98
|
-
// Show client breakdown
|
|
99
|
-
record.clientCalls.forEach((clientCall, clientIndex) => {
|
|
100
|
-
if (typeof clientCall.client === 'string') {
|
|
101
|
-
console.log(` ${clientIndex + 1}a. App "${clientCall.client}": ${clientCall.count} calls`);
|
|
102
|
-
} else if (clientCall.client) {
|
|
103
|
-
const serviceDisplay = clientCall.client.coordinate.kta.join('.');
|
|
104
|
-
const serviceScopeDisplay = clientCall.client.coordinate.scopes.join(', ');
|
|
105
|
-
console.log(` ${clientIndex + 1}b. Service ${clientCall.client.registryType}/${serviceDisplay}[${serviceScopeDisplay}]: ${clientCall.count} calls`);
|
|
106
|
-
} else {
|
|
107
|
-
console.log(` ${clientIndex + 1}c. Unidentified client: ${clientCall.count} calls`);
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
// Analysis by coordinate (aggregating across scopes)
|
|
113
|
-
console.log('\nAggregated analysis by coordinate:');
|
|
114
|
-
const coordinateMap = new Map<string, number>();
|
|
115
|
-
|
|
116
|
-
stats.coordinateCallRecords.forEach(record => {
|
|
117
|
-
const ktaKey = record.kta.join('.');
|
|
118
|
-
coordinateMap.set(ktaKey, (coordinateMap.get(ktaKey) || 0) + record.count);
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
for (const [coordinate, totalCalls] of coordinateMap) {
|
|
122
|
-
console.log(` ${coordinate}: ${totalCalls} total calls`);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Find the most accessed coordinate/scope combination
|
|
126
|
-
let mostAccessedRecord = stats.coordinateCallRecords[0];
|
|
127
|
-
for (const record of stats.coordinateCallRecords) {
|
|
128
|
-
if (record.count > mostAccessedRecord.count) {
|
|
129
|
-
mostAccessedRecord = record;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
if (mostAccessedRecord) {
|
|
134
|
-
const ktaDisplay = mostAccessedRecord.kta.join(' ā ');
|
|
135
|
-
const scopesDisplay = mostAccessedRecord.scopes.length > 0
|
|
136
|
-
? mostAccessedRecord.scopes.join(', ')
|
|
137
|
-
: 'no scopes';
|
|
138
|
-
console.log(`\nMost accessed: ${ktaDisplay} [${scopesDisplay}] (${mostAccessedRecord.count} calls)`);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// Environment-based analysis with client types
|
|
142
|
-
console.log('\nEnvironment-based analysis:');
|
|
143
|
-
let prodCalls = 0;
|
|
144
|
-
let devCalls = 0;
|
|
145
|
-
let noScopeCalls = 0;
|
|
146
|
-
let prodAppCalls = 0;
|
|
147
|
-
let prodServiceCalls = 0;
|
|
148
|
-
let devAppCalls = 0;
|
|
149
|
-
let devServiceCalls = 0;
|
|
150
|
-
|
|
151
|
-
stats.coordinateCallRecords.forEach(record => {
|
|
152
|
-
if (record.scopes.includes('production')) {
|
|
153
|
-
prodCalls += record.count;
|
|
154
|
-
record.clientCalls.forEach(clientCall => {
|
|
155
|
-
if (typeof clientCall.client === 'string') {
|
|
156
|
-
prodAppCalls += clientCall.count;
|
|
157
|
-
} else if (clientCall.client) {
|
|
158
|
-
prodServiceCalls += clientCall.count;
|
|
159
|
-
}
|
|
160
|
-
});
|
|
161
|
-
} else if (record.scopes.includes('development')) {
|
|
162
|
-
devCalls += record.count;
|
|
163
|
-
record.clientCalls.forEach(clientCall => {
|
|
164
|
-
if (typeof clientCall.client === 'string') {
|
|
165
|
-
devAppCalls += clientCall.count;
|
|
166
|
-
} else if (clientCall.client) {
|
|
167
|
-
devServiceCalls += clientCall.count;
|
|
168
|
-
}
|
|
169
|
-
});
|
|
170
|
-
} else if (record.scopes.length === 0) {
|
|
171
|
-
noScopeCalls += record.count;
|
|
172
|
-
}
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
console.log(` Production services: ${prodCalls} calls (${prodAppCalls} from apps, ${prodServiceCalls} from services)`);
|
|
176
|
-
console.log(` Development services: ${devCalls} calls (${devAppCalls} from apps, ${devServiceCalls} from services)`);
|
|
177
|
-
console.log(` Unscoped services: ${noScopeCalls} calls`);
|
|
178
|
-
|
|
179
|
-
// Demonstrate immutability
|
|
180
|
-
console.log('\nTesting immutability of returned statistics...');
|
|
181
|
-
const stats1 = registry.getStatistics();
|
|
182
|
-
const stats2 = registry.getStatistics();
|
|
183
|
-
|
|
184
|
-
console.log(`Are record arrays the same object? ${stats1.coordinateCallRecords === stats2.coordinateCallRecords}`);
|
|
185
|
-
console.log('(Should be false - each call returns a new array to prevent external mutation)');
|
|
186
|
-
|
|
187
|
-
// Try to modify the returned records (this won't affect the internal tracking)
|
|
188
|
-
if (stats1.coordinateCallRecords.length > 0) {
|
|
189
|
-
const originalCount = stats1.coordinateCallRecords[0].count;
|
|
190
|
-
stats1.coordinateCallRecords[0].count = 999;
|
|
191
|
-
|
|
192
|
-
const stats3 = registry.getStatistics();
|
|
193
|
-
console.log(`After trying to modify returned data, original count preserved? ${stats3.coordinateCallRecords[0].count === originalCount}`);
|
|
194
|
-
console.log('(Should be true - internal tracking is protected from external mutation)');
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
console.log('\n=== Advanced Statistics Example Complete ===');
|
|
198
|
-
|
|
199
|
-
// Demonstration of automatic service-to-service tracking via factory Registry
|
|
200
|
-
console.log('\n=== Automatic Service-to-Service Tracking Demo ===');
|
|
201
|
-
|
|
202
|
-
// Create a service that uses other services through the Registry passed to its factory
|
|
203
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
204
|
-
const orderProcessorService = registry.createInstance(['order', 'processor'], ['business'], (coordinate, context) => {
|
|
205
|
-
// The registry passed here is proxied to automatically track this service as the client
|
|
206
|
-
|
|
207
|
-
// When this service calls get() on the registry, it will automatically be tracked
|
|
208
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
209
|
-
const authService = context.registry.get(['auth'], { scopes: ['production'] });
|
|
210
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
211
|
-
const userService = context.registry.get(['user'], { scopes: ['production', 'sql'] });
|
|
212
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
213
|
-
const cacheService = context.registry.get(['cache', 'redis']);
|
|
214
|
-
|
|
215
|
-
console.log('Order processor created and retrieved dependencies automatically tracked!');
|
|
216
|
-
|
|
217
|
-
return {
|
|
218
|
-
coordinate,
|
|
219
|
-
registry: context.registry,
|
|
220
|
-
processOrder: (orderId: string) => {
|
|
221
|
-
console.log(`Processing order ${orderId} with dependencies`);
|
|
222
|
-
return { success: true, orderId };
|
|
223
|
-
}
|
|
224
|
-
};
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
// Get final statistics to show the automatic tracking
|
|
228
|
-
const finalStats = registry.getStatistics();
|
|
229
|
-
console.log(`\nAfter service creation with automatic tracking:`);
|
|
230
|
-
console.log(`Total get calls: ${finalStats.totalGetCalls}`);
|
|
231
|
-
console.log(`Service-to-service calls: ${finalStats.clientSummary.serviceCalls}`);
|
|
232
|
-
|
|
233
|
-
// Show the new automatically tracked calls
|
|
234
|
-
console.log('\nNew automatically tracked service calls:');
|
|
235
|
-
finalStats.coordinateCallRecords.forEach(record => {
|
|
236
|
-
record.clientCalls.forEach(clientCall => {
|
|
237
|
-
if (clientCall.client && typeof clientCall.client !== 'string' &&
|
|
238
|
-
clientCall.client.coordinate.kta.includes('order') &&
|
|
239
|
-
clientCall.client.coordinate.kta.includes('processor')) {
|
|
240
|
-
const ktaDisplay = record.kta.join(' ā ');
|
|
241
|
-
const scopesDisplay = record.scopes.length > 0 ? record.scopes.join(', ') : 'no scopes';
|
|
242
|
-
console.log(` ${ktaDisplay} [${scopesDisplay}] called by order.processor service: ${clientCall.count} calls`);
|
|
243
|
-
}
|
|
244
|
-
});
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
console.log('\n=== Automatic Tracking Demo Complete ===');
|
|
248
|
-
|
|
249
|
-
// Return key statistics for testing
|
|
250
|
-
return {
|
|
251
|
-
totalGetCalls: finalStats.totalGetCalls,
|
|
252
|
-
coordinateCallRecords: finalStats.coordinateCallRecords.length,
|
|
253
|
-
mostAccessedCount: mostAccessedRecord ? mostAccessedRecord.count : 0,
|
|
254
|
-
prodCalls,
|
|
255
|
-
devCalls,
|
|
256
|
-
noScopeCalls,
|
|
257
|
-
clientSummary: finalStats.clientSummary
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// Run the example if this file is executed directly
|
|
262
|
-
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
263
|
-
runRegistryStatisticsExample().catch(console.error);
|
|
264
|
-
}
|
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Simple Registry Example - No RegistryHub, No Scopes
|
|
3
|
-
*
|
|
4
|
-
* This example demonstrates the simplest possible way to use the Registry library:
|
|
5
|
-
* - Create a registry without a RegistryHub
|
|
6
|
-
* - Register instances without any scopes
|
|
7
|
-
* - Retrieve instances without any scopes
|
|
8
|
-
* - Perfect for simple applications that just need basic dependency injection
|
|
9
|
-
*
|
|
10
|
-
* Run this example with: npx tsx examples/simple-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
|
-
// ===== Simple Service Examples =====
|
|
21
|
-
|
|
22
|
-
// Example 1: A simple logger service
|
|
23
|
-
class SimpleLogger {
|
|
24
|
-
log(message: string) {
|
|
25
|
-
console.log(`[LOG] ${new Date().toISOString()}: ${message}`);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
error(message: string) {
|
|
29
|
-
console.error(`[ERROR] ${new Date().toISOString()}: ${message}`);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Example 2: A simple configuration service
|
|
34
|
-
class SimpleConfig {
|
|
35
|
-
private config = {
|
|
36
|
-
appName: 'My Simple App',
|
|
37
|
-
version: '1.0.0',
|
|
38
|
-
debugMode: true
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
get(key: string): any {
|
|
42
|
-
return this.config[key as keyof typeof this.config];
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
set(key: string, value: any): void {
|
|
46
|
-
(this.config as any)[key] = value;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Example 3: A simple data service
|
|
51
|
-
class SimpleDataService {
|
|
52
|
-
private data: string[] = [];
|
|
53
|
-
|
|
54
|
-
add(item: string): void {
|
|
55
|
-
this.data.push(item);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
getAll(): string[] {
|
|
59
|
-
return [...this.data];
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
count(): number {
|
|
63
|
-
return this.data.length;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// ===== Main Example =====
|
|
68
|
-
|
|
69
|
-
async function runSimpleExample() {
|
|
70
|
-
console.log('š Simple Registry Example - No RegistryHub, No Scopes\n');
|
|
71
|
-
|
|
72
|
-
// Step 1: Create a simple registry (no RegistryHub needed!)
|
|
73
|
-
console.log('1. Creating a simple registry...');
|
|
74
|
-
const registry = createRegistry('app');
|
|
75
|
-
console.log(' ā
Registry created with type: "app"\n');
|
|
76
|
-
|
|
77
|
-
// Step 2: Create instances using factories (no scopes needed!)
|
|
78
|
-
console.log('2. Creating and registering instances...');
|
|
79
|
-
|
|
80
|
-
// Logger instance
|
|
81
|
-
registry.createInstance(
|
|
82
|
-
['logger'],
|
|
83
|
-
[], // Empty scopes array - we don't need scopes!
|
|
84
|
-
(coordinate, context) => {
|
|
85
|
-
// Create the actual service
|
|
86
|
-
const service = new SimpleLogger();
|
|
87
|
-
|
|
88
|
-
// Create and return an instance that wraps the service
|
|
89
|
-
const instance = createInstance(context.registry, coordinate);
|
|
90
|
-
// Attach service methods to the instance for easy access
|
|
91
|
-
(instance as any).log = service.log.bind(service);
|
|
92
|
-
(instance as any).error = service.error.bind(service);
|
|
93
|
-
return instance;
|
|
94
|
-
}
|
|
95
|
-
);
|
|
96
|
-
console.log(' ā
Logger instance created and registered');
|
|
97
|
-
|
|
98
|
-
// Config instance
|
|
99
|
-
registry.createInstance(
|
|
100
|
-
['config'],
|
|
101
|
-
[], // No scopes needed
|
|
102
|
-
(coordinate, context) => {
|
|
103
|
-
const service = new SimpleConfig();
|
|
104
|
-
const instance = createInstance(context.registry, coordinate);
|
|
105
|
-
(instance as any).get = service.get.bind(service);
|
|
106
|
-
(instance as any).set = service.set.bind(service);
|
|
107
|
-
return instance;
|
|
108
|
-
}
|
|
109
|
-
);
|
|
110
|
-
console.log(' ā
Config instance created and registered');
|
|
111
|
-
|
|
112
|
-
// Data service instance
|
|
113
|
-
registry.createInstance(
|
|
114
|
-
['data'],
|
|
115
|
-
[], // No scopes needed
|
|
116
|
-
(coordinate, context) => {
|
|
117
|
-
const service = new SimpleDataService();
|
|
118
|
-
const instance = createInstance(context.registry, coordinate);
|
|
119
|
-
(instance as any).add = service.add.bind(service);
|
|
120
|
-
(instance as any).getAll = service.getAll.bind(service);
|
|
121
|
-
(instance as any).count = service.count.bind(service);
|
|
122
|
-
return instance;
|
|
123
|
-
}
|
|
124
|
-
);
|
|
125
|
-
console.log(' ā
Data service instance created and registered\n');
|
|
126
|
-
|
|
127
|
-
// Step 3: Retrieve instances (no scopes needed!)
|
|
128
|
-
console.log('3. Retrieving instances from registry...');
|
|
129
|
-
|
|
130
|
-
const retrievedLogger = registry.get(['logger']); // No scopes parameter needed!
|
|
131
|
-
const retrievedConfig = registry.get(['config']); // No scopes parameter needed!
|
|
132
|
-
const retrievedData = registry.get(['data']); // No scopes parameter needed!
|
|
133
|
-
|
|
134
|
-
console.log(' ā
All instances retrieved successfully\n');
|
|
135
|
-
|
|
136
|
-
// Step 4: Verify everything works
|
|
137
|
-
console.log('4. Verifying the registry works...');
|
|
138
|
-
|
|
139
|
-
if (retrievedLogger && retrievedConfig && retrievedData) {
|
|
140
|
-
console.log(' ā
All instances found in registry');
|
|
141
|
-
console.log(` š Logger coordinate: ${JSON.stringify(retrievedLogger.coordinate)}`);
|
|
142
|
-
console.log(` š Config coordinate: ${JSON.stringify(retrievedConfig.coordinate)}`);
|
|
143
|
-
console.log(` š Data coordinate: ${JSON.stringify(retrievedData.coordinate)}\n`);
|
|
144
|
-
} else {
|
|
145
|
-
console.log(' ā Some instances were not found');
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Step 5: Show practical usage
|
|
150
|
-
console.log('5. Practical usage example...');
|
|
151
|
-
console.log(' In a real app, you would extend the instances with your actual services:');
|
|
152
|
-
console.log(' - Attach your service methods to the instance');
|
|
153
|
-
console.log(' - Use the registry to get dependencies between services');
|
|
154
|
-
console.log(' - Access instances from anywhere in your app\n');
|
|
155
|
-
|
|
156
|
-
// Step 6: Demonstrate the services actually work!
|
|
157
|
-
console.log('6. Testing the services...');
|
|
158
|
-
|
|
159
|
-
// Test the logger
|
|
160
|
-
const logger = registry.get(['logger']);
|
|
161
|
-
if (logger) {
|
|
162
|
-
(logger as any).log('This is a test log message from the registry!');
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// Test the config
|
|
166
|
-
const config = registry.get(['config']);
|
|
167
|
-
if (config) {
|
|
168
|
-
console.log(` š App name from config: ${(config as any).get('appName')}`);
|
|
169
|
-
(config as any).set('newProperty', 'This was set dynamically!');
|
|
170
|
-
console.log(` š New property: ${(config as any).get('newProperty')}`);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// Test the data service
|
|
174
|
-
const dataService = registry.get(['data']);
|
|
175
|
-
if (dataService) {
|
|
176
|
-
(dataService as any).add('Item 1');
|
|
177
|
-
(dataService as any).add('Item 2');
|
|
178
|
-
(dataService as any).add('Item 3');
|
|
179
|
-
console.log(` š Data service has ${(dataService as any).count()} items`);
|
|
180
|
-
console.log(` š All items: ${JSON.stringify((dataService as any).getAll())}`);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
console.log(' ā
All services working correctly!\n');
|
|
184
|
-
|
|
185
|
-
console.log('⨠Simple Registry Example Complete!');
|
|
186
|
-
console.log('\nš Key Takeaways:');
|
|
187
|
-
console.log(' ⢠No RegistryHub required - just call createRegistry()');
|
|
188
|
-
console.log(' ⢠No scopes required - pass empty array [] or omit entirely');
|
|
189
|
-
console.log(' ⢠Perfect for simple dependency injection needs');
|
|
190
|
-
console.log(' ⢠You can always add RegistryHub and scopes later as your app grows');
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// ===== Advanced Simple Example =====
|
|
194
|
-
|
|
195
|
-
async function runAdvancedSimpleExample() {
|
|
196
|
-
console.log('\n' + '='.repeat(60));
|
|
197
|
-
console.log('š„ Advanced Simple Example - Service Dependencies');
|
|
198
|
-
console.log('='.repeat(60) + '\n');
|
|
199
|
-
|
|
200
|
-
const registry = createRegistry('advanced-app');
|
|
201
|
-
|
|
202
|
-
// Create a notification service that depends on the logger
|
|
203
|
-
class NotificationService {
|
|
204
|
-
constructor(private logger: any) { }
|
|
205
|
-
|
|
206
|
-
sendNotification(message: string) {
|
|
207
|
-
this.logger.log(`Sending notification: ${message}`);
|
|
208
|
-
// In a real app, this would send actual notifications
|
|
209
|
-
console.log(`š¢ Notification sent: ${message}`);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// Register logger first
|
|
214
|
-
registry.createInstance(['logger'], [], (coordinate, context) => {
|
|
215
|
-
const service = new SimpleLogger();
|
|
216
|
-
const instance = createInstance(context.registry, coordinate);
|
|
217
|
-
// Attach service methods to instance for easy access
|
|
218
|
-
(instance as any).log = service.log.bind(service);
|
|
219
|
-
(instance as any).error = service.error.bind(service);
|
|
220
|
-
return instance;
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
// Register notification service that uses the logger
|
|
224
|
-
registry.createInstance(['notification'], [], (coordinate, context) => {
|
|
225
|
-
// Get the logger dependency from the registry
|
|
226
|
-
const logger = context.registry.get(['logger']);
|
|
227
|
-
const service = new NotificationService(logger);
|
|
228
|
-
const instance = createInstance(context.registry, coordinate);
|
|
229
|
-
(instance as any).sendNotification = service.sendNotification.bind(service);
|
|
230
|
-
return instance;
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
// Use the services
|
|
234
|
-
const notificationService = registry.get(['notification']);
|
|
235
|
-
if (notificationService) {
|
|
236
|
-
(notificationService as any).sendNotification('Welcome to the simple registry!');
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
console.log('\n⨠This shows how services can depend on each other');
|
|
240
|
-
console.log(' even in the simple, no-scopes approach!');
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// Run the examples
|
|
244
|
-
// Note: In ES modules, we can't use require.main === module
|
|
245
|
-
// So we'll just run the examples directly when this file is executed
|
|
246
|
-
runSimpleExample()
|
|
247
|
-
.then(() => runAdvancedSimpleExample())
|
|
248
|
-
.catch(console.error);
|
|
249
|
-
|
|
250
|
-
export { runSimpleExample, runAdvancedSimpleExample };
|
package/tsconfig.docs.json
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2020",
|
|
4
|
-
"useDefineForClassFields": true,
|
|
5
|
-
"lib": [
|
|
6
|
-
"ES2020",
|
|
7
|
-
"DOM",
|
|
8
|
-
"DOM.Iterable"
|
|
9
|
-
],
|
|
10
|
-
"types": [
|
|
11
|
-
"vitest/globals"
|
|
12
|
-
],
|
|
13
|
-
"module": "ESNext",
|
|
14
|
-
"skipLibCheck": true,
|
|
15
|
-
/* Bundler mode */
|
|
16
|
-
"moduleResolution": "bundler",
|
|
17
|
-
"allowImportingTsExtensions": true,
|
|
18
|
-
"resolveJsonModule": true,
|
|
19
|
-
"isolatedModules": true,
|
|
20
|
-
"noEmit": true,
|
|
21
|
-
"jsx": "react-jsx",
|
|
22
|
-
/* Linting */
|
|
23
|
-
"strict": true,
|
|
24
|
-
"noUnusedLocals": true,
|
|
25
|
-
"noUnusedParameters": true,
|
|
26
|
-
"noFallthroughCasesInSwitch": true
|
|
27
|
-
}
|
|
28
|
-
}
|
package/vitest.config.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/// <reference types="vitest" />
|
|
2
|
-
import { defineConfig } from 'vitest/config'
|
|
3
|
-
|
|
4
|
-
export default defineConfig({
|
|
5
|
-
test: {
|
|
6
|
-
environment: 'jsdom',
|
|
7
|
-
setupFiles: ['./tests/setup.ts'],
|
|
8
|
-
globals: true,
|
|
9
|
-
testTimeout: 30000,
|
|
10
|
-
coverage: {
|
|
11
|
-
exclude: [
|
|
12
|
-
'build.js',
|
|
13
|
-
'docs/**',
|
|
14
|
-
'coverage/**',
|
|
15
|
-
'output/**',
|
|
16
|
-
'**/*.config.*',
|
|
17
|
-
'**/*.d.ts',
|
|
18
|
-
'dist/**',
|
|
19
|
-
]
|
|
20
|
-
}
|
|
21
|
-
},
|
|
22
|
-
})
|