@hkdigital/lib-core 0.4.18 → 0.4.20

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 (33) hide show
  1. package/dist/services/README.md +254 -47
  2. package/dist/services/manager-plugins/ConfigPlugin.d.ts +68 -0
  3. package/dist/services/manager-plugins/ConfigPlugin.js +329 -0
  4. package/dist/services/service-base/ServiceBase.d.ts +59 -22
  5. package/dist/services/service-base/ServiceBase.js +139 -61
  6. package/dist/services/service-base/constants.d.ts +30 -14
  7. package/dist/services/service-base/constants.js +42 -14
  8. package/dist/services/service-base/typedef.d.ts +15 -9
  9. package/dist/services/service-base/typedef.js +33 -11
  10. package/dist/services/service-manager/ServiceManager.d.ts +25 -5
  11. package/dist/services/service-manager/ServiceManager.js +103 -20
  12. package/dist/services/service-manager/constants.js +0 -1
  13. package/dist/services/service-manager/typedef.d.ts +36 -14
  14. package/dist/services/service-manager/typedef.js +30 -13
  15. package/dist/util/sveltekit/env/README.md +424 -0
  16. package/dist/util/sveltekit/env/all.d.ts +54 -0
  17. package/dist/util/sveltekit/env/all.js +97 -0
  18. package/dist/util/sveltekit/env/parsers.d.ts +135 -0
  19. package/dist/util/sveltekit/env/parsers.js +257 -0
  20. package/dist/util/sveltekit/env/private.d.ts +56 -0
  21. package/dist/util/sveltekit/env/private.js +87 -0
  22. package/dist/util/sveltekit/env/public.d.ts +52 -0
  23. package/dist/util/sveltekit/env/public.js +82 -0
  24. package/dist/util/sveltekit/env-all.d.ts +1 -0
  25. package/dist/util/sveltekit/env-all.js +19 -0
  26. package/dist/util/sveltekit/env-private.d.ts +1 -0
  27. package/dist/util/sveltekit/env-private.js +18 -0
  28. package/dist/util/sveltekit/env-public.d.ts +1 -0
  29. package/dist/util/sveltekit/env-public.js +18 -0
  30. package/package.json +1 -1
  31. package/dist/util/index.js__ +0 -20
  32. package/dist/util/sveltekit/index.d.ts +0 -0
  33. package/dist/util/sveltekit/index.js +0 -0
@@ -1,17 +1,17 @@
1
1
  /**
2
2
  * @fileoverview Type definitions for ServiceBase class.
3
- *
3
+ *
4
4
  * This file contains all TypeScript/JSDoc type definitions used by
5
5
  * the ServiceBase class and service implementations.
6
- *
6
+ *
7
7
  * @example
8
8
  * // In your service implementation
9
9
  * import { ServiceBase } from './ServiceBase.js';
10
- *
10
+ *
11
11
  * class MyService extends ServiceBase {
12
- * async _init(config) {
12
+ * async _configure(newConfig, oldConfig) {
13
13
  * }
14
- *
14
+ *
15
15
  * async _healthCheck() {
16
16
  * // Return type is HealthStatus
17
17
  * return { latency: 10 };
@@ -23,6 +23,24 @@
23
23
  // PUBLIC TYPES
24
24
  // ============================================================================
25
25
 
26
+ /**
27
+ * All possible service states during lifecycle management
28
+ *
29
+ * @typedef {import('./constants.js').STATE_NOT_CREATED |
30
+ * import('./constants.js').STATE_CREATED |
31
+ * import('./constants.js').STATE_CONFIGURING |
32
+ * import('./constants.js').STATE_CONFIGURED |
33
+ * import('./constants.js').STATE_STARTING |
34
+ * import('./constants.js').STATE_RUNNING |
35
+ * import('./constants.js').STATE_STOPPING |
36
+ * import('./constants.js').STATE_STOPPED |
37
+ * import('./constants.js').STATE_DESTROYING |
38
+ * import('./constants.js').STATE_DESTROYED |
39
+ * import('./constants.js').STATE_ERROR |
40
+ * import('./constants.js').STATE_RECOVERING
41
+ * } ServiceState
42
+ */
43
+
26
44
  /**
27
45
  * Options for creating a service instance
28
46
  *
@@ -57,11 +75,11 @@
57
75
  *
58
76
  * @typedef {Object & Record<string, any>} ServiceInstance
59
77
  * @property {string} name - Service name
60
- * @property {string} state - Current state
78
+ * @property {ServiceState} state - Current state
61
79
  * @property {boolean} healthy - Health status
62
80
  * @property {Error|null} error - Last error
63
81
  * @property {import('../../logging/index.js').Logger} logger - Service logger
64
- * @property {(config?: *) => Promise<boolean>} initialize
82
+ * @property {(config?: *) => Promise<boolean>} configure
65
83
  * @property {() => Promise<boolean>} start
66
84
  * @property {(options?: StopOptions) => Promise<boolean>} stop
67
85
  * @property {() => Promise<boolean>} recover
@@ -79,13 +97,18 @@
79
97
  /**
80
98
  * @typedef {Object} StateChangeEvent
81
99
  * @property {string} service - Service name (added by ServiceManager)
82
- * @property {string} oldState - Previous state
83
- * @property {string} newState - New state
100
+ * @property {ServiceState} oldState - Previous state
101
+ * @property {ServiceState} newState - New state
102
+ */
103
+
104
+ /**
105
+ * @typedef {Object} TargetStateChangeEvent
106
+ * @property {ServiceState} oldTargetState - Previous target state
107
+ * @property {ServiceState} newTargetState - New target state
84
108
  */
85
109
 
86
110
  /**
87
111
  * @typedef {Object} HealthChangeEvent
88
- * @property {string} service - Service name (added by ServiceManager)
89
112
  * @property {boolean} healthy - Current health status
90
113
  * @property {boolean} [wasHealthy] - Previous health status
91
114
  */
@@ -94,7 +117,6 @@
94
117
  * Event emitted when service encounters an error
95
118
  *
96
119
  * @typedef {Object} ServiceErrorEvent
97
- * @property {string} service - Service name
98
120
  * @property {string} operation - Operation that failed
99
121
  * @property {Error} error - Error that occurred
100
122
  */
@@ -3,6 +3,7 @@
3
3
  * @typedef {import('./typedef.js').ServiceRegistrationOptions} ServiceRegistrationOptions
4
4
  * @typedef {import('./typedef.js').ServiceManagerConfig} ServiceManagerConfig
5
5
  * @typedef {import('./typedef.js').ServiceEntry} ServiceEntry
6
+ * @typedef {import('./typedef.js').ServiceConfigOrLabel} ServiceConfigOrLabel
6
7
  * @typedef {import('./typedef.js').HealthCheckResult} HealthCheckResult
7
8
  *
8
9
  * @typedef {import('../service-base/typedef.js').StopOptions} StopOptions
@@ -24,17 +25,35 @@ export class ServiceManager extends EventEmitter {
24
25
  logger: Logger;
25
26
  /** @type {ServiceManagerConfig} */
26
27
  config: ServiceManagerConfig;
28
+ /**
29
+ * Attach a plugin to the ServiceManager
30
+ *
31
+ * @param {import('./typedef.js').ServiceManagerPlugin} plugin
32
+ * Plugin instance
33
+ *
34
+ * @throws {Error} If plugin name is already registered
35
+ */
36
+ attachPlugin(plugin: import("./typedef.js").ServiceManagerPlugin): void;
37
+ /**
38
+ * Detach a plugin from the ServiceManager
39
+ *
40
+ * @param {string} pluginName - Name of the plugin to detach
41
+ *
42
+ * @returns {boolean} True if plugin was detached
43
+ */
44
+ detachPlugin(pluginName: string): boolean;
27
45
  /**
28
46
  * Register a service class with the manager
29
47
  *
30
48
  * @param {string} name - Unique service identifier
31
49
  * @param {ServiceConstructor} ServiceClass - Service class constructor
32
- * @param {*} [config={}] - Service configuration
50
+ * @param {ServiceConfigOrLabel} [serviceConfigOrLabel={}]
51
+ * Service configuration object or config label string
33
52
  * @param {ServiceRegistrationOptions} [options={}] - Registration options
34
53
  *
35
54
  * @throws {Error} If service name is already registered
36
55
  */
37
- register(name: string, ServiceClass: ServiceConstructor, config?: any, options?: ServiceRegistrationOptions): void;
56
+ register(name: string, ServiceClass: ServiceConstructor, serviceConfigOrLabel?: ServiceConfigOrLabel, options?: ServiceRegistrationOptions): void;
38
57
  /**
39
58
  * Get or create a service instance
40
59
  *
@@ -45,13 +64,13 @@ export class ServiceManager extends EventEmitter {
45
64
  */
46
65
  get(name: string): import("../service-base/typedef.js").ServiceInstance | null;
47
66
  /**
48
- * Initialize a service
67
+ * Configure a service
49
68
  *
50
69
  * @param {string} name - Service name
51
70
  *
52
- * @returns {Promise<boolean>} True if initialization succeeded
71
+ * @returns {Promise<boolean>} True if configuration succeeded
53
72
  */
54
- initService(name: string): Promise<boolean>;
73
+ configureService(name: string): Promise<boolean>;
55
74
  /**
56
75
  * Start a service and its dependencies
57
76
  *
@@ -139,6 +158,7 @@ export type ServiceConstructor = import("./typedef.js").ServiceConstructor;
139
158
  export type ServiceRegistrationOptions = import("./typedef.js").ServiceRegistrationOptions;
140
159
  export type ServiceManagerConfig = import("./typedef.js").ServiceManagerConfig;
141
160
  export type ServiceEntry = import("./typedef.js").ServiceEntry;
161
+ export type ServiceConfigOrLabel = import("./typedef.js").ServiceConfigOrLabel;
142
162
  export type HealthCheckResult = import("./typedef.js").HealthCheckResult;
143
163
  export type StopOptions = import("../service-base/typedef.js").StopOptions;
144
164
  import { EventEmitter } from '../../generic/events.js';
@@ -67,10 +67,10 @@ import { EventEmitter } from '../../generic/events.js';
67
67
  import { Logger, DEBUG, INFO, WARN } from '../../logging/index.js';
68
68
 
69
69
  import {
70
- NOT_CREATED,
71
- CREATED,
72
- RUNNING,
73
- DESTROYED
70
+ STATE_NOT_CREATED,
71
+ STATE_CREATED,
72
+ STATE_RUNNING,
73
+ STATE_DESTROYED
74
74
  } from '../service-base/constants.js';
75
75
 
76
76
  /**
@@ -78,6 +78,7 @@ import {
78
78
  * @typedef {import('./typedef.js').ServiceRegistrationOptions} ServiceRegistrationOptions
79
79
  * @typedef {import('./typedef.js').ServiceManagerConfig} ServiceManagerConfig
80
80
  * @typedef {import('./typedef.js').ServiceEntry} ServiceEntry
81
+ * @typedef {import('./typedef.js').ServiceConfigOrLabel} ServiceConfigOrLabel
81
82
  * @typedef {import('./typedef.js').HealthCheckResult} HealthCheckResult
82
83
  *
83
84
  * @typedef {import('../service-base/typedef.js').StopOptions} StopOptions
@@ -88,6 +89,9 @@ import {
88
89
  * @extends EventEmitter
89
90
  */
90
91
  export class ServiceManager extends EventEmitter {
92
+ /** @type {Map<string, import('./typedef.js').ServiceManagerPlugin>} */
93
+ #plugins = new Map();
94
+
91
95
  /**
92
96
  * Create a new ServiceManager instance
93
97
  *
@@ -113,17 +117,55 @@ export class ServiceManager extends EventEmitter {
113
117
  this.#setupLogging();
114
118
  }
115
119
 
120
+ /**
121
+ * Attach a plugin to the ServiceManager
122
+ *
123
+ * @param {import('./typedef.js').ServiceManagerPlugin} plugin
124
+ * Plugin instance
125
+ *
126
+ * @throws {Error} If plugin name is already registered
127
+ */
128
+ attachPlugin(plugin) {
129
+ if (this.#plugins.has(plugin.name)) {
130
+ throw new Error(`Plugin '${plugin.name}' is already attached`);
131
+ }
132
+
133
+ this.#plugins.set(plugin.name, plugin);
134
+ plugin.attach(this);
135
+
136
+ this.logger.debug(`Attached plugin '${plugin.name}'`);
137
+ }
138
+
139
+ /**
140
+ * Detach a plugin from the ServiceManager
141
+ *
142
+ * @param {string} pluginName - Name of the plugin to detach
143
+ *
144
+ * @returns {boolean} True if plugin was detached
145
+ */
146
+ detachPlugin(pluginName) {
147
+ const plugin = this.#plugins.get(pluginName);
148
+ if (!plugin) return false;
149
+
150
+ plugin.detach();
151
+ this.#plugins.delete(pluginName);
152
+
153
+ this.logger.debug(`Detached plugin '${pluginName}'`);
154
+ return true;
155
+ }
156
+
116
157
  /**
117
158
  * Register a service class with the manager
118
159
  *
119
160
  * @param {string} name - Unique service identifier
120
161
  * @param {ServiceConstructor} ServiceClass - Service class constructor
121
- * @param {*} [config={}] - Service configuration
162
+ * @param {ServiceConfigOrLabel} [serviceConfigOrLabel={}]
163
+ * Service configuration object or config label string
122
164
  * @param {ServiceRegistrationOptions} [options={}] - Registration options
123
165
  *
124
166
  * @throws {Error} If service name is already registered
125
167
  */
126
- register(name, ServiceClass, config = {}, options = {}) {
168
+ register(name, ServiceClass, serviceConfigOrLabel = {}, options = {}) {
127
169
  if (this.services.has(name)) {
128
170
  throw new Error(`Service '${name}' already registered`);
129
171
  }
@@ -132,11 +174,11 @@ export class ServiceManager extends EventEmitter {
132
174
  const entry = {
133
175
  ServiceClass,
134
176
  instance: null,
135
- config,
177
+ serviceConfigOrLabel,
136
178
  dependencies: options.dependencies || [],
137
179
  dependents: new Set(),
138
180
  tags: options.tags || [],
139
- priority: options.priority || 0
181
+ startupPriority: options.startupPriority || 0
140
182
  };
141
183
 
142
184
  // Track dependents
@@ -194,18 +236,20 @@ export class ServiceManager extends EventEmitter {
194
236
  }
195
237
 
196
238
  /**
197
- * Initialize a service
239
+ * Configure a service
198
240
  *
199
241
  * @param {string} name - Service name
200
242
  *
201
- * @returns {Promise<boolean>} True if initialization succeeded
243
+ * @returns {Promise<boolean>} True if configuration succeeded
202
244
  */
203
- async initService(name) {
245
+ async configureService(name) {
204
246
  const instance = this.get(name);
205
247
  if (!instance) return false;
206
248
 
207
249
  const entry = this.services.get(name);
208
- return await instance.initialize(entry.config);
250
+ const config = await this.#resolveServiceConfig(name, entry);
251
+
252
+ return await instance.configure(config);
209
253
  }
210
254
 
211
255
  /**
@@ -240,10 +284,18 @@ export class ServiceManager extends EventEmitter {
240
284
  const instance = this.get(name);
241
285
  if (!instance) return false;
242
286
 
243
- // Initialize if needed
244
- if (instance.state === CREATED || instance.state === DESTROYED) {
245
- const initialized = await this.initService(name);
246
- if (!initialized) return false;
287
+ if (
288
+ instance.state === STATE_CREATED ||
289
+ instance.state === STATE_DESTROYED
290
+ ) {
291
+ // Service is not created or has been destroyed
292
+ // => configure needed
293
+
294
+ const configured = await this.configureService(name);
295
+
296
+ if (!configured) {
297
+ return false;
298
+ }
247
299
  }
248
300
 
249
301
  return await instance.start();
@@ -385,7 +437,6 @@ export class ServiceManager extends EventEmitter {
385
437
  return Object.fromEntries(results);
386
438
  }
387
439
 
388
-
389
440
  /**
390
441
  * Get health status for all services
391
442
  *
@@ -401,7 +452,7 @@ export class ServiceManager extends EventEmitter {
401
452
  } else {
402
453
  health[name] = {
403
454
  name,
404
- state: NOT_CREATED,
455
+ state: STATE_NOT_CREATED,
405
456
  healthy: false
406
457
  };
407
458
  }
@@ -419,7 +470,7 @@ export class ServiceManager extends EventEmitter {
419
470
  */
420
471
  async isRunning(name) {
421
472
  const instance = this.get(name);
422
- return instance ? instance.state === RUNNING : false;
473
+ return instance ? instance.state === STATE_RUNNING : false;
423
474
  }
424
475
 
425
476
  /**
@@ -472,7 +523,6 @@ export class ServiceManager extends EventEmitter {
472
523
  return services;
473
524
  }
474
525
 
475
-
476
526
  /**
477
527
  * Attach event listeners to forward service events
478
528
  *
@@ -503,6 +553,39 @@ export class ServiceManager extends EventEmitter {
503
553
 
504
554
  // Internal methods
505
555
 
556
+ /**
557
+ * Resolve service configuration using plugins
558
+ *
559
+ * @param {string} serviceName - Name of the service being configured
560
+ * @param {ServiceEntry} serviceEntry - Service registration entry
561
+ *
562
+ * @returns {Promise<*>} Resolved configuration object
563
+ */
564
+ async #resolveServiceConfig(serviceName, serviceEntry) {
565
+ let serviceConfigOrLabel = serviceEntry.serviceConfigOrLabel;
566
+
567
+ if (typeof serviceConfigOrLabel === 'string') {
568
+ const configLabel = serviceConfigOrLabel;
569
+
570
+ // Let plugins resolve the config
571
+ for (const plugin of this.#plugins.values()) {
572
+ if (plugin.resolveServiceConfig) {
573
+ const config = await plugin.resolveServiceConfig(
574
+ serviceName,
575
+ serviceEntry,
576
+ configLabel
577
+ );
578
+ if (config !== undefined) {
579
+ return config; // First plugin that resolves wins
580
+ }
581
+ }
582
+ }
583
+ } else {
584
+ const config = serviceConfigOrLabel;
585
+ return config;
586
+ }
587
+ }
588
+
506
589
  /**
507
590
  * Setup logging configuration based on config.dev
508
591
  */
@@ -1,4 +1,3 @@
1
-
2
1
  // Log event names
3
2
  export const SERVICE_STATE_CHANGED = 'service:state-changed';
4
3
  export const SERVICE_HEALTH_CHANGED = 'service:health-changed';
@@ -1,3 +1,9 @@
1
+ /**
2
+ * Service configuration - either a config object or a config label string
3
+ */
4
+ export type ServiceConfigOrLabel = {
5
+ [x: string]: any;
6
+ } | string;
1
7
  /**
2
8
  * Options for registering a service
3
9
  */
@@ -11,9 +17,9 @@ export type ServiceRegistrationOptions = {
11
17
  */
12
18
  tags?: string[];
13
19
  /**
14
- * - Startup priority (higher starts first)
20
+ * - Higher starts first
15
21
  */
16
- priority?: number;
22
+ startupPriority?: number;
17
23
  };
18
24
  /**
19
25
  * Configuration for ServiceManager
@@ -69,6 +75,31 @@ export type HealthCheckResult = {
69
75
  * Service class constructor type
70
76
  */
71
77
  export type ServiceConstructor = new (name: string, options?: import("../service-base/typedef.js").ServiceOptions) => import("../service-base/typedef.js").ServiceInstance;
78
+ /**
79
+ * ServiceManager plugin interface
80
+ */
81
+ export type ServiceManagerPlugin = {
82
+ /**
83
+ * - Unique plugin identifier
84
+ */
85
+ name: string;
86
+ /**
87
+ * - ServiceManager reference
88
+ */
89
+ manager: import("./ServiceManager.js").ServiceManager | null;
90
+ /**
91
+ * - Attach to ServiceManager
92
+ */
93
+ attach: (arg0: import("./ServiceManager.js").ServiceManager) => void;
94
+ /**
95
+ * - Detach from ServiceManager
96
+ */
97
+ detach: () => void;
98
+ /**
99
+ * - Optional config resolution method
100
+ */
101
+ resolveServiceConfig?: (arg0: string, arg1: ServiceEntry, arg2: any) => Promise<any | undefined>;
102
+ };
72
103
  /**
73
104
  * Internal service registry entry
74
105
  */
@@ -81,24 +112,15 @@ export type ServiceEntry = {
81
112
  * - Service instance (lazy-created)
82
113
  */
83
114
  instance: import("../service-base/typedef.js").ServiceInstance | null;
84
- /**
85
- * - Service configuration
86
- */
87
- config: any;
88
- /**
89
- * - Service dependencies
90
- */
115
+ serviceConfigOrLabel: ServiceConfigOrLabel;
91
116
  dependencies: string[];
92
117
  /**
93
- * - Services that depend on this one
118
+ * - Services that depend on this service
94
119
  */
95
120
  dependents: Set<string>;
96
- /**
97
- * - Service tags
98
- */
99
121
  tags: string[];
100
122
  /**
101
123
  * - Startup priority
102
124
  */
103
- priority: number;
125
+ startupPriority: number;
104
126
  };
@@ -1,28 +1,28 @@
1
1
  /**
2
2
  * @fileoverview Type definitions for ServiceManager class.
3
- *
3
+ *
4
4
  * This file contains all TypeScript/JSDoc type definitions used by
5
5
  * the ServiceManager class and service registration.
6
- *
6
+ *
7
7
  * @example
8
8
  * // When using ServiceManager
9
9
  * import { ServiceManager } from './ServiceManager.js';
10
- *
10
+ *
11
11
  * // @ typedef {import('./typedef-service-manager.js').ServiceManagerConfig} ServiceManagerConfig
12
12
  * // @ typedef {import('./typedef-service-manager.js').ServiceRegistrationOptions} ServiceRegistrationOptions
13
- *
13
+ *
14
14
  * const config = {
15
15
  * environment: 'development',
16
16
  * stopTimeout: 5000
17
17
  * };
18
- *
18
+ *
19
19
  * const manager = new ServiceManager(config);
20
- *
20
+ *
21
21
  * const options = {
22
22
  * dependencies: ['database'],
23
23
  * tags: ['critical']
24
24
  * };
25
- *
25
+ *
26
26
  * manager.register('auth', AuthService, {}, options);
27
27
  */
28
28
 
@@ -30,13 +30,19 @@
30
30
  // PUBLIC TYPES
31
31
  // ============================================================================
32
32
 
33
+ /**
34
+ * Service configuration - either a config object or a config label string
35
+ *
36
+ * @typedef {Object<string, *>|string} ServiceConfigOrLabel
37
+ */
38
+
33
39
  /**
34
40
  * Options for registering a service
35
41
  *
36
42
  * @typedef {Object} ServiceRegistrationOptions
37
43
  * @property {string[]} [dependencies=[]] - Services this service depends on
38
44
  * @property {string[]} [tags=[]] - Tags for grouping services
39
- * @property {number} [priority=0] - Startup priority (higher starts first)
45
+ * @property {number} [startupPriority=0] - Higher starts first
40
46
  */
41
47
 
42
48
  /**
@@ -70,6 +76,17 @@
70
76
  * @typedef {new (name: string, options?: import('../service-base/typedef.js').ServiceOptions) => import('../service-base/typedef.js').ServiceInstance} ServiceConstructor
71
77
  */
72
78
 
79
+ /**
80
+ * ServiceManager plugin interface
81
+ *
82
+ * @typedef {Object} ServiceManagerPlugin
83
+ * @property {string} name - Unique plugin identifier
84
+ * @property {import('./ServiceManager.js').ServiceManager|null} manager - ServiceManager reference
85
+ * @property {function(import('./ServiceManager.js').ServiceManager): void} attach - Attach to ServiceManager
86
+ * @property {function(): void} detach - Detach from ServiceManager
87
+ * @property {function(string, ServiceEntry, *): Promise<*|undefined>} [resolveServiceConfig] - Optional config resolution method
88
+ */
89
+
73
90
  // ============================================================================
74
91
  // INTERNAL TYPES
75
92
  // ============================================================================
@@ -80,11 +97,11 @@
80
97
  * @typedef {Object} ServiceEntry
81
98
  * @property {ServiceConstructor} ServiceClass - Service class constructor
82
99
  * @property {import('../service-base/typedef.js').ServiceInstance|null} instance - Service instance (lazy-created)
83
- * @property {*} config - Service configuration
84
- * @property {string[]} dependencies - Service dependencies
85
- * @property {Set<string>} dependents - Services that depend on this one
86
- * @property {string[]} tags - Service tags
87
- * @property {number} priority - Startup priority
100
+ * @property {ServiceConfigOrLabel} serviceConfigOrLabel
101
+ * @property {string[]} dependencies
102
+ * @property {Set<string>} dependents - Services that depend on this service
103
+ * @property {string[]} tags
104
+ * @property {number} startupPriority - Startup priority
88
105
  */
89
106
 
90
107
  export {};