Xeno Registry
Introduction
Section titled “Introduction”The Xeno Registry is the mechanism used by Xeno.JS to define the application’s dependency vocabulary.
It provides a centralized place for application-specific tokens and registrations, allowing different parts of an application to refer to dependencies explicitly rather than relying on implicit names or global state.
The registry works together with the App Builder and the Service Container to turn those definitions into runtime dependencies.
Why a Registry?
Section titled “Why a Registry?”As an application grows, it can have many different dependencies:
- application services
- repositories
- data sources
- infrastructure services
- clients
- configuration
- authentication services
- loggers
- caches
Those dependencies need stable identifiers so that they can be registered and resolved consistently.
Instead of scattering dependency identifiers throughout the application, Xeno.JS provides a registry as the place where the application’s dependency vocabulary can be defined.
The basic idea is:
Application │ ▼Xeno Registry │ ├── Dependency Token ├── Dependency Token ├── Dependency Token └── Dependency Token │ ▼ Service Container │ ▼ Runtime InstanceThe Registry describes what the application knows about.
The Service Container is responsible for resolving those dependencies at runtime.
Registry vs. Container
Section titled “Registry vs. Container”The Registry and the Service Container have different responsibilities.
| Component | Responsibility |
|---|---|
| Xeno Registry | Defines the application’s dependency identifiers |
| App Builder | Composes the application and its registrations |
| Service Container | Resolves registered dependencies at runtime |
This separation keeps application composition explicit.
The Registry is not intended to replace the container. It provides the vocabulary that the container uses when dependencies are registered and resolved.
The Xeno Registry
Section titled “The Xeno Registry”Xeno.JS provides a base XenoRegistry that can be extended by an application.
A project can define its own registry for application-specific dependency tokens.
For example:
import { XenoRegistry } from "@xeno-js/core";
export class MyRegistry extends XenoRegistry { // Application-specific tokens}The generated project structure uses this pattern so that application-specific registrations have a dedicated place.
For example, the scaffolded project may contain:
src/├── bootstrap.ts├── main.ts└── registry.tsThe registry.ts file is where the application’s registry can be customized.
Application-Specific Tokens
Section titled “Application-Specific Tokens”A registry becomes useful when an application introduces dependencies that are specific to its own architecture.
For example, an application might need to identify:
UserRepositoryPaymentServiceEmailClientStorageServiceInstead of coupling consumers to concrete implementations, the application can expose stable dependency tokens and let the composition layer decide which implementation should be provided.
Conceptually:
Registry │ ┌───────┼────────┐ ▼ ▼ ▼ UserRepo Email Storage Token Token Token │ │ │ └───────┼────────┘ ▼ App Composition │ ▼ Concrete ServicesThis allows the application code to depend on the dependency contract while the composition layer decides how that dependency is implemented.
The Registry as Part of the Composition Root
Section titled “The Registry as Part of the Composition Root”The registry belongs to the application’s composition model.
A typical Xeno.JS application has a flow similar to:
registry.ts │ ▼bootstrap.ts │ ▼App Builder │ ▼Service Container │ ▼ApplicationThe registry defines the application’s dependency vocabulary.
The bootstrap process then uses that vocabulary while composing the application.
This keeps dependency configuration close to the composition root instead of requiring individual application components to know how their dependencies are created.
Registry and Dependency Injection
Section titled “Registry and Dependency Injection”The Registry is closely related to Dependency Injection, but the two concepts should not be confused.
Dependency Injection describes how dependencies are provided to a component.
The Registry provides a consistent way to identify those dependencies within the application’s composition model.
For example:
Registry │ ▼ "UserRepository" │ ▼ Service Container │ ▼ PostgreSQL Repository │ ▼ Application ServiceThe application service does not need to know how the repository was constructed.
The composition layer connects the token to the implementation.
For more information about resolving dependencies, see Dependency Injection.
Registry and Infrastructure
Section titled “Registry and Infrastructure”The Registry can be used to keep application code independent from infrastructure implementations.
For example, an application may define a repository contract while infrastructure provides a concrete database implementation.
The composition can then connect the two:
Application │ ▼Repository Contract │ │ identified through ▼Registry Token │ ▼Infrastructure Registration │ ▼Database RepositoryThis is particularly useful when the same application architecture needs to work with different implementations.
The application does not need to change simply because the infrastructure implementation changes.
Customizing the Registry
Section titled “Customizing the Registry”The registry should contain application-specific dependency definitions rather than becoming a general-purpose container for unrelated application state.
A useful rule is:
Use the registry to name dependencies, not to store runtime state.
Runtime state belongs to the appropriate service, context, scope, or other application mechanism.
This keeps the registry focused and makes the application’s dependency graph easier to understand.
Registry in a Generated Project
Section titled “Registry in a Generated Project”Projects created through the Xeno CLI include a registry.ts file.
A generated Core project follows this general structure:
my-app/├── src/│ ├── bootstrap.ts│ ├── main.ts│ └── registry.ts├── .env├── .env.example├── package.json└── tsconfig.jsonThe generated registry extends XenoRegistry and provides the starting point for defining application-specific tokens.
As the application grows, this file can become part of the application’s composition model alongside bootstrap.ts.
See Project Structure for more information about the generated project.
Summary
Section titled “Summary”The Xeno Registry provides the dependency vocabulary of a Xeno.JS application.
Its main responsibilities are:
- defining application-specific dependency tokens;
- providing stable identifiers for dependencies;
- integrating those identifiers with application composition;
- keeping dependency definitions separate from their implementations;
- working together with the App Builder and Service Container.
The resulting model is explicit:
Registry │ ▼App Builder │ ▼Service Container │ ▼Resolved DependenciesOnce the Registry is understood, the next step is to understand how the application composition is assembled through the App Builder.
Support Us
Section titled “Support Us”Xeno.JS is an MIT-licensed open source project. It can grow thanks to the support of these awesome people. If you’d like to join them, please read more at support section
