diff --git a/bun.lockb b/bun.lockb index b6f2b1e9..fedb381e 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/packages/unplugin-typia/package.json b/packages/unplugin-typia/package.json index 0ae22a41..7d5da540 100644 --- a/packages/unplugin-typia/package.json +++ b/packages/unplugin-typia/package.json @@ -86,6 +86,8 @@ }, "dependencies": { "@rollup/pluginutils": "^5.1.0", + "@sxzz/ast-kit": "npm:@jsr/sxzz__ast-kit", + "@sxzz/magic-string-ast": "npm:@jsr/sxzz__magic-string-ast", "pathe": "^1.1.2", "typescript": "^5.3.2", "unplugin": "^1.5.1" diff --git a/packages/unplugin-typia/src/bun.ts b/packages/unplugin-typia/src/bun.ts index b6ffc4e3..6c29901a 100644 --- a/packages/unplugin-typia/src/bun.ts +++ b/packages/unplugin-typia/src/bun.ts @@ -6,6 +6,10 @@ import type { BunPlugin } from 'bun'; import type { UnpluginContextMeta } from 'unplugin'; +import { readPackageJSON, resolvePackageJSON } from 'pkg-types'; +import { babelParse, getLang } from '@sxzz/ast-kit'; +import { MagicStringAST } from '@sxzz/magic-string-ast'; +import { dirname, join } from 'pathe'; import { type Options, resolveOptions, unplugin } from './api.js'; import { defaultOptions } from './core/options.js'; @@ -13,6 +17,37 @@ if (globalThis.Bun == null) { throw new Error('You must use this plugin with bun'); } +/* cache typia mjs path */ +let typiaMjsPath: string | undefined; +/** + * Read typia mjs path. + * TODO: delete after [this issue](https://github.com/oven-sh/bun/issues/11783) is resolved. + */ +async function resolveTypiaPath(id: string, code: string) { + if (typiaMjsPath == null) { + const typiaPackageJson = await readPackageJSON('typia'); + const typiaDirName = dirname(await resolvePackageJSON('typia')); + typiaMjsPath = join(typiaDirName, typiaPackageJson?.module ?? ''); + } + + const ms = new MagicStringAST(code); + + const program = babelParse(code, getLang(id), {}); + for (const node of program.body) { + if ( + node.type === 'ImportDeclaration' + && node.importKind !== 'type' + && ms.sliceNode(node.source) === 'typia' + ) { + ms.overwriteNode(node.source, `${typiaMjsPath}"`); + } + } + + const r = ms.toString(); + + return r; +} + /** * bun plugin * @@ -79,7 +114,7 @@ function bunTypiaPlugin( const bunPlugin = ({ name: 'unplugin-typia', - setup(build) { + async setup(build) { const resolvedOptions = resolveOptions(options ?? {}); const { include } = resolvedOptions; @@ -105,7 +140,7 @@ function bunTypiaPlugin( case typeof result === 'string': return { contents: source }; default: - return { contents: result.code }; + return { contents: await resolveTypiaPath(path, result.code) }; } }); },