UNPKG

@opentui/solid

Version:
147 lines (124 loc) 4.38 kB
import { transformAsync } from "@babel/core" // @ts-expect-error - Types not important. import ts from "@babel/preset-typescript" // @ts-expect-error - Types not important. import moduleResolver from "babel-plugin-module-resolver" // @ts-expect-error - Types not important. import solid from "babel-preset-solid" import { plugin as registerBunPlugin, type BunPlugin } from "bun" export type ResolveImportPath = (specifier: string) => string | null const solidTransformStateKey = Symbol.for("opentui.solid.transform") type SolidTransformRuntime = { moduleName?: string resolvePath?: ResolveImportPath } type SolidTransformState = { installed: boolean runtime?: SolidTransformRuntime } type GlobalSolidTransformState = typeof globalThis & { [solidTransformStateKey]?: SolidTransformState } export interface CreateSolidTransformPluginOptions { moduleName?: string resolvePath?: ResolveImportPath } const getSolidTransformState = (): SolidTransformState => { const state = globalThis as GlobalSolidTransformState state[solidTransformStateKey] ??= { installed: false } return state[solidTransformStateKey] } const getSolidTransformRuntime = (): SolidTransformRuntime => { return getSolidTransformState().runtime ?? {} } const sourcePath = (path: string): string => { const searchIndex = path.indexOf("?") const hashIndex = path.indexOf("#") const end = [searchIndex, hashIndex].filter((index) => index >= 0).sort((a, b) => a - b)[0] return end === undefined ? path : path.slice(0, end) } const hasSolidTransformRuntime = (input: CreateSolidTransformPluginOptions): boolean => { return input.moduleName !== undefined || input.resolvePath !== undefined } export function ensureSolidTransformPlugin(input: CreateSolidTransformPluginOptions = {}): boolean { const state = getSolidTransformState() if (hasSolidTransformRuntime(input)) { state.runtime = { moduleName: input.moduleName, resolvePath: input.resolvePath, } } if (state.installed) { return false } registerBunPlugin(createSolidTransformPlugin()) state.installed = true return true } export function resetSolidTransformPluginState(): void { const state = getSolidTransformState() state.installed = false delete state.runtime } export function createSolidTransformPlugin(input: CreateSolidTransformPluginOptions = {}): BunPlugin { return { name: "bun-plugin-solid", setup: (build) => { build.onLoad({ filter: /[/\\]node_modules[/\\]solid-js[/\\]dist[/\\]server\.js(?:[?#].*)?$/ }, async (args) => { const path = sourcePath(args.path).replace("server.js", "solid.js") const file = Bun.file(path) const code = await file.text() return { contents: code, loader: "js" } }) build.onLoad( { filter: /[/\\]node_modules[/\\]solid-js[/\\]store[/\\]dist[/\\]server\.js(?:[?#].*)?$/ }, async (args) => { const path = sourcePath(args.path).replace("server.js", "store.js") const file = Bun.file(path) const code = await file.text() return { contents: code, loader: "js" } }, ) build.onLoad({ filter: /\.(js|ts)x(?:[?#].*)?$/ }, async (args) => { const path = sourcePath(args.path) const file = Bun.file(path) const code = await file.text() const runtime = getSolidTransformRuntime() const moduleName = input.moduleName ?? runtime.moduleName ?? "@opentui/solid" const resolvePath = input.resolvePath ?? runtime.resolvePath const plugins = resolvePath ? [ [ moduleResolver, { resolvePath(specifier: string) { return resolvePath(specifier) ?? specifier }, }, ], ] : [] const transforms = await transformAsync(code, { filename: path, plugins, presets: [ [ solid, { moduleName, generate: "universal", }, ], [ts], ], }) return { contents: transforms?.code ?? "", loader: "js", } }) }, } } const solidTransformPlugin = createSolidTransformPlugin() export default solidTransformPlugin