@rybosome/tspice
v0.0.8
Published
`@rybosome/tspice` is the public facade for this repo.
Readme
@rybosome/tspice
Overview
@rybosome/tspice is the public facade for this repo.
The canonical way to construct SPICE clients is the spiceClients builder:
- configure caching + kernel preload
- pick an execution mode via a terminal method:
toSync()(in-process, sync-ish calls)toAsync()(in-process, async calls)toWebWorker()(async calls in a Web Worker)
CSPICE / NAIF disclosure
See docs/cspice-naif-disclosure.md for the canonical disclosure text, NAIF links, and pointers to notice files.
Depending on @rybosome/tspice will typically pull in backend packages that ship CSPICE-derived components; see each backend package NOTICE for details.
Installation
ESM-only (published package)
The published @rybosome/tspice package is ESM-only (type: "module"). It does not ship a CommonJS (require()) entrypoint.
If you're in a CommonJS project, use a dynamic import:
const { kernels, spiceClients } = await import("@rybosome/tspice");Usage (Quickstart)
Browser / WASM (async)
Note: NAIF-hosted kernel URLs are blocked by browser CORS. For browsers,
kernels.tspice()provides a small CORS-enabled community mirror for quickstart/testing. It is not recommended for production. It is self-funded and may be rate-limited, disabled, or trimmed if hosting costs become an issue. For production, self-host kernels (or proxy) and usekernels.naif({ ... })/kernels.custom(...).
import { kernels, spiceClients } from "@rybosome/tspice";
const kernelPack = kernels.tspice().pick(
"lsk/naif0012.tls",
"pck/pck00011.tpc",
"spk/planets/de432s.bsp",
);
const { spice, dispose } = await spiceClients
// Optional: memoize responses at the transport/RPC layer.
.caching({ maxEntries: 2_000 })
// Optional: preload kernels over fetch().
.withKernels(kernelPack)
.toAsync({ backend: "wasm" });
try {
const et = await spice.kit.utcToEt("2000 JAN 01 12:00:00");
const state = await spice.kit.getState({ target: "EARTH", observer: "SUN", at: et });
console.log(state.position, state.velocity);
} finally {
await dispose();
}Node / native addon (sync-ish)
import { spiceClients } from "@rybosome/tspice";
const { spice, dispose } = await spiceClients.toSync({ backend: "node" });
try {
console.log(spice.raw.tkvrsn("TOOLKIT"));
} finally {
await dispose();
}Kernel loading
Note:
KernelPacknow carries an optionalbaseUrl; setpack.baseUrl(instead of passing a{ baseUrl }options object tospiceClients.withKernels(...)).
Public kernel packs
Use kernels.tspice() for a small, typed, zero-config kernel catalog rooted at tspice's hosted mirror (https://tspice-viewer.ryboso.me/).
- Intended for quickstart/testing.
- Not recommended for production.
- Returns fixed absolute URLs and does not accept configuration.
Use kernels.naif() to target the full NAIF generic_kernels inventory.
- IDs are leaf paths like
"lsk/naif0012.tls". - By default,
originishttps://naif.jpl.nasa.gov/pub/naif/generic_kernels/. - By default,
pathBaseis empty (""), sokernel.pathmatches the picked leaf id. - Optional overrides are available via
kernels.naif({ origin?, pathBase?, baseUrl? }). baseUrl(when set) becomespack.baseUrland is used at load time to resolve relative kernel URLs.
Note:
pick(...)preserves caller-provided ordering (no sorting / “safe load order” magic).
import { kernels, type NaifKernelId } from "@rybosome/tspice";
const NAIF_KERNEL_IDS: NaifKernelId[] = [
"lsk/naif0012.tls",
"pck/pck00011.tpc",
"spk/planets/de432s.bsp",
];
const pack = kernels.naif().pick(NAIF_KERNEL_IDS);
// Self-hosting / subpath deployment example:
const selfHostedPack = kernels
.naif({
origin: "kernels/naif/",
baseUrl: import.meta.env.BASE_URL,
pathBase: "naif/",
})
.pick(NAIF_KERNEL_IDS);Custom kernels
Use kernels.custom({ origin, pathBase, baseUrl? }) to build a KernelPack for arbitrary kernels.
- Passing string ids maps to
{ url: origin + id, path: pathBase + id }. - You can also pass explicit
{ url, path? }entries as an escape hatch. Ifpathis omitted, it defaults to a stable hashed path like/kernels/<hash>-<basename(url)>.
import { kernels, spiceClients } from "@rybosome/tspice";
const pack = kernels
.custom({
origin: "kernels/custom/",
baseUrl: import.meta.env.BASE_URL,
pathBase: "custom/",
})
.pick(
"my-kernel.bsp",
// Escape hatch:
{ url: "https://example.com/weird/location/attitude.ck" },
);
const { spice } = await spiceClients
.withKernels(pack)
.toAsync({ backend: "wasm" });Batching semantics
Kernel load order matches call order:
withKernels(pack)appends 1 batchwithKernels(packs)appends multiple batches
Backend notes
- Node backend (
backend: "node"): implemented by a native addon. Requires a compatible native binding to be present. - WASM backend (
backend: "wasm"): implemented with a prebuilt.wasm. Seetspice-backend-wasm.
Web Worker notes
spiceClients.toWebWorker() uses an inline blob worker by default (the worker
source is generated at build time and embedded into the JS bundle). This means
consumers do not need to separately bundle/host a worker entry JS file.
The worker still uses the WASM backend and must be able to fetch the .wasm
binary. Most bundlers handle this automatically.
If your bundler or deployment setup relocates the .wasm asset, pass an explicit
wasmUrl to toWebWorker():
import { spiceClients } from "@rybosome/tspice";
const { spice, dispose } = await spiceClients.toWebWorker({
wasmUrl: "/assets/tspice_backend_wasm.wasm",
});
try {
console.log(await spice.kit.toolkitVersion());
} finally {
await dispose();
}Development
pnpm --filter @rybosome/tspice run build
pnpm --filter @rybosome/tspice run typecheck
pnpm --filter @rybosome/tspice run testTroubleshooting / FAQ
“Native addon tspice_backend_node.node not found” / “Failed to load tspice native backend ...”
If you selected the Node/native backend (backend: "node") and you’re running from the workspace and haven’t built the addon yet:
pnpm --filter tspice-backend-node run build:nativeFor more details (including TSPICE_BACKEND_NODE_BINDING_PATH), see tspice-backend-node.
Versioning
This package is under active development and the API shape is expected to churn.
