npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@git.zone/tssea

v1.2.1

Published

Builds Node.js single executable applications for linux, macOS and Windows from one host: pinned and verified Node.js binaries, per-target native addons, embedded asset trees, smoke runs, size guards and third-party notices.

Readme

@git.zone/tssea

Builds Node.js single executable applications (SEAs) for linux, macOS and Windows from one Linux or macOS host. It is the successor of @git.zone/tsdeno.

From a bundle that @git.zone/tsbundle wrote for Node.js, tssea:

  1. Downloads the official Node.js executable of every target and checks it against a SHA-256 that tssea pins for the release.
  2. Selects the target's prebuilt native addons and embeds them, together with your asset trees and sidecar executables, through the @push.rocks/smartsea asset layout.
  3. Checks that every embedded Linux addon and sidecar loads wherever the pinned Node.js loads (see Linux compatibility), then strips Linux executables before the injection.
  4. Runs node --build-sea with the pinned Node.js of the host. The build uses an ESM main, execArgvExtension: "none", and code cache and snapshot off on every target.
  5. Signs macOS executables ad hoc and removes the stale Authenticode certificate table of Windows executables.
  6. Checks the result: a size floor and budget, a smoke run, and optionally a byte-identical rebuild. It writes third-party notices next to every executable.

Supported: builds run on linux-x64, linux-arm64, darwin-x64 and darwin-arm64 hosts with Node.js 22 or later. The build itself always uses the pinned Node.js release, never the Node.js that runs tssea. Deno is not supported and not tested.

Issue Reporting and Security

For reporting bugs, issues, or security vulnerabilities, please visit community.foss.global/. This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a code.foss.global/ account to submit Pull Requests directly.

Install

pnpm add --save-dev @git.zone/tssea @git.zone/tsbundle
pnpm add @push.rocks/smartsea   # the in-executable runtime your bundle imports

Quick start

.smartconfig.json:

{
  "@git.zone/tsbundle": {
    "bundles": [
      { "from": "./ts/cli.ts", "to": "./dist_node/main.mjs", "bundler": "esbuild", "platform": "node", "sea": true, "production": true }
    ]
  },
  "@git.zone/tssea": {
    "nodeVersion": "26.11.1",
    "bundle": "./dist_node/main.mjs",
    "outDir": "./dist/binaries",
    "targets": [
      { "target": "linux-x64", "name": "myapp-linux-x64" },
      { "target": "linux-arm64", "name": "myapp-linux-arm64" },
      { "target": "darwin-arm64", "name": "myapp-macos-arm64" },
      { "target": "win32-x64", "name": "myapp-windows-x64.exe" }
    ],
    "execArgv": ["--use-system-ca"],
    "smoke": { "args": ["--version"], "expectStdoutPattern": "^myapp \\d+\\.\\d+\\.\\d+$", "cleanEnv": true }
  }
}
tsbundle && tssea build

The sea: true bundle mode needs tsbundle 3.4 or later. It rewrites native addon loads to smartsea's loader and writes <bundle>.smartsea.json. tssea refuses a bundle without that file (REFERENCES_MISSING) or one whose file describes other bytes (REFERENCES_STALE). <bundle>.smartsea.json is a build intermediate that holds absolute paths of the build host; keep it out of a package's files.

Configuration

"@git.zone/tssea" in .smartconfig.json. Unknown keys are refused (CONFIG_INVALID).

| Key | Type | Required | Meaning | | --- | --- | --- | --- | | nodeVersion | string | yes | Exact Node.js release, x.y.z, 26 or later; this tssea must carry its pin (see Node.js releases) | | bundle | string | yes | The bundle: one ESM file from tsbundle (platform: "node", sea: true) | | outDir | string | yes | Directory of the executables and their notices | | targets | { target, name }[] | yes | Targets to build. name is the output file name, used exactly as given; a win32-x64 name must end in .exe | | appName | string | no | Names the runtime cache directory of the application. The default comes from package.json: @serve.zone/dcrouter becomes serve.zone-dcrouter | | execArgv | string[] | no | Node.js options for every start of the executable, e.g. --use-system-ca, --max-old-space-size=512. NODE_OPTIONS is ignored at run time | | trees | Record<string, { from, path?, targets? }> | no | Embedded asset trees (see below) | | sidecars | Record<string, { tree, path }> | no | Embedded executables, keyed by the name the application looks up | | hostLibraries | string[] | no | Sonames every Linux target host provides beyond glibc and Node.js's own libraries, e.g. ["libssl.so.3"] (see Linux compatibility) | | minSize, maxSize | size, or { <target>: size } | no | Floor and budget, e.g. "110MiB" (SIZE_BELOW_FLOOR, SIZE_BUDGET_EXCEEDED) | | smoke | object | no | Run the executable once after building it (see below) | | thirdPartyNotices | { enabled?, supplements?, include? } | no | Notices; on by default (see below) |

Targets

| Target | Node.js download | Notes | | --- | --- | --- | | linux-x64, linux-arm64 | node-v<version>-linux-<arch>.tar.gz | glibc ≥ 2.28, libstdc++ and libatomic on the host that runs it; Alpine/musl is not supported. Native addons are selected for glibc | | darwin-x64, darwin-arm64 | node-v<version>-darwin-<arch>.tar.gz | Signed ad hoc by tssea | | win32-x64 | win-x64/node.exe | Built and checked structurally, not smoke-tested on Windows |

Trees and sidecars

"trees": {
  "webroot": { "from": "./dist_serve" },
  "bin": { "from": { "linux-x64": "./dist_rust/proxy_linux_amd64", "linux-arm64": "./dist_rust/proxy_linux_arm64" }, "path": "proxy", "targets": ["linux-x64", "linux-arm64"] }
},
"sidecars": { "proxy": { "tree": "bin", "path": "proxy" } }
  • from is a directory (every file below it, at its path below the directory) or a single file (at path, default its file name). Give one source for all targets, or one per target (an object keyed by target, covering every target the tree is embedded for).
  • targets limits a tree, and the sidecars in it, to some targets.
  • Files: symbolic links are refused (TREE_SYMLINK). A file's mode comes from its executable bit, and sidecars are always embedded executable. The names addons and addons-* are tssea's.
  • Sidecar names: a sidecar's key is the name the application asks for. smartrust looks embedded binaries up with getSidecarPath(binaryName), so name a smartrust sidecar after its binaryName.
  • Native sidecars: a sidecar that is an ELF, Mach-O or PE file must fit the target like an addon (SIDECAR_TARGET_MISMATCH); scripts are not checked. On Linux targets it also passes the Linux compatibility checks.
  • Notices: every sidecar ships its notices next to its binary, see Third-party notices.
  • At run time: the application reads a tree with smartsea: extractTree(name), readTreeFile(name, path) or getSidecarPath(name).

Native addons

The bundle's references name every addon load by a target-independent id (see smartsea's addon ids). For each target, tssea resolves each reference to one .node file:

  • node-gyp-build: the prebuild node-gyp-build itself would load on the target. tssea uses node-gyp-build 4.8.4's own parsers (prebuilds/<platform>-<arch>[+…], the fewest architectures first, file name tags) and evaluates them for the target: runtime node, the pinned release's ABI and libuv, armv8 on arm64, and glibc. build/Release and build/Debug are host builds and never used. PREBUILDS_ONLY and <NAME>_PREBUILD affect node-gyp-build at run time only.
  • bindings: the locations the bindings package tries, evaluated for the target. A file in a target-independent build directory (build/Release, …) must still fit the target's header check, and its ABI must match the pinned Node.js (an N-API addon, or one built with the same release).
  • file: the .node file in the owner package.
  • package: the specifier resolved from the owner package with Node.js's resolution, to a .node file. napi-rs per-platform packages, which need a different candidate per target, are not supported yet.

Every selected file's object header must fit the target: ELF e_machine and a Linux OS/ABI, Mach-O CPU type (including universal binaries), or PE machine. A reference without a file for a configured target fails the build with ADDON_PREBUILD_MISSING, ADDON_FILE_MISSING or ADDON_TARGET_MISMATCH, which name what was searched; nothing is skipped. For example, argon2 0.45.1 ships no darwin-x64 prebuild (0.41.1 does), so a darwin-x64 build of an argon2 0.45.1 application fails. Remove the target, or use a package version that ships a prebuild for it. Linux addons also pass the Linux compatibility checks.

Addons are embedded in trees that mirror node_modules/<package>/…. Two versions of one package go into separate trees. Mach-O addons and sidecars without a code signature are signed ad hoc for darwin targets, and the build result lists them in signedFiles.

Linux compatibility

The official Linux builds of Node.js run on glibc 2.28 and later, so a SEA does too, unless an embedded file needs more. Before the injection, every embedded addon and native sidecar of a Linux target, and every library its tree carries for it, must load wherever the target's pinned Node.js loads. tssea reads the files' dynamic linking data itself (program headers, so stripped files work too) and compares it with the pinned Node.js executable of the same target:

  • C library: a file that asks for another program loader than Node.js's (/lib64/ld-linux-x86-64.so.2, /lib/ld-linux-aarch64.so.1) or needs musl's libc is ELF_LIBC_UNSUPPORTED: a dynamically linked musl file does not load on a glibc host. Static files pass, musl ones included (for example Rust's x86_64-unknown-linux-musl, which links a static PIE).

  • Libraries: every DT_NEEDED soname must be one of:

    • a library Node.js itself needs (libstdc++.so.6, libgcc_s.so.1, libatomic.so.1, …);
    • a glibc library (libc, libm, libpthread, libdl, librt, libresolv, libutil, libanl, libBrokenLocale, the loader, and libmvec on x64);
    • a library the same tree carries, found through the file's DT_RUNPATH (or DT_RPATH) $ORIGIN entries, as the loader finds it once the tree is extracted. Carried libraries are checked the same way;
    • a soname listed in hostLibraries: a requirement on the target hosts. Each Linux target's build result lists the ones its files need (hostLibraries), and the build logs them.

    Anything else is ELF_LIBRARY_UNAVAILABLE, naming the soname, the file and the target.

  • Symbol versions: the floor is what the target's Node.js needs, read from its version requirements: in 26.11.1, GLIBC_2.28, GLIBCXX_3.4.21, CXXABI_1.3.11, GCC_4.2.0 and LIBATOMIC_1.0. In each of these namespaces, a file needing a higher version, or a non-numeric name Node.js does not need itself (such as GLIBC_PRIVATE or GLIBC_ABI_DT_RELR), is ELF_VERSION_FLOOR_EXCEEDED. Other namespaces, and versions needed from a hostLibraries library, are not compared.

Binaries linked dynamically on a current distribution fail the floor: anything linked against glibc 2.34 or later needs GLIBC_2.34, and so do the linux prebuilds of argon2 0.43.1, 0.44.0 and 0.45.1 (0.41.1's need GLIBC_2.25). Build them on an older system, link them statically, or use a version whose prebuilds stay within the floor.

An addon tree holds the selected .node files only. An addon that loads libraries from a sibling package, such as sharp 0.35's libvips-cpp.so from @img/sharp-libvips-linux-x64 through $ORIGIN/../../sharp-libvips-linux-x64/lib, therefore fails with ELF_LIBRARY_UNAVAILABLE: tssea does not embed such companion packages yet.

Only addons and sidecars are checked, plus the libraries they carry. Other tree files are data: a tree may carry executables for other machines, so tssea cannot know they run on the target.

Smoke check

"smoke": { "args": ["--version"], "expectExitCode": 0, "expectStdoutPattern": "^myapp ", "timeoutMs": 30000, "cleanEnv": true, "env": { "QEMU_LD_PREFIX": "/usr/aarch64-linux-gnu" }, "emulate": true }
  • Where it runs: the executable of the host's target runs once, without a shell, in the project directory. Other targets are skipped with a notice.
  • emulate: true: also runs the other Linux architecture (linux-arm64 on a linux-x64 host, and the reverse) through the kernel's binfmt_misc emulation (qemu-user-static).
    • The probe: before the first emulated run of a target, tssea writes a 132-byte static executable for it next to the executable (.tssea-exec-probe-<target>-<pid>: same mount, same noexec) and runs it once; it only exits with code 73. The probe is removed again and runs once per target and build. tssea never reads /proc/sys/fs/binfmt_misc, because a handler listed there may not run in the build's mount namespace, and a container may run foreign executables while it lists no handler.
    • Containers: a handler registered on the host with flag F (the interpreter is opened at registration) runs foreign executables in every container, without mounting anything into it. Without F, the interpreter path must exist inside the container.
    • Failure: when the kernel does not run the probe, the build fails with SMOKE_EMULATION_UNAVAILABLE, says what happened and what to change. It is never skipped silently.
      • The probe started but did not exit 73, e.g. probe <path> exited 127 (stderr "…"): no handler ran it (Node.js then runs the file with /bin/sh). Register a binfmt_misc handler with flag F on the host (qemu-user-static), or turn smoke.emulate off.
      • The probe could not start with EACCES or EPERM: the kernel refuses to execute files in that directory (a noexec mount or a security policy), and the error names it. Build with outDir on a filesystem that allows execution, or turn smoke.emulate off.
    • Libraries: qemu-user needs the target's libraries: on Debian and Ubuntu, install the cross packages and set QEMU_LD_PREFIX in env. A missing one fails the smoke run itself (SMOKE_FAILED).
  • Environment: cleanEnv: true runs with env only. Recommended in CI, because a failure quotes the end of stdout and stderr.
  • Failure: any mismatch is SMOKE_FAILED. On POSIX the executable runs in its own process group, and whatever is left in that group is killed when the check ends.

Third-party notices

On by default. Every executable gets <name>.third-party-notices.txt and .json, covering:

  • The Node.js runtime: its LICENSE, and the pinned source tarball (node-v<version>.tar.gz with its SHA-256) as the corresponding source.
  • The bundle: its npm packages, from tsbundle's <bundle>.third-party-notices.json. tsbundle writes it for production bundles; without it, the build fails with NOTICES_BUNDLE_MISSING.
  • Embedded native addons: the owner package of every addon, plus every package its binding.gyp (with its relative includes) names through require('<name>') or require.resolve('<name>') in a <!(…) or <!@(…) command expansion, such as node-addon-api for its headers, applied recursively to those packages; package.json dependencies never count, and a name that does not resolve is NOTICES_PACKAGE_UNAVAILABLE. Their license and notice files are collected at every depth of each package (node_modules excluded, symbolic links to directories not followed), e.g. argon2's argon2/LICENSE for the reference C sources. A symbolic link to a license file is read, even when its target lies outside the package.
  • Sidecars: <binary>.third-party-notices.json next to each sidecar binary the tree selected for the target (the file from names, or the file below the from directory), in tsbundle's format. @git.zone/tsrust 4.6.0 and later writes it for the binaries it builds; a hand-made sidecar ships its own, { "generator": "<tool>", "packages": [] } for first-party code. Packages that are not npm packages are named by namespace, such as cargo:<crate>, native:<lib>, rust:std or runtime:musl. A missing file is NOTICES_SIDECAR_MISSING, an invalid one NOTICES_SIDECAR_INVALID. In a directory tree, the notices file is embedded with the binary.
  • include: further notices files in tsbundle's format, e.g. those of a web bundle embedded as a tree.

Packages that several sources list must agree (NOTICES_CONFLICT).

A package without license text needs a supplement (supplements, same format as tsbundle's), or the build fails. Turn notices off with "thirdPartyNotices": { "enabled": false }.

Node.js releases and the cache

  • Pins: tssea carries the SHA-256 of every download it uses for each supported Node.js release (ts/tssea.nodereleases.ts; 26.11.1 for now). Every download is compared with it (NODE_CHECKSUM_MISMATCH), and SHASUMS256.txt is never fetched at build time. A release this tssea does not carry fails with NODE_VERSION_UNPINNED: upgrade @git.zone/tssea.
  • Cache: downloads are cached as code assets in $TSSEA_CACHE_DIR, else $XDG_CACHE_HOME/tssea, else ~/.cache/tssea (macOS: ~/Library/Caches/tssea).
  • Integrity and concurrency: each entry records the SHA-256 of its files and is checked on every use. A damaged entry is fetched again. Concurrent first uses are safe without locks: each process stages its copy, and one rename publishes it.
  • The building Node.js: the build runs the pinned Node.js of the host, because the Node.js that builds a SEA must be the release it injects into. Code cache and snapshot are off, since they cannot cross platforms.

Reproducible builds

The same bundle, assets and Node.js release produce the same bytes. tssea passes the main by its file name relative to the build directory, because Node.js embeds the main's path, and it sorts every embedded list. tssea build --reproducible-check (API: reproducibleCheck: true) builds every target a second time in another directory and fails with NOT_REPRODUCIBLE unless both builds are byte-identical. Builds run one target after another; each --build-sea takes about 630 MB of memory.

CLI

tssea build [--target <target>]... [--no-smoke] [--reproducible-check] [--keep-work]
tssea fetch [--target <target>]...
tssea help | --help | -h
tssea --version | -v
  • build: builds every configured target, or only the --target ones.
    • It writes each executable through a work directory (<outDir>/.tssea-work-*, removed afterwards unless --keep-work). The executable is renamed into place only once all its checks passed.
    • The old executable and notices of a target are removed when its build starts.
  • fetch: downloads and verifies the Node.js executables of the targets and of the host into the cache, e.g. to warm a CI cache.
  • Exit codes:
    • 0: success.
    • 1: a build failure, printed as tssea: <message> [CODE].
    • 2: a usage error, followed by the help text.

API

import { TsSea } from '@git.zone/tssea';

const result = await new TsSea(process.cwd(), { reproducibleCheck: true }).build();
for (const target of result.targets) {
  console.log(target.target, target.executablePath, target.size, target.sha256, target.smoke);
}

ITsseaOptions: config (instead of .smartconfig.json), targets, smoke, reproducibleCheck, keepWork, cacheRoot, nodeDistributionUrl, log. TsSea.fetch() fills the cache. Every deliberate failure is a TsseaError with a stable code. FILE_UNREADABLE means a file exists but cannot be read (for example EACCES); missing files keep their specific codes, such as BUNDLE_MISSING. Layout errors keep their SmartSeaError (e.g. LAYOUT_INCOMPATIBLE when the bundle's smartsea major differs from tssea's).

Reading the configuration from other tools (@git.zone/tssea/config)

Tools that render files from a project's targets, such as installers, an npm wrapper or a release workflow, read the configuration through tssea itself, from the project's own install, so the tssea version that builds the project is the only interpreter of its configuration. The subpath loads node built-ins and @push.rocks/smartsea/layout only; tsbundle, smartarchive, smartrequest, smartconfig and node-gyp-build stay unloaded.

import { createRequire } from 'node:module';
import * as path from 'node:path';
import { pathToFileURL } from 'node:url';

// Resolve tssea from the project, not from the tool.
const entry = createRequire(path.join(projectDir, 'package.json')).resolve('@git.zone/tssea/config');
const tsseaConfig = await import(pathToFileURL(entry).href);

const { outDir, outputs } = tsseaConfig.resolveOutputs(smartconfigJson[tsseaConfig.tsseaConfigKey], projectDir);
for (const output of outputs) {
  console.log(output.target, output.platform, output.arch, path.join(outDir, output.name), output.noticeFiles);
}
export const tsseaConfigKey = '@git.zone/tssea';
export type TTsseaTarget = 'linux-x64' | 'linux-arm64' | 'darwin-x64' | 'darwin-arm64' | 'win32-x64';
export interface ITsseaOutput {
  target: TTsseaTarget;
  platform: 'linux' | 'darwin' | 'win32';
  arch: 'x64' | 'arm64';
  name: string;          // the executable file name in outDir, which is also the release asset name
  noticeFiles: string[]; // the notices file names next to it in outDir; [] when notices are off
}
export interface ITsseaOutputs { outDir: string; outputs: ITsseaOutput[] }
export function resolveOutputs(rawConfigArg: unknown, projectDirectoryArg: string): ITsseaOutputs;
export { TsseaError, type TTsseaErrorCode };
  • resolveOutputs runs the complete configuration validation of tssea build and returns what the build writes: outDir absolute and resolved against the project directory as the build resolves it, outputs in the order of targets. It is synchronous and reads nothing but the project's package.json, and only for the default appName. It checks no file the configuration names; a missing bundle or tree source fails at build time.
  • Errors: it throws a TsseaError (name "TsseaError", a string code) and never returns a partial result:
    • CONFIG_MISSING: rawConfigArg is undefined (the project has no "@git.zone/tssea" block).
    • CONFIG_INVALID: a bad value; the message starts with its key path, such as "@git.zone/tssea".targets[1].name.
    • NODE_VERSION_UNSUPPORTED: nodeVersion is not an exact release of Node.js 26 or later.
    • FILE_UNREADABLE: the default appName needs package.json, which exists but cannot be read or is not JSON. Without a package.json, a missing appName is CONFIG_INVALID.

Reading the cache from other tools (@git.zone/tssea/cache)

The layout of tssea's Node.js download cache is public and stable within a major version. @git.zone/tssea/cache exports it as pure code that imports nothing, and tssea writes and checks its entries with the same definitions, so disk-usage reports and cleanup tools classify the cache without a copy of its rules:

<cache>/node/v<version>/<target>/entry.json                 the entry record, written last
<cache>/node/v<version>/<target>/node | node.exe | LICENSE  the executable (and Node.js's LICENSE for tar.gz targets)
<cache>/node/v<version>/.tmp-<target>-<pid>-<random>/       staging of an entry in progress; its download is .download
<cache>/node/v<version>/.trash-<random>/                    a damaged entry being removed
export const nodeCacheDirName = 'node';
export function isVersionDirName(name: string): boolean; // v<major>.<minor>.<patch>
export const nodeEntryFileName = 'entry.json';
export const nodeEntryFormat = 'tssea-node-entry';
export const cacheStagingDirPrefix = '.tmp-';
export const cacheTrashDirPrefix = '.trash-';
export const staleScratchMs = 3_600_000; // 1 h
export function isNodeEntry(text: string): boolean;
export type TCacheEntryState = 'entry' | 'scratch' | 'stale-scratch';
export interface ICacheEntryFacts { name: string; mtimeMs: number; entryText?: string }
export interface ICacheEntryClassifyOptions { now: number }
export function classifyCacheEntry(facts: ICacheEntryFacts, options: ICacheEntryClassifyOptions): TCacheEntryState | undefined;
  • Finding the cache: by its structure. A nodeCacheDirName (node) directory whose children pass isVersionDirName holds the releases; pass every child directory of a version directory to classifyCacheEntry (files and symbolic links are never entries, and the classifier cannot tell them from directories). There is no marker file, and tools must not derive the location from the environment: it depends on the building process's TSSEA_CACHE_DIR and XDG_CACHE_HOME.
  • classifyCacheEntry classifies one directory of a node/v<version>/ level. entryText is the text of its entry.json (omitted when absent). A .tmp- or .trash- directory is scratch while now - mtimeMs < staleScratchMs and stale-scratch from then on, whatever it holds. Any other directory is an entry if its entry.json passes isNodeEntry, and undefined (not tssea's) otherwise. Files and symlinks are never entries.
  • mtimeMs is the newest lstat mtime of the directory itself and its direct children. Writing a file updates that file's mtime, not its directory's, and a stage's in-flight download (.download) and the files it unpacks are direct children. A download fails after 60 seconds without data, so a live stage's newest mtime is never more than about a minute old, and it never looks an hour idle; the directory's own mtime alone stays at its creation time for the whole download.
  • isNodeEntry identifies a record by its format. tssea itself also checks every file's size and SHA-256 against the record before it uses an entry.
  • Who deletes: tssea removes only what it is working on: its own stage once the entry is published or failed, and a damaged entry it renamed into the trash. It never removes stages or trash that other, killed, processes left behind; that is left to tools that classify the cache with this module, such as @git.zone/tsdisk.

Platform status

  • linux-x64 and linux-arm64: built and run in tssea's own tests (arm64 under qemu-user emulation).
  • darwin-arm64 and darwin-x64: built and signed in the tests. The signature is verified structurally, page hash by page hash; runs on a Mac are part of the release gate.
  • win32-x64: built in the tests; the certificate table is removed and the PE checksum is valid. Not smoke-tested on Windows.

Migrating from tsdeno

tssea builds from a bundle instead of compiling TypeScript itself:

  1. Add a tsbundle bundle with "platform": "node" and "sea": true.
  2. Move compileTargets to targets:

| tsdeno | tssea | | --- | --- | | compileTargets[].target x86_64-unknown-linux-gnu | targets[].target linux-x64 | | aarch64-unknown-linux-gnu | linux-arm64 | | x86_64-apple-darwin | darwin-x64 | | aarch64-apple-darwin | darwin-arm64 | | x86_64-pc-windows-msvc | win32-x64 | | compileTargets[].name | targets[].name, the same file name. Deno appended .exe for Windows; tssea does not, so write it | | compileTargets[].outDir | outDir, one for all targets | | compileTargets[].entryPoint | bundle, the tsbundle output | | denoVersion | nodeVersion (exact) | | v8Flags | execArgv | | minSize, maxSize, smoke | same names; sizes may be per target. smoke.emulate/env are new | | thirdPartyNotices.{enabled, supplements} | same; now on by default | | compileTargets[].thirdPartyNoticesInclude | thirdPartyNotices.include | | denoExecutable | dropped: tssea downloads and verifies the pinned Node.js | | dependencyAge | dropped: nothing is resolved at build time | | permissions, noCheck | dropped: Node.js has no Deno permissions; type checking belongs to tsbuild | | selfExtracting, keepStaging | dropped: smartsea extracts trees lazily into its cache and prunes old generations | | excludeUnusedNpm, include, pruneNatives, pruneExclude, pruneKeep | dropped: the bundle holds only reachable code, and only the target's addon files are embedded. Extra files go into trees | | DENO_TLS_CA_STORE=system | "execArgv": ["--use-system-ca"] |

Linux executables now need libatomic on the host that runs them.

Third-party code

The ad-hoc Mach-O signer is ported from Go's cmd/internal/codesign (BSD-3-Clause); see third-party-notices.md.

License and Legal Information

This repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the license.md file within this repository.

Please note: The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.

Trademarks

This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.

Company Information

Task Venture Capital GmbH Registered at District court Bremen HRB 35230 HB, Germany

For any legal inquiries or if you require further information, please contact us via email at [email protected].

By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.