05Project
Node.js JavaScript example
A plain JavaScript Node.js script using a client generated as JavaScript with JSDoc and .d.ts declarations from an OpenAPI 3.0 document (openapi.yaml).
pnpm example:node-javascript # from the repository root: build swaggerz, generate, runOr, inside this directory once swaggerz is built:
pnpm generate # src/generated/api (.js + .d.ts)pnpm start # starts a local in-memory API (src/server.js) and calls itpnpm check # type-checks the JavaScript with `checkJs`src/index.js configures the base URL, the apiKey security scheme and a logging middleware, then creates and lists tasks (with an exploded array query parameter) and handles a 404 with the operation’s error guard, which types the body by status. Editors show the generated types and documentation for every call.
Expected output (ports vary):
createTask: POST http://127.0.0.1:53816/tasks → 201Created task 2: Try swaggerz (todo) listTasks: GET http://127.0.0.1:53816/tasks?tag=demo&tag=docs → 200Tasks tagged demo and docs: Try swaggerz getTask: GET http://127.0.0.1:53816/tasks/404 → 404Expected failure: HTTP 404 — No task at /tasks/404Config
// A JavaScript project: the generated client is JavaScript with JSDoc and `.d.ts` declarations.import { defineConfig } from 'swaggerz';
export default defineConfig({ spec: { version: '3.0', input: './openapi.yaml' }, output: { directory: './src/generated/api', language: 'javascript' },});Sources
// @ts-checkimport { ApiError, RequestError, client, createTask, getTask, isGetTaskApiError, listTasks,} from './generated/api/index.js';import { startServer } from './server.js';
const apiKey = process.env.TASKS_API_KEY ?? 'demo-key';const server = await startServer({ apiKey });
client.setConfig({ baseUrl: server.url, timeout: 5_000, // Values for the security schemes in openapi.yaml. Functions are called for every request. auth: { apiKey: () => apiKey },});
// Middleware sees every request and response.client.use({ onResponse({ request, response, operation }) { console.log( ` ${operation.operationId}: ${request.method} ${request.url} → ${response.status}`, ); },});
try { // Parameters and the request body are checked by the editor through the generated .d.ts files. const task = await createTask({ body: { title: 'Try swaggerz', tags: ['demo', 'docs'], dueDate: '2026-12-31' }, }); console.log(`Created task ${task.id}: ${task.title} (${task.status})`);
// `tag` is an exploded array query parameter: ?tag=demo&tag=docs const tagged = await listTasks({ tag: ['demo', 'docs'] }); console.log(`Tasks tagged demo and docs: ${tagged.map((t) => t.title).join(', ')}`);
await getTask({ taskId: 404 });} catch (error) { if (isGetTaskApiError(error) && error.status === 404) { // The guard types errors by status: a 404 from getTask has a Problem body. console.log(`Expected failure: HTTP ${error.status} — ${error.body.title}`); } else if (error instanceof ApiError) { console.error(`Unexpected HTTP ${error.status} from ${error.operationId}`); process.exitCode = 1; } else if (error instanceof RequestError) { console.error(`Request failed (${error.kind}): ${error.message}`); process.exitCode = 1; } else { throw error; }} finally { server.close();}// @ts-check/** * A tiny in-memory implementation of openapi.yaml so the example runs without a backend. * Replace it with your real API by changing `baseUrl`. */import http from 'node:http';
/** @typedef {import('./generated/api/index.js').Task} Task *//** @typedef {import('./generated/api/index.js').NewTask} NewTask */
/** @type {Task[]} */const tasks = [{ id: 1, title: 'Read the README', status: 'done', tags: ['docs'], dueDate: null }];
/** * Starts the server on a random local port. * * @param {{ apiKey: string }} options * @returns {Promise<{ url: string, close: () => void }>} */export async function startServer({ apiKey }) { const server = http.createServer((req, res) => { /** @param {number} status @param {unknown} body */ const send = (status, body) => { res.writeHead(status, { 'content-type': 'application/json' }); res.end(JSON.stringify(body)); }; if (req.headers['x-api-key'] !== apiKey) return send(401, { title: 'Missing or wrong API key' }); const url = new URL(req.url ?? '/', 'http://localhost');
if (url.pathname === '/tasks' && req.method === 'GET') { const status = url.searchParams.get('status'); const tags = url.searchParams.getAll('tag'); return send( 200, tasks.filter( (task) => (status === null || task.status === status) && tags.every((tag) => task.tags.includes(tag)), ), ); } if (url.pathname === '/tasks' && req.method === 'POST') { let raw = ''; req.setEncoding('utf8'); req.on('data', (chunk) => (raw += chunk)); req.on('end', () => { /** @type {NewTask} */ const input = JSON.parse(raw); /** @type {Task} */ const task = { id: tasks.length + 1, title: input.title, status: 'todo', tags: input.tags ?? [], dueDate: input.dueDate ?? null, }; tasks.push(task); send(201, task); }); return; } const match = /^\/tasks\/(\d+)$/.exec(url.pathname); const task = match && tasks.find((t) => t.id === Number(match[1])); if (task) return send(200, task); send(404, { title: `No task at ${url.pathname}` }); }); await new Promise((resolve) => server.listen(0, '127.0.0.1', () => resolve(undefined))); const address = server.address(); const port = typeof address === 'object' && address !== null ? address.port : 0; return { url: `http://127.0.0.1:${port}`, close: () => server.close() };}Generated files
32 files for 3 operations and 4 models, generated with this config when the site was built:
client.d.ts, client.js, index.d.ts, index.jsmodels/8 filesruntime/14 filestasks/6 files