← Back to Blog

The generated file's contract

·5 min read

Open any generated __pyrpc.ts and the first thing you see is a long comment. It is not decoration. The header is a written contract between pyrpc and your project, and since v0.12.0 it documents things that were previously implicit.

The header, line by line

/**
 * Auto-generated by pyrpc dev, do not edit by hand.
 * Re-generated automatically whenever your Python procedures change.
 *
 * This file is a real runtime module: it carries both the compile-time
 * procedure types and the runtime procedure-kind map (`procedureKinds`).
 *
 * Resolved via tsconfig.json paths alias:
 *   "paths": { "@pyrpc/types": ["./__pyrpc.ts"] }
 *
 * Bundlers that don't honor tsconfig paths for imports inside node_modules
 * (Vite, SvelteKit, Next.js Turbopack) must alias "@pyrpc/types" to this file
 * explicitly, pyrpc dev configures this for known frameworks automatically.
 *
 * Usage:
 * ```ts
 * import type { Types } from "@pyrpc/types"
 * import { createNextClient } from "@pyrpc/next"
 * ...```
 */

Four commitments are being made here.

1. Ownership: "do not edit by hand"

The file is owned by codegen. Edits will be overwritten on the next regen. This is not a threat, it is a fact the author needs to know before they tweak a type and lose it. The eslint-disable pragma at the top reinforces it: this file opts out of your lint rules because your rules do not apply to machine output.

2. Lifetime: "re-generated whenever procedures change"

The contract states when the file changes. The dev watcher regenerates on edits and module reloads. Knowing the invalidation trigger lets a developer reason about why their types look stale, usually a procedure changed and the watcher had not fired yet, not a bug in their code.

3. Resolution: how @pyrpc/types finds this file

The header documents the two-layer resolution story. First, the tsconfig paths alias maps @pyrpc/types to this file for the compiler. Second (and this is the v0.12.0 addition) bundlers that do not honor tsconfig paths for imports inside node_modules need an explicit alias. The header names the offenders (Vite, SvelteKit, Next.js Turbopack) so the failure mode is diagnosable from the artifact itself.

4. Usage: how to consume it

The usage example shows the intended import pattern, import type { Types } from "@pyrpc/types", never a relative path to the file. The import surface is stable even though the artifact changes.

Why the header matters

Generated files are the most-debugged artifacts you never write. The header is the first thing a confused developer reads, and a good header pre-answers their questions: who owns this, when does it change, how is it wired, and how do I use it. Keeping that contract inside the file means the answer travels with the artifact instead of living in docs nobody reads.