@hkdigital/lib-core 0.5.91 → 0.5.93
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -9
- package/dist/browser/info/device.js +9 -7
- package/dist/logging/README.md +15 -53
- package/dist/services/PATTERNS.md +476 -0
- package/dist/services/PLUGINS.md +520 -0
- package/dist/services/README.md +156 -229
- package/dist/ui/components/game-box/ScaledContainer.svelte +3 -7
- package/package.json +1 -1
package/dist/services/README.md
CHANGED
|
@@ -1,19 +1,37 @@
|
|
|
1
1
|
# Services
|
|
2
2
|
|
|
3
|
-
A comprehensive service management system providing standardized
|
|
3
|
+
A comprehensive service management system providing standardized
|
|
4
|
+
lifecycle management, health monitoring, and dependency orchestration
|
|
5
|
+
for application services.
|
|
6
|
+
|
|
7
|
+
**See also:**
|
|
8
|
+
- **Architecture**: [docs/setup/services-logging.md](../../docs/setup/services-logging.md)
|
|
9
|
+
- How services and logging work together
|
|
10
|
+
- **Patterns**: [PATTERNS.md](./PATTERNS.md) - Service access patterns
|
|
11
|
+
and best practices
|
|
12
|
+
- **Plugins**: [PLUGINS.md](./PLUGINS.md) - ConfigPlugin and plugin
|
|
13
|
+
system
|
|
14
|
+
- **Logging**: [src/lib/logging/README.md](../logging/README.md) -
|
|
15
|
+
Logging system integration
|
|
16
|
+
- **Main README**: [README.md](../../README.md) - Library overview and
|
|
17
|
+
setup
|
|
4
18
|
|
|
5
19
|
## Overview
|
|
6
20
|
|
|
7
21
|
The services module provides two main components:
|
|
8
22
|
|
|
9
|
-
- **ServiceBase** - Base class for implementing services with lifecycle
|
|
10
|
-
|
|
23
|
+
- **ServiceBase** - Base class for implementing services with lifecycle
|
|
24
|
+
management
|
|
25
|
+
- **ServiceManager** - Orchestrates multiple services with dependency
|
|
26
|
+
resolution
|
|
11
27
|
|
|
12
|
-
All services follow a standardized state machine with proper error
|
|
28
|
+
All services follow a standardized state machine with proper error
|
|
29
|
+
handling, logging, and health monitoring.
|
|
13
30
|
|
|
14
|
-
## Service
|
|
31
|
+
## Service States
|
|
15
32
|
|
|
16
|
-
Services transition through these states during their lifecycle. Use
|
|
33
|
+
Services transition through these states during their lifecycle. Use
|
|
34
|
+
these constants from `$lib/services/service-base/constants.js`:
|
|
17
35
|
|
|
18
36
|
- `STATE_CREATED` - Service instantiated but not configured
|
|
19
37
|
- `STATE_CONFIGURING` - Currently running configuration
|
|
@@ -42,7 +60,8 @@ if (service.state === STATE_RUNNING) {
|
|
|
42
60
|
|
|
43
61
|
Base class that all services should extend. Provides:
|
|
44
62
|
|
|
45
|
-
- Standardized lifecycle methods (`configure`, `start`, `stop`,
|
|
63
|
+
- Standardized lifecycle methods (`configure`, `start`, `stop`,
|
|
64
|
+
`destroy`)
|
|
46
65
|
- Flexible configuration system with reconfiguration support
|
|
47
66
|
- Health monitoring and recovery
|
|
48
67
|
- Event emission for state changes
|
|
@@ -59,19 +78,17 @@ class DatabaseService extends ServiceBase {
|
|
|
59
78
|
async _configure(newConfig, oldConfig = null) {
|
|
60
79
|
if (!oldConfig) {
|
|
61
80
|
// Initial configuration
|
|
62
|
-
|
|
63
81
|
this.connectionString = newConfig.connectionString;
|
|
64
82
|
this.maxConnections = newConfig.maxConnections || 10;
|
|
65
83
|
return;
|
|
66
84
|
}
|
|
67
85
|
|
|
86
|
+
// Reconfiguration - handle changes intelligently
|
|
68
87
|
if (oldConfig.connectionString !== newConfig.connectionString) {
|
|
69
|
-
// Reconfiguration - handle changes intelligently
|
|
70
|
-
|
|
71
88
|
// Connection changed - need to reconnect
|
|
72
89
|
await this.connection?.close();
|
|
73
|
-
|
|
74
90
|
this.connectionString = newConfig.connectionString;
|
|
91
|
+
|
|
75
92
|
if (this.state === 'running') {
|
|
76
93
|
this.connection = await createConnection(this.connectionString);
|
|
77
94
|
}
|
|
@@ -79,7 +96,6 @@ class DatabaseService extends ServiceBase {
|
|
|
79
96
|
|
|
80
97
|
if (oldConfig.maxConnections !== newConfig.maxConnections) {
|
|
81
98
|
// Pool size changed - update without reconnect
|
|
82
|
-
//
|
|
83
99
|
this.maxConnections = newConfig.maxConnections;
|
|
84
100
|
await this.connection?.setMaxConnections(this.maxConnections);
|
|
85
101
|
}
|
|
@@ -122,16 +138,23 @@ await db.configure({
|
|
|
122
138
|
|
|
123
139
|
### Protected Methods to Override
|
|
124
140
|
|
|
125
|
-
|
|
141
|
+
Implement these methods to define service behavior:
|
|
142
|
+
|
|
143
|
+
- `_configure(newConfig, oldConfig = null)` - Configure service
|
|
144
|
+
(handles both initial setup and reconfiguration)
|
|
126
145
|
- `_start()` - Start the service
|
|
127
146
|
- `_stop()` - Stop the service
|
|
128
147
|
- `_destroy()` - Clean up resources (optional)
|
|
129
148
|
- `_recover()` - Custom recovery logic (optional)
|
|
130
149
|
- `_healthCheck()` - Return health status (optional)
|
|
131
150
|
|
|
132
|
-
|
|
151
|
+
**See [PATTERNS.md](./PATTERNS.md) for implementation patterns and best
|
|
152
|
+
practices.**
|
|
153
|
+
|
|
154
|
+
### Service Events
|
|
133
155
|
|
|
134
|
-
ServiceBase emits these events (constants from
|
|
156
|
+
ServiceBase emits these events (constants from
|
|
157
|
+
`$lib/services/service-base/constants.js`):
|
|
135
158
|
|
|
136
159
|
- `EVENT_STATE_CHANGED` - Service state transitions
|
|
137
160
|
- `EVENT_TARGET_STATE_CHANGED` - Target state changes
|
|
@@ -139,7 +162,8 @@ ServiceBase emits these events (constants from `$lib/services/service-base/const
|
|
|
139
162
|
- `EVENT_ERROR` - Service errors
|
|
140
163
|
|
|
141
164
|
```javascript
|
|
142
|
-
import { EVENT_STATE_CHANGED }
|
|
165
|
+
import { EVENT_STATE_CHANGED }
|
|
166
|
+
from '$lib/services/service-base/constants.js';
|
|
143
167
|
|
|
144
168
|
service.on(EVENT_STATE_CHANGED, ({ state, previousState }) => {
|
|
145
169
|
console.log(`Service transitioned from ${previousState} to ${state}`);
|
|
@@ -148,7 +172,8 @@ service.on(EVENT_STATE_CHANGED, ({ state, previousState }) => {
|
|
|
148
172
|
|
|
149
173
|
## ServiceManager
|
|
150
174
|
|
|
151
|
-
Manages multiple services with dependency resolution and coordinated
|
|
175
|
+
Manages multiple services with dependency resolution and coordinated
|
|
176
|
+
lifecycle operations.
|
|
152
177
|
|
|
153
178
|
### Features
|
|
154
179
|
|
|
@@ -160,7 +185,7 @@ Manages multiple services with dependency resolution and coordinated lifecycle o
|
|
|
160
185
|
- Service recovery management
|
|
161
186
|
- Plugin system for extending configuration resolution
|
|
162
187
|
|
|
163
|
-
### Usage
|
|
188
|
+
### Basic Usage
|
|
164
189
|
|
|
165
190
|
```javascript
|
|
166
191
|
import { ServiceManager } from '@hkdigital/lib-core/services/index.js';
|
|
@@ -199,121 +224,63 @@ const health = await manager.checkHealth();
|
|
|
199
224
|
await manager.stopAll();
|
|
200
225
|
```
|
|
201
226
|
|
|
202
|
-
### Service
|
|
203
|
-
|
|
204
|
-
Services receive helpful utilities in their constructor options for accessing other services:
|
|
227
|
+
### Service Registration
|
|
205
228
|
|
|
206
229
|
```javascript
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
230
|
+
manager.register(name, ServiceClass, serviceConfigOrLabel, options);
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**Parameters:**
|
|
234
|
+
- `name` - Unique service identifier
|
|
235
|
+
- `ServiceClass` - Class extending ServiceBase
|
|
236
|
+
- `serviceConfigOrLabel` - Service configuration object
|
|
237
|
+
(`Object<string, *>`) or config label string (when using ConfigPlugin)
|
|
238
|
+
- `options.dependencies` - Array of service names this service depends
|
|
239
|
+
on
|
|
240
|
+
- `options.startupPriority` - Higher priority services start first
|
|
241
|
+
(default: 0)
|
|
213
242
|
|
|
214
|
-
|
|
215
|
-
#getManager;
|
|
243
|
+
### Service Access
|
|
216
244
|
|
|
217
|
-
|
|
218
|
-
super(serviceName, options);
|
|
219
|
-
|
|
220
|
-
// Store service access utilities as private methods
|
|
221
|
-
this.#getService = options.getService; // Bound getService function
|
|
222
|
-
this.#getManager = options.getManager; // Function to get manager (lazy)
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
async authenticateUser(credentials) {
|
|
226
|
-
// Access other services with full type safety and error checking
|
|
227
|
-
const database = this.#getService('database');
|
|
228
|
-
const user = await database.findUser(credentials.username);
|
|
229
|
-
|
|
230
|
-
// Access manager for advanced operations when needed
|
|
231
|
-
const manager = this.#getManager();
|
|
232
|
-
const health = await manager.checkHealth();
|
|
233
|
-
|
|
234
|
-
return user;
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
```
|
|
245
|
+
ServiceManager provides methods to access registered services:
|
|
238
246
|
|
|
239
|
-
|
|
247
|
+
```javascript
|
|
248
|
+
// Permissive - returns undefined if not found/created
|
|
249
|
+
const service = manager.get('optional-service');
|
|
250
|
+
if (service) {
|
|
251
|
+
// Use service safely
|
|
252
|
+
}
|
|
240
253
|
|
|
241
|
-
|
|
254
|
+
// Strict - throws error if not found/created
|
|
255
|
+
const service = manager.getService('required-service');
|
|
256
|
+
```
|
|
242
257
|
|
|
243
|
-
|
|
244
|
-
- **Prevents serialization issues** - Private fields don't serialize to JSON
|
|
245
|
-
- **Enforces proper encapsulation** - Service dependencies stay internal
|
|
246
|
-
- **Provides type safety** - Full generic support with `this.#getService<DatabaseService>('database')`
|
|
258
|
+
**Within services**, use constructor utilities for type-safe access:
|
|
247
259
|
|
|
248
260
|
```javascript
|
|
249
|
-
|
|
250
|
-
* Unified service for tracking complete player data including progress and
|
|
251
|
-
* profile matches
|
|
252
|
-
*/
|
|
253
|
-
export default class PlayerService extends ServiceBase {
|
|
254
|
-
|
|
261
|
+
class AuthService extends ServiceBase {
|
|
255
262
|
/** @type {(<T>(serviceName: string) => T)} */
|
|
256
263
|
#getService;
|
|
257
264
|
|
|
258
|
-
/**
|
|
259
|
-
* @param {string} serviceName
|
|
260
|
-
* @param {import('@hkdigital/lib-core/services/typedef.js').ServiceOptions} [options]
|
|
261
|
-
*/
|
|
262
265
|
constructor(serviceName, options) {
|
|
263
266
|
super(serviceName, options);
|
|
264
|
-
|
|
265
|
-
this.#getService = options?.getService;
|
|
267
|
+
this.#getService = options.getService;
|
|
266
268
|
}
|
|
267
269
|
|
|
268
|
-
async
|
|
269
|
-
// Access dependent services cleanly
|
|
270
|
+
async authenticate(credentials) {
|
|
270
271
|
const database = this.#getService('database');
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
const profile = await database.getPlayer(playerId);
|
|
274
|
-
const stats = await analytics.getPlayerStats(playerId);
|
|
275
|
-
|
|
276
|
-
return { ...profile, stats };
|
|
272
|
+
return await database.findUser(credentials.username);
|
|
277
273
|
}
|
|
278
274
|
}
|
|
279
275
|
```
|
|
280
276
|
|
|
281
|
-
**
|
|
282
|
-
|
|
283
|
-
```javascript
|
|
284
|
-
// ServiceManager provides two access patterns:
|
|
285
|
-
|
|
286
|
-
// 1. Permissive - returns undefined if not found/created
|
|
287
|
-
const service = manager.get('optional-service');
|
|
288
|
-
if (service) {
|
|
289
|
-
// Use service safely
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
// 2. Strict - throws error if not found/created
|
|
293
|
-
const service = manager.getService('required-service'); // Throws if missing
|
|
294
|
-
```
|
|
295
|
-
|
|
296
|
-
**Benefits of constructor utilities:**
|
|
297
|
-
|
|
298
|
-
- **Lightweight** - Functions don't serialize, keeping services serialization-safe
|
|
299
|
-
- **Lazy access** - Manager is only accessed when needed
|
|
300
|
-
- **Type safety** - Full generic support with `getService<DatabaseService>('database')`
|
|
301
|
-
- **Error handling** - Clear errors when services are missing
|
|
302
|
-
|
|
303
|
-
### Service Registration
|
|
304
|
-
|
|
305
|
-
```javascript
|
|
306
|
-
manager.register(name, ServiceClass, serviceConfigOrLabel, options);
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
- `name` - Unique service identifier
|
|
310
|
-
- `ServiceClass` - Class extending ServiceBase
|
|
311
|
-
- `serviceConfigOrLabel` - Service configuration object (`Object<string, *>`) or config label string
|
|
312
|
-
- `options.dependencies` - Array of service names this service depends on
|
|
313
|
-
- `options.startupPriority` - Higher priority services start first (default: 0)
|
|
277
|
+
**See [PATTERNS.md](./PATTERNS.md) for detailed service access
|
|
278
|
+
patterns.**
|
|
314
279
|
|
|
315
280
|
### Health Monitoring
|
|
316
281
|
|
|
282
|
+
Monitor service health individually or system-wide:
|
|
283
|
+
|
|
317
284
|
```javascript
|
|
318
285
|
import {
|
|
319
286
|
SERVICE_HEALTH_CHANGED,
|
|
@@ -338,6 +305,21 @@ const systemHealth = await manager.checkHealth();
|
|
|
338
305
|
|
|
339
306
|
### Error Handling and Recovery
|
|
340
307
|
|
|
308
|
+
ServiceManager provides automatic error handling and recovery:
|
|
309
|
+
|
|
310
|
+
```javascript
|
|
311
|
+
// Listen for service errors
|
|
312
|
+
manager.on(SERVICE_ERROR, async ({ service, error }) => {
|
|
313
|
+
console.log(`Service ${service} failed:`, error.message);
|
|
314
|
+
|
|
315
|
+
// Attempt automatic recovery
|
|
316
|
+
await manager.recoverService(service);
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
// Manual recovery
|
|
320
|
+
await manager.recoverService('database');
|
|
321
|
+
```
|
|
322
|
+
|
|
341
323
|
### Logging Configuration
|
|
342
324
|
|
|
343
325
|
ServiceManager provides centralized logging control for all services:
|
|
@@ -369,31 +351,19 @@ manager.setServiceLogLevel({
|
|
|
369
351
|
manager.setServiceLogLevel('database:info,auth:debug');
|
|
370
352
|
```
|
|
371
353
|
|
|
372
|
-
### ServiceManager
|
|
354
|
+
### ServiceManager Events
|
|
373
355
|
|
|
374
|
-
ServiceManager emits these events (constants from
|
|
356
|
+
ServiceManager emits these events (constants from
|
|
357
|
+
`$lib/services/service-manager/constants.js`):
|
|
375
358
|
|
|
376
359
|
- `SERVICE_STATE_CHANGED` - Service state changes
|
|
377
360
|
- `SERVICE_HEALTH_CHANGED` - Service health changes
|
|
378
361
|
- `SERVICE_ERROR` - Service errors
|
|
379
362
|
- `SERVICE_LOG` - Service log messages
|
|
380
363
|
|
|
381
|
-
```javascript
|
|
382
|
-
// Listen for service errors
|
|
383
|
-
manager.on(SERVICE_ERROR, async ({ service, error }) => {
|
|
384
|
-
console.log(`Service ${service} failed:`, error.message);
|
|
385
|
-
|
|
386
|
-
// Attempt automatic recovery
|
|
387
|
-
await manager.recoverService(service);
|
|
388
|
-
});
|
|
389
|
-
|
|
390
|
-
// Manual recovery
|
|
391
|
-
await manager.recoverService('database');
|
|
392
|
-
```
|
|
393
|
-
|
|
394
364
|
### Log Event Forwarding
|
|
395
365
|
|
|
396
|
-
Forward all service log events to a
|
|
366
|
+
Forward all service log events to a centralized logger:
|
|
397
367
|
|
|
398
368
|
```javascript
|
|
399
369
|
import { ServiceManager } from '$lib/services/index.js';
|
|
@@ -417,149 +387,106 @@ await manager.startAll();
|
|
|
417
387
|
unsubscribe();
|
|
418
388
|
```
|
|
419
389
|
|
|
390
|
+
**See [docs/setup/services-logging.md](../../docs/setup/services-logging.md)
|
|
391
|
+
for complete integration examples.**
|
|
392
|
+
|
|
420
393
|
## Plugins
|
|
421
394
|
|
|
422
|
-
ServiceManager supports plugins
|
|
395
|
+
ServiceManager supports plugins to extend functionality, primarily for
|
|
396
|
+
dynamic configuration resolution.
|
|
423
397
|
|
|
424
398
|
### ConfigPlugin
|
|
425
399
|
|
|
426
|
-
The most common plugin for resolving service configuration from
|
|
427
|
-
|
|
428
|
-
#### Basic Usage with Environment Variables
|
|
400
|
+
The most common plugin for resolving service configuration from
|
|
401
|
+
environment variables or config files:
|
|
429
402
|
|
|
430
403
|
```javascript
|
|
431
404
|
import { ServiceManager } from '$lib/services/index.js';
|
|
432
|
-
|
|
433
405
|
import ConfigPlugin from '$lib/services/manager-plugins/ConfigPlugin.js';
|
|
434
|
-
|
|
435
406
|
import { getPrivateEnv } from '$lib/util/sveltekit/env-private.js';
|
|
436
407
|
|
|
437
|
-
// Load
|
|
408
|
+
// Load environment config
|
|
438
409
|
const envConfig = getPrivateEnv();
|
|
439
|
-
//
|
|
440
|
-
// Example:
|
|
441
|
-
//
|
|
442
|
-
// DATABASE_HOST=localhost
|
|
443
|
-
// DATABASE_PORT=5432
|
|
444
|
-
// DATABASE_NAME=myapp
|
|
445
|
-
// REDIS_HOST=cache-server
|
|
446
|
-
// REDIS_PORT=6379
|
|
447
|
-
// JWT_SECRET=mysecret
|
|
448
|
-
// =>
|
|
449
|
-
// {
|
|
450
|
-
// database: { host: 'localhost', port: 5432, name: 'myapp' },
|
|
451
|
-
// redis: { host: 'cache-server', port: 6379 },
|
|
452
|
-
// jwtSecret: 'mysecret'
|
|
453
|
-
// }
|
|
454
|
-
//
|
|
455
|
-
|
|
456
|
-
// Create plugin with grouped config
|
|
457
|
-
const configPlugin = new ConfigPlugin(envConfig);
|
|
458
410
|
|
|
459
|
-
//
|
|
411
|
+
// Create and attach plugin
|
|
412
|
+
const configPlugin = new ConfigPlugin(envConfig);
|
|
460
413
|
const manager = new ServiceManager();
|
|
461
414
|
manager.attachPlugin(configPlugin);
|
|
462
415
|
|
|
463
416
|
// Register services with config labels (not config objects)
|
|
464
|
-
manager.register('database', DatabaseService, 'database');
|
|
465
|
-
manager.register('cache', RedisService, 'redis');
|
|
417
|
+
manager.register('database', DatabaseService, 'database');
|
|
418
|
+
manager.register('cache', RedisService, 'redis');
|
|
466
419
|
|
|
467
420
|
await manager.startAll();
|
|
421
|
+
|
|
422
|
+
// Hot-reload configuration
|
|
423
|
+
await configPlugin.replaceConfig('database', newDatabaseConfig);
|
|
468
424
|
```
|
|
469
425
|
|
|
470
|
-
|
|
426
|
+
**See [PLUGINS.md](./PLUGINS.md) for complete plugin documentation and
|
|
427
|
+
live configuration updates.**
|
|
471
428
|
|
|
472
|
-
|
|
429
|
+
## Quick Reference
|
|
473
430
|
|
|
474
|
-
|
|
475
|
-
// Combine multiple config sources
|
|
476
|
-
const config = {
|
|
477
|
-
...getPrivateEnv(), // Environment variables
|
|
478
|
-
...(await loadConfigFile()), // Config file
|
|
479
|
-
database: {
|
|
480
|
-
// Override specific settings
|
|
481
|
-
...envConfig.database,
|
|
482
|
-
connectionTimeout: 5000
|
|
483
|
-
}
|
|
484
|
-
};
|
|
431
|
+
### Service Lifecycle
|
|
485
432
|
|
|
486
|
-
|
|
433
|
+
```
|
|
434
|
+
created → configuring → configured → starting → running
|
|
435
|
+
↓
|
|
436
|
+
stopping → stopped → destroying → destroyed
|
|
437
|
+
↓
|
|
438
|
+
error ← → recovering
|
|
487
439
|
```
|
|
488
440
|
|
|
489
|
-
###
|
|
441
|
+
### Common Operations
|
|
490
442
|
|
|
491
443
|
```javascript
|
|
492
|
-
//
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
await configPlugin.replaceConfig('database', newDatabaseConfig);
|
|
497
|
-
|
|
498
|
-
// Clean up configurations not used by any service
|
|
499
|
-
await configPlugin.cleanupConfigs();
|
|
500
|
-
```
|
|
444
|
+
// Create and start service
|
|
445
|
+
const service = new MyService('my-service');
|
|
446
|
+
await service.configure(config);
|
|
447
|
+
await service.start();
|
|
501
448
|
|
|
502
|
-
|
|
449
|
+
// Check health
|
|
450
|
+
const health = await service.healthCheck();
|
|
503
451
|
|
|
504
|
-
|
|
452
|
+
// Reconfigure
|
|
453
|
+
await service.configure(newConfig);
|
|
505
454
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
const updatedServices = await configPlugin.replaceConfig('database', {
|
|
509
|
-
host: 'new-host.example.com',
|
|
510
|
-
port: 5433,
|
|
511
|
-
maxConnections: 50
|
|
512
|
-
});
|
|
455
|
+
// Stop service
|
|
456
|
+
await service.stop();
|
|
513
457
|
|
|
514
|
-
//
|
|
515
|
-
|
|
458
|
+
// Destroy service
|
|
459
|
+
await service.destroy();
|
|
516
460
|
```
|
|
517
461
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
For services to support live configuration updates, they must:
|
|
521
|
-
|
|
522
|
-
1. **Implement intelligent `_configure()` logic** that can handle both initial setup and reconfiguration
|
|
523
|
-
2. **Check for meaningful changes** between old and new config
|
|
524
|
-
3. **Apply changes without full restart** when possible
|
|
462
|
+
### ServiceManager Operations
|
|
525
463
|
|
|
526
464
|
```javascript
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
async _configure(newConfig, oldConfig = null) {
|
|
530
|
-
if (!oldConfig) {
|
|
531
|
-
// Initial configuration
|
|
532
|
-
this.connectionString = newConfig.connectionString;
|
|
533
|
-
this.maxConnections = newConfig.maxConnections || 10;
|
|
534
|
-
return;
|
|
535
|
-
}
|
|
465
|
+
// Register services
|
|
466
|
+
manager.register('name', ServiceClass, config, options);
|
|
536
467
|
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
this.connectionString = newConfig.connectionString;
|
|
468
|
+
// Lifecycle
|
|
469
|
+
await manager.startAll();
|
|
470
|
+
await manager.stopAll();
|
|
471
|
+
await manager.destroyAll();
|
|
542
472
|
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
}
|
|
473
|
+
// Access
|
|
474
|
+
const service = manager.get('name');
|
|
475
|
+
const service = manager.getService('name'); // Throws if missing
|
|
547
476
|
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
}
|
|
477
|
+
// Health
|
|
478
|
+
const health = await manager.checkHealth();
|
|
479
|
+
const serviceHealth = await manager.getServiceHealth('name');
|
|
480
|
+
|
|
481
|
+
// Recovery
|
|
482
|
+
await manager.recoverService('name');
|
|
555
483
|
```
|
|
556
484
|
|
|
557
|
-
##
|
|
485
|
+
## Next Steps
|
|
558
486
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
7. **Use descriptive service names** for better logging and debugging
|
|
487
|
+
- **Patterns**: See [PATTERNS.md](./PATTERNS.md) for service access
|
|
488
|
+
patterns, configuration patterns, and best practices
|
|
489
|
+
- **Plugins**: See [PLUGINS.md](./PLUGINS.md) for ConfigPlugin and
|
|
490
|
+
custom plugins
|
|
491
|
+
- **Architecture**: See [docs/setup/services-logging.md](../../docs/setup/services-logging.md)
|
|
492
|
+
for integration with logging and SvelteKit hooks
|
|
@@ -48,12 +48,12 @@
|
|
|
48
48
|
!height ||
|
|
49
49
|
!design ||
|
|
50
50
|
!clamping
|
|
51
|
-
|
|
51
|
+
|| hidden
|
|
52
52
|
) {
|
|
53
53
|
return;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
console.debug(`Enable scaling [${width},${height}]`);
|
|
56
|
+
// console.debug(`Enable scaling [${width},${height}]`);
|
|
57
57
|
|
|
58
58
|
return enableContainerScaling({
|
|
59
59
|
container,
|
|
@@ -73,12 +73,8 @@
|
|
|
73
73
|
style:left="0"
|
|
74
74
|
style:width="{width}px"
|
|
75
75
|
style:height="{height}px"
|
|
76
|
-
style:
|
|
76
|
+
style:display={hidden ? "none" : "block"}
|
|
77
77
|
>
|
|
78
78
|
{@render snippet(snippetParams)}
|
|
79
79
|
</div>
|
|
80
80
|
{/if}
|
|
81
|
-
|
|
82
|
-
<style>
|
|
83
|
-
/* Positioning and visibility handled via inline styles */
|
|
84
|
-
</style>
|