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

@voxgig/sdkgen-langpack

v0.0.13

Published

Additional language targets for the Voxgig SDK Generator: Dart, Haskell and Lean.

Readme

@voxgig/sdkgen-langpack

Additional language targets for the Voxgig SDK Generator: Dart, Haskell and Lean.

npm install --save-dev @voxgig/sdkgen-langpack
voxgig-sdkgen package add @voxgig/sdkgen-langpack
npm run generate

That installs all three targets. To take just one:

voxgig-sdkgen target add @voxgig/sdkgen-langpack/dart

Generation is unchanged from there. These are ordinary language targets: they produce a full SDK with the same entity model, the same operation pipeline and the same feature set as any bundled target.

Why a pack rather than three packages

Three languages that nobody releases separately do not need three release trains. One package means one version, one test suite and one type-check lane, and a consumer still installs exactly the targets they name.

The trade is real and worth stating: a fix to Dart bumps the version Haskell and Lean ship under. If any of these languages later grows its own cadence and its own maintainer, splitting it out is the same move that brought it here.

Parity

Declared per target in sdkgen-package.json:

| target | tier | what that means | |---|---|---| | dart | FULL | drives the shared corpus for every section | | haskell | FULL | drives the shared corpus for every section | | lean | FULL | drives the shared corpus for every section |

haskell was MIRRORED until it gained an omni port: driving the shared corpus needs the shared runner, and hand-written cases cannot fail when the reference changes. Its first corpus run found two real defects — see .sdk/tm/haskell/test/TPrimaryCorpus.hs.

A tier here is checked, not just declared: test/parity.test.js reads the parity map and verifies each claim against what the target's suite actually does.

Where the corpus runs. The shared corpus is materialised into each project as .sdk/test/test.json, so a real generated SDK executes it. The sdks workflow does the same here: it takes the corpus from the published @voxgig/create-sdkgen, generates the three SDKs, builds each and runs its suite. The build workflow covers generation, component type-checking and per-target behaviour on Node alone, so a green build is not a green corpus.

Lean is deliberately different

Lean has no entity object. Its operations are namespaced free functions over the client value (Planet.load c m co), dispatched by the config-driven SdkRuntime, so there is no instance to return, no per-entity data or match state, and no .data() hop. Every other target resolves an operation to an entity instance.

That is a boundary, not a gap. Giving Lean the entity-returning contract means designing an entity layer for the language, which is a decision in its own right rather than a port of an existing one. The suite pins the current shape so the difference stays deliberate.

The live transport is not different. SdkRuntime.runOp runs the same pipeline as every other target, stage by stage through SdkUtility: makeContext, makePoint, makeSpec (method, path, params, query, headers, the body or the GraphQL envelope, then the credential), makeUrl, makeFetchDef, the transport, makeResponse and the response transform, with the feature hooks dispatched between them and PreUnexpected on the error exit. A hook that has already done a stage's work says so on ctx.out — point, spec, request, response or result — and that stage is then skipped, as the matching reference utility skips it.

Constructing a client resolves the options through makeOptions, so what the API model declares in config.options is in force from the first operation: its headers, prefix and suffix, and base where the model names none. allow.op and allow.method are defaulted there too, a list that is null, undefined or missing taking the default as it does in the other targets, and makePoint and makeSpec enforce them.

The transport is curl -i: every prepared header is sent, and the response status, headers and body come back for the result and for the features that read them (the cost feature's pricing header, for one). Reading that stream means skipping what precedes the response — an interim 100 Continue, and a proxy's own 200 Connection Established block, which curl prints for every https request tunnelled through an HTTP proxy, https_proxy in the environment included. SdkRuntime.mkClientWith builds a live client over a caller-supplied transport, which is how .sdk/tm/lean/test/TFeature.lean pins the wire without a server.

What the shared corpus covers, and what it does not. The corpus pins the utility FUNCTIONS one at a time — makeSpec, makeUrl, prepareMethod and the rest, each against its own fixture. It says nothing about how runOp composes them, so a stage left out or called in the wrong order passes it. That composition is pinned by the lean feature suite instead, over a recording transport: the url, the method, the headers and the body that reach the wire, the stages a failure dispatches, and each stage's ctx.out short-circuit.

dart and lean carry the secrets feature

Both declare provides: { sekreto: true } and ship a vendored sekreto port — dart under .sdk/tm/dart/lib/feature/secrets/ (34 files), lean under .sdk/tm/lean/src/feature/secrets/{sekreto,plugin} (38 files). Every file keeps the VENDORED: provenance header naming its upstream tag. A project that turns the feature on in its own model —

main: kit: feature: secrets: { active: true plugin: vault: active: true }

— gets exactly the plugin definitions its active groups name, the inactive groups' files trimmed from the tree, the secrets suite registered, and a secrets() accessor on the SDK. A project without the feature, or with it active: false, generates exactly as before.

The feature MODEL is sdkgen's, not this package's. model/feature/secrets.aontu in @voxgig/sdkgen carries the path lists and the def: dart: and def: lean: maps; packs consume core feature models rather than copying them. Those entries ship from 4.10.0 on; engines.sdkgen here requires >=4.34.2, comfortably past that. Against an sdkgen older than 4.10.0 the feature emits no plugin definitions at all, and each target's secrets test says so by name.

Lean builds through make. A plugin GROUP (vault, aws, ...) binds libcurl through two sdkgen-owned C stubs under src/feature/secrets/ffi/. Lake TOML cannot compile C, so make ffi uses the system compiler and writes a link response file that the lakefile reads — which means a plugin-bearing lean SDK is built and run with make build, make test, make exe EXE=secrets, not bare lake exe, which fails at link. Secrets on with no group, off, or absent: no libcurl, and the target's zero-dependency promise holds.

Vendoring is tag-pinned and guarded. vendor/routes.json is this pack's own route table — which upstream file, from which repository at the shared tag, lands where, and how it is adapted on the way in. make vendor executes it, stamping each file's VENDORED: provenance header and recording a sha256 in test/vendored.json; make vendor-check verifies without writing, and test/vendored.test.js runs that same check under npm test, so an edited or stale vendored file fails the suite. sdkgen's own route table records dart, haskell and lean as excluded precisely because they need a route root here — this is it. Resyncing is a tag bump in routes.json followed by make vendor, not a hand copy.

Developing

npm install
npm run build     # type-checks every target's components
npm test          # the comment and dependency gates, then the suite

The suite runs on @voxgig/sdkgen/testkit: it installs this package into a staged consumer through the real package add, compiles the components the way a consumer's build does, and generates.

All of that is Node and nothing else — no dart, no lake, no ghc is needed or looked for, so the suite is green on a machine that could not build a single generated SDK. Read a green build as what it is: components that type-check and targets that generate. Whether you can compile the output is a question about your own machine, and command -v is the way to ask it.

Where dart, ghc or lean is installed, the sdks workflow's commands build and run that target's SDK. CREATE_SDKGEN names an unpacked @voxgig/create-sdkgen package, whose test data writer and corpus a scaffolded project carries:

CREATE_SDKGEN=/path/to/create-sdkgen npm run sdks -- generate /tmp/sdk
npm run sdks -- run haskell /tmp/sdk   # or dart, or lean

run fails when a command fails, and when the suite prints no pass and fail counts or a count of no passes, since a suite that runs nothing exits cleanly. It reports the toolchain it ran under.

A lean SDK pins its release in the generated lean-toolchain, and run builds it under that release and no other, read from the SDK root it is given. The release is looked for unpacked under LEAN_TOOLCHAINS, a directory that install fills from the Lean release archives, and otherwise the lean on PATH serves, refused when it reports another version. elan honours the pin by itself, so with it on PATH nothing more is needed:

LEAN_TOOLCHAINS=/tmp/lean-toolchains npm run sdks -- install lean /tmp/sdk
LEAN_TOOLCHAINS=/tmp/lean-toolchains npm run sdks -- run lean /tmp/sdk

When a pull request's suite fails, the workflow generates the base branch's SDKs and runs compare, which installs and runs the base branch's SDK under the release that SDK pins, then names the toolchain each side ran under in its verdict. A base branch release that cannot be installed gives no verdict rather than a wrong one.

Validate the package itself with:

npx voxgig-sdkgen package check .

Provenance

All three targets were generated from the same trees that shipped inside @voxgig/sdkgen. Before each moved, its output was compared file by file against the bundled version from the same model:

| target | files generated | differences | |---|---|---| | dart | 77 | 0 | | lean | 26 | 0 | | haskell | 29 | 0 |

Byte-identical, with no placeholder leaks on either side. Nothing about a generated SDK changed in the move.