Upgrading to the typed APIs
This release removes any from the public APIs of @iskra-bun/core, @iskra-bun/web-kit and @iskra-bun/auth-kit. Values whose type the framework cannot know are now unknown, and each place that holds shared data gets a registry you extend with declaration merging, so your code gets real types instead of casts. The version bumps are minor (the packages are still 0.x).
core: app.context is typed
Section titled “core: app.context is typed”app.context was a Map<string, any>. It is now an AppContext (still a Map): the keys the kits register are typed, any other key holds unknown.
// Before: anyconst db = app.context.get('db');
// After: DbDriver | undefined (registered by db-kit; 'kv' and 'oracle' likewise)const db = app.context.get('db');Register your own keys once, and get/set are typed everywhere:
declare module '@iskra-bun/core' { interface AppContextRegistry { bridge: DesktopBridge; }}
app.context.set('bridge', new DesktopBridge(app));const bridge = app.context.get('bridge'); // DesktopBridge | undefinedWithout registering a key, get('key') returns unknown; get<T>('key') names the type yourself.
core: typed events
Section titled “core: typed events”app.on() handlers received ctx.payload: any. The kits now declare their events (process:*, socket:connected/disconnected, worker:dead-letter) in AppEvents, so those payloads are typed; any other event’s payload is unknown.
app.on('process:exit', (ctx) => { ctx.payload.exitCode; // number | null});Declare your own events the same way, and app.emit() checks the payload too:
declare module '@iskra-bun/core' { interface AppEvents { 'order:created': { id: string; total: number }; }}
app.on('order:created', (ctx) => ctx.payload.total); // numberapp.emit('order:created', { id: 'o1', total: 150 });process:message carries whatever JSON a child printed: its message is unknown, so check its shape before use.
core: AppConfig extra sections are unknown
Section titled “core: AppConfig extra sections are unknown”AppConfig‘s index signature is [key: string]: unknown (it was any). Read a section of your own with its type: app.config.mySection as MySection. The kits’ sections (db, kv, processes, socket) stay typed.
web-kit: validation middlewares replace the validation features
Section titled “web-kit: validation middlewares replace the validation features”ValidationFeature and JsonSchemaValidationFeature added untyped methods to Hono at run time (app.postValidated(), app.postJsonValidated()) and an untyped c.valid(). They are gone. Use the validate() (Zod) and validateJson() (JSON Schema) middlewares, which need no feature and give the handler typed data in c.get('validated'):
// Beforekernel.registerFeature(new ValidationFeature());// @ts-expect-errorapp.postValidated('/users', { body: userSchema }, (c) => c.json(c.valid().body));
// Afterimport { validate } from '@iskra-bun/web-kit';app.post('/users', validate({ body: userSchema }), (c) => { const user = c.get('validated').body; // inferred from userSchema return c.json(user);});
// JSON Schema: name the validated shape, a JSON Schema has no TypeScript typeapp.post('/users', validateJson<CreateUser>({ body: createUserSchema }), (c) => c.json(c.get('validated').body));validate() takes Zod v3 or v4 schemas. createValidationMiddleware and createJsonSchemaValidationMiddleware are renamed to validate and validateJson.
web-kit: WebDriver routes infer their types with defineRoute()
Section titled “web-kit: WebDriver routes infer their types with defineRoute()”RouteOptions and WebContext default to unknown instead of any. Wrap a route with a schema in defineRoute() so its handler gets the body and query types from it:
import { createRouter, defineRoute } from '@iskra-bun/web-kit';
createRouter([ defineRoute({ method: 'POST', path: '/users', schema: { body: z.object({ name: z.string() }) }, handler: (ctx) => userService.create(ctx.body.name), // ctx.body.name: string }),]);web-kit: typed session data
Section titled “web-kit: typed session data”c.get('session') was a Record<string, any>; it is a SessionData, whose fields are unknown until you declare them:
declare module '@iskra-bun/web-kit' { interface SessionData { userId?: string; }}
c.get('session').userId; // string | undefinedweb-kit: other type changes
Section titled “web-kit: other type changes”- Config callbacks receive Hono’s
Context(wasany):authorize,keyGenerator,skip,handler,customExtractor,onError,onValidated, healthchecksand the error handler’scustomHandlers/logger. CacheAdapter.get()returnsPromise<unknown>: narrow what you read.c.get('logger')(LoggerFeature) is aRequestLogger.OtelTracingConfigis@hono/otel’s options withserviceNamerequired, so its other options (disableTracing,captureActiveRequests) are accepted too.ApiKeyConfig.vaultServiceis removed: it was never used.ApiKeyMetadata.metadataand health checkdetailsareunknown.
auth-kit: custom user fields are unknown
Section titled “auth-kit: custom user fields are unknown”User and SignUpInput allow custom fields with [key: string]: unknown (was any): narrow them where you read them. socialProviders takes better-auth’s own option type. The OIDC profile mapping no longer returns an id: better-auth takes the account’s identity from the verified sub and ignored it anyway.