earendil-works/pi uses jiti 2.7 to load TypeScript extensions in three host shapes (source TS, bundled Node, Bun/Node-SEA binary). Some workarounds we carry that could be addressed upstream:
-
Lazy transform entry. jiti/static pulls Babel into startup. We patch it at bundle time into a shim that require("jiti") on first createJiti() call (build script). A jiti/lazy entry or a transform: () => import(...) option would avoid the bundler plugin.
-
Bare specifiers in alias. alias only accepts absolute paths, so we resolve host packages manually via import.meta.resolve (loader.ts). Resolving bare specifiers from parentURL would drop most of that.
-
Per-specifier native passthrough. tryNative is all-or-nothing and must be off in bundled/SEA mode. We need @earendil-works/* to resolve to the host's module instances so instanceof and module-level singletons work across the boundary; today that's virtualModules in bundled mode, alias otherwise, plus globalThis sharing on the host side. Something like nativeModules: ["@earendil-works/*"] (or virtualModules working uniformly) would unify it.
-
Cache invalidation API. For hot reload we set moduleCache: false and create a fresh createJiti() per load. A jiti.invalidate(path) would let us keep one instance.
-
Skipping transform for specific files. Emscripten glue breaks under Babel; we new Function it to bypass jiti. A skipTransform filter or per-import { transform: false } would be cleaner.
Happy to send PRs for any of these if you agree on direction.
earendil-works/pi uses jiti 2.7 to load TypeScript extensions in three host shapes (source TS, bundled Node, Bun/Node-SEA binary). Some workarounds we carry that could be addressed upstream:
Lazy transform entry.
jiti/staticpulls Babel into startup. We patch it at bundle time into a shim thatrequire("jiti")on firstcreateJiti()call (build script). Ajiti/lazyentry or atransform: () => import(...)option would avoid the bundler plugin.Bare specifiers in
alias.aliasonly accepts absolute paths, so we resolve host packages manually viaimport.meta.resolve(loader.ts). Resolving bare specifiers fromparentURLwould drop most of that.Per-specifier native passthrough.
tryNativeis all-or-nothing and must be off in bundled/SEA mode. We need@earendil-works/*to resolve to the host's module instances soinstanceofand module-level singletons work across the boundary; today that'svirtualModulesin bundled mode,aliasotherwise, plusglobalThissharing on the host side. Something likenativeModules: ["@earendil-works/*"](orvirtualModulesworking uniformly) would unify it.Cache invalidation API. For hot reload we set
moduleCache: falseand create a freshcreateJiti()per load. Ajiti.invalidate(path)would let us keep one instance.Skipping transform for specific files. Emscripten glue breaks under Babel; we
new Functionit to bypass jiti. AskipTransformfilter or per-import{ transform: false }would be cleaner.Happy to send PRs for any of these if you agree on direction.