import * as fs from 'fs'; import * as path from 'path'; import { fromUint8Array } from 'js-base64'; import { build } from 'vite'; import { createRequire } from 'module'; import type { InlineConfig } from 'vite'; import tsconfigPaths from 'vite-tsconfig-paths'; import * as inject from '@rollup/plugin-inject'; import { replaceCodePlugin } from 'vite-plugin-replace'; const require = createRequire(import.meta.url); const getWorkerScriptPathOrDie = () => { const scriptPath = path.resolve('../../core/js-peer/dist/marine/worker-script/index.js'); if (!fs.existsSync(scriptPath)) { console.error('Worker script not found, looking at: ' + scriptPath); process.exit(1); } return scriptPath; }; const commonConfig = (opts: { outDir: string; name: string; entry: string; }): InlineConfig & Required> => { return { mode: 'production', build: { minify: 'esbuild', lib: { entry: opts.entry, name: opts.name, fileName: opts.name, }, outDir: opts.outDir, }, base: '', plugins: [tsconfigPaths()], optimizeDeps: { esbuildOptions: { define: { global: 'globalThis', }, }, }, }; }; const readAsBase64 = async (filePath: string): Promise => { const scriptRaw = await fs.promises.readFile(filePath); const b64 = fromUint8Array(scriptRaw); return b64; }; const readWasmFromNpmAsBase64 = (pkg: string, wasmFileName: string): Promise => { const pkgPath = require.resolve(pkg); const wasmFilePath = path.join(path.dirname(pkgPath), wasmFileName); return readAsBase64(wasmFilePath); }; const buildClient = async () => { await fs.promises.mkdir('tmp', { recursive: true }); // build worker script const workerConfig = commonConfig({ outDir: './tmp', entry: getWorkerScriptPathOrDie(), name: 'worker-script', }); workerConfig.build!.rollupOptions = { plugins: [ // @ts-ignore inject.default({ Buffer: ['buffer', 'Buffer'], process: 'process', }), ], }; await build(workerConfig); // build js-client const jsClientConfig = commonConfig({ outDir: './dist', entry: './src/index.ts', name: 'js-client', }); const workerScriptB64 = await readAsBase64('./tmp/worker-script.umd.cjs'); const avmBase64 = await readWasmFromNpmAsBase64('@fluencelabs/avm', 'avm.wasm'); const marineBase64 = await readWasmFromNpmAsBase64('@fluencelabs/marine-js', 'marine-js.wasm'); jsClientConfig.plugins!.push( replaceCodePlugin({ replacements: [ { from: '___worker___', to: workerScriptB64, }, { from: '___avm___', to: avmBase64, }, { from: '___marine___', to: marineBase64, }, ], }), ); await build(jsClientConfig); // We should exclude the script with type=module because // - it might be confusing (i.e won't work in browsers that do not support ESM, or if you miss the `type` attribute) // - there is a problem when using `self.crypto` in web workers await fs.promises.rm('./dist/js-client.js'); // browsers don't understand `.cjs` extensions, just use `.js` await fs.promises.rename('./dist/js-client.umd.cjs', './dist/js-client.min.js'); }; buildClient() .then(() => console.log('Built successfully')) .catch((err) => console.error('failed', err));