Publishing Plugins
A plugin is one npm package containing a JS descriptor and Go source.
package.json
{
"name": "my-ttsc-plugin",
"version": "0.1.0",
"description": "What the plugin does.",
"main": "plugin.cjs",
"ttsc": {
"plugin": {
"transform": "my-ttsc-plugin"
}
},
"files": ["plugin.cjs", "plugin", "driver"],
"engines": {
"node": ">=18"
},
"keywords": ["ttsc", "ttsc-plugin", "tsgo"],
"license": "MIT"
}ttsc.plugin is a single object, not an array. One package contributes one auto-discovered entry. Explicit compilerOptions.plugins[] wins over auto-discovery; the name must equal the string consumers install you under. See Concepts → Auto-discovery.
Pin against ttsc
The plugin protocol is stable across patch releases. Minor releases may add new optional flags (--quiet, future additions) which existing plugins accept-and-ignore via filterHostArgs. Major releases (0.x → 0.(x+1)) may change --plugins-json shape, exit-code conventions, or LoadProgramOptions fields. Pin the minor range you tested against, whatever it is when you publish (the example below uses 0.18.x):
"peerDependencies": {
"ttsc": ">=0.18.0 <0.19.0",
"typescript": "*"
},
"peerDependenciesMeta": {
"ttsc": { "optional": false },
"typescript": { "optional": false }
}The consumer project supplies ttsc and the active typescript runtime; your plugin should not carry them in dependencies. Use peerDependencies to assert the compatibility window. Update the version range every time you re-test against a new ttsc release.
Required Package Contents
The tarball must include:
plugin.cjs(or the built JS descriptor entry);- every Go source directory referenced by your descriptor (
plugin/for an executable sidecar,driver/or another non-mainpackage for linked transform source); go.mod;go.sum, when present;README.mdand license.
Verify before publish:
npm pack --dry-runThe tarball contains Go source, not a prebuilt plugin binary. ttsc builds that source on the consumer machine: executable package main sources become sidecars, while linked non-main transform packages are compiled into the selected native host.
Dependencies
Published plugin packages carry their JS descriptor and Go source, while the consumer project supplies ttsc and the active typescript runtime.
Plugin go.mod files use require lines for host modules. ttsc owns github.com/samchon/ttsc/packages/ttsc, github.com/microsoft/typescript-go, and github.com/microsoft/typescript-go/shim/... through its build overlay. Plugin-specific wrappers live under the plugin’s own Go module.
Versioning
Practical rule:
| Change | Bump |
|---|---|
| bug fix | patch |
| new mode or option | minor |
| removed mode or changed transform contract | major |
newly verified ttsc compatibility | minor |
dropped old ttsc minor support | major |
Your package version is separate from the ttsc plugin protocol.
Pre-Publish Check
Modeled on the wasm-smoke post-publish job in .github/workflows/release.yml. Run before every tag:
set -euo pipefail
# 1. Pack the tarball.
pnpm pack
TARBALL=$(ls *.tgz | tail -n1)
# 2. Stand up a clean-room consumer.
WORKDIR=$(mktemp -d)
cd "$WORKDIR"
npm init -y >/dev/null
npm install --no-save "${OLDPWD}/${TARBALL}" ttsc typescript
# 3. Write a smallest reproducible tsconfig and source file.
cat > tsconfig.json <<'JSON'
{
"compilerOptions": {
"target": "ES2022",
"module": "ES2022",
"outDir": "dist",
"rootDir": "src",
"declaration": true,
"plugins": [{ "transform": "<your-plugin-name>" }]
},
"include": ["src"]
}
JSON
mkdir src
echo 'debugger; export const x = 1;' > src/main.ts
# 4. Build through the published binary and assert on the output.
npx ttsc --emit
test -f dist/main.js
! grep -q "debugger" dist/main.jsThe same shape works as a GitHub Actions job. The minimal one:
name: plugin-smoke
on: [push, pull_request]
jobs:
smoke:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v6
with: { node-version: 24.x }
- uses: actions/setup-go@v5
with: { go-version: "1.26" }
- run: pnpm install --frozen-lockfile
- name: Pin Go binary for ttsc plugin builds
run: echo "TTSC_GO_BINARY=$(go env GOROOT)/bin/go" >> "$GITHUB_ENV"
- run: pnpm test
- run: pnpm pack --pack-destination /tmp
- name: Smoke-install into a clean fixture
run: |
# Adapt the Bash recipe above against /tmp/<your-package>-*.tgzFor plugins that import shims or touch paths, test Linux and macOS. Add Windows when you compare path strings or support Windows users.
CI environment
Pin TTSC_GO_BINARY and TTSC_CACHE_DIR in CI so the build cache is deterministic across matrix runs. See Architecture → Build environment for what they do and Testing → Cache isolation for the per-worker pattern.
Next
→ Testing, assert your plugin works before you publish.