Surfaces and Packages
The most important distinction in Tsonic is:
- surface = ambient world
- package = imported library or source package
Confusing those two is the fastest way to misunderstand the current stack.
Surfaces
Tsonic separates the language prelude from the ambient runtime personality.
- compiler core: always-on noLib baseline
clr: default CLR-first ambient surface@tsonic/js: JavaScript ambient surface
A workspace selects one active surface.
Surface examples
clr
Use CLR APIs explicitly:
import { Console } from "@tsonic/dotnet/System.js";
Console.WriteLine("hello");
@tsonic/js
Use JS-style ambient APIs naturally:
console.log(" hello ".trim());
const value = JSON.parse<{ ok: boolean }>('{"ok": true}');
Packages
Packages are imported dependencies. They are not ambient worlds.
Examples:
@tsonic/nodejs@tsonic/express@tsonic/dotnet@tsonic/aspnetcore- local workspace packages
That is why:
@tsonic/jscan be a surface@tsonic/nodejsis still a package
First-party source packages
These are authored in TypeScript and consumed as source packages:
@tsonic/js@tsonic/nodejs@tsonic/express
Each uses tsonic.package.json metadata to declare:
- exported subpaths
- ambient files
- module aliases
- surface compatibility
- runtime metadata where needed
Example: @tsonic/nodejs
The Node package is not a surface. Instead it is a package that:
- is compatible with
@tsonic/js - declares
node:*aliases - exports subpaths like
./fs.js,./http.js, and./path.js - can pull in framework/runtime requirements through package metadata
That is why the normal model is:
- workspace surface:
@tsonic/js - package dependency:
@tsonic/nodejs
Generated binding packages
These are generated from CLR metadata by tsbindgen:
@tsonic/dotnet@tsonic/aspnetcore@tsonic/microsoft-extensions@tsonic/efcore*
They are:
- packages, not surfaces
- generated, not authored source packages
- owned by
tsbindgen, not by the source-package repos
Four package families you should keep separate
- surface packages
- ambient world selection
- example:
@tsonic/js
- authored source packages
- TypeScript source compiled transitively
- examples:
@tsonic/nodejs,@tsonic/express
- generated CLR binding packages
- declaration + metadata packages from
tsbindgen - examples:
@tsonic/dotnet,@tsonic/aspnetcore
- declaration + metadata packages from
- workspace-local package references
- sibling projects referenced as
sourceordll
- sibling projects referenced as
Practical decision table
| You want | Use |
|---|---|
| JS globals and JS-style methods | surface: "@tsonic/js" |
| Node-style modules | @tsonic/nodejs package |
| Express-style routing | @tsonic/express package |
| CLR BCL APIs | @tsonic/dotnet |
| ASP.NET Core APIs | @tsonic/aspnetcore |
| Local workspace package compiled transitively | references.packages with mode: "source" |
| Local workspace package as assembly boundary | references.packages with mode: "dll" |