json-schema-content-mapper
A JSONSchema content mapper for TypeScript 9.1.
A native TypeScript 7.1+ Content Mapper plugin that dynamically compiles
*.jsonschema files into fully-typed TypeScript sources on the fly using
schema2dts.
No build-step generators or generic wildcard ambient declarations required. Your JSON Schemas are treated as first-class typed modules.
Features
- Zero-Disk Overhead: Generates in-memory virtual
.tsdefinition files compiled directly bytsc. - JSON-RPC Multiplexed: Built on top of
vscode-jsonrpcto handle fast, concurrent, and non-blocking multi-project compilation contexts. - Seamless References: Supports multi-file architectures using standard JSON
Schema
$refpointers.
Installation
Install the content mapper as a development dependency in your project:
npm install -D json-schema-content-mapper
Note: Ensure your workspace uses TypeScript 7.1 (or later) to support Content Mappers.
Configuration (tsconfig.json)
Register the package under the new contentMappers compiler property. We
strongly recommend using the .jsonschema extension for your schema definition
files.
{
"compilerOptions": {
"module": "preserve",
"moduleResolution": "bundler",
"strict": true
},
"contentMappers": [
{
"package": "json-schema-content-mapper",
"extensions": [".jsonschema"],
"options": {
"exportNamespaces": true
}
}
],
"include": ["src"]
}
Multi-File Schema References ($ref)
One of the major benefits of this content mapper is its ability to handle
multi-file structures natively. Instead of bundling everything into a single
giant schema, you can split your definitions across multiple .jsonschema files
and reference them using JSON Pointers.
When a schema references another file via a $ref, the content mapper
dynamically translates this link into a standard JavaScript/TypeScript import
statement in the virtual .d.ts output. TypeScript's compiler then handles the
cross-file dependency graph automatically.
Example Setup
1. Define a shared base schema (src/phone.jsonschema)
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Phone",
"type": "string",
"pattern": "+[0-9]+.[0-9]+"
}
2. Reference it in your main schema (src/user.jsonschema)
Use the relative file path inside the $ref property:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "User",
"type": "object",
"properties": {
"name": { "type": "string" },
"email": { "type": "string" },
"phone": { "$ref": "./common.jsonschema" }
},
"required": ["name"]
}
3. Consume naturally in your TypeScript code (src/index.ts)
TypeScript resolves the full chain. The generated type for User will
automatically inherit the field (phone) from phone.jsonschema
through a TypeScript intersection type:
import { User } from './user.jsonschema';
const user: User = {
name: 'John Doe',
email: '[email protected]',
phone: '+33.16561655616',
};
console.log(user.id); // Available & Typed (string)
console.log(user.name); // Available & Typed (string)
console.log(user.phone); // Available & Typed (string)
Running Type Checking
Because Content Mappers invoke external code packages to compute module shapes, the TypeScript compiler requires an explicit security opt-in flag to run type-checking from your CLI:
npx tsc --runExternalCode --noEmit
Without the --runExternalCode flag, tsc will ignore the content mapper
process for security reasons and throw an import resolution error.
Technical Architecture
This plugin establishes an asynchronous JSON-RPC 2.0 communication process
pipeline with tsc via standard input/output streams (stdin/stdout).
initialize: Negotiates structural formatting parameters (e.g.,utf-16character positioning).openProject: Caches incomingtsconfig.jsonplugin configurations into an isolatedprojectRegistrymap linked to an opaque workspaceprojectHandle.transform: Extracts parameters, resolves the project context options, runsgenerateJSONSchemaTypes(), and delivers the compiled virtual code layer instantly back to the Go-compiledtsccore engine.closeProject: Clears references from the operational cache map to prevent memory leaks during watch modes.