How to Use the Cordis API: A Complete Guide to Context and Services
To use the Cordis API, instantiate a Context via the create() function, initialize it with await ctx.start(), and access built-in or custom services directly as properties on the context object.
The Cordis API provides a modular architecture centered around dependency injection and service-oriented design. In the cordiverse/cordis repository, all functionality flows through a central Context object that maintains a registry of Service classes. Understanding this relationship is essential for leveraging the full capabilities of the Cordis framework.
Core Architecture of the Cordis API
The Cordis API is built on three foundational components that manage application state and service lifecycle.
The Context Object
At the heart of the system lies the Context class defined in packages/core/src/context.ts. This object serves as an execution sandbox and service registry, storing all available services and providing the attachment points for plugins. Every Cordis application begins with a single root context that propagates to all child services and plugins.
Service Base Classes
Services in Cordis extend the base Service class located in packages/core/src/service.ts. When a service is registered, it becomes accessible as a property on the context using its designated name. For example, the HTTP service attaches as ctx.http, the timer service as ctx.timer, and the logger as ctx.logger. This convention ensures consistent access patterns across the entire API surface.
Application Creation
The entry point for any Cordis application is the create() function exported from packages/create/src/index.ts. This factory function constructs a new Context instance, registers all core services (logging, loader, HMR, timer), and returns an application object ready for startup. For CLI-based workflows, packages/create/src/bin.ts provides a command-line wrapper around this same initialization logic.
Implementing the Cordis API in Three Steps
Accessing and utilizing the Cordis API follows a deterministic pattern: create, start, and invoke.
Step 1: Instantiate the Application
Import the create function from @cordis/create and invoke it with optional configuration parameters. This returns a Context instance that represents your application.
import { create } from '@cordis/create'
const app = create({
// Optional configuration passed to core services
})
const ctx = app // The app itself is the Context
Step 2: Initialize Services
Before accessing any APIs, you must start the context. The await ctx.start() method (also available as app.start()) initializes all registered services and loads configured plugins. This step is mandatory as it triggers the dependency injection container and sets up the service registry.
await app.start()
Step 3: Access Service Methods
Once started, every service becomes available as a property on the context object. Invoke methods directly using the ctx.<serviceName>.<method>() pattern.
// HTTP client request
const response = await ctx.http.get('https://api.example.com/data')
// Schedule delayed execution
ctx.timer.setTimeout(() => console.log('Task complete'), 2000)
// Structured logging
ctx.logger.info('Application initialized successfully')
Working with Built-in Services
The Cordis API ships with several core services that provide essential infrastructure functionality.
HTTP Client Service
The ctx.http service handles outbound network requests. It supports standard HTTP methods and integrates with the context lifecycle for automatic cleanup.
const data = await ctx.http.get('https://api.example.com/users')
Timer and Scheduling
The ctx.timer service provides setTimeout and setInterval implementations that are scoped to the context lifecycle. When the context stops, pending timers automatically clean up to prevent memory leaks.
ctx.timer.setInterval(() => {
ctx.logger.debug('Periodic health check')
}, 5000)
Structured Logging
Access the logger via ctx.logger to emit categorized log messages. The logging service supports multiple levels (debug, info, warn, error) and integrates with the loader system for plugin-specific log scoping.
ctx.logger.info('Server listening on port 3000')
Extending the Cordis API with Custom Plugins
You can extend the Cordis API by creating custom plugins that inject new methods into the context. The definePlugin utility from @cordis/create provides type-safe plugin registration.
import { definePlugin } from '@cordis/create'
const helloPlugin = definePlugin('hello', ctx => ({
greet(name: string) {
ctx.logger.info(`Greeting generated for ${name}`)
return `Hello, ${name}!`
},
}))
// Register the plugin
app.plugin(helloPlugin)
// Use the new API
console.log(ctx.greet('World')) // Output: Hello, World!
The packages/loader/src/index.ts module handles the dynamic injection of these plugin-provided symbols. Once loaded, new methods appear on the context automatically without requiring additional imports in consuming code.
Summary
- Create a Cordis application using the
create()function frompackages/create/src/index.tsto obtain a rootContextinstance. - Start the application with
await ctx.start()to initialize the service registry and load plugins, as defined inpackages/core/src/context.ts. - Access all functionality through the context object, where services like
ctx.http,ctx.timer, andctx.loggerbecome available as properties. - Extend the API by creating custom plugins with
definePlugin()that inject new methods directly onto the context. - Understand that
packages/core/src/service.tsdefines how all services attach to the context, whilepackages/loader/src/index.tsmanages runtime plugin loading and hot-module replacement.
Frequently Asked Questions
How do I create a Cordis application instance?
Import the create function from @cordis/create and call it to instantiate a new Context. This function, located in packages/create/src/index.ts, constructs the execution sandbox and registers all core services including logging, loading, and HMR capabilities.
What is the difference between a Context and a Service in Cordis?
The Context (defined in packages/core/src/context.ts) is the central registry and execution environment, while Service classes (from packages/core/src/service.ts) are the functional units attached to that context. Services are accessible as properties on the context instance, such as ctx.http or ctx.logger, following the naming convention defined in their service implementation.
Do I need to call start() before using Cordis services?
Yes, you must await ctx.start() before accessing any service methods. This invocation triggers the initialization sequence in packages/loader/src/index.ts, which loads plugins, resolves dependencies, and activates all registered services. Attempting to use services before starting the context will result in undefined behavior or missing methods.
How can I add custom functionality to the Cordis API?
Use the definePlugin() utility to create a plugin that returns an object with your custom methods. When registered via app.plugin(), the loader injects these methods onto the context object, making them available as ctx.yourMethodName(). This mechanism allows seamless extension of the Cordis API without modifying core source files.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →