Changelog - 2026-09-23
Registration by hand, useRepository, and installs that load
Breaking Change New Feature Bug FixIn one line. An application registers its classes the two ways IGNIS does, by stereotype or by hand, and both resolve by class; useRepository is new, BaseApiService is gone, and the packages now load under Node ESM and install with strict linkers.
This entry covers everything since 0.1.1-3.
What changed
New
- Two ways to register, as in IGNIS. A class marked
@service()(or another stereotype) is still bound when the application starts. By hand,bindContext()callsthis.service(X),this.repository(X),this.dataSource(X)orthis.component(X). Each returns theBindingand takes{ binding, scope, allowOverride }. - Every path records the key on the class. A class registered by hand, through
bindingList()or throughinjectable()now resolves by{ target }, in a hook and in@inject({ target }). Before, only a stereotyped class did. useRepository. Resolves a repository by class and checks that it is bound underrepositories, likeuseServicedoes forservices.- Stereotype
scopeis honoured. Discovered classes used to bind as singletons whatever the stereotype declared. The default is still singleton.
Fixed
- The packages load under Node ESM. Compiled imports carried no file extension, and
lodashdeep imports had no.js, sonoderefused to load them. Only bundlers had worked. - The umbrella declares its optional peers.
@venizia/ardorre-exports./repositoryand./socket-iobut did not declare@venizia/ignis-connectorsorsocket.io-clientas peers, so a strict linker could not resolve them. react-reduxis a required peer ofardor-react. It was marked optional while the package imports it at load time, so an install without it crashed on import.
Who is affected
- Applications with a
BaseApiServicesubclass. ExtendBaseServiceinstead; see below. - Every application. Raise the IGNIS peers to
connectors 0.2.0-44,kernel 0.2.0-45,helpers 0.2.0-40,filter 0.2.0-22andinversion 0.2.0-23, and use Bun 1.4 or later. - Applications that resolve a class by key only because
{ target }used to throw. Nothing breaks;{ target }now works for them too.
Breaking changes
BaseApiService is removed. @api() works on any BaseService and logs a resource field when the class has one.
Before:
ts
export class ProductApi extends BaseApiService {
constructor() {
super({ scope: 'ProductApi', resource: 'products' });
}
// ...
}After:
ts
import { api, BaseService } from '@venizia/ardor';
export class PricingService extends BaseService {
protected resource = 'products';
constructor() {
super({ scope: 'PricingService' });
}
@api()
async quote(): Promise<number> {
return 42;
}
}For reads over HTTP, prefer an HttpRepository; see Repositories.
Details
- Every kind binds a singleton by default, discovery included. IGNIS's server defaults services and repositories to transient; a React hook resolves on every render, so a transient repository would give each render a new instance.
- The key is
opts.binding, else the stereotype'sbinding, else<namespace>.<ClassName>.allowOverride: falsethrows when the key is already bound. - Discovery of an
HttpRepositoryarrived a day later, with IGNIS kernel 0.2.0-46: see 2026-09-24.