You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
After days of research I wrote a plugin to make this cool node-api-dotnet works with electron. Hope it can help people later.
Create a vite plugin
importfsfrom"fs";importpathfrom"path";interfaceElectronNodeApiDotNetOptions{// The path to `node_modules/node-api-dotnetnodeModulePath: string,// The path to all generated files and assembliescsprojOutputPath: string,}exportdefault(options: ElectronNodeApiDotNetOptions)=>{constname="electron-node-api-dotnet";letassemblyName="Microsoft.JavaScript.NodeApi";letassemblyRoot=path.normalize(options.csprojOutputPath)consttransformInitJs=(code: string)=>{// Create require to dynamic require .node files.code=` import path from "path"; import { createRequire } from 'module'; const require = createRequire(import.meta.url); const bundleRoot = ${JSON.stringify(options.nodeModulePath)}; `+code// Since we use import above, we also need to replace the export style.// https://github.com/rollup/plugins/issues/1121code=code.replace("module.exports = initialize","export default initialize")// Get the dotnet assembly name, preventing upstream change.constregex=/const assemblyName\s*=\s*['"`](.*?)['"`];/;constmatch=code.match(regex);if(match){assemblyName=match[1];console.log(`[${name}] Using assembly name: ${assemblyName}`);}else{console.error(`[${name}] Cannot match assembly name, plugin may not work!`);}// Transform dynamic assemblyName require to a static one// Also transform the relative paths to be prefixed with provided bundle root.code=code.replace(/require\(`\.\/(.+?)\/\$\{assemblyName\}\.node`\)/g,"require(path.join(bundleRoot, `./$1/"+assemblyName+".node`))");// Transform the default case.code=code.replace("nativeHost = require(__dirname + `/${rid}/${assemblyName}.node`)","nativeHost = require(path.join(bundleRoot, `./${rid}/${assemblyName}.node`))")// Transform the path for managed host.code=code.replace("const managedHostPath = __dirname + `/${targetFramework}/${assemblyName}.DotNetHost.dll`","const managedHostPath = path.join(bundleRoot, `./${targetFramework}/${assemblyName}.DotNetHost.dll`)")returncode;}consttransformAssemblyJs=(code: string,filePath: string)=>{// Instead of use import.meta.urlcode=code.replace("import { fileURLToPath } from 'node:url';","")// Use the absolute path, because these files will be rollup // to one single file (for example main.js)code=code.replace("const __filename = fileURLToPath(import.meta.url)",`const __filename = ${JSON.stringify(filePath)}`)returncode}return{
name,resolveId(source: string,importer: string|undefined,options: any){returnnull;},transform(code: string,id: string){constnormId=path.normalize(id)if(id.endsWith("node_modules/node-api-dotnet/init.js")){returntransformInitJs(code)}elseif(normId.startsWith(assemblyRoot)){returntransformAssemblyJs(code,normId)}returncode;},load(id: string){if(id.endsWith(`${assemblyName}.node`)){// Treat .node files as empty string, otherwise there'll be error because binary are// not valid js files.return``;}returnnull;},generateBundle(options: any,bundle: any){// bundle whatever way you want},};};
Include it in vite config, or nuxt config, if you like. Remember to exclude files from commonjs plugin.
After days of research I wrote a plugin to make this cool
node-api-dotnet
works with electron. Hope it can help people later.The text was updated successfully, but these errors were encountered: