Cordis Meta-Framework
Cordis is an actively developed meta-framework for building modern applications, emphasizing a concept of "Spatiotemporal Composability" and a highly modular, plugin-based architecture. Currently in release candidate phase (v4.0.0-rc.3), it aims to provide a structured and opinionated layer on top of underlying JavaScript runtime environments, facilitating the development of complex systems by handling common concerns like service orchestration, lifecycle management, and resource allocation. Its "everything is a plugin" philosophy promotes high cohesion, low coupling, and extensive extensibility, allowing developers to customize and extend core functionalities through well-defined plugin interfaces. The framework is written in TypeScript, providing strong type safety across its API. While an exact release cadence isn't specified, its `cordiverse` organization shows continuous, active development across its ecosystem. It differentiates itself by offering a robust context and service management system designed for flexible application composition, particularly useful in environments requiring dynamic loading and unloading of modules or services.
Common errors
-
TypeError: Cannot read properties of undefined (reading 'plugin')
cause Attempting to call `.plugin()` or other context methods on an uninitialized or incorrectly initialized Cordis instance, often when `new Context()` is not called or its result is not assigned.fixAlways initialize your Cordis application with `const app = new Context();` and ensure `app` is correctly referenced before calling its methods. -
Error: Service 'myService' already exists in current context
cause Attempting to register a service with the same name multiple times within the same Cordis context. This can happen if a plugin is registered more than once or if two different plugins provide the same service name.fixEnsure each service has a unique name within a given context. If you need different implementations of the same service, use child contexts or conditional plugin registration. For services that should be singletons, manage their registration carefully. -
TS2345: Argument of type 'typeof MyService' is not assignable to parameter of type 'Plugin'.
cause Your service class or plugin function does not fully conform to the `Plugin` type definition. This often occurs if `static inject` is missing, `constructor` arguments are incorrect, or the service lacks expected properties/methods.fixReview your service/plugin definition against Cordis's `Plugin` interface and service class examples. Ensure all `static inject` dependencies are correctly declared and the constructor matches the expected `(ctx: Context, ...injectedDeps)` signature.
Warnings
- breaking Cordis v4 introduces significant breaking changes compared to v3, particularly in its internal architecture and API surface related to context management, service registration, and plugin definition. While specific details for `rc.3` are still being finalized, expect existing v3 codebases to require substantial updates.
- gotcha Cordis heavily leverages an "everything is a plugin" philosophy and context-based dependency injection. Misunderstanding the lifecycle of plugins or the scope of services within different contexts can lead to unexpected behavior or services not being available where anticipated.
- gotcha As a modern TypeScript framework, Cordis v4 is built with ESM (ECMAScript Modules) as the primary module system. Attempting to use `require()` for imports in a CommonJS environment without proper configuration (e.g., `"type": "module"` in `package.json` or transpilation) can lead to module resolution errors.
- deprecated Being in a release candidate phase, some APIs or behaviors introduced in earlier `4.0.0-rc` versions may be deprecated or altered before the stable `4.0.0` release. Relying heavily on specific `rc` internal APIs could lead to breakage upon upgrading to a stable version.
Install
-
npm install cordis -
yarn add cordis -
pnpm add cordis
Imports
- Context
const { Context } = require('cordis')import { Context } from 'cordis' - Service
import Service from 'cordis'
import { Service } from 'cordis' - Plugin
import { Plugin } from 'cordis'import type { Plugin } from 'cordis'
Quickstart
import { Context, Service } from 'cordis';
interface MyConfig {
greeting: string;
}
class GreeterService extends Service {
static inject = ['config']; // Declare dependencies
constructor(ctx: Context, public config: MyConfig) {
super(ctx, 'greeter'); // Register service as 'greeter'
this.logger.info(`GreeterService initialized with config: ${this.config.greeting}`);
}
greet(name: string): string {
return `${this.config.greeting}, ${name}!`;
}
}
// Main application context
async function bootstrap() {
const app = new Context();
// Register the configuration for the greeter service
app.provide('config', { greeting: 'Hello from Cordis' });
// Register the GreeterService as a plugin
app.plugin(GreeterService);
// Access the greeter service from the context
const greeter = app.greeter as GreeterService; // Type assertion for convenience
if (greeter) {
console.log(greeter.greet('World'));
} else {
console.error('Greeter service not found!');
}
// Demonstrate a child context with different config
const childCtx = app.createContext();
childCtx.provide('config', { greeting: 'Greetings, developer' });
childCtx.plugin(GreeterService);
const childGreeter = childCtx.greeter as GreeterService;
if (childGreeter) {
console.log(childGreeter.greet('Cordis User'));
}
await app.start();
console.log('Cordis application started successfully.');
await app.stop();
console.log('Cordis application stopped.');
}
bootstrap().catch(console.error);