npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@typra/emitter

v2.1.8

Published

Generic TypeSpec emitter for generating multi-runtime model surfaces

Readme

@typra/emitter

@typra/emitter generates runtime model surfaces from TypeSpec. Use it when you want TypeSpec to be the source of truth for shared model contracts and need generated code, tests, JSON AST output, or documentation for one or more runtimes.

Typra is emitter-only: it generates model/protocol surfaces, but it does not ship runtime service implementations or product-specific contracts.

Transport ownership boundary

TypeSpec remains the durable source of truth for HTTP contracts. Typra lowers the contract-visible transport shape into shared IR and projects equivalent producer/consumer seams from that IR, including path, query, header, cookie, body, content type, status, auth requirements, and success/error response selection behavior.

Generated producer seams bind HTTP requests to callable handler protocols/interfaces. Generated consumer seams bind callable-shaped client methods to an injected transport function and hydrate only status-matched 2xx success bodies through Typra model load() helpers. Non-2xx responses are reported through the transport error seam with the original status/body instead of being loaded as success models. Wildcard/default response bodies are used as a 2xx success fallback only when an operation has no explicit success response, so default error envelopes do not override declared success models.

Auth requirements modeled with TypeSpec HTTP are emitted as metadata on the adapter/client seams. Generated code reports the requirement shape, but it does not acquire tokens, refresh credentials, store secrets, or enforce provider policy.

Host applications own runtime policy: business logic, token acquisition and refresh, credential storage, cookie jars, retries, logging, tracing, persistence, deployment, and provider-specific identity behavior. Cookie values modeled in TypeSpec are projected as contract-visible bindings; session management and cookie persistence remain host-owned.

Runtime auth integration

Typra treats TypeSpec HTTP auth as contract metadata, not runtime behavior. A producer projection can expose AUTH_REQUIREMENTS so the host can wire its own middleware, dependency injection, or request guards. A consumer projection passes the same requirement metadata to the injected transport seam so the host can choose how to attach credentials.

For example, a generated TypeScript fetch client passes:

{
  method: "GET",
  url,
  headers,
  cookies,
  auth: {
    options: [{ schemes: [{ id: "BearerAuth", type: "http", scheme: "Bearer" }] }],
  },
}

The host-owned transport decides whether that metadata means a bearer token, API-key lookup, mTLS context, test credential, or no credential at all. Typra does not synthesize an Authorization header, manage refresh, persist tokens, retry after challenges, or interpret provider-specific identity policy.

Install

npm install --save-dev @typra/emitter @typespec/compiler@1 @typespec/json-schema@1

Typra supports TypeSpec compiler and JSON schema emitter across the >=1.10.0 <2.0.0 range (validated in CI against 1.10.0 and 1.15.0). TypeSpec versions outside that range report a clear diagnostic during emit; set allow-unsupported-typespec-version: true only when you intentionally accept possible generated output churn.

Current release highlights

The current package focuses on cross-runtime semantic parity, native interop options that delegate to Typra's canonical load/save path, and validation that keeps generated output reviewable:

  • typra-generate supports every emitted runtime, accepts a --spec TypeSpec entrypoint, and resolves the installed TypeSpec compiler directly.
  • Invalid programmatic targets and misspelled emit-targets configuration now fail clearly instead of being ignored.
  • TypeScript can opt into Zod validators; Python can opt into Pydantic v2; Java can opt into Jackson; Rust can opt into explicit serde; and Swift can opt into explicit Codable.
  • Publish runs generated-fixture validation, including Swift, and npm packing always builds the distributable artifacts.
  • Cross-language validation includes generated native-interop variants and a save-side executable conformance oracle.

Configure TypeSpec

Add the emitter to tspconfig.yaml:

emit:
  - "@typra/emitter"

options:
  "@typra/emitter":
    emitter-output-dir: "{cwd}/generated"
    root-object: "MyProject.ApiRoot"
    root-namespace: "MyProject"
    emit-targets:
      - type: TypeScript
        output-dir: "generated/typescript"
        test-dir: "generated/typescript/tests"
        import-path: "../index"
        # Optional: emit Zod validators that validate Typra's canonical load/save wire shape.
        native-serialization: "zod"
      - type: Swift
        output-dir: "generated/swift"
        test-dir: "generated/swift/Tests/MyProjectTests"
        package-name: "MyProject"
      - type: Java
        output-dir: "generated/java"
        test-dir: "generated/java/tests"
        package-name: "myproject.api"

Import the emitter library from your TypeSpec entry point:

import "@typra/emitter";

namespace MyProject;

Use TypeSpec-native interface/op declarations for new callable seams. Typra operation decorators describe runtime-only callable effects: @runtimeCancellable, @sync, @optionalOperation, and @effect(#{ atomic: true, nonFatal: true }). Runtime cancellation is emitted as a native synthetic parameter and never becomes a model or serialized field. Set cancellation-token-path to the full runtime-native symbol path, such as crate::engine::CancellationToken for Rust or prompty.core.cancellation.CancellationToken for Python.

Python supports opt-in Pydantic v2 model emission with native-serialization: "pydantic" on the Python target. The default remains "none" and keeps dataclass output. In Pydantic mode, generated model_validate(), model_validate_json(), model_dump(), and model_dump_json() delegate to Typra's generated load(), save(), and to_json() methods so Typra's pathful diagnostics and wire semantics remain the authoritative contract. model_validate_strings() hard-fails because Pydantic's string-coercing validation would bypass Typra's loader semantics.

Compile with TypeSpec:

npx tsp compile ./path/to/main.tsp --config ./tspconfig.yaml

CLI

The package includes typra-generate, typra-verify, and a generic typra-consumer-smoke harness:

npx typra-generate --help
npx typra-generate --spec ./typespec/main.tsp --root-object MyProject.ApiRoot --deterministic -o ./generated
npx typra-verify --baseline ./baseline --current ./generated
npx typra-consumer-smoke --config ./typra-smoke.json

typra-verify compares committed .typra-generated metadata against current generated metadata and prints deterministic review summaries for exports, protocols, files, package/module identity, toolchain, protected paths, schema evolution, stale cleanup dry-runs, hydration seams, and breaking-change classification. It never deletes files.

Supported output

Typra includes emitters for:

  • TypeScript
  • Python
  • C#
  • Go
  • Java
  • Rust
  • Swift
  • Markdown documentation
  • JSON AST

The Typra fixture slice validates TypeScript, Python, C#, Go, Java, Rust, Swift, Markdown, and JSON AST generation from synthetic TypeSpec shapes. Fixture validation also exercises generated metadata, verifier CLI output, consumer smoke wiring, and cross-language generated-code compile/test surfaces. Broad integration coverage lives under fixtures/integration/. Focused, runtime-agnostic feature coverage lives under fixtures/features/<feature>/; runtime-specific quirks live under fixtures/runtimes/<runtime>/<case>/ so generated output can be inspected by feature or runtime without turning the top-level fixture folder into a flat list of test names.

TypeScript web/runtime compatibility

The generated TypeScript library is runtime-neutral: it loads and runs under native ESM, bundlers, and browser/edge/Deno — not just Node. There is nothing to configure and nothing to activate; web compatibility is a property of the emitted code, not a mode or option. YAML support is centralized in LoadContext.parseYaml over a module-level import * as yaml, so model classes never call require() and the yaml dependency resolves its browser build under bundler/browser conditions. Consuming projects get this for free by regenerating; the public API (load/save/toYaml/fromYaml) is unchanged.

Three stages in npm run validate:fixtures keep it that way. These are internal CI guards for contributors, not consumer-facing features — they inspect generated output and fail the build on a Node-only coupling, but add no options and change no emitted code:

  • typescript.runtime-neutrality — scans the shipped library source for require(), Node builtins, or process.* coupling.
  • typescript.web-compile — type-checks the shipped library with no @types/node and the DOM lib, catching type-level Node leaks (e.g. a field typed Buffer) the source scan cannot see.
  • typescript.web-runtime — emits the library to ESM and runs a real YAML round-trip under forced browser export conditions with Node builtins rejected, proving it loads and runs off Node.

Each runs for the typescript and typescript-zod targets. The tests/ subtree and consumer-authored vector-adapters.ts legitimately run under Node and are excluded from these gates.

Go parity and validation

Generated Go models include Load*, Save, ToJSON, ToYAML, *FromJSON, and *FromYAML helpers. For models with scalar coercions, *FromJSON and *FromYAML pass the parsed scalar value through to Load* so JSON/YAML shorthand inputs behave the same way as direct Load* calls.

Nested object and polymorphic collection loads return child load errors instead of discarding them. Abstract polymorphic dispatch reports unknown or missing discriminators as Go errors, while default variants continue to handle fallback cases.

npm run validate:fixtures regenerates the fixture slice and verifies Go with gofmt -l, go vet ./..., go test ./..., generated coercion helper tests, and executable conformance alongside the other runtime targets. The executable conformance step is save-side: each backend saves the canonical fixture sample and the harness compares normalized output across the target set, with every semantic rule recorded in the rule-by-backend conformance matrix.

Generated files

Generated source files include Typra markers, and the emitter records a generated-file manifest for each output root. Stale-file deletion is not enabled yet, so Typra will not remove hand-authored runtime files.

For CI or committed generated output, enable deterministic metadata with the TypeSpec emitter option:

options:
  "@typra/emitter":
    deterministic-output: true

This keeps .typra-generated/manifest.json stable across equivalent generations by replacing wall-clock generatedAt values with a fixed timestamp. Generated text artifacts are also normalized to LF line endings, trimmed trailing whitespace, and final newlines. Blank generated artifacts are skipped unless the file format requires an empty sentinel such as Python py.typed.

Each generation also writes .typra-generated/report.json, a stable single-run report that lists emitted files, skipped empty outputs, marker-owned stale files removed during skipped-output cleanup, preserved unmarked skipped files, hygiene policy, and warnings. Baseline-aware checks such as protected-path touches remain in typra-verify, and per-file formatter status is not recorded yet.

Rust targets can opt into case-insensitive string-union/enum parsing without changing the default case-sensitive behavior:

emit-targets:
  - type: Rust
    output-dir: generated/rust
    enum-parsing: case-insensitive

When enabled, generated Rust from_str_opt methods accept enum values with ASCII case differences while preserving the canonical serialized casing.

Java targets can opt into Jackson databind support without changing the default generated Java surface:

emit-targets:
  - type: Java
    output-dir: generated/java
    native-serialization: jackson

native-serialization defaults to none. With jackson, generated Java models include Jackson annotations and serializers/deserializers that delegate to Typra's generated save and load, so Jackson output is derived from the same wire mapping as Typra JSON/YAML helpers. The emitter does not create or mutate a consumer build manifest; projects enabling this option must provide jackson-databind on their Java compile/runtime classpath.

Rust targets can also make the existing serde support explicit without changing the default generated model surface:

emit-targets:
  - type: Rust
    output-dir: generated/rust
    native-serialization: serde

Rust already emits #[cfg(feature = "serde")] Serialize/Deserialize impls for generated models and string unions for compatibility with current output. The impls delegate through Typra's canonical to_value/load_from_value mapping so serde output cannot silently diverge from Typra save semantics. Consumers should declare a crate feature named serde and include the serde dependency when compiling with that feature. Set native-serialization: none to opt out of these Rust impls.

Consumers can declare hand-authored boundaries in verifier config:

{
  "protectedPaths": ["src/adapters/**"],
  "hydrationZones": ["src/extensions/**"]
}

The emitter records hydration seam metadata for generated protocol adapters, but runtime behavior remains hand-authored by the consuming project.

Links