content-mapper
Webda's compile-time code generation, as a TypeScript 7.1 content mapper.
TypeScript 7 removed custom emit transformers, ts-patch and language-service plugins. This package replaces them
with the supported mechanism: it rewrites model and service sources (*.model.ts, *.service.ts) into ordinary
TypeScript before the compiler sees them, with span maps so diagnostics, hover and rename still land on the authored
text.
You rarely use it directly: webdac build (from @webda/compiler) runs it for you.
What it generates
| Generator | Output |
|---|---|
accessors | Typed accessors that coerce on assignment (user.createdAt = "2020-01-01" stores a Date) and relations |
behaviors | Members of the Behaviors attached to a model |
loadParameters | loadParameters() for services extending Service<T>, from their parameters class |
qlValidator | Compile-time validation of WebdaQLString<T> queries, reported as TypeScript diagnostics; a sealed field in a query, in a getPermissionQuery or under an @Index / @Unique tag is a warning (WQL9004), logged by the build |
It also discovers the Webda objects of a project and produces the JSON schemas of models, services and operations
used in webda.module.json.
Editor support
Starting in typescript@7.1.0-dev.20261102.1, tsgo rejects content mapper extensions that end in .ts (TS18066).
You can choose between two strategies depending on whether you prefer standard .ts file suffixes or an unmodified tsc binary:
Strategy A: Keep .model.ts / .service.ts with patchTsc (Default)
Patch the installed native tsc binary so compound .model.ts and .service.ts extensions remain allowed in tsc and tsc --lsp:
node node_modules/@webda/content-mapper/lib/patch-tsc.js
Then register .model.ts and .service.ts in tsconfig.json:
{
"contentMappers": [{ "package": "@webda/content-mapper", "extensions": [".model.ts", ".service.ts"] }]
}
Strategy B: Use .model.wts / .service.wts with outputExtensions (Unmodified tsc)
If you prefer not to patch the tsc binary, use .model.wts and .service.wts source suffixes and configure outputExtensions in @webda/content-mapper's manifest (or your mapper wrapper) so emitted files and ESM imports remain ./user.model.js and ./query.service.js:
// tsconfig.json
{
"contentMappers": [{ "package": "@webda/content-mapper", "extensions": [".model.wts", ".service.wts"] }]
}
// package.json
{
"typescript": {
"contentMapper": {
"exec": ["node", "lib/server.js"],
"compilerOptions": ["module", "target"],
"outputExtensions": {
".model.wts": ".model.js",
".service.wts": ".service.js",
".flow.wts": ".flow.js"
}
}
}
}
Note: With
.wtsfiles, configure your editor and tools (e.g. VS Code"files.associations": { "*.wts": "typescript" }, ESLint, Prettier) to treat*.wtsas TypeScript.
Content mappers run external code, so TypeScript asks you to trust them: tsc --runExternalCode on the command line,
initializationOptions.runExternalCode for the language server.
A model or service declared in a file without a mapped suffix (.model.ts / .service.ts or .model.wts / .service.wts) is never transformed: webdac build fails and names the file to rename (WEBDA_STRICT_FILE_NAMING=0 downgrades it to a warning while migrating).
Tests with Vitest
The Vite plugin applies the same generators, so specs exercise the code webdac build emits:
import { webdaContentMapper } from "@webda/content-mapper/vite";
import { defineConfig } from "vitest/config";
export default defineConfig({
plugins: [webdaContentMapper()]
});
Entry points
| Export | Use |
|---|---|
@webda/content-mapper | Generators, WarmSession, runTwoPass, schema generation |
@webda/content-mapper/server | The content mapper process started by TypeScript |
@webda/content-mapper/vite | The webdaContentMapper() Vite/Vitest plugin |
@webda/content-mapper/coercions | The default coercion rules |
@webda/content-mapper/schema-worker | Schema generation in a worker thread |
Requires TypeScript >=7.1.
See also
Classes
Interfaces
- AccessorOptions
- ActionSchemaOptions
- AnalysisContext
- BehaviorOptions
- CoercionRule
- CompiledFlow
- ConverterOptions
- DefaultGeneratorOptions
- DiscoveredObject
- DiscoveryOptions
- Edit
- FileEdits
- FlowCompileError
- FlowCompileResult
- FlowCron
- GeneratedDiagnostic
- Generator
- JSONSchema7
- MappedText
- ModelMetadata
- ModelRelations
- ModelSchemaOptions
- ModelSchemas
- ModuleOptions
- ModuleResult
- OperationTarget
- PatchTscOptions
- PatchTscResult
- QlValidatorOptions
- ReflectedAttribute
- RelationDependent
- ServiceSchemaOptions
- Session
- TopLevelSchemaOptions
- TransformOutcome
- TransformTiming
- TwoPassOptions
- TwoPassResult
- WarmSessionOptions
- WebdaModuleJson
Type Aliases
Variables
- BEHAVIOR_PARENT_KEY
- DEFAULT_COERCIONS
- DELETE_POLICIES
- FLOW_ERROR
- HAS_RESERVED_EXTENSION_SYMBOL
- IS_PACKAGE_ALLOWED_SYMBOL
- SECRET_KEYWORD
- SpanMapKind
- WQL_CODES
Functions
- accessorsGenerator
- applyEdits
- backfillModelRelations
- baseNames
- behaviorsGenerator
- buildMappedText
- buildModelMetadata
- buildRelations
- classesOf
- compileFlows
- defaultGenerators
- discoverWebdaObjects
- findGoFunctionFileOffset
- findParametersNode
- findTextSectionFileOffset
- findTscBinary
- flowsGenerator
- formatFlowError
- generateActionInput
- generateActionOutput
- generateModelSchemas
- generateServiceSchema
- generateTopLevelSchemas
- generateWebdaModule
- isStatic
- loadParametersGenerator
- memberName
- mergePlan
- namespaceOf
- normalizeDefinitions
- openSession
- patchTsc
- qlValidatorGenerator
- reflectAttributes
- runTwoPass
- textOf
- triviaOf