alepha 0.8.1 → 0.9.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.
package/core.d.ts CHANGED
@@ -2,308 +2,132 @@ import { AsyncLocalStorage } from "node:async_hooks";
2
2
  import { TypeCheck } from "@sinclair/typebox/compiler";
3
3
  import * as TypeBoxValue from "@sinclair/typebox/value";
4
4
  import * as TypeBox from "@sinclair/typebox";
5
- import { ArrayOptions, FormatRegistry, IntegerOptions, NumberOptions, ObjectOptions, SchemaOptions, Static, Static as Static$1, StaticDecode, StaticEncode, StringOptions, TAny, TAny as TAny$1, TArray, TArray as TArray$1, TBoolean, TBoolean as TBoolean$1, TComposite, TInteger, TIntersect, TMappedResult, TNull, TNumber, TNumber as TNumber$1, TObject, TObject as TObject$1, TOmit, TOptional, TOptionalWithFlag, TPartial, TPartialFromMappedResult, TPick, TProperties, TProperties as TProperties$1, TRecord, TRecord as TRecord$1, TRecordOrObject, TSchema, TSchema as TSchema$1, TString, TString as TString$1, TUndefined, TUnion, TUnsafe, TVoid, Type, TypeGuard, Union, UnsafeOptions } from "@sinclair/typebox";
5
+ import { ArrayOptions, FormatRegistry, IntegerOptions, NumberOptions, ObjectOptions, SchemaOptions, Static, Static as Static$1, StaticDecode, StaticEncode, StringOptions, TAny, TAny as TAny$1, TArray, TArray as TArray$1, TBoolean, TBoolean as TBoolean$1, TComposite, TInteger, TIntersect, TNull, TNumber, TNumber as TNumber$1, TObject, TObject as TObject$1, TOmit, TOptional, TOptionalWithFlag, TPartial, TPick, TProperties, TProperties as TProperties$1, TRecord, TRecord as TRecord$1, TSchema, TSchema as TSchema$1, TString, TString as TString$1, TUnion, TUnsafe, TypeGuard, UnsafeOptions } from "@sinclair/typebox";
6
6
  import { ValueError } from "@sinclair/typebox/errors";
7
7
  import { Readable } from "node:stream";
8
8
  import { ReadableStream as ReadableStream$1 } from "node:stream/web";
9
9
 
10
10
  //#region src/constants/KIND.d.ts
11
11
  /**
12
- * Used for identifying descriptors.
13
- *
14
- * @internal
15
- */
12
+ * Used for identifying descriptors.
13
+ *
14
+ * @internal
15
+ */
16
16
  declare const KIND: unique symbol;
17
- //#endregion
18
- //#region src/constants/OPTIONS.d.ts
19
- /**
20
- * Used for descriptors options.
21
- *
22
- * @internal
23
- */
24
- declare const OPTIONS: unique symbol;
25
- //#endregion
26
- //#region src/interfaces/Async.d.ts
27
- // ---------------------------------------------------------------------------------------------------------------------
28
- /**
29
- * Represents a value that can be either a value or a promise.
30
- */
31
- type Async<T> = T | Promise<T>;
32
- // ---------------------------------------------------------------------------------------------------------------------
33
- /**
34
- * Represents a function that returns a promise.
35
- */
36
- type PromiseFn = (...args: any[]) => Promise<any>;
37
- // ---------------------------------------------------------------------------------------------------------------------
38
- /**
39
- * Represents a function that returns an async value.
40
- */
41
- type AsyncFn = (...args: any[]) => Async<any>;
42
- // ---------------------------------------------------------------------------------------------------------------------
43
- type MaybePromise<T> = T extends Promise<any> ? T : Promise<T>;
17
+ //# sourceMappingURL=KIND.d.ts.map
44
18
  //#endregion
45
19
  //#region src/interfaces/Service.d.ts
46
- // ---------------------------------------------------------------------------------------------------------------------
47
20
  /**
48
- * In Alepha, a service is a class that can be instantiated. Nothing more, nothing less.
49
- */
50
- type Service<T extends object = any> = InstantiableService<T> | AbstractService<T>;
51
- type InstantiableService<T extends object = any> = new (...args: any[]) => T;
52
- type AbstractService<T extends object = any> = abstract new (...args: any[]) => T;
53
- // ---------------------------------------------------------------------------------------------------------------------
21
+ * In Alepha, a service is a class that can be instantiated or an abstract class. Nothing more, nothing less...
22
+ */
23
+ type Service<T extends object = any> = InstantiableClass<T> | AbstractClass<T>;
24
+ type InstantiableClass<T extends object = any> = new (...args: any[]) => T;
25
+ /**
26
+ * Abstract class is a class that cannot be instantiated directly!
27
+ * It widely used for defining interfaces.
28
+ */
29
+ type AbstractClass<T extends object = any> = abstract new (...args: any[]) => T;
54
30
  /**
55
- * Service substitution allows you to register a class as a different class.
56
- */
31
+ * Service substitution allows you to register a class as a different class.
32
+ * Providing class A, but using class B instead.
33
+ * This is useful for testing, mocking, or providing a different implementation of a service.
34
+ *
35
+ * class A is mostly an AbstractClass, while class B is an InstantiableClass.
36
+ */
57
37
  interface ServiceSubstitution<T extends object = any> {
58
38
  /**
59
- * Every time someone asks for this service, it will be provided with the 'use' service.
60
- */
39
+ * Every time someone asks for this class, it will be provided with the 'use' class.
40
+ */
61
41
  provide: Service<T>;
62
42
  /**
63
- * Service to use instead of the 'provide' service.
64
- *
65
- * Note: Syntax is based on Angular's DI system.
66
- */
43
+ * Service to use instead of the 'provide' service.
44
+ *
45
+ * Syntax is inspired by Angular's DI system.
46
+ */
67
47
  use: Service<T>;
68
48
  /**
69
- * If true and the service already exists, just ignore the substitution and do not throw an error.
70
- * Mostly used for plugins to enforce a substitution without throwing an error.
71
- */
49
+ * If true, if the service already exists -> just ignore the substitution and do not throw an error.
50
+ * Mostly used for plugins to enforce a substitution without throwing an error.
51
+ */
72
52
  optional?: boolean;
73
53
  }
74
- // ---------------------------------------------------------------------------------------------------------------------
75
54
  /**
76
- * Every time you register a service, you can use this type to define it.
77
- *
78
- * alepha.with( ServiceEntry )
79
- * or
80
- * alepha.with( provide: ServiceEntry, use: MyOwnServiceEntry )
81
- *
82
- * And yes, you declare the *type* of the service, not the *instance*.
83
- */
55
+ * Every time you register a service, you can use this type to define it.
56
+ *
57
+ * alepha.with( ServiceEntry )
58
+ * or
59
+ * alepha.with( provide: ServiceEntry, use: MyOwnServiceEntry )
60
+ *
61
+ * And yes, you declare the *type* of the service, not the *instance*.
62
+ */
84
63
  type ServiceEntry<T extends object = any> = Service<T> | ServiceSubstitution<T>;
64
+ //# sourceMappingURL=Service.d.ts.map
85
65
  //#endregion
86
- //#region src/descriptors/$hook.d.ts
87
- declare const KEY = "HOOK";
88
- /**
89
- * Registers a new hook.
90
- *
91
- * ```ts
92
- * import { $hook } from "alepha";
93
- *
94
- * class MyProvider {
95
- * onStart = $hook({
96
- * name: "start", // or "configure", "ready", "stop", ...
97
- * handler: async (app) => {
98
- * // await db.connect(); ...
99
- * }
100
- * });
101
- * }
102
- * ```
103
- *
104
- * Hooks are used to run async functions from all registered providers/services.
105
- *
106
- * You can't register a hook after the App has started.
107
- *
108
- * It's used under the hood by the `configure`, `start`, and `stop` methods.
109
- * Some modules also use hooks to run their own logic. (e.g. `@alepha/server`).
110
- *
111
- * You can create your own hooks by using module augmentation:
112
- *
113
- * ```ts
114
- * declare module "alepha" {
115
- *
116
- * interface Hooks {
117
- * "my:custom:hook": {
118
- * arg1: string;
119
- * }
120
- * }
121
- * }
122
- *
123
- * await alepha.emit("my:custom:hook", { arg1: "value" });
124
- * ```
125
- *
126
- */
127
- declare const $hook: {
128
- <T extends keyof Hooks>(options: HookOptions<T>): HookDescriptor<T>;
129
- [KIND]: string;
66
+ //#region src/helpers/descriptor.d.ts
67
+ declare const descriptorEvents: {
68
+ events: Map<Service, ((alepha: Alepha) => void)[]>;
69
+ on(descriptor: Service, callback: (alepha: Alepha) => void): void;
70
+ emit(descriptor: Service, alepha: Alepha): void;
71
+ bind(when: Service, register: Service): void;
130
72
  };
131
- interface HookOptions<T extends keyof Hooks> {
132
- /**
133
- * The name of the hook. "configure", "start", "ready", "stop", ...
134
- */
135
- on: T;
136
- /**
137
- * The handler to run when the hook is triggered.
138
- */
139
- handler: (app: Hooks[T]) => Async<any>;
140
- /**
141
- * Force the hook to run first or last on the list of hooks.
142
- */
143
- priority?: "first" | "last";
144
- /**
145
- * Empty placeholder, not working yet. :-)
146
- */
147
- before?: object | Array<object>;
148
- /**
149
- * Empty placeholder, not working yet. :-)
150
- */
151
- after?: object | Array<object>;
73
+ interface DescriptorArgs<T extends object = {}> {
74
+ options: T;
75
+ alepha: Alepha;
76
+ service: InstantiableClass<Service>;
77
+ module?: Service;
152
78
  }
153
- interface Hook<T extends keyof Hooks = any> {
154
- caller?: Service;
155
- priority?: "first" | "last";
156
- callback: (payload: Hooks[T]) => Async<void>;
79
+ interface DescriptorConfig {
80
+ propertyKey: string;
81
+ service: InstantiableClass<Service>;
82
+ module?: Service;
157
83
  }
158
- interface HookDescriptor<T extends keyof Hooks> {
159
- [KIND]: typeof KEY;
160
- [OPTIONS]: HookOptions<T>;
161
- (app: Hooks[T]): Async<any>;
84
+ declare abstract class Descriptor<T extends object = {}> {
85
+ protected readonly alepha: Alepha;
86
+ readonly options: T;
87
+ readonly config: DescriptorConfig;
88
+ constructor(args: DescriptorArgs<T>);
89
+ /**
90
+ * Called automatically by Alepha after the descriptor is created.
91
+ */
92
+ protected onInit(): void;
162
93
  }
94
+ type DescriptorFactory<TDescriptor extends Descriptor = Descriptor> = {
95
+ (options: TDescriptor["options"]): TDescriptor;
96
+ [KIND]: InstantiableClass<TDescriptor>;
97
+ };
98
+ type DescriptorFactoryLike<T extends object = any> = {
99
+ (options: T): any;
100
+ [KIND]: any;
101
+ };
102
+ declare const createDescriptor: <TDescriptor extends Descriptor>(descriptor: InstantiableClass<TDescriptor>, options: TDescriptor["options"]) => TDescriptor;
103
+ //# sourceMappingURL=descriptor.d.ts.map
163
104
  //#endregion
164
105
  //#region src/helpers/Module.d.ts
165
106
  interface Module {
166
- name?: string;
107
+ $name?: string;
167
108
  $services: (alepha: Alepha) => void | Alepha;
168
109
  }
169
110
  interface ModuleDefinition extends Module {
170
111
  services: Array<Service>;
171
112
  }
172
- // ---------------------------------------------------------------------------------------------------------------------
173
113
  declare const isModule: (value: unknown) => value is Module;
174
114
  declare const toModuleName: (name: string) => string;
115
+ //# sourceMappingURL=Module.d.ts.map
175
116
  //#endregion
176
- //#region src/descriptors/$cursor.d.ts
177
- /**
178
- * Get Alepha instance and Class definition from the current context.
179
- * This should be used inside a descriptor only.
180
- *
181
- * ```ts
182
- * import { $cursor } from "alepha";
183
- *
184
- * const $ = () => {
185
- *
186
- * const { context, definition } = $cursor();
187
- *
188
- * // context - alepha instance
189
- * // definition - class which is creating this descriptor
190
- *
191
- * return {};
192
- * }
193
- *
194
- * ```
195
- *
196
- * @internal
197
- */
198
- declare const $cursor: () => CursorDescriptor;
199
- // ---------------------------------------------------------------------------------------------------------------------
200
- /**
201
- * /!\ Global variable /!\
202
- *
203
- * Store the current context and definition during injection phase.
204
- *
205
- * @internal
206
- */
207
- declare const __alephaRef: {
208
- context?: Alepha;
209
- definition?: Service;
210
- module?: ModuleDefinition;
211
- $services?: {
212
- module: ModuleDefinition;
213
- parent: Service;
214
- };
215
- };
216
- // ---------------------------------------------------------------------------------------------------------------------
217
- /**
218
- * Cursor descriptor.
219
- */
220
- interface CursorDescriptor {
221
- context: Alepha;
222
- definition?: Service;
223
- module?: ModuleDefinition;
224
- }
225
- //#endregion
226
- //#region src/helpers/EventEmitterLike.d.ts
227
- // ---------------------------------------------------------------------------------------------------------------------
228
- /**
229
- * Low-cost event emitter like for internal use.
230
- * Used only for descriptor implicit registration.
231
- */
232
- declare class EventEmitterLike<TEvents extends {
233
- [key: string]: any;
234
- }> {
235
- private hooks;
236
- on<T extends keyof TEvents>(event: T, callback: (data: TEvents[T]) => void): void;
237
- emit<T extends keyof TEvents>(event: T, data: TEvents[T]): void;
238
- }
239
- //#endregion
240
- //#region src/helpers/descriptor.d.ts
241
- // ---------------------------------------------------------------------------------------------------------------------
242
- /**
243
- * Descriptor events.
244
- *
245
- * - `create` - Emitted when a descriptor is created.
246
- */
247
- declare const descriptorEvents: EventEmitterLike<{
248
- create: CursorDescriptor & {
249
- [KIND]: string;
250
- };
251
- }>;
252
- // ---------------------------------------------------------------------------------------------------------------------
253
- /**
254
- * Register a descriptor.
255
- *
256
- * This is used to run the event "create" and allow auto-registration of descriptors.
257
- *
258
- * @internal
259
- * @param kind
260
- */
261
- declare const __descriptor: (kind: string) => void;
262
- // ---------------------------------------------------------------------------------------------------------------------
263
- /**
264
- * Auto-inject a class/module when a descriptor is created.
265
- *
266
- * Like, you auto-inject the ServerModule when a `$route` descriptor is used.
267
- *
268
- * @param descriptor
269
- * @param to
270
- */
271
- declare const __bind: (descriptor: {
272
- [KIND]: string;
273
- }, ...to: Service[]) => void;
274
- // ---------------------------------------------------------------------------------------------------------------------
275
- /**
276
- * Check if the value is a descriptor value.
277
- *
278
- * @param value - Value to check.
279
- * @returns Is the value a descriptor value.
280
- */
281
- declare const isDescriptorValue: (value: any) => value is DescriptorIdentifier;
282
- // ---------------------------------------------------------------------------------------------------------------------
117
+ //#region src/interfaces/Async.d.ts
283
118
  /**
284
- * The "$descriptor" function.
285
- */
286
- interface Descriptor<T extends object = any> {
287
- [KIND]: string;
288
- (options: T): DescriptorIdentifier<T>;
289
- }
290
- // ---------------------------------------------------------------------------------------------------------------------
119
+ * Represents a value that can be either a value or a promise of value.
120
+ */
121
+ type Async<T> = T | Promise<T>;
291
122
  /**
292
- * Class member descriptor.
293
- */
294
- interface DescriptorIdentifier<T = object> {
295
- [KIND]: string;
296
- [OPTIONS]: T;
297
- }
298
- // ---------------------------------------------------------------------------------------------------------------------
123
+ * Represents a function that returns an async value.
124
+ */
125
+ type AsyncFn = (...args: any[]) => Async<any>;
299
126
  /**
300
- * Descriptor identifier + his instance + his key.
301
- */
302
- interface DescriptorItem<T extends Descriptor> {
303
- value: ReturnType<T>;
304
- key: string;
305
- instance: Record<string, any>;
306
- }
127
+ * Transforms a type T into a promise if it is not already a promise.
128
+ */
129
+ type MaybePromise<T> = T extends Promise<any> ? T : Promise<T>;
130
+ //# sourceMappingURL=Async.d.ts.map
307
131
  //#endregion
308
132
  //#region src/providers/AlsProvider.d.ts
309
133
  type AsyncLocalStorageData = any;
@@ -316,70 +140,70 @@ declare class AlsProvider {
316
140
  get<T>(key: string): T | undefined;
317
141
  set<T>(key: string, value: T): void;
318
142
  }
143
+ //# sourceMappingURL=AlsProvider.d.ts.map
319
144
  //#endregion
320
145
  //#region src/services/Logger.d.ts
321
- // ---------------------------------------------------------------------------------------------------------------------
322
146
  type LogLevel = "error" | "warn" | "info" | "debug" | "trace" | "silent";
323
- // ---------------------------------------------------------------------------------------------------------------------
324
147
  interface LoggerEnv {
325
148
  /**
326
- * Default log level for the application.
327
- * Default by environment:
328
- * - dev = "debug"
329
- * - test = "error"
330
- * - prod = "info"
331
- *
332
- * "trace" | "debug" | "info" | "warn" | "error" | "silent"
333
- */
149
+ * Default log level for the application.
150
+ * Default by environment:
151
+ * - dev = "debug"
152
+ * - test = "error"
153
+ * - prod = "info"
154
+ *
155
+ * "trace" | "debug" | "info" | "warn" | "error" | "silent"
156
+ */
334
157
  LOG_LEVEL?: string;
335
158
  /**
336
- * Disable colors in the console output.
337
- */
159
+ * Disable colors in the console output.
160
+ */
338
161
  NO_COLOR?: string;
339
162
  /**
340
- * Force color output for the application.
341
- */
163
+ * Force color output for the application.
164
+ */
342
165
  FORCE_COLOR?: string;
343
166
  /**
344
- * Log format.
345
- *
346
- * @default "text"
347
- */
167
+ * Log format.
168
+ *
169
+ * @default "text"
170
+ */
348
171
  LOG_FORMAT?: "json" | "text" | "cli" | "raw";
349
172
  }
350
- // ---------------------------------------------------------------------------------------------------------------------
351
173
  interface LoggerOptions {
352
174
  /**
353
- * The logging level. Can be one of "error", "warn", "info", "debug", or "trace".
354
- */
175
+ * The logging level. Can be one of "error", "warn", "info", "debug", or "trace".
176
+ */
355
177
  level?: string;
178
+ /**
179
+ * The name of the application. Used to identify the source of the log messages.
180
+ */
356
181
  app?: string;
357
182
  /**
358
- * The name of the logger. Like a module name or a service name.
359
- */
183
+ * The name of the logger. Like a module name or a service name.
184
+ */
360
185
  name?: string;
361
186
  /**
362
- * An optional context to include in the log output. Like a request ID or a correlation ID.
363
- */
187
+ * An optional context to include in the log output. Like a request ID or a correlation ID.
188
+ */
364
189
  context?: string;
365
190
  /**
366
- * An optional tag to include in the log output. Like a class name or a module name.
367
- */
191
+ * An optional tag to include in the log output. Like a class name or a module name.
192
+ */
368
193
  caller?: string;
369
194
  /**
370
- * Whether to use colors in the log output. Defaults to true.
371
- */
195
+ * Whether to use colors in the log output. Defaults to true.
196
+ */
372
197
  color?: boolean;
373
198
  /**
374
- * Log output format. Can be "json", "text", or "cli".
375
- */
199
+ * Log output format. Can be "json", "text", or "cli".
200
+ */
376
201
  format?: string;
377
202
  /**
378
- * An optional async local storage provider to use for storing context information.
379
- */
203
+ * An optional async local storage provider to use for storing context information.
204
+ */
380
205
  als?: AlsProvider;
381
206
  }
382
- // ---------------------------------------------------------------------------------------------------------------------
383
207
  declare const COLORS: {
384
208
  reset: string;
385
209
  grey: string;
@@ -392,7 +216,6 @@ declare const COLORS: {
392
216
  darkGrey: string;
393
217
  };
394
218
  declare const LEVEL_COLORS: Record<string, string>;
395
- // ---------------------------------------------------------------------------------------------------------------------
396
219
  declare class Logger {
397
220
  protected levelOrder: Record<string, number>;
398
221
  readonly level: string;
@@ -414,32 +237,34 @@ declare class Logger {
414
237
  debug(message: unknown, data?: object | Error | string): void;
415
238
  trace(message: unknown, data?: object | Error | string): void;
416
239
  /**
417
- * Log a message to the console.
418
- */
240
+ * Log a message to the console.
241
+ */
419
242
  protected log(level: LogLevel, message: unknown, data?: object | Error | string): void;
420
243
  /**
421
- * Print a log message to the console.
422
- */
244
+ * Print a log message to the console.
245
+ */
423
246
  protected print(formatted: string): void;
424
247
  /**
425
- * Format a log message to JSON.
426
- */
248
+ * Format a log message to JSON.
249
+ */
427
250
  protected formatJson(level: LogLevel, message: unknown, data?: object | Error | string): string;
428
251
  protected formatJsonError(error: Error): object;
429
252
  /**
430
- * Format a log message to a string.
431
- */
253
+ * Format a log message to a string.
254
+ */
432
255
  protected formatLog(level: LogLevel, message: string, data?: object | Error): string;
256
+ protected nowTimeFormatted(): string;
257
+ protected pad2: (n: number) => string;
258
+ protected pad3: (n: number) => string;
433
259
  protected colorize(color: string, text: string, reset?: string): string;
434
260
  /**
435
- * Format an error to a string.
436
- *
437
- * @param error
438
- * @protected
439
- */
261
+ * Format an error to a string.
262
+ *
263
+ * @param error
264
+ * @protected
265
+ */
440
266
  protected formatError(error: Error): string;
441
267
  }
442
- // ---------------------------------------------------------------------------------------------------------------------
443
268
  declare class MockLogger extends Logger {
444
269
  store: MockLoggerStore;
445
270
  constructor(options?: LoggerOptions & {
@@ -449,7 +274,6 @@ declare class MockLogger extends Logger {
449
274
  child(options: LoggerOptions): MockLogger;
450
275
  reset(): void;
451
276
  }
452
- // ---------------------------------------------------------------------------------------------------------------------
453
277
  interface MockLoggerStore {
454
278
  stack: Array<{
455
279
  date: string;
@@ -459,515 +283,591 @@ interface MockLoggerStore {
459
283
  app?: string;
460
284
  } & Record<string, any>>;
461
285
  }
286
+ //# sourceMappingURL=Logger.d.ts.map
462
287
  //#endregion
463
288
  //#region src/Alepha.d.ts
464
289
  /**
465
- * Core container of the Alepha framework.
466
- *
467
- * It is responsible for managing the lifecycle of services,
468
- * handling dependency injection,
469
- * and providing a unified interface for the application.
470
- *
471
- * @example
472
- * ```ts
473
- * import { Alepha, run } from "alepha";
474
- *
475
- * class MyService {
476
- * // business logic here
477
- * }
478
- *
479
- * const alepha = Alepha.create({
480
- * // state, env, and other properties
481
- * })
482
- *
483
- * alepha.with(MyService);
484
- *
485
- * run(alepha); // trigger .start (and .stop) automatically
486
- * ```
487
- *
488
- * > Some alepha methods are not intended to be used directly, use descriptors instead.
489
- * >
490
- * > - $hook -> alepha.on()
491
- * > - $inject -> alepha.get(), alepha.parseEnv()
492
- */
290
+ * Core container of the Alepha framework.
291
+ *
292
+ * It is responsible for managing the lifecycle of services,
293
+ * handling dependency injection,
294
+ * and providing a unified interface for the application.
295
+ *
296
+ * @example
297
+ * ```ts
298
+ * import { Alepha, run } from "alepha";
299
+ *
300
+ * class MyService {
301
+ * // business logic here
302
+ * }
303
+ *
304
+ * const alepha = Alepha.create({
305
+ * // state, env, and other properties
306
+ * })
307
+ *
308
+ * alepha.with(MyService);
309
+ *
310
+ * run(alepha); // trigger .start (and .stop) automatically
311
+ * ```
312
+ *
313
+ * ### Alepha Factory
314
+ *
315
+ * Alepha.create() is an enhanced version of new Alepha().
316
+ * - It merges `process.env` with the provided state.env when available.
317
+ * - It populates the test hooks for Vitest or Jest environments when available.
318
+ *
319
+ * new Alepha() is fine if you don't need these helpers.
320
+ *
321
+ * ### Platforms & Environments
322
+ *
323
+ * Alepha is designed to work in various environments:
324
+ * - **Browser**: Runs in the browser, using the global `window` object.
325
+ * - **Serverless**: Runs in serverless environments like Vercel or Vite.
326
+ * - **Test**: Runs in test environments like Jest or Vitest.
327
+ * - **Production**: Runs in production environments, typically with NODE_ENV set to "production".
328
+ * * You can check the current environment using the following methods:
329
+ *
330
+ * - `isBrowser()`: Returns true if the App is running in a browser environment.
331
+ * - `isServerless()`: Returns true if the App is running in a serverless environment.
332
+ * - `isTest()`: Returns true if the App is running in a test environment.
333
+ * - `isProduction()`: Returns true if the App is running in a production environment.
334
+ *
335
+ * ### State & Environment
336
+ *
337
+ * The state of the Alepha container is stored in the `store` property.
338
+ * Most important property is `store.env`, which contains the environment variables.
339
+ *
340
+ * ```ts
341
+ * const alepha = Alepha.create({ env: { MY_VAR: "value" } });
342
+ *
343
+ * // You can access the environment variables using alepha.env
344
+ * console.log(alepha.env.MY_VAR); // "value"
345
+ *
346
+ * // But you should use $env() descriptor to get typed values from the environment.
347
+ * class App {
348
+ * env = $env(
349
+ * t.object({
350
+ * MY_VAR: t.string(),
351
+ * })
352
+ * );
353
+ * }
354
+ * ```
355
+ *
356
+ * ### Modules
357
+ *
358
+ * Modules are a way to group services together.
359
+ * You can register a module using the `$module` descriptor.
360
+ *
361
+ * ```ts
362
+ * import { $module } from "alepha";
363
+ *
364
+ * class MyLib {}
365
+ *
366
+ * const myModule = $module({
367
+ * name: "my.project.module",
368
+ * services: [MyLib],
369
+ * });
370
+ * ```
371
+ *
372
+ * Do not use modules for small applications.
373
+ *
374
+ * ### Hooks
375
+ *
376
+ * Hooks are a way to run async functions from all registered providers/services.
377
+ * You can register a hook using the `$hook` descriptor.
378
+ *
379
+ * ```ts
380
+ * import { $hook } from "alepha";
381
+ *
382
+ * class App {
383
+ * log = $logger();
384
+ * onCustomerHook = $hook({
385
+ * on: "my:custom:hook",
386
+ * handler: () => {
387
+ * this.log.info("App is being configured");
388
+ * },
389
+ * });
390
+ * }
391
+ *
392
+ * Alepha.create()
393
+ * .with(App)
394
+ * .start()
395
+ * .then(alepha => alepha.emit("my:custom:hook"));
396
+ * ```
397
+ *
398
+ * Hooks are fully typed. You can create your own hooks by using module augmentation:
399
+ *
400
+ * ```ts
401
+ * declare module "alepha" {
402
+ * interface Hooks {
403
+ * "my:custom:hook": {
404
+ * arg1: string;
405
+ * }
406
+ * }
407
+ * }
408
+ * ```
409
+ */
493
410
  declare class Alepha {
494
411
  /**
495
- * Creates a new instance of the Alepha container with some helpers:
496
- *
497
- * - merges `process.env` with the provided state.env when available.
498
- * - populates the test hooks for Vitest or Jest environments when available.
499
- *
500
- * If you are not interested about these helpers, you can use the constructor directly.
501
- */
412
+ * Creates a new instance of the Alepha container with some helpers:
413
+ *
414
+ * - merges `process.env` with the provided state.env when available.
415
+ * - populates the test hooks for Vitest or Jest environments when available.
416
+ *
417
+ * If you are not interested about these helpers, you can use the constructor directly.
418
+ */
502
419
  static create(state?: Partial<State>): Alepha;
503
420
  /**
504
- * List of all services + how they are provided.
505
- */
421
+ * List of all services + how they are provided.
422
+ */
506
423
  protected registry: Map<Service, ServiceDefinition>;
507
424
  /**
508
- * Flag indicating whether the App won't accept any further changes.
509
- * Pass to true when #start() is called.
510
- */
425
+ * Flag indicating whether the App won't accept any further changes.
426
+ * Pass to true when #start() is called.
427
+ */
511
428
  protected locked: boolean;
512
429
  /**
513
- * True if the App has been configured.
514
- */
430
+ * True if the App has been configured.
431
+ */
515
432
  protected configured: boolean;
516
433
  /**
517
- * True if the App has started.
518
- */
434
+ * True if the App has started.
435
+ */
519
436
  protected started: boolean;
520
437
  /**
521
- * True if the App is ready.
522
- */
438
+ * True if the App is ready.
439
+ */
523
440
  protected ready: boolean;
524
441
  /**
525
- * A promise that resolves when the App has started.
526
- */
442
+ * A promise that resolves when the App has started.
443
+ */
527
444
  protected starting?: PromiseWithResolvers<this>;
528
445
  /**
529
- * The current state of the App.
530
- *
531
- * It contains the environment variables, logger, and other state-related properties.
532
- *
533
- * You can declare your own state properties by extending the `State` interface.
534
- *
535
- * ```ts
536
- * declare module "alepha" {
537
- * interface State {
538
- * myCustomValue: string;
539
- * }
540
- * }
541
- * ```
542
- *
543
- * Same story for the `Env` interface.
544
- * ```ts
545
- * declare module "alepha" {
546
- * interface Env {
547
- * readonly myCustomValue: string;
548
- * }
549
- * }
550
- * ```
551
- *
552
- * State values can be function or primitive values.
553
- * However, all .env variables must serializable to JSON.
554
- */
446
+ * The current state of the App.
447
+ *
448
+ * It contains the environment variables, logger, and other state-related properties.
449
+ *
450
+ * You can declare your own state properties by extending the `State` interface.
451
+ *
452
+ * ```ts
453
+ * declare module "alepha" {
454
+ * interface State {
455
+ * myCustomValue: string;
456
+ * }
457
+ * }
458
+ * ```
459
+ *
460
+ * Same story for the `Env` interface.
461
+ * ```ts
462
+ * declare module "alepha" {
463
+ * interface Env {
464
+ * readonly myCustomValue: string;
465
+ * }
466
+ * }
467
+ * ```
468
+ *
469
+ * State values can be function or primitive values.
470
+ * However, all .env variables must serializable to JSON.
471
+ */
555
472
  protected store: State;
556
473
  /**
557
- * During the instantiation process, we keep a list of pending instantiations.
558
- * > It allows us to detect circular dependencies.
559
- */
474
+ * During the instantiation process, we keep a list of pending instantiations.
475
+ * > It allows us to detect circular dependencies.
476
+ */
560
477
  protected pendingInstantiations: Service[];
561
478
  /**
562
- * Cache for environment variables.
563
- * > It allows us to avoid parsing the same schema multiple times.
564
- */
479
+ * Cache for environment variables.
480
+ * > It allows us to avoid parsing the same schema multiple times.
481
+ */
565
482
  protected cacheEnv: Map<TSchema$1, any>;
566
483
  /**
567
- * Cache for TypeBox type checks.
568
- * > It allows us to avoid compiling the same schema multiple times.
569
- */
484
+ * Cache for TypeBox type checks.
485
+ * > It allows us to avoid compiling the same schema multiple times.
486
+ */
570
487
  protected cacheTypeCheck: Map<TSchema$1, TypeCheck<TSchema$1>>;
571
488
  /**
572
- * List of events that can be triggered. Powered by $hook().
573
- */
489
+ * List of events that can be triggered. Powered by $hook().
490
+ */
574
491
  protected events: Record<string, Array<Hook>>;
575
492
  /**
576
- * List of modules that are registered in the container.
577
- *
578
- * Modules are used to group services and provide a way to register them in the container.
579
- */
493
+ * List of modules that are registered in the container.
494
+ *
495
+ * Modules are used to group services and provide a way to register them in the container.
496
+ */
580
497
  protected modules: Array<ModuleDefinition>;
581
- /**
582
- * Node.js feature that allows to store context across asynchronous calls.
583
- *
584
- * This is used for logging, tracing, and other context-related features.
585
- *
586
- * Mocked for browser environments.
587
- */
498
+ protected substitutions: Map<Service, {
499
+ use: Service;
500
+ module?: ModuleDefinition;
501
+ }>;
502
+ protected configurations: Map<Service, object>;
503
+ protected descriptorRegistry: Map<Service<Descriptor<{}>>, Descriptor<{}>[]>;
504
+ /**
505
+ * Node.js feature that allows to store context across asynchronous calls.
506
+ *
507
+ * This is used for logging, tracing, and other context-related features.
508
+ *
509
+ * Mocked for browser environments.
510
+ */
588
511
  readonly context: AlsProvider;
589
512
  /**
590
- * Get logger instance.
591
- */
513
+ * Get logger instance.
514
+ */
592
515
  get log(): Logger;
593
516
  /**
594
- * The environment variables for the App.
595
- */
517
+ * The environment variables for the App.
518
+ */
596
519
  get env(): Readonly<Env>;
597
520
  constructor(state?: Partial<State>);
598
521
  /**
599
- * State accessor and mutator.
600
- */
522
+ * State accessor and mutator.
523
+ */
601
524
  state<Key extends keyof State>(key: Key, value?: State[Key]): State[Key];
602
- // -------------------------------------------------------------------------------------------------------------------
603
525
  /**
604
- * True when start() is called.
605
- *
606
- * -> No more services can be added, it's over, bye!
607
- */
526
+ * True when start() is called.
527
+ *
528
+ * -> No more services can be added, it's over, bye!
529
+ */
608
530
  isLocked(): boolean;
609
531
  /**
610
- * Returns whether the App is configured.
611
- *
612
- * It means that Alepha#configure() has been called.
613
- *
614
- * > By default, configure() is called automatically when start() is called, but you can also call it manually.
615
- */
532
+ * Returns whether the App is configured.
533
+ *
534
+ * It means that Alepha#configure() has been called.
535
+ *
536
+ * > By default, configure() is called automatically when start() is called, but you can also call it manually.
537
+ */
616
538
  isConfigured(): boolean;
617
539
  /**
618
- * Returns whether the App has started.
619
- *
620
- * It means that #start() has been called but maybe not all services are ready.
621
- */
540
+ * Returns whether the App has started.
541
+ *
542
+ * It means that #start() has been called but maybe not all services are ready.
543
+ */
622
544
  isStarted(): boolean;
623
545
  /**
624
- * True if the App is ready. It means that Alepha is started AND ready() hook has beed called.
625
- */
546
+ * True if the App is ready. It means that Alepha is started AND ready() hook has beed called.
547
+ */
626
548
  isReady(): boolean;
627
549
  /**
628
- * True if the App is running in a browser environment.
629
- */
550
+ * True if the App is running in a browser environment.
551
+ */
630
552
  isBrowser(): boolean;
631
553
  /**
632
- * Returns whether the App is running in a serverless environment.
633
- *
634
- * > Vite developer mode is also considered serverless.
635
- */
554
+ * Returns whether the App is running in a serverless environment.
555
+ *
556
+ * > Vite developer mode is also considered serverless.
557
+ */
636
558
  isServerless(): boolean | "vite" | "vercel";
637
559
  /**
638
- * Returns whether the App is in test mode. (Running in a test environment)
639
- *
640
- * > This is automatically set when running tests with Jest or Vitest.
641
- */
560
+ * Returns whether the App is in test mode. (Running in a test environment)
561
+ *
562
+ * > This is automatically set when running tests with Jest or Vitest.
563
+ */
642
564
  isTest(): boolean;
643
565
  /**
644
- * Returns whether the App is in production mode. (Running in a production environment)
645
- *
646
- * > This is automatically set by Vite or Vercel. However, you have to set it manually when running Docker apps.
647
- */
566
+ * Returns whether the App is in production mode. (Running in a production environment)
567
+ *
568
+ * > This is automatically set by Vite or Vercel. However, you have to set it manually when running Docker apps.
569
+ */
648
570
  isProduction(): boolean;
649
- // -------------------------------------------------------------------------------------------------------------------
650
- /**
651
- * Starts the App.
652
- *
653
- * - Lock any further changes to the container.
654
- * - Run "configure" hook for all services. Descriptors will be processed.
655
- * - Run "start" hook for all services. Providers will connect/listen/...
656
- * - Run "ready" hook for all services. This is the point where the App is ready to serve requests.
657
- *
658
- * @return A promise that resolves when the App has started.
659
- */
571
+ /**
572
+ * Starts the App.
573
+ *
574
+ * - Lock any further changes to the container.
575
+ * - Run "configure" hook for all services. Descriptors will be processed.
576
+ * - Run "start" hook for all services. Providers will connect/listen/...
577
+ * - Run "ready" hook for all services. This is the point where the App is ready to serve requests.
578
+ *
579
+ * @return A promise that resolves when the App has started.
580
+ */
660
581
  start(): Promise<this>;
661
582
  /**
662
- * Stops the App.
663
- *
664
- * - Run "stop" hook for all services.
665
- *
666
- * Stop will NOT reset the container.
667
- * Stop will NOT unlock the container.
668
- *
669
- * > Stop is used to gracefully shut down the application, nothing more. There is no "restart".
670
- *
671
- * @return A promise that resolves when the App has stopped.
672
- */
583
+ * Stops the App.
584
+ *
585
+ * - Run "stop" hook for all services.
586
+ *
587
+ * Stop will NOT reset the container.
588
+ * Stop will NOT unlock the container.
589
+ *
590
+ * > Stop is used to gracefully shut down the application, nothing more. There is no "restart".
591
+ *
592
+ * @return A promise that resolves when the App has stopped.
593
+ */
673
594
  stop(): Promise<void>;
674
- // -------------------------------------------------------------------------------------------------------------------
675
595
  /**
676
- * Check if entry is registered in the container.
677
- */
596
+ * Check if entry is registered in the container.
597
+ */
678
598
  has(entry: ServiceEntry, opts?: {
679
599
  /**
680
- * Check if the entry is registered in the pending instantiation stack.
681
- *
682
- * Default: true
683
- */
600
+ * Check if the entry is registered in the pending instantiation stack.
601
+ *
602
+ * Default: true
603
+ */
684
604
  inStack?: boolean;
685
605
  /**
686
- * Check if the entry is registered in the container registry.
687
- *
688
- * Default: true
689
- */
606
+ * Check if the entry is registered in the container registry.
607
+ *
608
+ * Default: true
609
+ */
690
610
  inRegistry?: boolean;
691
611
  }): boolean;
692
612
  /**
693
- * Registers the specified service in the container.
694
- *
695
- * - If the service is ALREADY registered, the method does nothing.
696
- * - If the service is NOT registered, a new instance is created and registered.
697
- *
698
- * Method is chainable, so you can register multiple services in a single call.
699
- *
700
- * > ServiceEntry allows to provide a service **substitution** feature.
701
- *
702
- * @example
703
- * ```ts
704
- * class A { value = "a"; }
705
- * class B { value = "b"; }
706
- * class M { a = $inject(A); }
707
- *
708
- * Alepha.create().with({ provide: A, use: B }).get(M).a.value; // "b"
709
- * ```
710
- *
711
- * > **Substitution** is an advanced feature that allows you to replace a service with another service.
712
- * > It's useful for testing or for providing different implementations of a service.
713
- * > If you are interested in configuring a service, use Alepha#configure() instead.
714
- *
715
- * @param entry - The service to register in the container.
716
- * @return Current instance of Alepha.
717
- */
718
- with<T extends object>(entry: ServiceEntry<T>): this;
719
- /**
720
- * Get the instance of the specified service and apply some changes, depending on the options.
721
- * - If the service is already registered, it will return the existing instance. (except if `skipCache` is true)
722
- * - If the service is not registered, it will create a new instance and register it. (except if `skipRegistration` is true)
723
- * - New instance can be created with custom constructor arguments. (`args` option)
724
- *
725
- * > This method is used by $inject() under the hood.
726
- *
727
- * @return The instance of the specified class or type.
728
- */
729
- get<T extends object>(serviceEntry: ServiceEntry<T>, opts?: {
613
+ * Registers the specified service in the container.
614
+ *
615
+ * - If the service is ALREADY registered, the method does nothing.
616
+ * - If the service is NOT registered, a new instance is created and registered.
617
+ *
618
+ * Method is chainable, so you can register multiple services in a single call.
619
+ *
620
+ * > ServiceEntry allows to provide a service **substitution** feature.
621
+ *
622
+ * @example
623
+ * ```ts
624
+ * class A { value = "a"; }
625
+ * class B { value = "b"; }
626
+ * class M { a = $inject(A); }
627
+ *
628
+ * Alepha.create().with({ provide: A, use: B }).get(M).a.value; // "b"
629
+ * ```
630
+ *
631
+ * > **Substitution** is an advanced feature that allows you to replace a service with another service.
632
+ * > It's useful for testing or for providing different implementations of a service.
633
+ * > If you are interested in configuring a service, use Alepha#configure() instead.
634
+ *
635
+ * @param serviceEntry - The service to register in the container.
636
+ * @return Current instance of Alepha.
637
+ */
638
+ with<T extends object>(serviceEntry: ServiceEntry<T> | {
639
+ default: ServiceEntry<T>;
640
+ }): this;
641
+ /**
642
+ * Get the instance of the specified service and apply some changes, depending on the options.
643
+ * - If the service is already registered, it will return the existing instance. (except if `skipCache` is true)
644
+ * - If the service is not registered, it will create a new instance and register it. (except if `skipRegistration` is true)
645
+ * - New instance can be created with custom constructor arguments. (`args` option)
646
+ *
647
+ * > This method is used by $inject() under the hood.
648
+ *
649
+ * @return The instance of the specified class or type.
650
+ */
651
+ inject<T extends object>(service: Service<T>, opts?: {
730
652
  /**
731
- * Ignore current existing instance.
732
- */
653
+ * Ignore current existing instance.
654
+ */
733
655
  skipCache?: boolean;
734
656
  /**
735
- * Don't store the instance in the registry.
736
- */
657
+ * Don't store the instance in the registry.
658
+ */
737
659
  skipRegistration?: boolean;
738
660
  /**
739
- * Constructor arguments to pass when creating a new instance.
740
- */
741
- args?: ConstructorParameters<InstantiableService<T>>;
661
+ * Constructor arguments to pass when creating a new instance.
662
+ */
663
+ args?: ConstructorParameters<InstantiableClass<T>>;
742
664
  /**
743
- * Parent service that requested the instance.
744
- * @internal
745
- */
665
+ * Parent service that requested the instance.
666
+ * @internal
667
+ */
746
668
  parent?: Service | null;
747
669
  /**
748
- * If the service is provided by a module, the module definition.
749
- * @internal
750
- */
670
+ * If the service is provided by a module, the module definition.
671
+ * @internal
672
+ */
751
673
  module?: ModuleDefinition;
752
674
  }): T;
753
- /**
754
- * Configures the specified service with the provided state.
755
- * If service is not registered, it will do nothing.
756
- *
757
- * It's recommended to use this method on the `configure` hook.
758
- * @example
759
- * ```ts
760
- * class AppConfig {
761
- * configure = $hook({
762
- * name: "configure",
763
- * handler: (a) => {
764
- * a.configure(MyProvider, { some: "data" });
765
- * }
766
- * })
767
- * }
768
- * ```
769
- */
675
+ protected pushModule(instance: Module): void;
676
+ /**
677
+ * Configures the specified service with the provided state.
678
+ * If service is not registered, it will do nothing.
679
+ *
680
+ * It's recommended to use this method on the `configure` hook.
681
+ * @example
682
+ * ```ts
683
+ * class AppConfig {
684
+ * configure = $hook({
685
+ * name: "configure",
686
+ * handler: (a) => {
687
+ * a.configure(MyProvider, { some: "data" });
688
+ * }
689
+ * })
690
+ * }
691
+ * ```
692
+ */
770
693
  configure<T extends {
771
694
  options: object;
772
695
  }>(service: Service<T>, state: Partial<T["options"]>): this;
773
- // -------------------------------------------------------------------------------------------------------------------
774
- protected useCounter: number;
775
- use<T extends Descriptor>(descriptor: T, options: Parameters<T>[0]): ReturnType<T>;
776
- // -------------------------------------------------------------------------------------------------------------------
777
696
  /**
778
- * Registers a hook for the specified event.
779
- */
697
+ * Registers a hook for the specified event.
698
+ */
780
699
  on<T extends keyof Hooks>(event: T, hookOrFunc: Hook<T> | ((payload: Hooks[T]) => Async<void>)): () => void;
781
700
  /**
782
- * Emits the specified event with the given payload.
783
- */
701
+ * Emits the specified event with the given payload.
702
+ */
784
703
  emit<T extends keyof Hooks>(func: keyof Hooks, payload: Hooks[T], options?: {
785
704
  /**
786
- * If true, the hooks will be executed in reverse order.
787
- * This is useful for "stop" hooks that should be executed in reverse order.
788
- *
789
- * @default false
790
- */
705
+ * If true, the hooks will be executed in reverse order.
706
+ * This is useful for "stop" hooks that should be executed in reverse order.
707
+ *
708
+ * @default false
709
+ */
791
710
  reverse?: boolean;
792
711
  /**
793
- * If true, the hooks will be logged with their execution time.
794
- *
795
- * @default false
796
- */
712
+ * If true, the hooks will be logged with their execution time.
713
+ *
714
+ * @default false
715
+ */
797
716
  log?: boolean;
798
717
  /**
799
- * If true, errors will be caught and logged instead of throwing.
800
- *
801
- * @default false
802
- */
718
+ * If true, errors will be caught and logged instead of throwing.
719
+ *
720
+ * @default false
721
+ */
803
722
  catch?: boolean;
804
723
  }): Promise<void>;
805
- // -------------------------------------------------------------------------------------------------------------------
806
724
  /**
807
- * Casts the given value to the specified schema.
808
- *
809
- * It uses the TypeBox library to validate the value against the schema.
810
- */
725
+ * Casts the given value to the specified schema.
726
+ *
727
+ * It uses the TypeBox library to validate the value against the schema.
728
+ */
811
729
  parse<T extends TSchema$1>(schema: T, value?: any, opts?: {
812
730
  /**
813
- * Clone the value before parsing.
814
- * @default true
815
- */
731
+ * Clone the value before parsing.
732
+ * @default true
733
+ */
816
734
  clone?: boolean;
817
735
  /**
818
- * Apply default values defined in the schema.
819
- * @default true
820
- */
736
+ * Apply default values defined in the schema.
737
+ * @default true
738
+ */
821
739
  default?: boolean;
822
740
  /**
823
- * Remove all values not defined in the schema.
824
- * @default true
825
- */
741
+ * Remove all values not defined in the schema.
742
+ * @default true
743
+ */
826
744
  clean?: boolean;
827
745
  /**
828
- * Try to cast/convert some data based on the schema.
829
- * @default true
830
- */
746
+ * Try to cast/convert some data based on the schema.
747
+ * @default true
748
+ */
831
749
  convert?: boolean;
832
750
  /**
833
- * Prepare value after being deserialized.
834
- * @default true
835
- */
751
+ * Prepare value after being deserialized.
752
+ * @default true
753
+ */
836
754
  check?: boolean;
837
755
  }): Static$1<T>;
838
756
  /**
839
- * Applies environment variables to the provided schema and state object.
840
- *
841
- * It replaces also all templated $ENV inside string values.
842
- *
843
- * @param schema - The schema object to apply environment variables to.
844
- * @return The schema object with environment variables applied.
845
- */
757
+ * Applies environment variables to the provided schema and state object.
758
+ *
759
+ * It replaces also all templated $ENV inside string values.
760
+ *
761
+ * @param schema - The schema object to apply environment variables to.
762
+ * @return The schema object with environment variables applied.
763
+ */
846
764
  parseEnv<T extends TObject$1>(schema: T): Static$1<T>;
847
- // -------------------------------------------------------------------------------------------------------------------
848
765
  /**
849
- * Dump the current dependency graph of the App.
850
- *
851
- * This method returns a record where the keys are the names of the services.
852
- */
766
+ * Dump the current dependency graph of the App.
767
+ *
768
+ * This method returns a record where the keys are the names of the services.
769
+ */
853
770
  graph(): Record<string, {
854
771
  from: string[];
855
- as?: string;
772
+ as?: string[];
856
773
  module?: string;
857
774
  }>;
858
- // -------------------------------------------------------------------------------------------------------------------
859
- /**
860
- * @internal
861
- */
862
- getDescriptorValues<T extends Descriptor>(descriptor: T): Array<DescriptorItem<T>>;
863
- /**
864
- * @internal
865
- */
866
- protected new<T extends object>(definition: Service<T>, args?: any[], module?: ModuleDefinition): T;
867
- /**
868
- * @internal
869
- */
775
+ descriptors<TDescriptor extends Descriptor>(factory: {
776
+ [KIND]: InstantiableClass<TDescriptor> | string;
777
+ }): Array<TDescriptor>;
778
+ protected new<T extends object>(service: Service<T>, args?: any[], module?: ModuleDefinition): T;
779
+ protected processDescriptor(value: Descriptor, propertyKey?: string): void;
780
+ /**
781
+ * @internal
782
+ */
870
783
  protected createLogger(env: Env): Logger;
871
- getModuleOf(service: Service): Module | undefined;
872
784
  }
873
- // ---------------------------------------------------------------------------------------------------------------------
785
+ interface Hook<T extends keyof Hooks = any> {
786
+ caller?: Service;
787
+ priority?: "first" | "last";
788
+ callback: (payload: Hooks[T]) => Async<void>;
789
+ }
874
790
  /**
875
- * This is how we store services in the Alepha container.
876
- */
791
+ * This is how we store services in the Alepha container.
792
+ */
877
793
  interface ServiceDefinition<T extends object = any> {
878
794
  /**
879
- * The class or type definition to provide.
880
- */
881
- provide: Service<T>;
882
- /**
883
- * The class or type definition to use. This will override the 'provide' property.
884
- */
885
- use?: Service<T>;
886
- /**
887
- * The instance of the class or type definition.
888
- * Mostly used for caching / singleton but can be used for other purposes like forcing the instance.
889
- */
795
+ * The instance of the class or type definition.
796
+ * Mostly used for caching / singleton but can be used for other purposes like forcing the instance.
797
+ */
890
798
  instance: T;
891
799
  /**
892
- * List of classes which use this class.
893
- */
800
+ * List of classes which use this class.
801
+ */
894
802
  parents: Array<Service | null>;
895
803
  /**
896
- * If the service is provided by a module, the module definition.
897
- */
804
+ * If the service is provided by a module, the module definition.
805
+ */
898
806
  module?: ModuleDefinition;
899
807
  }
900
- // ---------------------------------------------------------------------------------------------------------------------
901
808
  interface Env extends LoggerEnv {
902
809
  [key: string]: string | boolean | number | undefined;
903
810
  /**
904
- * Optional environment variable that indicates the current environment.
905
- */
811
+ * Optional environment variable that indicates the current environment.
812
+ */
906
813
  NODE_ENV?: "dev" | "test" | "production";
907
814
  /**
908
- * Optional name of the application.
909
- */
815
+ * Optional name of the application.
816
+ */
910
817
  APP_NAME?: string;
911
818
  /**
912
- * Optional root module name.
913
- */
819
+ * Optional root module name.
820
+ */
914
821
  MODULE_NAME?: string;
915
- /**
916
- * If true, the container will not automatically register the default providers based on the descriptors.
917
- *
918
- * It means that you have to alepha.with(ServiceModule) manually. No magic.
919
- *
920
- * @default false
921
- */
922
- EXPLICIT_PROVIDERS?: boolean;
923
822
  }
924
- // ---------------------------------------------------------------------------------------------------------------------
925
823
  interface State {
926
824
  log: Logger;
927
825
  env?: Readonly<Env>;
928
- // test hooks
826
+ /**
827
+ * If defined, the Alepha container will only register this service and its dependencies.
828
+ */
829
+ target?: Service;
929
830
  beforeAll?: (run: any) => any;
930
831
  afterAll?: (run: any) => any;
931
832
  afterEach?: (run: any) => any;
932
833
  onTestFinished?: (run: any) => any;
933
834
  }
934
- // ---------------------------------------------------------------------------------------------------------------------
935
835
  interface Hooks {
936
836
  echo: any;
937
837
  /**
938
- * Triggered during the configuration phase. Before the start phase.
939
- */
838
+ * Triggered during the configuration phase. Before the start phase.
839
+ */
940
840
  configure: Alepha;
941
841
  /**
942
- * Triggered during the start phase. When `Alepha#start()` is called.
943
- */
842
+ * Triggered during the start phase. When `Alepha#start()` is called.
843
+ */
944
844
  start: Alepha;
945
845
  /**
946
- * Triggered during the ready phase. After the start phase.
947
- */
846
+ * Triggered during the ready phase. After the start phase.
847
+ */
948
848
  ready: Alepha;
949
849
  /**
950
- * Triggered during the stop phase.
951
- *
952
- * - Stop should be called after a SIGINT or SIGTERM signal in order to gracefully shutdown the application. (@see `run()` method)
953
- *
954
- */
850
+ * Triggered during the stop phase.
851
+ *
852
+ * - Stop should be called after a SIGINT or SIGTERM signal in order to gracefully shutdown the application. (@see `run()` method)
853
+ *
854
+ */
955
855
  stop: Alepha;
956
856
  /**
957
- * Triggered when a state value is mutated.
958
- */
857
+ * Triggered when a state value is mutated.
858
+ */
959
859
  "state:mutate": {
960
860
  /**
961
- * The key of the state that was mutated.
962
- */
861
+ * The key of the state that was mutated.
862
+ */
963
863
  key: keyof State;
964
864
  /**
965
- * The new value of the state.
966
- */
865
+ * The new value of the state.
866
+ */
967
867
  value: any;
968
868
  /**
969
- * The previous value of the state.
970
- */
869
+ * The previous value of the state.
870
+ */
971
871
  prevValue: any;
972
872
  };
973
873
  }
@@ -975,321 +875,578 @@ interface Hooks {
975
875
  //#region src/interfaces/Run.d.ts
976
876
  interface RunOptions {
977
877
  /**
978
- * Environment variables to be used by the application.
979
- * If not provided, it will use the current process environment.
980
- */
878
+ * Environment variables to be used by the application.
879
+ * It will be merged with the current process environment.
880
+ */
981
881
  env?: Env;
982
882
  /**
983
- * A callback that will be executed before the application starts.
984
- */
883
+ * A callback that will be executed before the application starts.
884
+ */
985
885
  configure?: (alepha: Alepha) => Async<void>;
986
886
  /**
987
- * A callback that will be executed once the application is ready.
988
- * This is useful for initializing resources or starting background tasks.
989
- */
887
+ * A callback that will be executed once the application is ready.
888
+ * This is useful for initializing resources or starting background tasks.
889
+ */
990
890
  ready?: (alepha: Alepha) => Async<void>;
991
891
  /**
992
- * If true, the application will stop after the ready callback is executed.
993
- */
892
+ * If true, the application will .stop() after the ready callback is executed.
893
+ * Useful for one-time tasks!
894
+ */
994
895
  once?: boolean;
896
+ /**
897
+ * If true, the application will run in cluster mode.
898
+ */
899
+ cluster?: boolean;
995
900
  }
901
+ //# sourceMappingURL=Run.d.ts.map
996
902
  //#endregion
997
- //#region src/descriptors/$inject.d.ts
903
+ //#region src/constants/OPTIONS.d.ts
904
+ /**
905
+ * Used for descriptors options.
906
+ *
907
+ * @internal
908
+ */
909
+ declare const OPTIONS: unique symbol;
910
+ //# sourceMappingURL=OPTIONS.d.ts.map
911
+
912
+ //#endregion
913
+ //#region src/descriptors/$cursor.d.ts
998
914
  /**
999
- * Get the instance of the specified type from the context.
1000
- *
1001
- * - If the type is a class, it will be resolved from the context.
1002
- * - If the type is a schema, it will be parsed from the environment.
1003
- *
1004
- * ```ts
1005
- * class A { }
1006
- * class B {
1007
- * a = $inject(A);
1008
- * }
1009
- * ```
1010
- *
1011
- * @param type - Type (or TypeBox schema) to resolve
1012
- * @returns Instance of the specified type
1013
- */
1014
- declare function $inject<T extends TObject$1>(type: T): Static$1<T>;
1015
- declare function $inject<T extends object>(type: Service<T>): T;
1016
- declare class InjectResolverRegistry {
1017
- resolvers: Array<(it: any) => any>;
1018
- register(fn: (it: any) => any): void;
1019
- resolve(it: any): any;
915
+ * Get Alepha instance and Class definition from the current context.
916
+ * This should be used inside a descriptor only.
917
+ *
918
+ * ```ts
919
+ * import { $cursor } from "alepha";
920
+ *
921
+ * const $ = () => {
922
+ *
923
+ * const { context, definition } = $cursor();
924
+ *
925
+ * // context - alepha instance
926
+ * // definition - class which is creating this descriptor
927
+ *
928
+ * return {};
929
+ * }
930
+ *
931
+ * ```
932
+ *
933
+ * @internal
934
+ */
935
+ declare const $cursor: () => CursorDescriptor;
936
+ /**
937
+ * /!\ Global variable /!\
938
+ *
939
+ * Store the current context and definition during injection phase.
940
+ *
941
+ * @internal
942
+ */
943
+ declare const __alephaRef: {
944
+ context?: Alepha;
945
+ definition?: Service;
946
+ module?: ModuleDefinition;
947
+ $services?: {
948
+ module: ModuleDefinition;
949
+ parent: Service;
950
+ };
951
+ };
952
+ /**
953
+ * Cursor descriptor.
954
+ */
955
+ interface CursorDescriptor {
956
+ context: Alepha;
957
+ definition?: Service;
958
+ module?: ModuleDefinition;
1020
959
  }
1021
- declare const $injectResolverRegistry: InjectResolverRegistry;
960
+ //# sourceMappingURL=$cursor.d.ts.map
961
+ //#endregion
962
+ //#region src/descriptors/$env.d.ts
963
+ /**
964
+ * Get typed values from environment variables.
965
+ *
966
+ * @example
967
+ * ```ts
968
+ * const alepha = Alepha.create({
969
+ * env: {
970
+ * // Alepha.create() will also use process.env when running on Node.js
971
+ * HELLO: "world",
972
+ * }
973
+ * });
974
+ *
975
+ * class App {
976
+ * log = $logger();
977
+ *
978
+ * // program expect a var env "HELLO" as string to works
979
+ * env = $env(t.object({
980
+ * HELLO: t.string()
981
+ * }));
982
+ *
983
+ * sayHello = () => this.log.info("Hello ${this.env.HELLO}")
984
+ * }
985
+ *
986
+ * run(alepha.with(App));
987
+ * ```
988
+ */
989
+ declare const $env: <T extends TObject$1>(type: T) => Static$1<T>;
990
+ //# sourceMappingURL=$env.d.ts.map
991
+
992
+ //#endregion
993
+ //#region src/descriptors/$hook.d.ts
994
+ /**
995
+ * Registers a new hook.
996
+ *
997
+ * ```ts
998
+ * import { $hook } from "alepha";
999
+ *
1000
+ * class MyProvider {
1001
+ * onStart = $hook({
1002
+ * name: "start", // or "configure", "ready", "stop", ...
1003
+ * handler: async (app) => {
1004
+ * // await db.connect(); ...
1005
+ * }
1006
+ * });
1007
+ * }
1008
+ * ```
1009
+ *
1010
+ * Hooks are used to run async functions from all registered providers/services.
1011
+ *
1012
+ * You can't register a hook after the App has started.
1013
+ *
1014
+ * It's used under the hood by the `configure`, `start`, and `stop` methods.
1015
+ * Some modules also use hooks to run their own logic. (e.g. `@alepha/server`).
1016
+ *
1017
+ * You can create your own hooks by using module augmentation:
1018
+ *
1019
+ * ```ts
1020
+ * declare module "alepha" {
1021
+ *
1022
+ * interface Hooks {
1023
+ * "my:custom:hook": {
1024
+ * arg1: string;
1025
+ * }
1026
+ * }
1027
+ * }
1028
+ *
1029
+ * await alepha.emit("my:custom:hook", { arg1: "value" });
1030
+ * ```
1031
+ *
1032
+ */
1033
+ declare const $hook: {
1034
+ <T extends keyof Hooks>(options: HookOptions<T>): HookDescriptor<T>;
1035
+ [KIND]: typeof HookDescriptor;
1036
+ };
1037
+ interface HookOptions<T extends keyof Hooks> {
1038
+ /**
1039
+ * The name of the hook. "configure", "start", "ready", "stop", ...
1040
+ */
1041
+ on: T;
1042
+ /**
1043
+ * The handler to run when the hook is triggered.
1044
+ */
1045
+ handler: (app: Hooks[T]) => Async<any>;
1046
+ /**
1047
+ * Force the hook to run first or last on the list of hooks.
1048
+ */
1049
+ priority?: "first" | "last";
1050
+ /**
1051
+ * Empty placeholder, not implemented yet. :-)
1052
+ */
1053
+ before?: object | Array<object>;
1054
+ /**
1055
+ * Empty placeholder, not implemented yet. :-)
1056
+ */
1057
+ after?: object | Array<object>;
1058
+ }
1059
+ declare class HookDescriptor<T extends keyof Hooks> extends Descriptor<HookOptions<T>> {
1060
+ called: number;
1061
+ protected onInit(): void;
1062
+ }
1063
+ //# sourceMappingURL=$hook.d.ts.map
1064
+ //#endregion
1065
+ //#region src/descriptors/$inject.d.ts
1066
+ /**
1067
+ * Get the instance of the specified type from the context.
1068
+ *
1069
+ * ```ts
1070
+ * class A { }
1071
+ * class B {
1072
+ * a = $inject(A);
1073
+ * }
1074
+ * ```
1075
+ */
1076
+ declare const $inject: <T extends object>(type: Service<T>) => T;
1077
+ declare class InjectDescriptor extends Descriptor {}
1078
+ //# sourceMappingURL=$inject.d.ts.map
1079
+
1022
1080
  //#endregion
1023
1081
  //#region src/descriptors/$logger.d.ts
1024
1082
  /**
1025
- * Create a logger.
1026
- *
1027
- * `name` is optional, by default it will use the name of the service.
1028
- *
1029
- * @example
1030
- * ```ts
1031
- * import { $logger } from "alepha";
1032
- *
1033
- * class MyService {
1034
- * log = $logger();
1035
- *
1036
- * constructor() {
1037
- * // print something like 'date - [MyService] Service initialized'
1038
- * this.log.info("Service initialized");
1039
- * }
1040
- * }
1041
- * ```
1042
- */
1043
- declare const $logger: (name?: string) => Logger;
1083
+ * Create a logger.
1084
+ *
1085
+ * `name` is optional, by default it will use the name of the service.
1086
+ *
1087
+ * @example
1088
+ * ```ts
1089
+ * import { $logger } from "alepha";
1090
+ *
1091
+ * class MyService {
1092
+ * log = $logger();
1093
+ *
1094
+ * constructor() {
1095
+ * // print something like 'date - [MyService] Service initialized'
1096
+ * this.log.info("Service initialized");
1097
+ * }
1098
+ * }
1099
+ * ```
1100
+ */
1101
+ declare const $logger: {
1102
+ (options?: LoggerDescriptorOptions): Logger;
1103
+ [KIND]: typeof Logger;
1104
+ };
1105
+ interface LoggerDescriptorOptions {
1106
+ name?: string;
1107
+ }
1108
+ //# sourceMappingURL=$logger.d.ts.map
1109
+
1110
+ //#endregion
1111
+ //#region src/descriptors/$module.d.ts
1112
+ /**
1113
+ * Wrap services and descriptors into a module.
1114
+ *
1115
+ * Module is just a class.
1116
+ * You must attach a `name` to it.
1117
+ *
1118
+ * It's recommended to use `project.module.submodule` format.
1119
+ *
1120
+ * @example
1121
+ * ```ts
1122
+ * import { $module } from "alepha";
1123
+ * import { MyService } from "./MyService.ts";
1124
+ *
1125
+ * // export MyService so it can be used everywhere
1126
+ * export * from "./MyService.ts";
1127
+ *
1128
+ * export default $module({
1129
+ * name: "my.project.module",
1130
+ * // MyService will have a module context "my.project.module"
1131
+ * services: [MyService],
1132
+ * });
1133
+ * ```
1134
+ *
1135
+ * - Module is used for logging and other purposes.
1136
+ * - It's useful for large applications or libraries to group services and descriptors together.
1137
+ * - It's probably overkill for small applications.
1138
+ */
1139
+ declare const $module: (args: ModuleDescriptorOptions) => ModuleDescriptor;
1140
+ type ModuleDescriptor = Service<Module>;
1141
+ interface ModuleDescriptorOptions {
1142
+ /**
1143
+ * Name of the module.
1144
+ *
1145
+ * It should be in the format of `project.module.submodule`.
1146
+ */
1147
+ name: string;
1148
+ /**
1149
+ * List of services to register in the module.
1150
+ */
1151
+ services?: Array<ServiceEntry>;
1152
+ /**
1153
+ * List of $descriptors to register in the module.
1154
+ */
1155
+ descriptors?: Array<DescriptorFactoryLike>;
1156
+ /**
1157
+ * By default, module will register all services.
1158
+ * You can override this behavior by providing a register function.
1159
+ * It's useful when you want to register services conditionally or in a specific order.
1160
+ */
1161
+ register?: (alepha: Alepha) => void;
1162
+ }
1163
+ //# sourceMappingURL=$module.d.ts.map
1044
1164
  //#endregion
1045
1165
  //#region src/errors/AlephaError.d.ts
1046
- // ---------------------------------------------------------------------------------------------------------------------
1047
1166
  /**
1048
- * Default error class for Alepha.
1049
- */
1167
+ * Default error class for Alepha.
1168
+ */
1050
1169
  declare class AlephaError extends Error {}
1170
+ //# sourceMappingURL=AlephaError.d.ts.map
1051
1171
  //#endregion
1052
1172
  //#region src/errors/AppNotStartedError.d.ts
1053
1173
  declare class AppNotStartedError extends Error {
1054
1174
  constructor();
1055
1175
  }
1176
+ //# sourceMappingURL=AppNotStartedError.d.ts.map
1056
1177
  //#endregion
1057
1178
  //#region src/errors/CircularDependencyError.d.ts
1058
1179
  declare class CircularDependencyError extends Error {
1059
1180
  constructor(provider: string, parents?: string[]);
1060
1181
  }
1182
+ //# sourceMappingURL=CircularDependencyError.d.ts.map
1061
1183
  //#endregion
1062
1184
  //#region src/errors/ContainerLockedError.d.ts
1063
1185
  declare class ContainerLockedError extends Error {
1064
1186
  constructor(message?: string);
1065
1187
  }
1188
+ //# sourceMappingURL=ContainerLockedError.d.ts.map
1066
1189
  //#endregion
1067
1190
  //#region src/errors/NotImplementedError.d.ts
1068
1191
  declare class NotImplementedError extends Error {
1069
1192
  constructor(provider: string);
1070
1193
  }
1194
+ //# sourceMappingURL=NotImplementedError.d.ts.map
1071
1195
  //#endregion
1072
1196
  //#region src/errors/TypeBoxError.d.ts
1073
1197
  declare class TypeBoxError extends Error {
1074
1198
  readonly value: ValueError;
1075
1199
  constructor(value: ValueError);
1076
1200
  }
1201
+ //# sourceMappingURL=TypeBoxError.d.ts.map
1202
+
1077
1203
  //#endregion
1078
1204
  //#region src/providers/TypeProvider.d.ts
1079
- // ---------------------------------------------------------------------------------------------------------------------
1080
1205
  declare class TypeProvider {
1081
1206
  static DEFAULT_STRING_MAX_LENGTH: number;
1082
1207
  static DEFAULT_LONG_STRING_MAX_LENGTH: number;
1083
1208
  static DEFAULT_RICH_STRING_MAX_LENGTH: number;
1084
1209
  static DEFAULT_ARRAY_MAX_ITEMS: number;
1085
1210
  static FormatRegistry: typeof FormatRegistry;
1086
- raw: typeof Type;
1087
- any(options?: SchemaOptions): TAny$1;
1088
- void(options?: SchemaOptions): TVoid;
1089
- undefined(options?: SchemaOptions): TUndefined;
1090
- record<Key extends TSchema$1, Value extends TSchema$1>(key: Key, value: Value, options?: ObjectOptions): TRecordOrObject<Key, Value>;
1091
- omit<Type extends TSchema$1, Key extends TSchema$1>(type: Type, key: Key, options?: SchemaOptions): TOmit<Type, Key>;
1092
- partial<MappedResult extends TMappedResult>(type: MappedResult, options?: SchemaOptions): TPartialFromMappedResult<MappedResult>;
1093
- union<Types extends TSchema$1[]>(types: [...Types], options?: SchemaOptions): Union<Types>;
1094
- composite<T extends TSchema$1[]>(schemas: [...T], options?: ObjectOptions): TComposite<T>;
1095
- pick<Type extends TSchema$1, Key extends PropertyKey[]>(type: Type, key: readonly [...Key], options?: SchemaOptions): TPick<Type, Key>;
1096
- /**
1097
- * Create a schema for an object.
1098
- *
1099
- * @param properties The properties of the object.
1100
- * @param options The options for the object.
1101
- */
1211
+ raw: TypeBox.JavaScriptTypeBuilder;
1212
+ any: (options?: SchemaOptions) => TAny$1;
1213
+ void: (options?: SchemaOptions) => TypeBox.TVoid;
1214
+ undefined: (options?: SchemaOptions) => TypeBox.TUndefined;
1215
+ record: <Key extends TSchema$1, Value extends TSchema$1>(key: Key, value: Value, options?: ObjectOptions) => TypeBox.TRecordOrObject<Key, Value>;
1216
+ omit: {
1217
+ <Type extends TSchema$1, Key extends PropertyKey[]>(type: Type, key: readonly [...Key], options?: SchemaOptions): TOmit<Type, Key>;
1218
+ <Type extends TSchema$1, Key extends TSchema$1>(type: Type, key: Key, options?: SchemaOptions): TOmit<Type, Key>;
1219
+ };
1220
+ partial: {
1221
+ <MappedResult extends TypeBox.TMappedResult>(type: MappedResult, options?: SchemaOptions): TypeBox.TPartialFromMappedResult<MappedResult>;
1222
+ <Type extends TSchema$1>(type: Type, options?: SchemaOptions): TPartial<Type>;
1223
+ };
1224
+ union: <Types extends TSchema$1[]>(types: [...Types], options?: SchemaOptions) => TypeBox.Union<Types>;
1225
+ composite: <T extends TSchema$1[]>(schemas: [...T], options?: ObjectOptions) => TComposite<T>;
1226
+ pick: {
1227
+ <Type extends TSchema$1, Key extends PropertyKey[]>(type: Type, key: readonly [...Key], options?: SchemaOptions): TPick<Type, Key>;
1228
+ <Type extends TSchema$1, Key extends TSchema$1>(type: Type, key: Key, options?: SchemaOptions): TPick<Type, Key>;
1229
+ };
1230
+ /**
1231
+ * Create a schema for an object.
1232
+ *
1233
+ * @param properties The properties of the object.
1234
+ * @param options The options for the object.
1235
+ */
1102
1236
  object<T extends TProperties$1>(properties: T, options?: ObjectOptions): TObject$1<T>;
1103
1237
  /**
1104
- * Create a schema for an array.
1105
- *
1106
- * @param schema
1107
- * @param options
1108
- */
1238
+ * Create a schema for an array.
1239
+ *
1240
+ * @param schema
1241
+ * @param options
1242
+ */
1109
1243
  array<T extends TSchema$1>(schema: T, options?: ArrayOptions): TArray$1<T>;
1110
1244
  /**
1111
- * Create a schema for a string.
1112
- *
1113
- * @param options
1114
- */
1245
+ * Create a schema for a string.
1246
+ *
1247
+ * @param options
1248
+ */
1115
1249
  string(options?: AlephaStringOptions): TString$1;
1116
1250
  /**
1117
- * Create a schema for a JSON object.
1118
- *
1119
- * @param options
1120
- */
1251
+ * Create a schema for a JSON object.
1252
+ *
1253
+ * @param options
1254
+ */
1121
1255
  json(options?: SchemaOptions): TRecord$1<TString$1, TAny$1>;
1122
1256
  /**
1123
- * Create a schema for a boolean.
1124
- *
1125
- * @param options
1126
- */
1257
+ * Create a schema for a boolean.
1258
+ *
1259
+ * @param options
1260
+ */
1127
1261
  boolean(options?: SchemaOptions): TBoolean$1;
1128
1262
  /**
1129
- * Create a schema for a number.
1130
- *
1131
- * @param options
1132
- */
1263
+ * Create a schema for a number.
1264
+ *
1265
+ * @param options
1266
+ */
1133
1267
  number(options?: NumberOptions): TNumber$1;
1134
1268
  /**
1135
- * Create a schema for an unsigned 8-bit integer.
1136
- *
1137
- * @param options
1138
- */
1269
+ * Create a schema for an unsigned 8-bit integer.
1270
+ *
1271
+ * @param options
1272
+ */
1139
1273
  uchar(options?: IntegerOptions): TInteger;
1140
1274
  /**
1141
- * Create a schema for an unsigned 32-bit integer.
1142
- */
1275
+ * Create a schema for an unsigned 32-bit integer.
1276
+ */
1143
1277
  uint(options?: IntegerOptions): TNumber$1;
1144
1278
  /**
1145
- * Create a schema for a signed 32-bit integer.
1146
- */
1279
+ * Create a schema for a signed 32-bit integer.
1280
+ */
1147
1281
  int(options?: IntegerOptions): TInteger;
1148
1282
  /**
1149
- * Create a schema for a signed 32-bit integer.
1150
- */
1283
+ * Create a schema for a signed 32-bit integer.
1284
+ */
1151
1285
  integer(options?: IntegerOptions): TInteger;
1152
1286
  /**
1153
- * Create a schema for a bigint. Bigint is a 64-bit integer.
1154
- * This is a workaround for TypeBox, which does not support bigint natively.
1155
- */
1287
+ * Create a schema for a bigint. Bigint is a 64-bit integer.
1288
+ * This is a workaround for TypeBox, which does not support bigint natively.
1289
+ */
1156
1290
  bigint(options?: IntegerOptions): TNumber$1;
1157
1291
  /**
1158
- * Make a schema optional.
1159
- *
1160
- * @param schema The schema to make optional.
1161
- */
1292
+ * Make a schema optional.
1293
+ *
1294
+ * @param schema The schema to make optional.
1295
+ */
1162
1296
  optional<T extends TSchema$1>(schema: T): TOptionalWithFlag<T, true>;
1163
1297
  /**
1164
- * Make a schema nullable.
1165
- *
1166
- * @param schema The schema to make nullable.
1167
- * @param options The options for the schema.
1168
- */
1298
+ * Make a schema nullable.
1299
+ *
1300
+ * @param schema The schema to make nullable.
1301
+ * @param options The options for the schema.
1302
+ */
1169
1303
  nullable<T extends TSchema$1>(schema: T, options?: ObjectOptions): TUnion<[TNull, T]>;
1170
- /**
1171
- * Map a schema to another schema.
1172
- *
1173
- * @param schema The schema to map.
1174
- * @param operations The operations to perform on the schema.
1175
- * @param options The options for the schema.
1176
- * @returns The mapped schema.
1177
- */
1304
+ nullify: <T extends TSchema$1>(schema: T, options?: ObjectOptions) => TObject$1<TypeBox.Evaluate<TypeBox.TMappedFunctionReturnType<TypeBox.TIndexPropertyKeys<TypeBox.TKeyOf<T>>, TUnion<[TNull, TypeBox.TMappedResult<TypeBox.Evaluate<TypeBox.TIndexPropertyKeys<TypeBox.TKeyOf<T>> extends infer T_1 ? T_1 extends TypeBox.TIndexPropertyKeys<TypeBox.TKeyOf<T>> ? T_1 extends [infer Left extends PropertyKey, ...infer Right extends PropertyKey[]] ? Right extends [infer Left extends PropertyKey, ...infer Right extends PropertyKey[]] ? Right extends [infer Left extends PropertyKey, ...infer Right extends PropertyKey[]] ? Right extends [infer Left extends PropertyKey, ...infer Right extends PropertyKey[]] ? Right extends [infer Left extends PropertyKey, ...infer Right extends PropertyKey[]] ? Right extends [infer Left extends PropertyKey, ...infer Right extends PropertyKey[]] ? Right extends [infer Left extends PropertyKey, ...infer Right extends PropertyKey[]] ? Right extends [infer Left extends PropertyKey, ...infer Right extends PropertyKey[]] ? Right extends [infer Left extends PropertyKey, ...infer Right extends PropertyKey[]] ? Right extends [infer Left extends PropertyKey, ...infer Right extends PropertyKey[]] ? Right extends [infer Left extends PropertyKey, ...infer Right extends PropertyKey[]] ? /*elided*/any : { [_ in Left]: TypeBox.Assert<TypeBox.TIndexFromPropertyKey<T, Left>, TSchema$1> } : { [_ in Left]: TypeBox.Assert<TypeBox.TIndexFromPropertyKey<T, Left>, TSchema$1> } : { [_ in Left]: TypeBox.Assert<TypeBox.TIndexFromPropertyKey<T, Left>, TSchema$1> } : { [_ in Left]: TypeBox.Assert<TypeBox.TIndexFromPropertyKey<T, Left>, TSchema$1> } : { [_ in Left]: TypeBox.Assert<TypeBox.TIndexFromPropertyKey<T, Left>, TSchema$1> } : { [_ in Left]: TypeBox.Assert<TypeBox.TIndexFromPropertyKey<T, Left>, TSchema$1> } : { [_ in Left]: TypeBox.Assert<TypeBox.TIndexFromPropertyKey<T, Left>, TSchema$1> } : { [_ in Left]: TypeBox.Assert<TypeBox.TIndexFromPropertyKey<T, Left>, TSchema$1> } : { [_ in Left]: TypeBox.Assert<TypeBox.TIndexFromPropertyKey<T, Left>, TSchema$1> } : { [_ in Left]: TypeBox.Assert<TypeBox.TIndexFromPropertyKey<T, Left>, TSchema$1> } : {} : never : never>>]>, {}>>>;
1305
+ /**
1306
+ * Map a schema to another schema.
1307
+ *
1308
+ * @param schema The schema to map.
1309
+ * @param operations The operations to perform on the schema.
1310
+ * @param options The options for the schema.
1311
+ * @returns The mapped schema.
1312
+ */
1178
1313
  map<T extends TObject$1 | TIntersect, Omit extends (keyof T["properties"])[], Optional extends (keyof T["properties"])[]>(schema: T, operations: {
1179
1314
  omit: readonly [...Omit];
1180
1315
  optional: [...Optional];
1181
1316
  }, options?: ObjectOptions): TComposite<[TOmit<T, [...Omit, ...Optional]>, TPartial<TPick<T, Optional>>]>;
1182
1317
  /**
1183
- * Create a schema for a string enum.
1184
- *
1185
- * @param values
1186
- * @param options
1187
- */
1318
+ * Create a schema for a string enum.
1319
+ *
1320
+ * @param values
1321
+ * @param options
1322
+ */
1188
1323
  enum<T extends string[]>(values: [...T], options?: StringOptions): TUnsafe<T[number]>;
1189
1324
  /**
1190
- * Create a schema for a datetime.
1191
- *
1192
- * @param options The options for the date.
1193
- */
1325
+ * Create a schema for a datetime.
1326
+ *
1327
+ * @param options The options for the date.
1328
+ */
1194
1329
  datetime(options?: StringOptions): TString$1;
1195
1330
  /**
1196
- * Create a schema for a date.
1197
- *
1198
- * @param options
1199
- */
1331
+ * Create a schema for a date.
1332
+ *
1333
+ * @param options
1334
+ */
1200
1335
  date(options?: StringOptions): TString$1;
1201
1336
  /**
1202
- * Create a schema for uuid.
1203
- *
1204
- * @param options The options for the duration.
1205
- */
1337
+ * Create a schema for uuid.
1338
+ *
1339
+ * @param options The options for the duration.
1340
+ */
1206
1341
  uuid(options?: StringOptions): TString$1;
1207
1342
  unsafe<T>(kind: string, options?: UnsafeOptions): TUnsafe<T>;
1208
1343
  file(options?: {
1209
1344
  max?: number;
1210
1345
  }): TFile;
1211
1346
  stream(): TStream;
1347
+ /**
1348
+ * Create a schema for a string enum e.g. LIKE_THIS.
1349
+ *
1350
+ * @param options
1351
+ */
1352
+ snakeCase: (options?: StringOptions) => TString$1;
1353
+ /**
1354
+ * Create a schema for an object with a value and label.
1355
+ */
1356
+ valueLabel: (options?: ObjectOptions) => TObject$1<{
1357
+ value: TString$1;
1358
+ label: TString$1;
1359
+ description: TypeBox.TOptional<TString$1>;
1360
+ }>;
1212
1361
  }
1213
- // ---------------------------------------------------------------------------------------------------------------------
1214
1362
  interface FileLike {
1215
1363
  /**
1216
- * Filename.
1217
- * @default "file"
1218
- */
1364
+ * Filename.
1365
+ * @default "file"
1366
+ */
1219
1367
  name: string;
1220
1368
  /**
1221
- * Mandatory MIME type of the file.
1222
- * @default "application/octet-stream"
1223
- */
1369
+ * Mandatory MIME type of the file.
1370
+ * @default "application/octet-stream"
1371
+ */
1224
1372
  type: string;
1225
1373
  /**
1226
- * Size of the file in bytes.
1227
- *
1228
- * Always 0 for streams, as the size is not known until the stream is fully read.
1229
- *
1230
- * @default 0
1231
- */
1374
+ * Size of the file in bytes.
1375
+ *
1376
+ * Always 0 for streams, as the size is not known until the stream is fully read.
1377
+ *
1378
+ * @default 0
1379
+ */
1232
1380
  size: number;
1233
1381
  /**
1234
- * Last modified timestamp in milliseconds since epoch.
1235
- *
1236
- * Always the current timestamp for streams, as the last modified time is not known.
1237
- * We use this field to ensure compatibility with File API.
1238
- *
1239
- * @default Date.now()
1240
- */
1382
+ * Last modified timestamp in milliseconds since epoch.
1383
+ *
1384
+ * Always the current timestamp for streams, as the last modified time is not known.
1385
+ * We use this field to ensure compatibility with File API.
1386
+ *
1387
+ * @default Date.now()
1388
+ */
1241
1389
  lastModified: number;
1242
1390
  /**
1243
- * Returns a ReadableStream or Node.js Readable stream of the file content.
1244
- *
1245
- * For streams, this is the original stream.
1246
- */
1391
+ * Returns a ReadableStream or Node.js Readable stream of the file content.
1392
+ *
1393
+ * For streams, this is the original stream.
1394
+ */
1247
1395
  stream(): StreamLike;
1248
1396
  /**
1249
- * Returns the file content as an ArrayBuffer.
1250
- *
1251
- * For streams, this reads the entire stream into memory.
1252
- */
1397
+ * Returns the file content as an ArrayBuffer.
1398
+ *
1399
+ * For streams, this reads the entire stream into memory.
1400
+ */
1253
1401
  arrayBuffer(): Promise<ArrayBuffer>;
1254
1402
  /**
1255
- * Returns the file content as a string.
1256
- *
1257
- * For streams, this reads the entire stream into memory and converts it to a string.
1258
- */
1403
+ * Returns the file content as a string.
1404
+ *
1405
+ * For streams, this reads the entire stream into memory and converts it to a string.
1406
+ */
1259
1407
  text(): Promise<string>;
1260
- // -- node specific fields --
1261
1408
  /**
1262
- * Optional file path, if the file is stored on disk.
1263
- *
1264
- * This is not from the File API, but rather a custom field to indicate where the file is stored.
1265
- */
1409
+ * Optional file path, if the file is stored on disk.
1410
+ *
1411
+ * This is not from the File API, but rather a custom field to indicate where the file is stored.
1412
+ */
1266
1413
  filepath?: string;
1267
1414
  }
1268
1415
  /**
1269
- * TypeBox view of FileLike.
1270
- */
1416
+ * TypeBox view of FileLike.
1417
+ */
1271
1418
  type TFile = TUnsafe<FileLike>;
1272
1419
  declare const isTypeFile: (value: TSchema$1) => value is TFile;
1273
1420
  declare const isFileLike: (value: any) => value is FileLike;
1274
- // ---------------------------------------------------------------------------------------------------------------------
1275
1421
  type StreamLike = ReadableStream | ReadableStream$1 | Readable | NodeJS.ReadableStream;
1276
1422
  type TStream = TUnsafe<StreamLike>;
1277
1423
  declare const isTypeStream: (value: TSchema$1) => value is TStream;
1278
- // ---------------------------------------------------------------------------------------------------------------------
1279
1424
  type TextLength = "short" | "long" | "rich";
1280
1425
  interface AlephaStringOptions extends StringOptions {
1281
1426
  size?: TextLength;
1282
1427
  }
1283
- // ---------------------------------------------------------------------------------------------------------------------
1284
1428
  declare const t: TypeProvider;
1285
- // ---------------------------------------------------------------------------------------------------------------------
1286
- declare const isUUID: (value: string) => boolean;
1429
+ declare function isISODate(str: string): boolean;
1430
+ declare function isISODateTime(value: string): boolean;
1431
+ declare function isUUID(value: string): boolean;
1432
+ declare function isEmail(value: string): boolean;
1433
+ //# sourceMappingURL=TypeProvider.d.ts.map
1287
1434
  //#endregion
1288
1435
  //#region src/index.d.ts
1436
+ declare global {
1437
+ interface ImportMetaEnv {
1438
+ SSR: boolean;
1439
+ }
1440
+ interface ImportMeta {
1441
+ readonly env: ImportMetaEnv;
1442
+ }
1443
+ }
1289
1444
  /**
1290
- *
1291
- */
1292
- declare const run: (entry: Alepha | Service | Array<Service>, opts?: RunOptions) => Alepha;
1445
+ *
1446
+ */
1447
+ declare const run: (entry: Alepha | Service | Array<Service>, opts?: RunOptions) => void;
1448
+ //# sourceMappingURL=index.d.ts.map
1449
+
1293
1450
  //#endregion
1294
- export { $cursor, $hook, $inject, $injectResolverRegistry, $logger, AbstractService, Alepha, AlephaError, AlephaStringOptions, AlsProvider, AppNotStartedError, Async, AsyncFn, AsyncLocalStorageData, COLORS, CircularDependencyError, ContainerLockedError, CursorDescriptor, Descriptor, DescriptorIdentifier, DescriptorItem, Env, FileLike, Hook, HookDescriptor, HookOptions, Hooks, InstantiableService, KIND, LEVEL_COLORS, LogLevel, Logger, LoggerEnv, LoggerOptions, MaybePromise, MockLogger, MockLoggerStore, Module, ModuleDefinition, NotImplementedError, OPTIONS, PromiseFn, Service, ServiceEntry, ServiceSubstitution, State, Static, StaticDecode, StaticEncode, StreamLike, TAny, TArray, TBoolean, TFile, TNumber, TObject, TOptional, TProperties, TRecord, TSchema, TStream, TString, TextLength, TypeBox, TypeBoxError, TypeBoxValue, TypeGuard, TypeProvider, __alephaRef, __bind, __descriptor, descriptorEvents, isDescriptorValue, isFileLike, isModule, isTypeFile, isTypeStream, isUUID, run, t, toModuleName };
1451
+ export { $cursor, $env, $hook, $inject, $logger, $module, AbstractClass, Alepha, AlephaError, AlephaStringOptions, AlsProvider, AppNotStartedError, Async, AsyncFn, AsyncLocalStorageData, COLORS, CircularDependencyError, ContainerLockedError, CursorDescriptor, Descriptor, DescriptorArgs, DescriptorConfig, DescriptorFactory, DescriptorFactoryLike, Env, FileLike, Hook, HookDescriptor, HookOptions, Hooks, InjectDescriptor, InstantiableClass, KIND, LEVEL_COLORS, LogLevel, Logger, LoggerDescriptorOptions, LoggerEnv, LoggerOptions, MaybePromise, MockLogger, MockLoggerStore, Module, ModuleDefinition, ModuleDescriptor, ModuleDescriptorOptions, NotImplementedError, OPTIONS, Service, ServiceEntry, ServiceSubstitution, State, type Static, type StaticDecode, type StaticEncode, StreamLike, type TAny, type TArray, type TBoolean, TFile, type TNumber, type TObject, type TOptional, type TProperties, type TRecord, type TSchema, TStream, type TString, TextLength, TypeBox, TypeBoxError, TypeBoxValue, TypeGuard, TypeProvider, __alephaRef, createDescriptor, descriptorEvents, isEmail, isFileLike, isISODate, isISODateTime, isModule, isTypeFile, isTypeStream, isUUID, run, t, toModuleName };
1295
1452
  //# sourceMappingURL=index.d.ts.map