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

typespec-extension-exporter

v0.4.0

Published

TypeSpec emitter that exports @extension metadata as raw occurrences, Java beta inputs, or grouped beta name lists, serialized as JSON, YAML, or CSV.

Readme

typespec-extension-exporter

A TypeSpec emitter that exports @extension metadata as raw occurrences, Java-oriented beta suppression/customization inputs, or a language-neutral list shape that groups beta class/field names into two arrays. Outputs can be serialized as JSON, YAML, or CSV.

Features

  • Detects all @extension applications across the compiled program.
  • Records, for each occurrence: extension key, value, the target's kind and fully-qualified name, the containing namespace, and the exact file/line/column of the decorator.
  • Optional filtering by target kind (e.g. only models, fields, or operations).
  • Output file name is configurable.

Installation

npm install typespec-extension-exporter

The emitter has @typespec/compiler, @typespec/openapi, and @azure-tools/typespec-client-generator-core as peer dependencies, so they must be present in your TypeSpec project. TCGC is used by the SDK-derived shapes (revapi, tsp-ast-input, and list) and is still a required peer dependency because the emitter imports it directly.

Usage

Run it as part of tsp compile:

tsp compile <path> --emit typespec-extension-exporter

By default, this writes extensions.json into the emitter output directory (tsp-output/typespec-extension-exporter/).

You can also enable it from tspconfig.yaml:

emit:
  - typespec-extension-exporter

The default raw output is a JSON array of @extension occurrences. See Output shapes and formats for every shape and format.

Options

Pass options via --option typespec-extension-exporter.<name>=<value> (or under options.typespec-extension-exporter in tspconfig.yaml).

| Option | Type | Description | | --------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | keys | string | Comma-separated, case-sensitive extension keys to include (e.g. x-ms-foundry-meta). Omit to include any key. | | kinds | string | Comma-separated, case-insensitive target kinds to include (e.g. model,modelProperty,operation,enum,union,scalar). The alias field maps to modelProperty. Omit to include all kinds. | | output-shape | string | Semantic output shape: raw (default) emits raw occurrences; revapi emits a revapi differences ignore list; tsp-ast-input emits annotation-insertion requests for downstream AST customization; list collapses the beta type;name rows into two lists (class FQNs and field references). | | output-format | string | Serialization format: json (default), yaml, or csv. CSV output uses ; as the delimiter. | | output-file | string | Name of the output file to write. Defaults to extensions.<format> for raw, revapi.<format> for revapi, tsp-ast-input.<format> for tsp-ast-input, or list.<format> for list. |

SDK-output options (used when output-shape is revapi, tsp-ast-input, or list)

| Option | Type | Description | | --------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | language | string | Target SDK language for the language-neutral list shape. Known values: java (default), csharp. Any other value is treated as a raw TCGC emitter name. revapi and tsp-ast-input are Java-specific; non-Java values for those shapes are an error and no output is emitted. | | namespace | string | Override for the generated SDK base namespace/package, e.g. com.azure.ai.agents (Java) or Azure.AI.Projects.Agents (.NET). When omitted, the client namespace resolved by TCGC (which honours @@clientNamespace) is used. Set this when the package comes from the language emitter's own namespace option instead of @@clientNamespace. | | models-subpackage | string | Subpackage for public models/enums. Defaults to models. (Applies to revapi/tsp-ast-input; list uses no subpackage.) | | internal-subpackage | string | Subpackage for non-public (internal-access) types. Defaults to implementation.models. | | justification | string | Base annotation/justification text attached to every generated Java output entry. The gating preview feature keys (from the @extension value's required_previews/conditional_previews) are appended automatically. |

Option validation

The emitter reports a compiler warning (without failing the build) for option values that can never match:

  • unknown-kind: a kinds value that is not a recognized TypeSpec kind.
  • non-extension-key: a keys value that does not start with x- (OpenAPI @extension keys always do).

Examples:

options:
  typespec-extension-exporter:
    output-shape: tsp-ast-input
    output-format: yaml
tsp compile <path> --emit typespec-extension-exporter \
  --option typespec-extension-exporter.output-shape=revapi \
  --option typespec-extension-exporter.output-format=csv

For details on each output shape (including the revapi regex anchoring and the tsp-ast-input entry format), the Java naming rules, and the serialization formats, see Output shapes and formats.

Running against the Foundry spec

The Foundry spec lives in the azure-rest-api-specs repo. Its two Java SDK projects carry Java tsp-ast-input options in their own tspconfig.yaml:

| Project | tspconfig.yaml | | ---------------------------- | ----------------------------------------------------------- | | sdk-java-azure-ai-agents | .../Foundry/src/sdk-java-azure-ai-agents/tspconfig.yaml | | sdk-java-azure-ai-projects | .../Foundry/src/sdk-java-azure-ai-projects/tspconfig.yaml |

Each has an options.typespec-extension-exporter block (default output: the tsp-ast-input CSV the Java SDK consumes as <library-module>/customizations/beta-annotations.csv). The C# Foundry project can use output-shape: list to emit list.yaml. These blocks are inert during a normal tsp compile — they only take effect when the emitter is explicitly selected with --emit typespec-extension-exporter, so they never disrupt other contributors.

One-time onboarding: make the emitter resolvable

TypeSpec resolves emitters from the spec's own directory tree (it does not consult global installs), so the emitter must be present in a node_modules above the spec files. Pick whichever you prefer:

# Option A — npm link (no publish; picks up local rebuilds):
npm install -g typespec-extension-exporter   # or: npm link  (from this repo)
cd /path/to/azure-rest-api-specs
npm link typespec-extension-exporter

# Option B — install into the spec repo without touching its package.json:
cd /path/to/azure-rest-api-specs
npm install --no-save typespec-extension-exporter

Both may emit a harmless "multiple versions of @typespec/*" warning if your emitter install resolves newer TypeSpec libraries than the spec repo's; the output is unaffected.

Emit

With the emitter onboarded, compile a project's client.tsp with --emit; the options come from that project's committed tspconfig.yaml:

tsp compile .../Foundry/src/sdk-java-azure-ai-agents/client.tsp \
  --emit typespec-extension-exporter --output-dir <out>

For local development against a checkout of the spec, this repo ships a cross-platform helper that builds the emitter, makes it resolvable in the spec tree, and emits each project. By default it writes under foundry/tsp-output/<project>/, but --<project>-out <dir> writes beta-annotations.csv straight into a Java SDK module's customizations/ folder (where the @Beta customization reads it):

export FOUNDRY_DIR=/path/to/azure-rest-api-specs/specification/ai-foundry/data-plane/Foundry

# Generate into this repo's output dir:
npm run foundry:emit            # both projects
npm run foundry:emit:agents     # one project

# Generate straight into the Java SDK module (one command, ready to commit):
node foundry/emit.mjs agents \
  --agents-out /path/to/azure-sdk-for-java/sdk/ai/azure-ai-agents/customizations
node foundry/emit.mjs projects \
  --projects-out /path/to/azure-sdk-for-java/sdk/ai/azure-ai-projects/customizations

(FOUNDRY_DIR can also be passed as --foundry-dir <path>; it must contain src/sdk-java-azure-ai-<project>/client.tsp. The helper is Java-project focused and writes the file directly — no typespec-extension-exporter/ subfolder — via the built-in emitter-output-dir option.)

Using tsp-client from the Java SDK repo

The committed options flow through the Java SDK repo's tsp-location.yaml process. Each project's tspconfig.yaml sets emitter-output-dir: "{cwd}/../customizations", so — when tsp compile is run from inside TempTypeSpecFiles — the CSV lands in the library module's customizations/ folder automatically, with no --output-dir or other flag needed ({cwd} is the process working directory, and TempTypeSpecFiles sits directly beside customizations/ in the module).

From the library module (e.g. sdk/ai/azure-ai-agents):

npx tsp-client sync                                    # materializes TempTypeSpecFiles/

cd TempTypeSpecFiles
npm install --no-save typespec-extension-exporter      # the published emitter + its deps

npx tsp compile <synced client.tsp> \                  # run from within TempTypeSpecFiles
  --emit typespec-extension-exporter
cd ..

npx tsp-client generate                                # Java codegen; @Beta customization reads the CSV

The @Beta customization requires customizations/beta-annotations.csv to exist, so the tsp compile step must run before tsp-client generate. No emitter option needs to be passed — the output location comes from the committed emitter-output-dir. Because that path is {cwd}-relative, the tsp compile must be invoked from inside TempTypeSpecFiles; running it elsewhere puts the CSV in the wrong place.

Documentation

  • Output shapes and formats — the raw, revapi, tsp-ast-input, and list shapes in depth, SDK naming rules, and the JSON/YAML/CSV formats.
  • Contributing — local setup, scripts, project structure, testing, and how foundry/emit.mjs works.