import path from 'node:path' import { execSync } from 'node:child_process' export namespace PlataBuildWasm { export async function compileWasm(outDir: string) { const wasmPath = path.join(Plata.ProjectDir, 'wasm') const hasGoWasmModule = await Plata.files.access( wasmPath ) if (hasGoWasmModule !== true) { return true } console.log('⚠️ - Modulos WASM foram identificados') console.log('⚠️ - Esse funcionalidade é experimental! e só suporta Golang') const modules = await PlataBuildWasm.listWasmModules(wasmPath, true) for (let i = 0; i < modules.length; i++) { await buildGoWasmModule( path.join(wasmPath, modules[i]), modules[i], outDir, ) } console.log('✅ - Modulos buildados!') } export async function listWasmModules(wasmPath: string, log: boolean) { // TODO melhorar isso transformando em uma chamada da Plata.files const wasmFolderContent = await Plata.files.fs.readdir(wasmPath, { withFileTypes: true }).catch( (err): string => err.toString() ) if (typeof wasmFolderContent === 'string') { console.log(wasmFolderContent) process.exit(1) } const modules = wasmFolderContent .filter(w => w.isDirectory()).map(w => w.name) ; if (log) { console.log('💡 - Modulos encontrados: ', modules.join(',')) } return modules } export async function listWasmFiles(wasmPath: string) { // TODO melhorar isso transformando em uma chamada da Plata.files const wasmFolderContent = await Plata.files.fs.readdir(wasmPath, { withFileTypes: true }).catch( (err): string => err.toString() ) if (typeof wasmFolderContent === 'string') { console.log(wasmFolderContent) process.exit(1) } const files = wasmFolderContent .filter(w => w.isFile() && w.name.endsWith('.wasm')).map(w => w.name) ; return files } // Pega uma pasta em especifico e roda o go build para ele gerar o .wasm export async function buildGoWasmModule(wasmModulePath: string, name: string, outDir: string) { console.log('🔨 - Buildando WASM GO ', name) const wasmFileName = `go.main.${name}.wasm` const wasmPath = path.resolve(outDir, 'wasm', wasmFileName) execSync(`go build -trimpath -o ${wasmPath}`, { cwd: wasmModulePath, windowsHide: true, env: { ...process.env, GOOS: 'js', GOARCH: 'wasm' } }) } export function setupRuntime() { require('++/misc/golang/wasm_exec') } export async function loadFilesWasm() { const wasmPath = path.join(Plata.ProjectDir, '__BUILD__', 'wasm') const hasGoWasmModule = await Plata.files.access( wasmPath ) if (hasGoWasmModule !== true) { return true } const files = await PlataBuildWasm.listWasmFiles(wasmPath) setupRuntime() const promises: Promise[] = [] for (let i = 0; i < files.length; i++) { promises.push(...files.map(f => Plata.FastPromise( () => PlataBuildWasm.loadGoWasmFile(path.join(wasmPath, f), f) ))) } await Promise.all(promises) } export async function loadGoWasmFile(wasmFilePath: string, wasmName: string) { if (Plata._loadedsWasms.has(wasmName)) { return true } const go = new Go() const fileContet: PlataResult = await Plata.files.fs.readFile(wasmFilePath).catch( (err) => ({ errorID: 'PLBUILDWASMLDGO0001', msg: 'Erro ao ler arquivo WASM', error: err }) ) if (fileContet.errorID !== undefined) { console.log(JSON.stringify(fileContet, null, 4)) process.exit(1) } const resultWASM: PlataResult = await WebAssembly.instantiate(fileContet, go.importObject).then( r => r as any as WebAssembly.WebAssemblyInstantiatedSource, err => ({ errorID: 'PLBUILDWASMLDGO0002', msg: 'Erro ao iniciar WASM', error: err }) ) if (resultWASM.errorID !== undefined) { console.log(JSON.stringify(resultWASM, null, 4)) process.exit(1) } go.run(resultWASM.instance) // Adiciona todas as funções que forem exportada com PlataWasm_ for (const k in resultWASM.instance.exports) { if (k.startsWith('PlataWasm_')) { const funcName = k.replace(/PlataWasm_/g, '') global[funcName] = resultWASM.instance.exports[k] } } Plata._loadedsWasms.add(wasmName) } }