Edit source

Source profiles, surfaces, and capabilities

These concepts are independent.

Native source profile

With no selected surface, each target supplies its native source profile.

C# can use .NET virtual declarations:

import { Console } from "@tsonic/dotnet/System.js";
Console.WriteLine("native C# profile");

Rust can use compiler-backed Rust declarations:

import { HashMap } from "@tsonic/rust/std/collections.js";
const values = new HashMap<string, int32>();

JavaScript surface

Select the JavaScript source profile explicitly:

{
  "targets": [{
    "id": "rust",
    "surfaces": ["js"]
  }]
}

The same source contract can then be used for either target:

const parts = "/posts/42".split("/");
console.log(parts.length);

The source profile defines JavaScript-visible declarations and semantics. Each target still owns its carrier, operation mapping, runtime implementation, and precise rejection boundaries.

Native TypeScript string remains the default string domain. Exact JavaScript UTF-16 code-unit behavior is requested explicitly with JsString and jsstr:

import { jsstr } from "@tsonic/js/lang.js";

const exact = jsstr("😀");

Targets do not infer JsString from a string literal or from selecting the JS surface.

Capability packages

A capability adds importable APIs without selecting an ambient source profile. Node is the principal example:

import { statSync } from "node:fs";

export function isDirectory(path: string): boolean {
  return statSync(path).isDirectory();
}

Install @tsonic/csharp-nodejs or @tsonic/rust-nodejs for the selected target. The source continues to use normal node:* module specifiers. Installing the package does not make JavaScript globals available and does not add surfaces: ["js"] implicitly.

See the JavaScript profile reference and Node capability reference.