npm (TypeScript)

dsdlc emits TypeScript source: point tsconfig.json at the generated tree and compile it with everything else. npm installs the compiler and runs the scripts.

Language TypeScript
Build system npm
Idiom B -- your project owns the manifest
Regeneration None -- regeneration is an explicit step

Notes

This is Idiom B even though dsdlc writes a package.json. The emitted manifest declares "type": "module" but no main, exports, or types, and the tree contains only .ts files. npm install file:generated therefore succeeds and then fails at run time: Node falls back to looking for index.js and finds only index.ts. Consuming the tree as a package would mean compiling it to JavaScript first and patching entry points into a generated manifest.

The tsconfig.json here targets commonjs rather than an ES module build: the generated files import each other without file extensions, which Node's ESM resolver rejects, so an ESM emit would produce JavaScript that Node will not load without a bundler rewriting every specifier. The CommonJS emit resolves those specifiers at require() time and runs unmodified.

Prerequisites

Tool Why
npm installs the TypeScript compiler and runs the scripts
node runs the compiled round-trip program

Commands

Run these from the recipe directory, with dsdl/ and src/ copied alongside it. This is the exact sequence CI runs.

# generate
dsdlc --target-language ts dsdl/lanyard --ts-module lanyard --outdir generated
# install
npm install --silent --no-audit --no-fund
# build
npm run --silent build
# round-trip
npm run --silent start

The types this builds

The whole lanyard namespace -- twenty-four definitions, browsable from the showroom overview, where each one is paired with its wire-layout facts and a declaration excerpt in every language.

The build files

package.json

{
  "name": "lanyard-roundtrip",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "build": "tsc -p .",
    "start": "node dist/src/ts/roundtrip.js"
  },
  "devDependencies": {
    "@types/node": "^22.0.0",
    "typescript": "^5.6.0"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "target": "es2022",
    // commonjs, not esnext, and this is the load-bearing choice.
    //
    // The generated files import each other without file extensions ("./reading_1_0"). Node's ESM
    // resolver requires extensions, so an ESM build emits JavaScript that Node then refuses to load
    // -- you would need a bundler to rewrite the specifiers. The CommonJS emit resolves them at
    // require() time and runs as-is, which is why this is a two-command build with no bundler.
    "module": "commonjs",
    "moduleResolution": "node",
    "strict": true,
    "outDir": "dist",
    "skipLibCheck": true
  },
  "include": ["src/ts/**/*.ts", "generated/**/*.ts"]
}