@elysiumjs/core 0.6.1 → 0.8.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,42 @@
1
1
  # @elysiumjs/core
2
2
 
3
+ ## 0.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`8ac91ab`](https://github.com/na2axl/elysiumjs/commit/8ac91ab676b1119b4eecf0ddb3fd0a3e84017cac) Thanks [@na2axl](https://github.com/na2axl)! - Upgrade dependencies to their latest major versions: wampy 8, zod 4, commander 15, @casl/ability 7, OpenTelemetry SDK 2 (sdk-node 0.300, resources 3), @sentry/bun 11. Generated projects now use TypeScript 7.
8
+
9
+ Breaking in `@elysiumjs/mnemosyne-drizzle`: it now requires drizzle-orm 1.0 (release candidate) and generated projects use drizzle-kit 1.0. `ColumnsWithTable` is no longer re-exported. `migration:generate` writes 1.0 migration folders (`<timestamp>_<name>/migration.sql`), and `migration:run` tracks those by folder name while still running flat `*.sql` files. Existing projects can upgrade their migrations folder with `drizzle-kit up`: `migration:run` recognises the moved migrations as already applied and renames their records. The `make:model` stub now generates a `pgTable` and a `DrizzleModel` built from it.
10
+
11
+ Breaking in `@elysiumjs/core`: the deprecated `@elysiajs/swagger` plugin is replaced by `@elysiajs/openapi`, and the app option `swagger` is renamed `openapi` (typed `ElysiaOpenAPIConfig | false`). Without a `path`, the docs now live at `/openapi` instead of `/swagger`. The UI options `scalarConfig` and `swaggerOptions` are now `scalar` and `swagger`. Elysia stays on 1.4 (now `^1.4.30`) until Elysia 2 and its OpenAPI plugin are stable.
12
+
13
+ Also in `@elysiumjs/core`: the WAMP `onChallenge` callback must return a string (or a promise of one); `null` is no longer accepted. `onError` now receives the error and `onReconnectSuccess` receives wampy's details object. `WampClient` is now wampy's own `Wampy` type. `onOpen` is called by Elysium once the connection is established, since wampy 8 no longer has that callback.
14
+
15
+ - [`3625883`](https://github.com/na2axl/elysiumjs/commit/3625883dba92f1596e7444ee52f9399d8e9b049f) Thanks [@na2axl](https://github.com/na2axl)! - Drop the `reflect-metadata` dependency. Decorator metadata now lives in a small store in `@elysiumjs/core`, exported as `Metadata` (`define`, `get`, `getOwn`, `has`). Use it instead of `Reflect.defineMetadata` and `Reflect.getMetadata` to read or write Elysium metadata.
16
+
17
+ Apps no longer need `import 'reflect-metadata'` in their entrypoint, and generated projects leave it out. Keep `emitDecoratorMetadata` enabled: `@Service.inject()` and `@Command.arg()` still infer types from it. An app that loads `reflect-metadata` for another library keeps working; Elysium also reads the types stored there.
18
+
19
+ - [`07236b3`](https://github.com/na2axl/elysiumjs/commit/07236b386c2506590d74e8753ce847c1e184b3ee) Thanks [@na2axl](https://github.com/na2axl)! - Introduce the module system. Modules are now the only way to register anything in an Elysium.js app. This is a breaking change with no compatibility layer.
20
+
21
+ Breaking changes:
22
+
23
+ - `@Module.register()` takes `imports`, `services`, `exports`, `controllers`, `commands`, `jobs`, `prefix` and `env`. Services are private to their module unless exported (or global). The `beforeRegister` and `afterRegister` hooks are replaced by `onInit`, `onServe` and `onDestroy`.
24
+ - Configurable modules are bound with `with()`, for example `HermesModule.with({ level: 'debug' })`. `with()` accepts an object or a function.
25
+ - Decorators only record metadata. Importing a file no longer registers commands, services or event wiring, and the side-effect imports of the packages are removed. List commands, jobs and services in the module that owns them.
26
+ - `@Application.register()` no longer takes `database`, `redis`, `wamp` or `'elysium:hermes'`/`'elysium:cerberus'` keys. Use `DrizzleModule`, `RedisModule`, `WampModule`, `HermesModule` and `CerberusModule`. Package plugins are replaced by modules: add `SentryModule` instead of the `plugin()` function. `plugins` still accepts plain Elysia plugin factories.
27
+ - Constructing an `Application` no longer runs it. Use `await App.start()`; `Application.testing()` boots a module graph for tests. The `styx` binary loads `src/app.ts` (or `index.ts`) and starts the exported application, so a project entry no longer needs to import commands.
28
+ - The job system of core (`Job`, `Worker`, `WorkerPool`, `commandWork`) is removed. `@elysiumjs/heracles` is the only job system: extend its `Job`, list jobs in a module's `jobs`, declare queues with `HeraclesModule.with({ queues })`, and dispatch with `Heracles.dispatch()`.
29
+ - `@elysiumjs/styx` ships `StyxModule`, active in development only. The `migration:generate` and `migration:run` commands move to `DrizzleModule` and are available in production.
30
+ - `@elysiumjs/mnemosyne` ships `MnemosyneModule` for its caches (`redis: false` or `memory: false` opts out). `DrizzleModule` imports it.
31
+ - New modules: `HephaestusModule`, `ArgusModule` (`serviceName` is required), `SentryModule` (needs a `dsn` or `SENTRY_DSN`) and `CerberusModule` (`getSubject` is required).
32
+ - Module and service code throws typed errors (for example `InvalidModuleConfigError`) instead of exiting the process. `Application.run()` prints them and exits; command `run()` methods may still exit, and package plugin factories are unchanged.
33
+ - `Application.register` merges subclass props over the parent's (own props, then own metadata, then parent, then defaults), and concatenates `modules` parent first. Previously defaults and parent values won, so `openapi` could not be enabled.
34
+ - `Heracles.dispatch` starts a stopped queue on first use, so producers no longer start queues. `Queue.start()` is idempotent.
35
+ - `create-elysium` generates apps that use modules, and adds Sentry and Hephaestus to the `modules` list.
36
+ - `@Event.on`/`@Event.once` method listeners on classes in a loaded module's `services` or `controllers` are wired by the kernel and run in their module's context. Jobs, commands and middlewares are not wired, and an instance listener on a class that is not a service throws `EventListenerNotSupportedError`. Listeners on classes not listed in a loaded module no longer fire.
37
+ - New typed errors: `CircularDependencyError` (services that depend on each other, in sync and async resolution), `DuplicateModuleNameError` (two different module classes sharing a name; module scopes and config tokens are name based) and `EventListenerNotSupportedError`.
38
+ - Lazy boot contract: a CLI command initialises only its own module and that module's imports. Sync helpers such as `Database.getConnection()` work when the owning module's `onInit` is synchronous; otherwise they throw `ServiceNotReadyError` naming the module. Use `await Service.resolve()` or set `static boot = true` on the command.
39
+
3
40
  ## 0.6.0
4
41
 
5
42
  ### Minor Changes
package/README.md CHANGED
@@ -24,7 +24,7 @@ bun install @elysiumjs/core
24
24
  - PostgreSQL database support with Drizzle ORM
25
25
  - Model classes and repositories for database interactions
26
26
  - Multi-tenancy support enabled
27
- - Swagger documentation
27
+ - OpenAPI documentation (Scalar or Swagger UI)
28
28
 
29
29
  ## Usage
30
30
 
@@ -42,40 +42,39 @@ export class UserController {
42
42
  }
43
43
  ```
44
44
 
45
- Create a module class:
45
+ Create a module class. A module is the only way to register anything in an Elysium.js app:
46
+ controllers, commands, jobs and services are all declared by the module that owns them.
46
47
 
47
48
  ```typescript
48
49
  import { Module } from '@elysiumjs/core';
49
50
 
50
51
  import { UserController } from './controllers/http/user.controller';
52
+ import { UserService } from './services/user.service';
51
53
 
52
54
  @Module.register({
55
+ services: [UserService],
53
56
  controllers: [UserController]
54
57
  })
55
- export class MainModule extends Module {
56
- public constructor() {
57
- super();
58
- }
59
-
60
- public async beforeRegister(): Promise<void> {
61
- console.log('Module is being registered');
62
- }
63
-
64
- public async afterRegister(): Promise<void> {
65
- console.log('Module registered successfully');
66
- }
67
- }
58
+ export class MainModule extends Module {}
68
59
  ```
69
60
 
70
- Create an application class:
61
+ Create an application class. Modules that need configuration are bound to it with `with()`:
71
62
 
72
63
  ```typescript
73
- import { Application } from '@elysiumjs/core';
64
+ import { Application, RedisModule } from '@elysiumjs/core';
65
+ import { HermesModule } from '@elysiumjs/hermes';
74
66
 
75
67
  import { MainModule } from './main.module';
76
68
 
77
69
  @Application.register({
78
- modules: [MainModule],
70
+ modules: [
71
+ HermesModule.with({ level: 'debug', format: 'pretty' }),
72
+ RedisModule.with({
73
+ default: 'cache',
74
+ connections: { cache: { url: process.env.REDIS_URL! } }
75
+ }),
76
+ MainModule
77
+ ],
79
78
  server: {
80
79
  name: 'Elysium',
81
80
  port: 3000
@@ -87,11 +86,9 @@ export class App extends Application {}
87
86
  Create an entrypoint file:
88
87
 
89
88
  ```typescript
90
- import 'reflect-metadata'; // <- IMPORTANT TO ADD THIS LINE IN THE ENTRYPOINT FILE
91
-
92
89
  import { App } from './app';
93
90
 
94
- new App();
91
+ await App.start();
95
92
  ```
96
93
 
97
94
  Start the server:
@@ -106,6 +103,24 @@ Or, if using `styx`, run:
106
103
  bun styx serve
107
104
  ```
108
105
 
106
+ ## Lazy boot
107
+
108
+ A CLI command boots lazily: running `app:cmd` initialises the command's own module and the modules it imports, not the whole graph. `help <cmd>` is always lazy, even for commands with `static boot = true`.
109
+
110
+ - **Sync helpers are safe** (`Service.get()`, `Database.getConnection()`, `Redis.getConnection()`, ...) when the module that owns the service initialises synchronously. Elysium then initialises that module on the spot, even if the command does not import it.
111
+ - **Use `await Service.resolve(...)`** when the owning module has an asynchronous `onInit`. A sync `get` then throws `ServiceNotReadyError`, which names the module.
112
+ - **Use `static boot = true`** on a command that needs every module initialised before it runs (workers, servers). It initialises every module and builds every service first.
113
+ - Service factories receive a synchronous `get`; it may only read services whose owning modules initialise synchronously, otherwise it throws `ServiceNotReadyError`.
114
+
115
+ ## Migrating from the pre-module API
116
+
117
+ - The `database`, `redis`, `wamp` and `elysium:hermes` keys of `@Application.register()` are gone. Add `DrizzleModule.with()`, `RedisModule.with()`, `WampModule.with()` and `HermesModule.with()` to `modules` instead.
118
+ - `plugins` no longer takes package plugins. Add the package's module (for example `SentryModule`) to `modules`.
119
+ - Importing a file no longer registers its commands or services. List commands in a module's `commands`, services in `services`, and jobs in `jobs`.
120
+ - `new App()` is replaced by `await App.start()`. `Application.testing()` boots a module graph for tests.
121
+ - The `beforeRegister` and `afterRegister` module hooks are replaced by `onInit`, `onServe` and `onDestroy`.
122
+ - Jobs and workers moved to `@elysiumjs/heracles`; `WorkerPool` is removed.
123
+
109
124
  ## Documentation
110
125
 
111
126
  TODO
package/dist/app.d.ts CHANGED
@@ -1,24 +1,22 @@
1
- import type { ElysiaSwaggerConfig } from '@elysiajs/swagger';
1
+ import type { ElysiaOpenAPIConfig } from '@elysiajs/openapi';
2
2
  import type { AnyElysia, ElysiaConfig, ErrorContext, TSchema } from 'elysia';
3
- import type { DatabaseConnectionProps } from './database';
4
3
  import type { Route } from './http';
5
- import type { ModuleClass } from './module';
6
- import type { RedisConnectionProps } from './redis';
7
- import type { WampClientProps } from './wamp';
4
+ import type { ConfiguredModule, ModuleClass } from './module';
5
+ import type { TestingApp, TestingOptions } from './testing';
8
6
  import { AsyncLocalStorage } from 'node:async_hooks';
9
7
  import { Elysia } from 'elysia';
10
8
  import { InteractsWithConsole } from './console';
9
+ import { Kernel } from './kernel';
11
10
  /**
12
11
  * An application plugin, consisting of a function that returns an Elysia instance.
13
12
  * @author Axel Nana <axel.nana@workbud.com>
14
13
  */
15
14
  export type ElysiumPlugin = (app: Application) => Promise<AnyElysia>;
16
15
  /**
17
- * Properties required when declaring an app using the `@app()` decorator.
16
+ * Properties required when declaring an app using the `@Application.register()` decorator.
18
17
  * @author Axel Nana <axel.nana@workbud.com>
19
18
  */
20
19
  export type AppProps = {
21
- [key: string]: any;
22
20
  /**
23
21
  * Enables or disables debug mode.
24
22
  */
@@ -33,54 +31,15 @@ export type AppProps = {
33
31
  port?: number;
34
32
  };
35
33
  /**
36
- * The wamp client configuration for the app.
34
+ * The modules the application is made of. They act as the imports of the root module.
37
35
  */
38
- wamp?: {
39
- /**
40
- * The default connection name.
41
- */
42
- default: string;
43
- /**
44
- * The list of connections.
45
- */
46
- connections: Record<string, WampClientProps>;
47
- };
48
- /**
49
- * The list of modules provided the app.
50
- */
51
- modules?: ModuleClass[];
52
- /**
53
- * The database configuration for the app.
54
- */
55
- database?: {
56
- /**
57
- * The default connection name.
58
- */
59
- default: string;
60
- /**
61
- * The list of connections.
62
- */
63
- connections: Record<string, DatabaseConnectionProps>;
64
- };
36
+ modules?: (ModuleClass | ConfiguredModule<any>)[];
65
37
  /**
66
- * The redis configuration for the app.
67
- */
68
- redis?: {
69
- /**
70
- * The default connection name.
71
- */
72
- default: string;
73
- /**
74
- * The list of connections.
75
- */
76
- connections: Record<string, RedisConnectionProps>;
77
- };
78
- /**
79
- * Swagger documentation configuration.
38
+ * OpenAPI documentation configuration.
80
39
  *
81
- * Set it to `false` to disable Swagger documentation.
40
+ * Set it to `false` to disable OpenAPI documentation.
82
41
  */
83
- swagger?: ElysiaSwaggerConfig<Route> | false;
42
+ openapi?: ElysiaOpenAPIConfig | false;
84
43
  /**
85
44
  * The validation schema for the application environment.
86
45
  */
@@ -108,6 +67,7 @@ export declare abstract class Application extends InteractsWithConsole {
108
67
  static get instance(): Application;
109
68
  /**
110
69
  * Gets the application context shared between asynchronous operations.
70
+ * Falls back to a module-level storage when no application instance exists.
111
71
  */
112
72
  static get context(): AppContext;
113
73
  /**
@@ -119,6 +79,21 @@ export declare abstract class Application extends InteractsWithConsole {
119
79
  * Creates a new instance of the application.
120
80
  */
121
81
  constructor();
82
+ /**
83
+ * Creates the application and runs it.
84
+ * @author Axel Nana <axel.nana@workbud.com>
85
+ */
86
+ static start<T extends Application>(this: new () => T): Promise<void>;
87
+ /**
88
+ * Boots a module graph without a CLI or an HTTP server, for tests.
89
+ * @param options The modules to boot, service overrides, environment and boot mode.
90
+ * @author Axel Nana <axel.nana@workbud.com>
91
+ */
92
+ static testing(options: TestingOptions): Promise<TestingApp>;
93
+ /**
94
+ * The kernel running this application's module graph. Available once `run()` has started.
95
+ */
96
+ get kernel(): Kernel;
122
97
  /**
123
98
  * Gets the Elysia instance.
124
99
  */
@@ -148,32 +123,55 @@ export declare abstract class Application extends InteractsWithConsole {
148
123
  * @param _elysia The Elysia instance.
149
124
  */
150
125
  protected onStop(_elysia: Elysia<Route>): Promise<void>;
151
- protected run(): Promise<void>;
152
126
  /**
153
- * Retrieves the configuration value for the given key.
154
- * @param key The key to retrieve the configuration value for.
155
- * @returns The configuration value for the given key, or `null` if not found.
127
+ * Runs the CLI action given in `argv`: describe, `list`, `help`, `serve` or a command.
128
+ * Prints any error and exits with a non-zero code.
129
+ * @param argv The command line arguments, without the executable and script.
130
+ * @author Axel Nana <axel.nana@workbud.com>
131
+ */
132
+ run(argv?: string[]): Promise<void>;
133
+ private props;
134
+ private dispatch;
135
+ /** Prints an error, shuts down what was started and exits with code 1. */
136
+ private fail;
137
+ /** Exits the process, after detaching the signal handlers. */
138
+ private exit;
139
+ private removeSignalHandlers;
140
+ private installSignalHandlers;
141
+ /** The commands available in the module graph, with their owning module. */
142
+ private getCommands;
143
+ private findCommand;
144
+ /**
145
+ * Builds a command inside its owning module: lazily by default, after an eager boot
146
+ * when the command sets `boot`.
147
+ */
148
+ private prepareCommand;
149
+ /** Registers the kernel (and boots it eagerly if asked), then announces the launch. */
150
+ private bootKernel;
151
+ /**
152
+ * Prints the help of a command.
153
+ * @param name The command name.
156
154
  */
157
- getConfig<T>(key: keyof AppProps): T | null;
155
+ private commandHelp;
158
156
  /**
159
157
  * Executes a command.
160
- * @param command The command to execute.
158
+ * @param name The command to execute.
161
159
  * @param argv The command line arguments.
162
160
  */
163
161
  private commandExec;
164
162
  /**
165
- * Discovers all registered commands from the service container.
166
- * Commands are registered via `@Command.register()` and stored with the
167
- * `elysium.command.*` service name pattern.
168
- *
169
- * @returns An array of all discovered command classes, filtered by build mode.
170
- */
171
- private getCommands;
172
- private commandWork;
173
- /**
174
- * Starts the server on the specified port.
163
+ * Starts the server: boots the kernel, builds the root Elysia app, lets modules hook into it,
164
+ * mounts their controllers and listens.
175
165
  */
176
166
  private commandServe;
167
+ /** Lets every module hook into the root app, then mounts the controllers of each module. */
168
+ private serveModules;
169
+ /** Builds the Elysia plugin of a module: its middlewares and the plugins of its controllers. */
170
+ private mountModule;
171
+ /** Registers the error handler and the start and stop hooks of the root app. */
172
+ private setupServerHooks;
173
+ /** Turns an error raised while handling a request into the response sent to the client. */
174
+ private handleServerError;
177
175
  /**
178
176
  * Describes the CLI and available commands.
179
177
  */
package/dist/command.d.ts CHANGED
@@ -90,7 +90,18 @@ export type CommandClass<T extends Command = Command> = Class<T> & {
90
90
  * Whether the command is only available in development mode.
91
91
  */
92
92
  readonly dev: boolean;
93
+ /**
94
+ * Whether the application is booted eagerly before the command runs.
95
+ */
96
+ readonly boot: boolean;
93
97
  };
98
+ /**
99
+ * Gets the name a command is invoked by: the `name` given to `@Command.register()`,
100
+ * or else the static `command`.
101
+ * @param cls The command class.
102
+ * @author Axel Nana <axel.nana@workbud.com>
103
+ */
104
+ export declare function getCommandName(cls: Class<any>): string;
94
105
  /**
95
106
  * Base class for commands.
96
107
  *
@@ -118,12 +129,17 @@ export declare abstract class Command extends InteractsWithConsole {
118
129
  */
119
130
  static readonly dev: boolean;
120
131
  /**
121
- * Registers a command in the service container for autodiscovery.
122
- *
123
- * Commands registered with this decorator will be automatically discovered
124
- * and made available in the CLI without needing to be listed explicitly.
132
+ * Whether the whole application is booted before the command runs.
133
+ * When `true`, every module is initialised and every service constructed first,
134
+ * as for `serve`. Otherwise modules are initialised lazily, on demand.
135
+ */
136
+ static readonly boot: boolean;
137
+ /**
138
+ * Marks a class as a command. Records metadata only: the command still has to be
139
+ * listed in the `commands` of a module to be available in the CLI.
125
140
  *
126
141
  * @param options Optional registration options.
142
+ * @author Axel Nana <axel.nana@workbud.com>
127
143
  */
128
144
  static register(options?: {
129
145
  name?: string;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Checks the `default` and `connections` keys of a connection module's config.
3
+ * @author Axel Nana <axel.nana@workbud.com>
4
+ * @param module The module name, for error messages.
5
+ * @param config The resolved config.
6
+ * @returns Whether a separate alias entry is needed for the default connection.
7
+ * @throws {InvalidModuleConfigError} When the default is unknown or collides with a `default` connection.
8
+ */
9
+ export declare function needsDefaultAlias(module: string, config: {
10
+ default: string;
11
+ connections: Record<string, unknown>;
12
+ }): boolean;
13
+ /**
14
+ * Runs every task even if some fail, then rethrows: the single error, or an `AggregateError`.
15
+ * @author Axel Nana <axel.nana@workbud.com>
16
+ */
17
+ export declare function runAll(tasks: (() => unknown)[]): Promise<void>;
@@ -0,0 +1,128 @@
1
+ import type { Class } from 'type-fest';
2
+ import type { ModuleNode } from './module-graph';
3
+ import type { ServiceDefinition } from './service';
4
+ import { ServiceScope } from './service';
5
+ /**
6
+ * A service registered in the container.
7
+ * @author Axel Nana <axel.nana@workbud.com>
8
+ */
9
+ export type ContainerEntry = {
10
+ /** The name the service is registered under. */
11
+ name: string;
12
+ /** The service's scope. */
13
+ scope: ServiceScope;
14
+ /** Whether the service is visible from every scope. */
15
+ global: boolean;
16
+ /** The module that declared the service, or `null` for services registered imperatively. */
17
+ owner: ModuleNode | null;
18
+ /** Builds a new instance of the service. */
19
+ create: () => unknown;
20
+ /** The singleton instance, once built. */
21
+ instance?: unknown;
22
+ /** Whether the instance has been built and its `onInit` has completed. */
23
+ initialised: boolean;
24
+ /** Pending `onInit` of a singleton, when it is asynchronous. */
25
+ initPromise?: Promise<void>;
26
+ /** The error thrown by a singleton's `onInit`, once it has failed. */
27
+ initFailure?: {
28
+ error: unknown;
29
+ };
30
+ /** The service class, when the entry was registered from one. Used to await its dependencies. */
31
+ cls?: Class<any>;
32
+ };
33
+ /**
34
+ * Supplies the visibility rules of the module graph to the container.
35
+ * @author Axel Nana <axel.nana@workbud.com>
36
+ */
37
+ export type VisibilityResolver = {
38
+ /** The modules whose exports `node` can see. */
39
+ visibleOwners(node: ModuleNode): readonly ModuleNode[];
40
+ /** The service names `owner` exports, or `true` when it exports all its services. */
41
+ exportsOf(owner: ModuleNode): readonly string[] | true;
42
+ };
43
+ /**
44
+ * The scoped service container: a global scope plus one scope per module.
45
+ * Visibility between module scopes is supplied by the module graph.
46
+ *
47
+ * @author Axel Nana <axel.nana@workbud.com>
48
+ */
49
+ export declare namespace Container {
50
+ /**
51
+ * Registers a service definition.
52
+ * @param owner The declaring module, or `null` for a service registered outside any module.
53
+ * @param def A service class or factory definition.
54
+ * @param config The owning module's resolved config, handed to factory definitions.
55
+ * @returns The name the service was registered under.
56
+ * @throws {DuplicateGlobalServiceError} If a global service with that name already exists.
57
+ */
58
+ function register(owner: ModuleNode | null, def: ServiceDefinition, config: unknown): string;
59
+ /**
60
+ * Adds a prebuilt entry. A global entry goes to the global scope, any other to its owner's scope.
61
+ * @throws {DuplicateGlobalServiceError} If the name is already taken in the global scope.
62
+ */
63
+ function add(entry: ContainerEntry): void;
64
+ /**
65
+ * Declares global service names that win over module registrations: `register` skips
66
+ * any definition with one of these names, so lookups reach the global entry.
67
+ * Pass `null` to clear.
68
+ */
69
+ function setOverrides(names: Iterable<string> | null): void;
70
+ /**
71
+ * Sets the module graph's visibility rules. Without a resolver, a module only sees
72
+ * its own services and the global ones.
73
+ */
74
+ function setVisibility(resolver: VisibilityResolver | null): void;
75
+ /**
76
+ * Sets the hook called before building a service whose owning module may not be initialised.
77
+ * It returns `void` when the module is ready, or a promise while initialisation is pending.
78
+ */
79
+ function setModuleInitHook(hook: ((owner: ModuleNode) => Promise<void> | void) | null): void;
80
+ /**
81
+ * Sets the lookup consulted when a name isn't found, to report services
82
+ * that belong to modules skipped for the current environment.
83
+ */
84
+ function setSkippedLookup(lookup: ((name: string) => {
85
+ module: string;
86
+ environment: string;
87
+ } | null) | null): void;
88
+ /**
89
+ * Finds a service visible from `from`: its own scope, then the exports of the modules
90
+ * it can see, then the global scope. Without `from`, only the global scope is searched.
91
+ */
92
+ function lookup(name: string, from: ModuleNode | undefined): {
93
+ entry: ContainerEntry;
94
+ owner: ModuleNode | null;
95
+ } | null;
96
+ /**
97
+ * Gets a service visible from the current module context.
98
+ * @returns The service, or `null` if none is visible.
99
+ * @throws {ServiceNotReadyError} If the service or its module is still initialising.
100
+ */
101
+ function get(name: string): unknown;
102
+ /**
103
+ * Like {@link get}, but awaits the `onInit` of the service and of its owning module.
104
+ * @throws {ServiceNotFoundError | ServiceNotVisibleError | EnvironmentSkippedModuleError}
105
+ */
106
+ function resolve(name: string, requester: string): Promise<unknown>;
107
+ /**
108
+ * Builds `cls` with its injected dependencies, resolved from the current module context.
109
+ * @throws {ServiceNotFoundError | ServiceNotVisibleError | EnvironmentSkippedModuleError}
110
+ */
111
+ function make<T>(cls: Class<T>): T;
112
+ /** Whether the global scope has a service with that name. */
113
+ const hasGlobal: (name: string) => boolean;
114
+ /** The names registered in the global scope. */
115
+ const globalNames: () => string[];
116
+ /** Removes a service from the global scope. */
117
+ const removeGlobal: (name: string) => void;
118
+ /** Clears the global scope. */
119
+ const clearGlobal: () => void;
120
+ /** The live singletons, in construction order (those whose `onInit` failed are left out). Returns a snapshot. */
121
+ const constructed: () => readonly {
122
+ name: string;
123
+ instance: unknown;
124
+ owner: ModuleNode | null;
125
+ }[];
126
+ /** Clears every scope and the construction record. */
127
+ function reset(): void;
128
+ }