Migrate from Ky
Move from hand-written ky calls to worma's type-safe generated calls
If your project currently calls APIs by hand with ky, you can use worma to generate type-safe calls from the OpenAPI spec. The generated code is still standard ky under the hood, so compatibility is excellent — your existing ky calls can stay as-is, and you don't have to migrate everything at once.
Before: hand-written ky calls
import ky from 'ky';
interface User {
id: number;
name: string;
email: string;
}
const users = await ky
.get('api/users', { searchParams: { page: 1, size: 10 } })
.json<User>();
const created = await ky
.post('api/users', { json: { name: 'Alice', email: 'alice@example.com' } })
.json<User>();Migration steps
Create the config with init
npx wormajs init --template kyThis generates worma.config.ts (or .js) in the project root, with the ky template selected by default. You can also skip --template and pick ky in the interactive menu.
Generate the calls with gen
npx wormajs genThe output lives under src/api/ky/, with each API exported as a standalone function, supporting tree-shaking:
index.ts creates a default kyInstance:
// src/api/ky/index.ts
import ky from 'ky';
export const kyInstance = ky.create({
prefix: 'https://api.example.com/',
});Swap the instance (the only part you need to change)
Migration is very simple: just import your existing ky instance file and re-export it under the same name in the generated index.ts; no other files need changes.
// src/api/ky/index.ts
// Import from your existing ky instance file and re-export it as kyInstance
export { myKy as kyInstance } from '@/lib/request';
@/lib/requestis your project's ky instance file, already configured with prefix, hooks, etc.myKyis its export name. This way, thekyInstancereferenced inservicespoints directly at your instance, with no other files touched.
Compatibility notes
The generated calls are still standard ky, so compatibility is excellent — your existing ky calls can stay, and you can migrate gradually, replacing hand-written calls with generated type-safe functions in parallel with the original ky.get/post calls without conflict.
Replace hand-written calls
// After migration: no .json() needed, return type inferred from OpenAPI
import { getUserList, createUser } from './api/ky/services/user';
const users = await getUserList({ params: { page: 1, size: 10 } });
const created = await createUser({
data: { name: 'Alice', email: 'alice@example.com' },
});Call mapping:
| Hand-written ky | worma generated function |
|---|---|
ky.get(url, { searchParams }) | fn({ params }) |
ky.post(url, { json }) | fn({ data }) |
ky.get(url, { searchParams: { id } }) | fn({ pathParams: { id } }) |
await ky.x().json<T>() | await fn(...) returns T directly |
The generated functions also accept native ky request options (timeout, headers, retry, signal, etc.).
Migration checklist
- Run
worma init --template kyto generate the config - Run
worma gento generatesrc/api/ky/ - Replace the default
kyInstanceinindex.tswith your existing instance and re-export it (no other files need changes) - Replace hand-written
ky.get/postcalls with the generated type-safe functions as needed, mappingsearchParams→paramsandjsonbody →data