TypeScript Extension
The @putnami/typescript extension provides the standard TypeScript toolchain for Putnami workspaces. It handles building, testing, linting, serving, and publishing for JS/TS projects using Bun and Biome.
Scope: All jobs are project-only — they require a project context.
External tools
Enable the extension
putnami deps add @putnami/typescriptThe extension is auto-discovered from workspace dependencies.
Jobs
generate
Run code generation hooks before building. Automatically invoked by build and test, but can be run standalone.
Key steps:
- Discover pre-build hooks from plugin dependencies
- Execute hooks in dependency order
- Output generated exports and assets to
.gen/
Options:
--verbose— Show detailed generation output--clear— Clear existing generated artifacts before generating
putnami generate .
putnami generate . --clearbuild
Compile TypeScript packages for distribution using Bun's bundler.
Pipeline phases:
generate— pre-build hooks + generated artifactstranspile— JS package output (output/lib)types— declaration output (output/types)compile— standalone binary output (output/compile)
Default behavior: if no phase flags are provided, build runs generate + transpile + types. The compile phase is opt-in via --compile. If any phase flag is provided, only selected phases run.
Options:
- Phase control:
--generate,--transpile,--types,--compile --target <bun|browser|node>(default:bun)--compile-target <bun-*>(single executable target, e.g.,bun-linux-x64)--bundle <standalone|local|none>(default:none)--sourcemap <inline|external|none>(default:external)--minify <boolean>(default:true)--splitting— Enable code splitting (ESM format required)--assets <path>(multiple allowed)--publish-config-access <public|restricted>(default:public)--version-suffix <suffix>(overrides git-derived suffix)--release— Build for stable release (skips version suffix)--fast— Skip type generation--skip-package-json,--skip-artifacts--clear— Wipe output folder first
Compile targets: default targets when --compile is enabled:
bun-linux-x64,bun-linux-arm64bun-darwin-x64,bun-darwin-arm64
Executable outputs are discovered from build.compile in .putnamirc.json or bin entries in package metadata.
Version and metadata: the build automatically reads the workspace version and adds a suffix for pre-release builds ({baseVersion}-{hash}, e.g., 1.0.0-a1b2c3d). The suffix is a 7-character hash of source files, ensuring deterministic versions.
putnami build . --target bun
putnami build . --compile
putnami build . --compile --compile-target bun-linux-x64test
Run tests using Bun's test runner.
- Discovers tests with
**/*.{test,spec}.{ts,tsx,js,jsx} - If no tests are found, returns
SKIP - Produces JUnit output and optional LCOV coverage
Options:
--timeout <ms>(default:5000)--coverage--test-name-pattern <regex>--test <filter>/-t--only,--todo,--bail <n>,--concurrent <n>--update-snapshots--pass-with-no-tests <boolean>(default:true)
putnami test . --coveragelint
Format and lint using Biome.
- Runs
biome formatthenbiome lint - Config resolution: project
biome.json→ workspace rootbiome.json→ built-in config
Options:
--config-path <path>(default:node_modules/@putnami/typescript/config)--fix <boolean>(default:true)--max-diagnostics <number>(default:10)--diagnostic-level <error|warn|info|off>(default:warn)
putnami lint . --fixserve
Start a dev server with hot reload.
- Resolves
./serveexport frompackage.jsonor uses--entrypoint - If
./serveis missing, runsputnami build <project> --fastfirst
Options:
--entrypoint <path>--watch <boolean>(default:true)--port <number>(default:3000)--debug— ForwardLOG_LEVEL=debugto the application--no-services— Disable multi-service discovery--inspect,--inspect-wait,--inspect-brk
putnami serve . --port 4000Multi-service mode: declare runtime service dependencies in package.json:
{
"putnami": {
"runsWith": ["catalogue-api", "profile-api"]
}
}Running putnami serve web-app --watch auto-discovers, allocates ports, and starts all declared services. If runsWith is not declared, the system walks the dependency graph for projects with ./serve exports.
Port conflict resolution: the system checks for port conflicts before starting. Conflicts are resolved interactively (or automatically in CI), and the chosen port is saved to the project config for future runs.
publish
Provided by the
@putnami/ciextension. Documented here because it handles TypeScript-specific publishing behavior.
Publish built packages, optional binary assets, and optional extension archives.
Subtasks (enabled by project publish channels):
npm— publish package(s) and manage dist-tagsassets— upload compiled binaries to GCSarchives— upload extension.tar.gzarchives to GCS
Options:
--stable— Publish stable version (strips suffix, tags aslatest)--dist-tag <tag>— Override npm dist-tag--also-branch-tag— Also publish branch-derived tag manifest--access <public|restricted>(default:public)--otp <code>--registry <url>— Custom npm registry--assets-bucket <bucket>,--assets-prefix <prefix>— GCS config for binaries--archives-bucket <bucket>,--archives-prefix <prefix>— GCS config for archives--dry-run
Enable channels in project config:
{
"publish": ["npm", "assets", "archives"]
}# Pre-release
putnami build .
putnami publish .
# Stable
putnami build .
putnami publish . --stableDocker
When the docker publish channel is enabled, the TypeScript extension generates a Dockerfile using oven/bun:slim as the base image and copies the pre-compiled standalone bundle into the container.
Enable in project config:
{
"publish": ["npm", "docker"]
}Options: --docker-registry <registry>, --docker-tag <tag>, --platform <platform> (default: linux/amd64), --port <number> (default: 3000), --stable.
putnami publish my-app --docker-registry ghcr.io/myorgCaching and dependencies
- generate depends on
^generate, cached with:src/**/*.ts,src/**/*.tsx,package.json. Quiet job (hidden from recap on success). - build depends on
generateand^build, cached with:src/**/*.ts,src/**/*.tsx,tsconfig.json,tsconfig.app.json,tsconfig.lib.json,package.json,doc/**/*. - test depends on
generate, cached with:src/**/*.ts,src/**/*.tsx,test/**/*.ts,test/**/*.tsx,package.json. - lint cached with:
src/**/*.ts,src/**/*.tsx,biome.json,package.json. - serve depends on
build --fast, never cached. - publish depends on
build --transpile --typesand^publish.
Pre-build hooks
Dependencies can contribute pre-build hooks to generate sources or assets before compilation. Hooks are discovered from plugin packages via the pre-build export.
Hook CLI arguments: the runner passes --context <path> and --result <path>. Write the JSON result to --result:
{
"exports": {
"./generated": "./.gen/main.ts"
},
"assets": [
{ "src": ".gen/schema.json", "dest": "schema.json" }
]
}Create a hook
- Create
src/pre-build/index.tsexportingpreBuildwithcommandand optionalargs - Create the command script that writes JSON to
--result - Add an export in
package.json:
{
"exports": {
"./pre-build": "./src/pre-build/index.ts"
}
}Project templates
| Template | Description |
|---|---|
typescript-web |
React SSR web app with file-based routing, layouts, and client hydration |
typescript-server |
HTTP server with @putnami/application, file-based API routing, and tests |
typescript-library |
TypeScript library with exports and tests |
putnami projects create my-app --template typescript-web
putnami projects create my-api --template typescript-server
putnami projects create my-lib --template typescript-libraryEvery template produces a project you can serve or test immediately.