Plugin Configuration Validation in Cordis Using @standard-schema/spec
Cordis validates plugin configuration by treating the static Config property as a Standard Schema and invoking its ~standard.validate method during fiber initialization, throwing a dedicated ValidationError for any constraint violations.
Cordis leverages the @standard-schema/spec package to enforce runtime type safety on plugin configurations. When a plugin defines a schema via its Config static property, the framework automatically validates all provided options against that schema before the plugin's apply function executes.
Declaring Configuration Schemas in Plugins
In Cordis, plugins expose their configuration requirements through a static Config property defined on the Plugin.Base interface.
The Plugin.Base Interface
As defined in packages/core/src/registry.ts, the base plugin interface accepts an optional Config property typed as StandardSchemaV1:
export interface Plugin.Base<T = any> {
/** optional schema for the plugin's config */
Config?: StandardSchemaV1<any, T>
}
This property connects the plugin to a concrete schema object that conforms to the Standard Schema specification.
Runtime Schema Storage
When a plugin is registered, Cordis stores its configuration schema on the internal Plugin.Runtime object. From packages/core/src/registry.ts:
runtime = { name, callback, fibers: new DisposableList(), Config: plugin.Config }
This ensures the schema remains accessible throughout the plugin's lifecycle for validation during instantiation.
The Configuration Validation Pipeline
Cordis validates configuration during fiber construction through a dedicated resolution function that interfaces directly with the Standard Schema validator.
Validation Entry Point
The Fiber constructor initiates validation by calling resolveConfig with the runtime object and user-provided configuration. In packages/core/src/fiber.ts:
this.config = resolveConfig(runtime, config)
This single call triggers the entire validation workflow before the plugin receives its configuration.
Schema Resolution and Validation
The resolveConfig function checks for the special ~standard key introduced by @standard-schema/spec and executes the schema's validate method. From packages/core/src/fiber.ts:
const result = runtime.Config['~standard'].validate(config)
The ~standard property contains the standardized validation interface defined by the @standard-schema/spec package, ensuring interoperability with any schema library that implements the specification.
Error Handling with ValidationError
When validation fails, Cordis throws a custom ValidationError that formats schema issues for readability. In packages/core/src/fiber.ts:
if (result.issues) throw new ValidationError(result.issues)
Defined in packages/core/src/fiber.ts (lines 19‑27), this error class bubbles up to the plugin registration point, causing instantiation to fail and logging detailed constraint violations.
Practical Implementation Examples
Defining a Plugin with Schema Validation
Here is a complete example of defining a Cordis plugin with a Standard Schema configuration:
import { StandardSchemaV1 } from '@standard-schema/spec'
export const MyPlugin = {
name: 'my',
// Define a schema using the StandardSchemaV1 DSL
Config: StandardSchemaV1.object({
port: StandardSchemaV1.number().minimum(0).maximum(65535).default(8080),
debug: StandardSchemaV1.boolean().default(false),
}),
apply(ctx, config) {
// `config` is already validated and coerced to the correct types
ctx.logger.info(`Listening on ${config.port}, debug=${config.debug}`)
},
}
Loading and Validating Plugins
When loading the plugin, valid configurations proceed normally while invalid inputs trigger immediate errors:
import { createContext } from 'cordis'
const ctx = createContext()
await ctx.plugin(MyPlugin, { port: 3000 }) // valid – runs normally
await ctx.plugin(MyPlugin, { port: -1 }) // throws ValidationError
Catching Validation Errors
Handle configuration errors gracefully by catching ValidationError:
try {
await ctx.plugin(MyPlugin, { port: -1 })
} catch (err) {
if (err instanceof ValidationError) {
console.error('Plugin config error:', err.message)
}
}
Key Source Files and Dependencies
The configuration validation system spans three critical locations in the Cordis core:
packages/core/src/registry.ts– DeclaresPlugin.Base.ConfigasStandardSchemaV1and stores the schema on the runtime object during plugin registration.packages/core/src/fiber.ts– ImplementsresolveConfig, invokesruntime.Config['~standard'].validate, and throwsValidationErrorwhen issues are detected.packages/core/src/fiber.ts(lines 19‑27) – Defines theValidationErrorclass that formats schema validation issues for debugging.packages/core/package.json– Lists@standard-schema/specas a dependency (^1.1.0), providing the standardized validation interface.
Summary
- Cordis delegates all configuration validation to
@standard-schema/spec, checking plugin configs against Standard Schema definitions before initialization. - Plugins declare schemas via the static
Configproperty onPlugin.Base, which gets stored on thePlugin.Runtimeobject for lifecycle access. - The
Fiberconstructor triggers validation throughresolveConfig, which calls the schema's~standard.validatemethod. - Validation failures throw
ValidationErrorwith detailed formatting of schema issues, halting plugin instantiation immediately. - No manual validation is required in plugin code; Cordis guarantees type-safe, validated configuration objects in the
applyfunction.
Frequently Asked Questions
What happens if a plugin doesn't define a Config schema?
If the Config property is undefined on the plugin object, Cordis skips schema validation entirely and passes the raw configuration object directly to the plugin's apply function. According to the source in packages/core/src/registry.ts, the Config property is optional on Plugin.Base, making schema validation an opt-in feature for type safety.
Can I use any schema library with Cordis configuration validation?
Yes, any library that implements the Standard Schema specification (@standard-schema/spec) is compatible with Cordis. The framework specifically looks for the ~standard property on the schema object and calls its validate method, as implemented in packages/core/src/fiber.ts, ensuring interoperability across Zod, Valibot, ArkType, or other compliant validators.
How does Cordis handle nested configuration objects?
Cordis delegates nested object validation entirely to the Standard Schema implementation. When resolveConfig calls runtime.Config['~standard'].validate(config) in packages/core/src/fiber.ts, the schema library handles deep validation of nested properties. Any issues found at any depth are aggregated in the result.issues array and thrown as a single ValidationError.
Where is the ValidationError class defined and how do I import it?
The ValidationError class is defined in packages/core/src/fiber.ts between lines 19‑27. You can import it from the @cordis/core package to perform instance checks when catching configuration errors: import { ValidationError } from '@cordis/core'. This allows you to distinguish schema validation failures from other runtime errors during plugin registration.
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 →