Before v0.8.0, every codegen run called npx json-schema-to-typescript as a subprocess. That took 3.3 seconds per call. With a file watcher regenerating types on every save, that was unacceptable. The fix: keep npx running in the background.
The problem
npx is a Node.js wrapper that resolves packages, downloads them if needed, and runs the binary. Every invocation pays the startup cost: resolve the package, load V8, parse json-schema-to-typescript, compile TypeScript schemas. That is 3.3 seconds on a cold start.
The solution: a persistent process
jsonschema-ts v0.3.0 spawns a single Node.js process that stays alive. It loads json-schema-to-typescript once and keeps it in V8's code cache. Subsequent conversions read from stdin, write to stdout:
# First call (cold): 3.3s # Second call (warm): 4.6ms # 715× faster
How it works in pyrpc
The pyrpc dev file watcher triggers codegen on Python file changes. The codegen step calls jsonschema-ts to convert Pydantic models to TypeScript interfaces. With the daemon:
- First save: 3.3s (daemon starts, cold load)
- Every save after: ~4.6ms (warm, daemon is alive)
The daemon is shared across pyrpc codegen, pyrpc dev, and the @pyrpc/types postinstall script. One process, many callers.
Windows fix
On Windows, npx is a script file, not an executable. subprocess.run(["npx", ...]) fails with [WinError 2]. The fix in jsonschema-ts v0.2.1: use "npx.cmd" when os.name == "nt".
File watcher debounce
Alongside the daemon, the file watcher debounce dropped from 1.6s to 200ms. Combined, the feedback loop from saving a Python file to seeing updated TypeScript types is now sub-second.

pyRPC