Skip to content

feat(standalone): bundle a pinned compiler into the single-executable#11299

Draft
timotheeguerin wants to merge 1 commit into
tsp-init-template-sourcefrom
standalone-bundle-compiler
Draft

feat(standalone): bundle a pinned compiler into the single-executable#11299
timotheeguerin wants to merge 1 commit into
tsp-init-template-sourcefrom
standalone-bundle-compiler

Conversation

@timotheeguerin

Copy link
Copy Markdown
Member

Summary

The standalone tsp executable now embeds a pinned @typespec/compiler — its code, standard library, and tsp init templates — as single-executable assets and serves them from memory, instead of installing the latest compiler with yarn at runtime.

As a result, commands like tsp init and tsp compile work fully offline: no package manager, no network access, and nothing written to disk.

Compiler resolution precedence

  1. --server <path> / TYPESPEC_COMPILER_PATH
  2. A project-local @typespec/compiler resolvable from the cwd (always wins over the bundled one)
  3. Otherwise, the pinned compiler bundled into the executable

How it works

  • Built in one step with node --build-sea (Node.js 25.5+); the CLI pipeline now uses Node 26.x. End users need no Node.js installed.
  • The compiler is bundled as a separate ESM asset (it uses top-level await, which a CommonJS single-executable main can't) and loaded from memory via module.registerHooks.
  • New internal, bundler-only APIs behind @typespec/compiler/internals:
    • createBundledCompilerHost(base, assets) returns a CompilerHost that serves the compiler's own files from an in-memory asset map, delegating everything else to the base host (no mutation of the shared NodeHost).
    • setCliBaseHost(host) injects that host as the base used by every CLI action.
  • The yarn/postject build dependencies are removed.

Temporary workarounds (each tagged WORKAROUND(...) in code, tracked upstream)

  • A Node single-executable main can only import builtin modules (nodejs/node#62726), so the ESM compiler bundle is reached through a tiny CommonJS bridge via createRequire(process.execPath).
  • js-yaml's optional require("esprima") warns under SEA (nodejs/node#50547); it is stripped at bundle time.

Validation

  • pnpm build + type-checks (compiler, standalone)
  • Standalone SEA build + check.ts: command runs, bundled offline compile, and local-compiler precedence
  • New createBundledCompilerHost unit tests + existing internals guard / init template tests

@microsoft-github-policy-service microsoft-github-policy-service Bot added compiler:core Issues for @typespec/compiler eng labels Jul 17, 2026
@pkg-pr-new

pkg-pr-new Bot commented Jul 17, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@typespec/bundler@11299
npm i https://pkg.pr.new/@typespec/compiler@11299

commit: f63a8d8

@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

❌ There is undocummented changes. Run chronus add to add a changeset or click here.

The following packages have changes but are not documented.

  • @typespec/bundler

The following packages have already been documented:

  • @typespec/compiler
Show changes

@typespec/compiler - internal ✏️

Refactor tsp init template loading around a TemplateSource abstraction (filesystem, in-memory, and remote sources) instead of resolving templates through CompilerHost.getExecutionRoot().

@typespec/compiler - internal ✏️

Add internal runTypeSpecCli API (behind @typespec/compiler/internals/standalone) so a self-contained CLI can run the compiler CLI with a custom CompilerHost that serves the compiler's init templates from an in-memory asset map, running tsp init offline without a package manager, network access, or writing files to disk.

@azure-sdk-automation

azure-sdk-automation Bot commented Jul 17, 2026

Copy link
Copy Markdown

You can try these changes here

🛝 Playground 🌐 Website 🛝 VSCode Extension

@microsoft-github-policy-service microsoft-github-policy-service Bot added the ide Issues for VS, VSCode, Monaco, etc. label Jul 18, 2026
@timotheeguerin
timotheeguerin changed the base branch from main to tsp-init-template-source July 18, 2026 19:02
… CLI

Build the standalone `tsp` executable with Node's `node --build-sea`
(Node >= 25.5) instead of postject, dropping the `@yarnpkg/*` and
`postject` bundling dependencies. The pinned compiler is bundled as
assets and loaded through a createRequire bridge / module-loader
workaround for embedder-only-builtins.

Adds an internal `runTypeSpecCli` API (`@typespec/compiler/internals/standalone`)
that runs the compiler CLI with an injected `internalTemplateSource`, so the
standalone CLI serves the bundled `init` templates from an in-memory asset
map — running `tsp init` offline without a package manager, network access,
or writing files to disk. `tsp compile` is disallowed without a local project.

Also wires up macOS/Windows code-signing for the SEA in the CLI pipelines.
@timotheeguerin
timotheeguerin force-pushed the standalone-bundle-compiler branch from f63a8d8 to 01c7a7f Compare July 18, 2026 21:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

compiler:core Issues for @typespec/compiler eng ide Issues for VS, VSCode, Monaco, etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant