@digital-alchemy/core 26.2.17 → 26.5.1

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 (85) hide show
  1. package/CLAUDE.md +302 -0
  2. package/README.md +19 -3
  3. package/dist/helpers/async.d.mts +37 -0
  4. package/dist/helpers/async.mjs +50 -15
  5. package/dist/helpers/async.mjs.map +1 -1
  6. package/dist/helpers/config-environment-loader.d.mts +39 -0
  7. package/dist/helpers/config-environment-loader.mjs +51 -11
  8. package/dist/helpers/config-environment-loader.mjs.map +1 -1
  9. package/dist/helpers/config-file-loader.d.mts +65 -0
  10. package/dist/helpers/config-file-loader.mjs +80 -4
  11. package/dist/helpers/config-file-loader.mjs.map +1 -1
  12. package/dist/helpers/config.d.mts +202 -5
  13. package/dist/helpers/config.mjs +60 -0
  14. package/dist/helpers/config.mjs.map +1 -1
  15. package/dist/helpers/context.d.mts +12 -1
  16. package/dist/helpers/cron.d.mts +154 -7
  17. package/dist/helpers/cron.mjs +47 -4
  18. package/dist/helpers/cron.mjs.map +1 -1
  19. package/dist/helpers/errors.d.mts +45 -0
  20. package/dist/helpers/errors.mjs +45 -0
  21. package/dist/helpers/errors.mjs.map +1 -1
  22. package/dist/helpers/events.d.mts +23 -0
  23. package/dist/helpers/events.mjs +23 -0
  24. package/dist/helpers/events.mjs.map +1 -1
  25. package/dist/helpers/extend.d.mts +50 -0
  26. package/dist/helpers/extend.mjs +63 -0
  27. package/dist/helpers/extend.mjs.map +1 -1
  28. package/dist/helpers/index.d.mts +9 -0
  29. package/dist/helpers/index.mjs +9 -0
  30. package/dist/helpers/index.mjs.map +1 -1
  31. package/dist/helpers/lifecycle.d.mts +102 -16
  32. package/dist/helpers/lifecycle.mjs +19 -1
  33. package/dist/helpers/lifecycle.mjs.map +1 -1
  34. package/dist/helpers/logger.d.mts +178 -17
  35. package/dist/helpers/logger.mjs +41 -1
  36. package/dist/helpers/logger.mjs.map +1 -1
  37. package/dist/helpers/module.d.mts +110 -0
  38. package/dist/helpers/module.mjs +55 -6
  39. package/dist/helpers/module.mjs.map +1 -1
  40. package/dist/helpers/service-runner.d.mts +27 -1
  41. package/dist/helpers/service-runner.mjs +27 -1
  42. package/dist/helpers/service-runner.mjs.map +1 -1
  43. package/dist/helpers/utilities.d.mts +123 -3
  44. package/dist/helpers/utilities.mjs +110 -3
  45. package/dist/helpers/utilities.mjs.map +1 -1
  46. package/dist/helpers/wiring.d.mts +385 -0
  47. package/dist/helpers/wiring.mjs +120 -0
  48. package/dist/helpers/wiring.mjs.map +1 -1
  49. package/dist/services/als.service.d.mts +10 -0
  50. package/dist/services/als.service.mjs +49 -0
  51. package/dist/services/als.service.mjs.map +1 -1
  52. package/dist/services/configuration.service.d.mts +22 -0
  53. package/dist/services/configuration.service.mjs +140 -12
  54. package/dist/services/configuration.service.mjs.map +1 -1
  55. package/dist/services/index.d.mts +8 -0
  56. package/dist/services/index.mjs +8 -0
  57. package/dist/services/index.mjs.map +1 -1
  58. package/dist/services/internal.service.d.mts +98 -19
  59. package/dist/services/internal.service.mjs +91 -9
  60. package/dist/services/internal.service.mjs.map +1 -1
  61. package/dist/services/is.service.d.mts +64 -4
  62. package/dist/services/is.service.mjs +67 -4
  63. package/dist/services/is.service.mjs.map +1 -1
  64. package/dist/services/lifecycle.service.d.mts +26 -0
  65. package/dist/services/lifecycle.service.mjs +67 -9
  66. package/dist/services/lifecycle.service.mjs.map +1 -1
  67. package/dist/services/logger.service.d.mts +27 -0
  68. package/dist/services/logger.service.mjs +133 -9
  69. package/dist/services/logger.service.mjs.map +1 -1
  70. package/dist/services/scheduler.service.d.mts +19 -0
  71. package/dist/services/scheduler.service.mjs +87 -4
  72. package/dist/services/scheduler.service.mjs.map +1 -1
  73. package/dist/services/wiring.service.d.mts +28 -0
  74. package/dist/services/wiring.service.mjs +152 -19
  75. package/dist/services/wiring.service.mjs.map +1 -1
  76. package/dist/testing/index.d.mts +4 -0
  77. package/dist/testing/index.mjs +4 -0
  78. package/dist/testing/index.mjs.map +1 -1
  79. package/dist/testing/mock-logger.d.mts +8 -0
  80. package/dist/testing/mock-logger.mjs +9 -0
  81. package/dist/testing/mock-logger.mjs.map +1 -1
  82. package/dist/testing/test-module.d.mts +107 -27
  83. package/dist/testing/test-module.mjs +58 -1
  84. package/dist/testing/test-module.mjs.map +1 -1
  85. package/package.json +33 -31
@@ -1,3 +1,23 @@
1
+ /**
2
+ * @file helpers/wiring.mts — types and pure functions for the DI wiring engine.
3
+ *
4
+ * @remarks
5
+ * This file is the **type backbone** of `@digital-alchemy/core`. It owns
6
+ * `TServiceParams`, `CreateLibrary`, `buildSortOrder`, `wireOrder`, and the
7
+ * two wiring-boundary symbols (`COERCE_CONTEXT`, `WIRE_PROJECT`). Every
8
+ * downstream `@digital-alchemy` library depends on these types.
9
+ *
10
+ * **Split rationale.** This file was deliberately separated from
11
+ * `services/wiring.service.mts` to break a circular module reference that
12
+ * would form if types and the runtime bootstrap logic lived together. Do not
13
+ * merge them. Runtime orchestration (`CreateApplication`, `bootstrap`,
14
+ * `wireService`, `teardown`) lives in `services/wiring.service.mts`; pure
15
+ * types and pure functions live here.
16
+ *
17
+ * **Downstream impact.** Changes to `TServiceParams` shape or to any exported
18
+ * type here ripple into every library. Treat all public exports as breaking
19
+ * surface.
20
+ */
1
21
  import type { AsyncLocalStorage } from "node:async_hooks";
2
22
  import type { EventEmitter } from "node:events";
3
23
  import type { Dayjs } from "dayjs";
@@ -8,9 +28,37 @@ import type { CronExpression, TOffset } from "./cron.mts";
8
28
  import type { TLifecycleBase } from "./lifecycle.mts";
9
29
  import type { GetLogger, TConfigLogLevel } from "./logger.mts";
10
30
  import type { TBlackHole } from "./utilities.mts";
31
+ /**
32
+ * The value a service factory may return.
33
+ *
34
+ * @remarks
35
+ * A service that returns `void` is wired for its side effects only (e.g.
36
+ * attaching lifecycle hooks). A service that returns an `OBJECT` exposes that
37
+ * object as its public API, accessible to other services via the module's
38
+ * namespace on `TServiceParams`.
39
+ */
11
40
  export type TServiceReturn<OBJECT extends object = object> = void | OBJECT;
41
+ /**
42
+ * Unresolved mapping of service name → factory function within a module.
43
+ *
44
+ * @internal
45
+ */
12
46
  export type TModuleMappings = Record<string, ServiceFunction>;
47
+ /**
48
+ * Resolved mapping of service name → return value after the factory has run.
49
+ *
50
+ * @internal
51
+ */
13
52
  export type TResolvedModuleMappings = Record<string, TServiceReturn>;
53
+ /**
54
+ * Shape of the options object passed to `CreateApplication`.
55
+ *
56
+ * @remarks
57
+ * `name` must be declared in `LoadedModules` via declaration merging so the
58
+ * type system can track which modules are loaded. `services` is the record of
59
+ * service factories that make up the application. `priorityInit` lets callers
60
+ * force specific services to wire before the rest.
61
+ */
14
62
  export interface ApplicationConfigurationOptions<S extends ServiceMap, C extends OptionalModuleConfiguration> {
15
63
  name: keyof LoadedModules;
16
64
  services: S;
@@ -21,33 +69,78 @@ export interface ApplicationConfigurationOptions<S extends ServiceMap, C extends
21
69
  */
22
70
  priorityInit?: Extract<keyof S, string>[];
23
71
  }
72
+ /**
73
+ * Union of all module definition shapes — either a library or an application.
74
+ *
75
+ * @remarks
76
+ * Used as a generic bound wherever code needs to accept either kind without
77
+ * caring which one it is.
78
+ */
24
79
  export type TConfigurable<S extends ServiceMap = ServiceMap, C extends OptionalModuleConfiguration = OptionalModuleConfiguration> = LibraryDefinition<S, C> | ApplicationDefinition<S, C>;
80
+ /**
81
+ * Type-safe config accessor bound to a specific configurable module.
82
+ *
83
+ * @remarks
84
+ * `K` is constrained to the keys of the config block extracted from `PARENT`,
85
+ * and the return type is the concrete resolved type for that key.
86
+ */
25
87
  export type TGetConfig<PARENT extends TConfigurable = TConfigurable> = <K extends keyof ExtractConfig<PARENT>>(key: K) => CastConfigResult<ExtractConfig<PARENT>[K]>;
88
+ /**
89
+ * Maps a `ServiceMap` to the resolved return types of each factory.
90
+ *
91
+ * @remarks
92
+ * Async factories are unwrapped — `Promise<T>` becomes `T`. This is the shape
93
+ * of the API object exposed on `TServiceParams` for a loaded module.
94
+ */
26
95
  export type GetApisResult<S extends ServiceMap> = {
27
96
  [K in keyof S]: ReturnType<S[K]> extends Promise<infer AsyncResult> ? AsyncResult : ReturnType<S[K]>;
28
97
  };
98
+ /** @internal — extracts the config block from a library or application definition. */
29
99
  type ExtractConfig<T> = T extends LibraryDefinition<ServiceMap, infer C> ? C : T extends ApplicationDefinition<ServiceMap, infer C> ? C : never;
100
+ /** A cron expression string or a `CronExpression` enum member. */
30
101
  export type Schedule = string | CronExpression;
102
+ /** A runnable item that can be started and stopped. */
31
103
  export type ScheduleItem = {
32
104
  start: () => void;
33
105
  stop: () => void;
34
106
  };
107
+ /** Base options required by every scheduler method. */
35
108
  export type SchedulerOptions = {
36
109
  exec: () => TBlackHole;
37
110
  };
38
111
  /**
112
+ * General code scheduling functions.
113
+ *
114
+ * @remarks
115
+ * Injected as `scheduler` into every `TServiceParams`. The scheduler is
116
+ * lifecycle-aware — scheduled callbacks do not begin firing until the
117
+ * `onReady` lifecycle stage. Each method returns a `RemoveCallback` so
118
+ * temporary schedules can be torn down without waiting for full shutdown.
119
+ *
39
120
  * General code scheduling functions
40
121
  *
41
122
  * Each method returns a stop function, for temporary scheduling items
42
123
  */
43
124
  export type TScheduler = {
44
125
  /**
126
+ * Run code on a cron schedule.
127
+ *
128
+ * @remarks
129
+ * Accepts a single schedule string or an array of schedules to fire `exec`
130
+ * on multiple cron patterns simultaneously.
131
+ *
45
132
  * Run code on a cron schedule
46
133
  */
47
134
  cron: (options: SchedulerOptions & {
48
135
  schedule: Schedule | Schedule[];
49
136
  }) => RemoveCallback;
50
137
  /**
138
+ * Run code at a dynamically computed time each period.
139
+ *
140
+ * @remarks
141
+ * Calls `next` at startup and again after each `reset` schedule fires.
142
+ * `next` returns the absolute `Dayjs` of the next desired execution.
143
+ *
51
144
  * Run code at a different time every {period}
52
145
  *
53
146
  * Calls `next` at start, and as determined by `reset`.
@@ -59,6 +152,8 @@ export type TScheduler = {
59
152
  next: () => Dayjs;
60
153
  }) => RemoveCallback;
61
154
  /**
155
+ * Lifecycle-aware `setInterval` replacement.
156
+ *
62
157
  * Same as setInterval but:
63
158
  *
64
159
  * - handles shutdown events properly
@@ -66,6 +161,8 @@ export type TScheduler = {
66
161
  */
67
162
  setInterval: (callback: () => TBlackHole, target: TOffset) => RemoveCallback;
68
163
  /**
164
+ * Lifecycle-aware `setTimeout` replacement.
165
+ *
69
166
  * Same as setTimeout but:
70
167
  *
71
168
  * - handles shutdown events properly
@@ -73,13 +170,49 @@ export type TScheduler = {
73
170
  */
74
171
  setTimeout: (callback: () => TBlackHole, target: TOffset) => RemoveCallback;
75
172
  };
173
+ /**
174
+ * Registry of all loaded module definitions.
175
+ *
176
+ * @remarks
177
+ * Downstream libraries extend this interface via declaration merging so that
178
+ * `TServiceParams` can expose their APIs under the correct key. The
179
+ * `boilerplate` entry is always present; every other entry is added by a
180
+ * library's declaration merge.
181
+ *
182
+ * @example Declaration merge in a library
183
+ * ```typescript
184
+ * declare module "@digital-alchemy/core" {
185
+ * export interface LoadedModules {
186
+ * my_lib: typeof MY_LIB;
187
+ * }
188
+ * }
189
+ * ```
190
+ */
76
191
  export interface LoadedModules {
77
192
  boilerplate: typeof LIB_BOILERPLATE;
78
193
  }
194
+ /** @internal — maps a config definition type to its concrete injected value. */
79
195
  type CastConfigResult<T extends AnyConfig> = T extends StringConfig<infer STRING> ? STRING : T extends BooleanConfig ? boolean : T extends NumberConfig ? number : T extends StringArrayConfig ? string[] : T extends InternalConfig<infer VALUE> ? VALUE : never;
196
+ /**
197
+ * The fully-typed config object injected as `config` into `TServiceParams`.
198
+ *
199
+ * @remarks
200
+ * Shaped as `{ [ModuleName]: { [ConfigKey]: ResolvedType } }`. Populated at
201
+ * bootstrap time by the configuration service and kept in sync via the
202
+ * `configSources` loaders.
203
+ */
80
204
  export type TInjectedConfig = {
81
205
  [ModuleName in keyof ModuleConfigs]: ConfigTypes<ModuleConfigs[ModuleName]>;
82
206
  };
207
+ /**
208
+ * Per-request data that can be attached to a log entry via ALS.
209
+ *
210
+ * @remarks
211
+ * Extend this interface via declaration merging to attach application-specific
212
+ * fields to every log line emitted within an ALS context.
213
+ *
214
+ * SEE DOCS http://docs.digital-alchemy.app/docs/core/declaration-merging
215
+ */
83
216
  export interface AsyncLogData {
84
217
  /**
85
218
  * return ms since entry, precision is on you
@@ -90,9 +223,24 @@ export interface AsyncLogData {
90
223
  */
91
224
  logger?: GetLogger;
92
225
  }
226
+ /**
227
+ * Shape of the data stored inside the `AsyncLocalStorage` instance managed by
228
+ * the ALS service.
229
+ *
230
+ * @remarks
231
+ * Extend via declaration merging to carry additional request-scoped fields
232
+ * alongside `logs`.
233
+ */
93
234
  export interface AsyncLocalData {
94
235
  logs: AsyncLogData;
95
236
  }
237
+ /**
238
+ * Public API of the ALS service as injected into `TServiceParams`.
239
+ *
240
+ * @remarks
241
+ * Wraps `AsyncLocalStorage<AsyncLocalData>` with helpers for entering a
242
+ * context, reading the store, and merging per-request log data.
243
+ */
96
244
  export type AlsExtension = {
97
245
  asyncStorage: () => AsyncLocalStorage<AsyncLocalData>;
98
246
  getStore: () => AsyncLocalData;
@@ -100,7 +248,41 @@ export type AlsExtension = {
100
248
  enterWith(data: AsyncLocalData): void;
101
249
  getLogData: () => AsyncLogData;
102
250
  };
251
+ /** A function that returns additional data to merge into ALS log context. */
103
252
  export type AlsHook = () => object;
253
+ /**
254
+ * The single parameter received by every service factory in the DI graph.
255
+ *
256
+ * @remarks
257
+ * `TServiceParams` is the core contract of `@digital-alchemy/core`. There is
258
+ * no class hierarchy, no decorators, no reflection — services are plain
259
+ * functions that destructure the params they need:
260
+ *
261
+ * ```typescript
262
+ * export function MyService({ logger, lifecycle, config }: TServiceParams) {
263
+ * lifecycle.onReady(() => logger.info("ready"));
264
+ * }
265
+ * ```
266
+ *
267
+ * **Well-known injections:**
268
+ * - `als` — `AsyncLocalStorage` wrapper for per-request context
269
+ * - `context` — branded string describing this service's wiring path
270
+ * - `event` — application-global `EventEmitter`
271
+ * - `internal` — utility methods and boot-state introspection
272
+ * - `lifecycle` — hooks into the seven boot/shutdown stages
273
+ * - `logger` — context-aware logger bound to this service
274
+ * - `scheduler` — cron/interval/sliding scheduling; respects lifecycle
275
+ * - `config` — typed config object; safe to read after `onPostConfig`
276
+ * - `params` — self-reference, useful when passing the full block deeper
277
+ *
278
+ * **Module APIs** are added as additional properties via declaration merging on
279
+ * {@link LoadedModules}. Each loaded library exposes its return value under the
280
+ * library's declared name.
281
+ *
282
+ * **Note:** `TServiceParams` lives in `helpers/wiring.mts`, not in
283
+ * `services/wiring.service.mts`. The split breaks a circular module reference
284
+ * that would form if types and the runtime bootstrap lived together.
285
+ */
104
286
  export type TServiceParams = {
105
287
  /**
106
288
  * hooks for AsyncLocalStorage
@@ -150,24 +332,80 @@ export type TServiceParams = {
150
332
  } & {
151
333
  [K in ExternalLoadedModules]: GetApis<LoadedModules[K]>;
152
334
  };
335
+ /** Names of all modules registered in `LoadedModules`. */
153
336
  export type LoadedModuleNames = Extract<keyof LoadedModules, string>;
337
+ /** `LoadedModuleNames` minus `"boilerplate"` — the user-land module names. */
154
338
  type ExternalLoadedModules = Exclude<LoadedModuleNames, "boilerplate">;
339
+ /**
340
+ * Maps each loaded module name to its declared configuration block.
341
+ *
342
+ * @internal
343
+ */
155
344
  type ModuleConfigs = {
156
345
  [K in LoadedModuleNames]: LoadedModules[K] extends LibraryDefinition<ServiceMap, infer Config> ? Config : LoadedModules[K] extends ApplicationDefinition<ServiceMap, infer Config> ? Config : never;
157
346
  };
347
+ /**
348
+ * Resolves each key of a config block to its concrete injected type.
349
+ *
350
+ * Now, map these configurations to their respective types using CastConfigResult for each property in the configs
351
+ */
158
352
  export type ConfigTypes<Config> = {
159
353
  [Key in keyof Config]: Config[Key] extends AnyConfig ? CastConfigResult<Config[Key]> : never;
160
354
  };
355
+ /**
356
+ * Maps each loaded module name to its flattened `"module.service"` strings.
357
+ *
358
+ * @remarks
359
+ * Used to build the `levelOverrides` key set in `LoggerOptions` so callers can
360
+ * address per-service log levels with full type safety.
361
+ */
161
362
  export type ServiceNames<T extends Extract<LoadedModuleNames, string> = Extract<LoadedModuleNames, string>> = {
162
363
  [key in T]: LoadedModules[key] extends LibraryDefinition<infer S, OptionalModuleConfiguration> ? `${key}.${Extract<keyof S, string>}` : LoadedModules[key] extends ApplicationDefinition<infer S, OptionalModuleConfiguration> ? `${key}.${Extract<keyof S, string>}` : never;
163
364
  };
365
+ /**
366
+ * Union of all `"module.service"` strings across every loaded module.
367
+ *
368
+ * @remarks
369
+ * Flattened variant of {@link ServiceNames} — the distributed union rather
370
+ * than the mapped object form.
371
+ */
164
372
  export type FlatServiceNames<T extends Extract<LoadedModuleNames, string> = Extract<LoadedModuleNames, string>> = {
165
373
  [key in T]: LoadedModules[key] extends LibraryDefinition<infer S, OptionalModuleConfiguration> ? `${key}.${Extract<keyof S, string>}` : LoadedModules[key] extends ApplicationDefinition<infer S, OptionalModuleConfiguration> ? `${key}.${Extract<keyof S, string>}` : never;
166
374
  }[T];
375
+ /**
376
+ * Extracts the resolved API object type for a loaded module definition.
377
+ *
378
+ * @remarks
379
+ * Used internally to type the per-module properties on `TServiceParams`.
380
+ */
167
381
  export type GetApis<T> = T extends LibraryDefinition<infer S, OptionalModuleConfiguration> ? GetApisResult<S> : T extends ApplicationDefinition<infer S, OptionalModuleConfiguration> ? GetApisResult<S> : never;
382
+ /**
383
+ * A function that accepts a service name and returns the resolved API for that
384
+ * service, handling async factories transparently.
385
+ *
386
+ * @internal
387
+ */
168
388
  export type Loader<PARENT extends TConfigurable> = <K extends keyof PARENT["services"]>(serviceName: K) => ReturnType<PARENT["services"][K]> extends Promise<infer AsyncResult> ? AsyncResult : ReturnType<PARENT["services"][K]>;
389
+ /**
390
+ * The function signature every service factory must satisfy.
391
+ *
392
+ * @remarks
393
+ * A service receives `TServiceParams` and returns either a value or a
394
+ * `Promise` of a value. The wiring engine awaits async factories before
395
+ * exposing the result to other services.
396
+ */
169
397
  export type ServiceFunction<R = unknown> = (params: TServiceParams) => R | Promise<R>;
398
+ /** A record of service-name → service factory. */
170
399
  export type ServiceMap = Record<string, ServiceFunction>;
400
+ /**
401
+ * Shape of the options object passed to `CreateLibrary`.
402
+ *
403
+ * @remarks
404
+ * `name` must match the key declared in `LoadedModules`. `depends` lists
405
+ * libraries that must be wired before this one; `optionalDepends` lists
406
+ * libraries that should be wired first *if* they are present in the
407
+ * application but do not cause a boot failure when absent.
408
+ */
171
409
  export interface LibraryConfigurationOptions<S extends ServiceMap, C extends OptionalModuleConfiguration> {
172
410
  name: keyof LoadedModules;
173
411
  services: S;
@@ -192,9 +430,29 @@ export interface LibraryConfigurationOptions<S extends ServiceMap, C extends Opt
192
430
  */
193
431
  priorityInit?: Extract<keyof S, string>[];
194
432
  }
433
+ /**
434
+ * Partial snapshot of the full application configuration hierarchy.
435
+ *
436
+ * @remarks
437
+ * Used by `BootstrapOptions.configuration` to supply override values before
438
+ * env/argv/file loaders run, and by the `merge` method on
439
+ * `DigitalAlchemyConfiguration`.
440
+ */
195
441
  export type PartialConfiguration = Partial<{
196
442
  [ModuleName in keyof ModuleConfigs]: Partial<ConfigTypes<ModuleConfigs[ModuleName]>>;
197
443
  }>;
444
+ /**
445
+ * Options passed to `ApplicationDefinition.bootstrap()` to customise the boot
446
+ * sequence.
447
+ *
448
+ * @remarks
449
+ * Most fields have safe defaults and are optional. The most commonly used are:
450
+ * - `configuration` — seed values applied before loaders run
451
+ * - `appendLibrary` / `appendService` — inject test doubles without modifying
452
+ * the application definition
453
+ * - `configSources` — opt individual loader channels in/out
454
+ * - `loggerOptions` — tune the built-in logger's output format
455
+ */
198
456
  export type BootstrapOptions = {
199
457
  /**
200
458
  * An extra library to load after the application is constructed.
@@ -250,6 +508,14 @@ export type BootstrapOptions = {
250
508
  */
251
509
  configSources?: Partial<Record<DataTypes, boolean>>;
252
510
  };
511
+ /**
512
+ * Fine-grained controls for the built-in chalk/stdout logger.
513
+ *
514
+ * @remarks
515
+ * Passed as `loggerOptions` inside `BootstrapOptions`. Overrides here only
516
+ * affect the built-in logger; they are ignored when `customLogger` is
517
+ * provided.
518
+ */
253
519
  export type LoggerOptions = {
254
520
  /**
255
521
  * Generic data to include as data payload for all logs
@@ -299,7 +565,26 @@ export type LoggerOptions = {
299
565
  */
300
566
  stdOut?: boolean;
301
567
  };
568
+ /**
569
+ * Symbol used as the key for the `[WIRE_PROJECT]` method on library and
570
+ * application definitions.
571
+ *
572
+ * @remarks
573
+ * This symbol is the wiring boundary between a module definition and the
574
+ * bootstrap engine. `wiring.service.mts` calls `[WIRE_PROJECT]` on each
575
+ * module to initialise its lifecycle, load its configuration, and wire each
576
+ * service in priority order. Do not call `[WIRE_PROJECT]` outside of the
577
+ * bootstrap process.
578
+ *
579
+ * @internal
580
+ */
302
581
  export declare const WIRE_PROJECT: unique symbol;
582
+ /**
583
+ * Internal wiring method present on every `LibraryDefinition` and
584
+ * `ApplicationDefinition`.
585
+ *
586
+ * @internal
587
+ */
303
588
  type Wire = {
304
589
  /**
305
590
  * Internal method used in bootstrapping, do not call elsewhere
@@ -309,9 +594,26 @@ type Wire = {
309
594
  */
310
595
  [WIRE_PROJECT]: (internal: InternalDefinition, WireService: (project: string, service: string, definition: ServiceFunction, lifecycle: TLifecycleBase, internal: InternalDefinition) => Promise<TServiceReturn<object>>) => Promise<TLifecycleBase>;
311
596
  };
597
+ /**
598
+ * A fully-constructed library module, ready to be listed in
599
+ * `ApplicationConfigurationOptions.libraries`.
600
+ *
601
+ * @remarks
602
+ * Created by `CreateLibrary`. The `[WIRE_PROJECT]` symbol key is the bootstrap
603
+ * engine's entry point into this module; every other field is readable for
604
+ * introspection but should not be mutated after construction.
605
+ */
312
606
  export type LibraryDefinition<S extends ServiceMap, C extends OptionalModuleConfiguration> = LibraryConfigurationOptions<S, C> & Wire & {
313
607
  type: "library";
314
608
  };
609
+ /**
610
+ * A fully-constructed application module, ready to be bootstrapped.
611
+ *
612
+ * @remarks
613
+ * Created by `CreateApplication` in `services/wiring.service.mts`. Extends the
614
+ * library configuration shape with the `bootstrap` and `teardown` methods, a
615
+ * `booted` flag, and a `logger` pre-bound to the application context.
616
+ */
315
617
  export type ApplicationDefinition<S extends ServiceMap, C extends OptionalModuleConfiguration> = ApplicationConfigurationOptions<S, C> & Wire & {
316
618
  logger: GetLogger;
317
619
  type: "application";
@@ -319,11 +621,94 @@ export type ApplicationDefinition<S extends ServiceMap, C extends OptionalModule
319
621
  bootstrap: (options?: BootstrapOptions) => Promise<TServiceParams>;
320
622
  teardown: () => Promise<void>;
321
623
  };
624
+ /** Convenience alias for a library definition with unknown service/config types. */
322
625
  export type TLibrary = LibraryDefinition<ServiceMap, OptionalModuleConfiguration>;
626
+ /**
627
+ * Topologically sort the libraries declared by an application so that each
628
+ * library's dependencies are wired before it.
629
+ *
630
+ * @remarks
631
+ * Uses a simple iterative approach: on each pass, pick the first library whose
632
+ * required dependencies have all already been placed in `out`, then remove it
633
+ * from the working set. Optional dependencies that are not present in the
634
+ * application's library list are skipped rather than causing a failure.
635
+ *
636
+ * Version mismatches (same name, different object reference) emit a warning
637
+ * but do not block boot — the application-declared version wins.
638
+ *
639
+ * @throws {BootstrapException} `MISSING_DEPENDENCY` when a required dependency
640
+ * is not listed in the application's `libraries` array.
641
+ * @throws {BootstrapException} `BAD_SORT` when no progress can be made —
642
+ * usually indicates a circular dependency.
643
+ */
323
644
  export declare function buildSortOrder<S extends ServiceMap, C extends OptionalModuleConfiguration>(app: ApplicationDefinition<S, C>, logger: GetLogger): TLibrary[];
645
+ /**
646
+ * Cast a plain string to the branded `TContext` type.
647
+ *
648
+ * @remarks
649
+ * Used at the wiring boundary to produce context strings without importing the
650
+ * `TContext` brand into every caller. Prefer descriptive names like
651
+ * `"boilerplate:wiring"` over opaque identifiers so logs are readable.
652
+ *
653
+ * @internal
654
+ */
324
655
  export declare const COERCE_CONTEXT: (context: string) => TContext;
656
+ /**
657
+ * Fixed context string used for all errors and log messages emitted during the
658
+ * wiring phase itself.
659
+ *
660
+ * @internal
661
+ */
325
662
  export declare const WIRING_CONTEXT: TContext;
663
+ /**
664
+ * Assert that a library name and service map meet the minimum requirements to
665
+ * be wired.
666
+ *
667
+ * @remarks
668
+ * Called by `CreateLibrary` before any other work. Throws immediately if the
669
+ * name is empty or if any entry in `serviceList` is not a function, so
670
+ * misconfiguration surfaces at library-construction time rather than at wire
671
+ * time.
672
+ *
673
+ * @throws {BootstrapException} `MISSING_LIBRARY_NAME` when `project` is empty.
674
+ * @throws {BootstrapException} `INVALID_SERVICE_DEFINITION` when any service is not a function.
675
+ *
676
+ * @internal
677
+ */
326
678
  export declare function validateLibrary<S extends ServiceMap>(project: string, serviceList: S): void | never;
679
+ /**
680
+ * Produce a wiring order for a service list, hoisting `priority` items to the
681
+ * front and appending the remainder in their original order.
682
+ *
683
+ * @remarks
684
+ * Validates that `priority` contains no duplicates before merging, since a
685
+ * service wired twice would produce subtle bugs that are hard to diagnose at
686
+ * runtime.
687
+ *
688
+ * @throws {BootstrapException} `DOUBLE_PRIORITY` when `priority` contains
689
+ * duplicate service names.
690
+ */
327
691
  export declare function wireOrder<T extends string>(priority: T[], list: T[]): T[];
692
+ /**
693
+ * Construct a `LibraryDefinition` from a configuration options object.
694
+ *
695
+ * @remarks
696
+ * `CreateLibrary` is the public factory for all non-application modules. It
697
+ * validates the name and service map, then builds the `[WIRE_PROJECT]`
698
+ * implementation that the bootstrap engine calls to wire each service in order.
699
+ *
700
+ * **Lifecycle hook timing.** Services should attach all lifecycle hooks at the
701
+ * top level of their factory function. Hooks attached after the
702
+ * `[WIRE_PROJECT]` call completes will be silently lost (worst case) or cause
703
+ * a fatal error (best case).
704
+ *
705
+ * **Priority init.** `priorityInit` services are wired before all others in
706
+ * declaration order. The remaining services wire in no guaranteed order.
707
+ *
708
+ * @throws {BootstrapException} `MISSING_LIBRARY_NAME` — via `validateLibrary`.
709
+ * @throws {BootstrapException} `INVALID_SERVICE_DEFINITION` — via `validateLibrary`.
710
+ * @throws {BootstrapException} `MISSING_PRIORITY_SERVICE` when a name listed in
711
+ * `priorityInit` does not correspond to a service in the `services` map.
712
+ */
328
713
  export declare function CreateLibrary<S extends ServiceMap, C extends OptionalModuleConfiguration>({ name: libraryName, configuration, priorityInit, services, depends, optionalDepends, ...extra }: LibraryConfigurationOptions<S, C>): LibraryDefinition<S, C>;
329
714
  export {};