Classes

@system-inc/base-foundation · 515c140 · 15 symbols

Base

class

The engine of a worker. Initializes the app from its BaseConfiguration — binding GraphQL, RPC, WebSocket, and HTTP routes — and turns each platform event (request, queue message, scheduled run, WebSocket event) into work on a freshly scoped child container of the worker's dependency-injection container.

Applications don't construct this directly: BaseWorker.create(settings) builds one lazily on the first event and drives it from the platform's fetch/queue/scheduled handlers.

Members

  • context: BaseWorkerContext

  • configuration: BaseConfiguration

  • delegate: BaseWorkerDelegate | null

    The delegate for the Worker. Receives events from the Worker.

  • isInitialized: boolean

    Indicates whether Base has been initialized.

  • platformDelegate: BaseWorkerPlatformDelegate

    The platform delegate for the Worker. Handles platform specific operations.

  • getGqlSchema(): Promise<GraphQLSchema>

  • handleMessages(messages: readonly (Message<WorkerQueueMessage<PayloadType>>)[], executionContext: BaseExecutionContext): Promise<void>

    Initialize the worker and handle the message (queue).

  • handleRequest(request: Request, executionContext: BaseExecutionContext, webSocketInfo?: WebSocketInfo): Promise<Response>

    Initialize the worker and handle the request.

  • handleScheduled(scheduledEvent: ScheduledEvent, executionContext: BaseExecutionContext): Promise<void>

    Initialize the worker and run the ScheduledExecutable(s).

  • initialize(): Promise<void>

    Initializes this Base instance. Base cannot be used until it has been initialized.

  • webSocketClose(webSocket: BaseWebSocket): Promise<void>

  • webSocketError(webSocket: BaseWebSocket, error: unknown): Promise<void>

  • webSocketMessage(webSocket: BaseWebSocket, message: string | ArrayBuffer): Promise<void>

  • webSocketRegister(webSocket: BaseWebSocket, webSocketInfo: WebSocketInfo): Promise<void>

    Register a web socket with the web socket service. Only called in Node environments.

  • webSocketUnregister(webSocketInfo: WebSocketInfo): Promise<void>

    Unregister a web socket from the web socket service. Only called in Node environments.

View source ↗

The flattened view of a worker's whole module dependency graph. Each registered services class is sorted by its decorator marks into the dispatch buckets (GraphQL resolvers, router services, RPC services, queue processors, scheduled executables, event-bus listeners), alongside ORM entities, GraphQL directives, WebSocket delegates, and middleware — the single structure the engine and dispatchers read instead of re-walking modules. Built lazily by BaseConfiguration via BaseAppManifest.fromSettings; validate() performs the boot-time checks that sorting alone can't.

Members

  • accessControl: { provider: Constructor<SessionContextProvider> | null; providerSource: string | null }

    The worker's session-context provider — the single identity seam for access control, registered via accessControl.provider in worker or module settings. providerSource records who registered it, for conflict errors.

  • cli: { configValidators: WorkerConfigValidator[] }

    Aggregated CLI-time extension points across all modules.

  • defaultDatabaseName: string

    The database name an undeclared module resolves to. Normally DefaultConfigurationKey ('@default'), but when the worker configures exactly one database under a non-default name, that single database is the default in spirit (matching getDatabaseNameForClass) — otherwise a module's entities would be orphaned in a phantom '@default' database. Set from settings in fromSettings.

  • eventBus: { listeners: (Constructor<BaseEventListener<BaseEvent>>)[] }

  • graphql: { directives: GraphQLDirective[]; resolvers: (Constructor<object>)[] }

  • middleware: { global: BaseMiddlewareRegistration[]; handler: HandlerMiddlewareRegistration[] }

    Aggregated middleware across all modules, ordered by module dependency (as declared by uses:).

  • orm: PartialDictionary<{ entities: OrmEntityClass[]; externalEntities: OrmEntityClass[] }>

  • queue: { processors: (Constructor<WorkerQueueProcessorInterface<unknown>>)[] }

  • router: { services: (Constructor<object>)[] }

  • rpc: { services: (Constructor<object>)[] }

  • scheduled: { executables: (Constructor<ScheduledExecutableInterface>)[] }

  • webSocket: { delegates: WebSocketDelegateSettings[]; mappings: (WebSocketContextMapping<Json>)[] }

  • getDatabaseForClass(target: Constructor): string | undefined

    The database name the registration carrying target resolves to, or undefined if the class isn't registered by any module or worker settings slot. Validation only — token-less ORM injections resolve through declared module membership or the default database, never through registration.

  • getDatabaseForModule(moduleName: string): string | undefined

    The database name a module resolves to in this worker, or undefined if no module with that name is registered here.

  • getOrmSettings(databaseName: string): { entities: OrmEntityClass[]; externalEntities: OrmEntityClass[] }

  • registerAccessControlProvider(provider: Constructor<SessionContextProvider>, source: string): void

    Registers the session-context provider. Exactly one provider may be registered across the worker and all its modules — a second, different registration is a contradiction and throws. Registering the same class twice is idempotent.

  • registerClassDatabase(target: Constructor, databaseName: string, moduleName: string): void

    Records that target is registered by moduleName, which resolves to databaseName. Idempotent for the same database; a class registered in two modules that resolve to different databases is a contradictory attribution and throws — the class must declare its membership (or take an explicit binding) instead.

  • registerModuleDatabase(moduleName: string, databaseName: string): void

    Records the database a module resolves to in this worker. called while the module graph flattens

  • validate(): void

    Boot-time validation of the flattened manifest. The dispatch buckets need no decorator assertions — they can only be filled by the services sorter, which requires the decorator to place a class at all (a class with no recognized decorator throws during sorting). What remains: entity slots (still registered directly, not sorted by decorator) and declared-module-membership consistency.

  • static fromSettings(settings: BaseSettings): BaseAppManifest

    Builds a manifest by aggregating all registered classes and handlers from the provided settings, including all module dependencies.

View source ↗

Base configuration information that can be injected by consumers.

Environment variables are not directly exposed. Use typed BaseEnvironmentKey instances with getEnvironmentVariable or requireEnvironmentVariable to access individual values.

Members

  • instanceId: string

  • accessControl: { provider: Constructor<SessionContextProvider> | null; providerSource: string | null }

    The worker's access-control registration (the session-context provider), aggregated from worker and module settings.

    Framework use only. The session-access middleware resolves the provider through this.

  • cli: { configValidators: WorkerConfigValidator[] }

    CLI-time extension points aggregated across all modules.

    CLI use only.

  • containers: CfDurableObjectSettings[] | undefined

  • delegate: Constructor<BaseWorkerDelegate> | undefined

  • durableObjects: CfDurableObjectSettings[] | undefined

  • eventBus: EventBusConfiguration | undefined

  • graphql: GqlConfiguration | undefined

  • keyValueStorage: KeyValueStorageSettings | undefined

  • logging: LoggingConfiguration

  • middleware: { global: BaseMiddlewareRegistration[]; handler: HandlerMiddlewareRegistration[] }

    The aggregated middleware across all modules, ordered by module dependency.

    Framework use only. The router iterates this on every request.

  • modules: (BaseModule<any>)[] | undefined

  • name: string

    The name of this Base application.

  • objectStore: ObjectStoreSettings | undefined

  • queue: WorkerQueueConfiguration | undefined

  • router: RouterConfiguration

  • rpcClient: RpcClientSettings[] | undefined

  • rpcServer: RpcServerConfiguration | undefined

  • runtime: Runtime

    The environment Base is running in, eg. Development or Production.

  • scheduled: ScheduledConfiguration | undefined

  • title: string

  • version: string

    The version of this Base application.

  • webSocket: WebSocketSettings | undefined

    WebSocket configuration, including delegate settings and module-registered context mappings.

  • getDatabaseNameForClass(target: Constructor): string

    The database name a class's token-less @InjectRepository/ @InjectDatabase resolves to.

    Precedence:

    1. the class's declared module membership (@Injectable(SomeModuleKey), @WorkerScoped(SomeModuleKey), …) — resolved through the module graph, so the worker's database registration modifier applies;
    2. the default database — a deliberate, uniform contract for an undeclared class, identical in every worker. (When exactly one database is configured under a non-default name, that database is the default in spirit and is used.)

    Registration deliberately does NOT route injections — it is discovery and exposure, not attribution. BaseAppManifest.validate() catches, at boot, a class registered by a non-default-database module that carries token-less injections without declaring its membership; a misrouted default is additionally caught by the runtime entity guard (requireOwnEntity).

  • getEnvironmentVariable(key: BaseEnvironmentKey<T>): T | undefined

    Gets an environment variable by typed key. Returns undefined if the variable is not set.

    Keys declared via BaseEnvironmentKey.createSecret are auto-wrapped in a Secret so the raw value never flows into logs without an explicit .reveal().

  • getModuleSettings(key: BaseModuleKey<T>): ModuleSettings<T>

    Gets the settings for a specific module by typed key.

  • getOrmConfiguration(databaseName?: string): OrmConfiguration

  • getVersionInfo(): VersionInfo

  • requireEnvironmentVariable(key: BaseEnvironmentKey<T>): T

    Gets an environment variable by typed key. Throws if the variable is not set.

  • toJSON(): { environmentVariables: string[]; graphql: GqlConfiguration | undefined; instanceId: string; name: string; runtime: Runtime; version: string }

    Controls JSON.stringify() output.

  • toString(): string

    Controls string coercion (template literals, String(), "" + obj).

View source ↗

A branded key for type-safe access to environment variables.

Modules define keys for the env vars they need, preventing bulk access to the full environment (which may contain secrets):

const CommitSha = BaseEnvironmentKey.create<string>('COMMIT_SHA');
const StripeKey = BaseEnvironmentKey.createSecret('STRIPE_SECRET_KEY');

configuration.getEnvironmentVariable(CommitSha);   // string | undefined
configuration.getEnvironmentVariable(StripeKey);   // Secret<string> | undefined

Keys declared with createSecret are auto-wrapped in a Secret by the configuration loader, so the value can never flow into logs or JSON without an explicit .reveal() at the consuming call site.

Extends TypedKey with the 'environment' scope brand so environment keys cannot be confused with request-context, module, or WebSocket keys at the type level.

extends TypedKey<T, "environment">

Members

  • _brand: T

    phantom type brand — never assigned at runtime

  • _scope: "environment"

    phantom scope brand — never assigned at runtime

  • isSecret: boolean

  • name: string

  • static create(name: string): BaseEnvironmentKey<T>

    Creates a typed environment variable key for a non-secret value.

  • static createSecret(name: string): BaseEnvironmentKey<Secret<T>>

    Creates a typed environment variable key for a secret value.

    The loader will automatically wrap the raw env string in a Secret, so the typed value is Secret<T> (default Secret<string>) and cannot be logged without an explicit .reveal().

View source ↗

Object for holding the framework's own cross-cutting metadata registries — the ones decorators write into and the dispatchers read.

Modules do NOT register metadata here: a module's bespoke metadata is just import-time singleton state, owned by the module as a module-scope singleton in its own file (the same pattern as DecoratorRegistry). The framework assumes ONE copy of the code per process — DecoratorRegistry's static instance already depends on it — so a central registry would buy no extra safety, while its globalThis lifetime would outlive jest's per-file module registry and dev-server reloads that reset everything else.

Members

  • eventBus: EventBusMetadata

    Metadata for the event bus.

  • graphql: GqlMetadata

    Metadata for GraphQL.

  • middleware: MiddlewareMetadata

    Metadata for middleware.

  • queue: WorkerQueueMetadata

    Metadata for queues.

  • scheduled: ScheduledMetadata

    Metadata for sceduled executations.

  • validation: ValidationMetadata

    Metadata for validation rules attached to classes via the @Verify* decorators. Consumed by ValidationEngine.validate().

View source ↗

Class for defining a module in Base.

Members

  • key: BaseModuleKey<ModuleSpecificSettings>

    The module's identity — the same BaseModuleKey consumers use with uses, configuration.getModuleSettings(key), and declared module membership (@Injectable(key)). Its phantom settings type is bound to this module's settings at create, so the key and the module can't drift apart in name or in type.

  • settings: ModuleSettings<ModuleSpecificSettings>

    Settings for this module.

  • uses?: readonly ModuleUse[]

    A list of modules that this module uses. Entries may be feature-scoped ({ module, when }) so they drop out when that feature is stripped.

  • name: string

    The name of the module (derived from key).

  • options: BaseModuleOptions | undefined

    Registration modifiers applied to this module instance (recorded by create/with, applied when the manifest is flattened).

  • onCreate(): void

    Called when the module is created. This is usually right after the constructor is called.

  • onInitialize(configuration: BaseConfiguration): void | Promise<void>

    Called when the module is initialized. At this point the Base configuration is available.

  • with(options: BaseModuleOptions): this

    Applies registration modifiers to this module instance and returns it, for chaining at the point of registration:

  • static create(create: BaseModuleCreate<ModuleSpecificSettings>, options?: BaseModuleOptions): BaseModule<ModuleSpecificSettings>

    Creates a Base module.

View source ↗

A branded key for type-safe access to module settings.

Modules define keys for their settings, binding the module name and settings type together so consumers can't get them out of sync:

const StripeSettings = BaseModuleKey.create<StripeModuleSettings>('Stripe');

const settings = configuration.getModuleSettings(StripeSettings);
settings.queues?.webhookEvents?.name;  // fully typed

Extends TypedKey with the 'module' scope brand so module settings keys cannot be confused with request-context, environment, or WebSocket keys at the type level.

extends TypedKey<T, "module">

Members

  • _brand: T

    phantom type brand — never assigned at runtime

  • _scope: "module"

    phantom scope brand — never assigned at runtime

  • name: string

  • static create(name: string): BaseModuleKey<T>

    Creates a typed module settings key.

View source ↗

Base class for a Worker that uses Base.

Members

View source ↗

Bundles a worker's BaseConfiguration (constructed from the environment variables and settings) with its worker-scoped dependency-injection container. Created by BaseWorker and registered in the container so both are injectable.

Members

  • configuration: BaseConfiguration

  • container: BaseInjectionContainer

  • toJSON(): { environmentVariables: string[]; graphql: GqlConfiguration | undefined; instanceId: string; name: string; runtime: Runtime; version: string }

    Controls JSON.stringify() output.

  • toString(): string

    Controls string coercion (template literals, String(), "" + obj).

View source ↗

Creates a nodejs server and runs the worker on it.

Members

  • start(environmentVariables: EnvironmentVariables): Promise<void>

    Registers fetch as the request handler for the Node.js server, then starts the node server.

View source ↗

The environment the worker is running in, parsed from the ENVIRONMENT environment variable. Defaults to Development; custom environment names are preserved as-is.

Members

  • type: string

  • isDevelopment: boolean

    Check for a development environment.

  • isProduction: boolean

    Check for a production environment.

View source ↗

How the worker process was started — normal serving (Default), under the CLI (CommandLine), in tests (Test), or serving locally (Local) — parsed from the EXECUTION_MODE environment variable. Gates mode-dependent behavior such as CLI-safe routing and local RPC visibility.

Members

  • type: ExecutionModeType

  • isCommandLine: boolean

  • isDefault: boolean

  • isLocal: boolean

  • isTest: boolean

View source ↗

The platform the worker is running on, parsed from the PLATFORM environment variable. Defaults to Cloudflare (which sets no platform variable); Base switches on this to select the platform delegate.

Members

  • type: PlatformType

  • isCloudflare: boolean

    True if running on the Cloudflare platform.

  • isNode: boolean

    True if running on the Node platform.

View source ↗

Runtime

class

The Runtime class provides information about the current runtime environment the worker is running on. This includes the environment, execution mode, and platform.

Members

  • environment: Environment

    The environment of the worker.

  • mode: ExecutionMode

    The execution mode of the worker.

  • platform: Platform

    The platform the worker is running on.

  • toString(): string

View source ↗

Thrown by a WorkerConfigValidator to signal that the deployment configuration is missing something the module requires.

extends Error

View source ↗