feat(tui): run on Node 26 (one runtime), finalize copy UX, rename to ui-opentui
Ports the engine off the second JS runtime onto Node 26.3 (node:ffi) so the repo ships a single JavaScript runtime: child_process for the gateway, vitest for tests, an esbuild + Solid build step. Mouse selection copies the rendered text you highlight, and the clipboard path is crash-proofed (a broken copy pipe no longer quits the UI). Renames the engine dir ui-tui-opentui-v2/ -> ui-opentui/ and updates the launcher/installer/Docker references.
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Build the OpenTUI v2 Solid app for Node 26 (no Bun).
|
||||
*
|
||||
* Mirrors OpenTUI's own Node recipe (`~/github/opentui/.../run-node26.mjs` +
|
||||
* `packages/solid/scripts/solid-transform.ts`): apply babel-preset-solid in
|
||||
* `generate:"universal"` mode with `moduleName:"@opentui/solid"` to every app
|
||||
* .tsx/.jsx, and force solid-js to its CLIENT/universal build (the package's
|
||||
* `node` export condition points at the SSR `server.js`, which lacks the
|
||||
* reactive primitives the universal renderer needs).
|
||||
*
|
||||
* `@opentui/core` stays EXTERNAL: it resolves its per-arch native `libopentui.so`
|
||||
* (and the tree-sitter worker) from its own package dir via `import.meta.url`;
|
||||
* bundling it would break those paths.
|
||||
*
|
||||
* Run with the Node that will launch the app:
|
||||
* node scripts/build.mjs # → dist/main.js (app entry)
|
||||
* node scripts/build.mjs <entry.tsx> <outdir> # build an arbitrary entry (smokes/spikes)
|
||||
* Launch:
|
||||
* node --experimental-ffi --no-warnings dist/main.js
|
||||
*/
|
||||
import { readFile } from 'node:fs/promises'
|
||||
import { createRequire } from 'node:module'
|
||||
import { dirname, resolve } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
import { transformAsync } from '@babel/core'
|
||||
import tsPreset from '@babel/preset-typescript'
|
||||
import solidPreset from 'babel-preset-solid'
|
||||
import * as esbuild from 'esbuild'
|
||||
|
||||
const require = createRequire(import.meta.url)
|
||||
const root = resolve(dirname(fileURLToPath(import.meta.url)), '..')
|
||||
|
||||
/** esbuild plugin that reproduces @opentui/solid's transform + solid-js resolution. */
|
||||
const opentuiSolid = {
|
||||
name: 'opentui-solid',
|
||||
setup(build) {
|
||||
// App JSX (.tsx/.jsx, never node_modules) → babel-preset-solid (universal).
|
||||
build.onLoad({ filter: /\.[cm]?[jt]sx$/ }, async args => {
|
||||
if (args.path.includes('/node_modules/')) return null
|
||||
const code = await readFile(args.path, 'utf8')
|
||||
const out = await transformAsync(code, {
|
||||
filename: args.path,
|
||||
configFile: false,
|
||||
babelrc: false,
|
||||
presets: [[solidPreset, { moduleName: '@opentui/solid', generate: 'universal' }], [tsPreset]]
|
||||
})
|
||||
return { contents: out?.code ?? '', loader: 'js' }
|
||||
})
|
||||
|
||||
// Force the universal/client solid-js build (node condition → server.js otherwise).
|
||||
build.onResolve({ filter: /^solid-js$/ }, () => ({ path: require.resolve('solid-js/dist/solid.js') }))
|
||||
build.onResolve({ filter: /^solid-js\/store$/ }, () => ({ path: require.resolve('solid-js/store/dist/store.js') }))
|
||||
}
|
||||
}
|
||||
|
||||
const [, , entryArg, outdirArg] = process.argv
|
||||
const entry = entryArg ? resolve(process.cwd(), entryArg) : resolve(root, 'src/entry/main.tsx')
|
||||
const outdir = outdirArg ? resolve(process.cwd(), outdirArg) : resolve(root, 'dist')
|
||||
|
||||
await esbuild.build({
|
||||
entryPoints: [entry],
|
||||
outdir,
|
||||
bundle: true,
|
||||
format: 'esm',
|
||||
platform: 'node',
|
||||
target: 'node26',
|
||||
splitting: true,
|
||||
sourcemap: true,
|
||||
logLevel: 'info',
|
||||
// Native blob + tree-sitter worker resolve from @opentui/core's own dir at runtime.
|
||||
external: ['@opentui/core', '@opentui/core/*'],
|
||||
plugins: [opentuiSolid],
|
||||
define: { 'process.env.OPENTUI_BUN_ONLY_EXAMPLES': '"false"' }
|
||||
})
|
||||
Reference in New Issue
Block a user