An easy-to-use platform for EEG experimentation in the classroom
at main 109 lines 3.4 kB view raw
1#!/usr/bin/env node 2/** 3 * Copies the Pyodide runtime from the installed npm package into the renderer's 4 * publicDir so Vite can serve it as static assets. 5 * 6 * Source: node_modules/pyodide/ 7 * Dest: src/renderer/utils/webworker/src/pyodide/ 8 * 9 * Key files copied: 10 * pyodide.mjs – ESM entry point (imported by the web worker via npm) 11 * pyodide.js – UMD fallback 12 * pyodide.asm.js – compiled Python interpreter 13 * pyodide.asm.wasm – WebAssembly binary 14 * python_stdlib.zip – Python standard library 15 * pyodide-lock.json – package registry (read by InstallMNE.mjs) 16 * 17 * Intentionally skipped: 18 * package.json – would make Vite treat the dir as an npm package 19 * and attempt to transform pyodide.mjs as a module 20 * *.d.ts – TypeScript declaration files, not needed at runtime 21 * *.html – console demo pages 22 * README.md – documentation 23 * *.map – source maps (large, optional for debugging) 24 * 25 * A version stamp (.pyodide-version) is written so subsequent runs are skipped 26 * when the installed version has not changed. 27 * 28 * Usage: node internals/scripts/InstallPyodide.mjs 29 * Runs automatically via the postinstall npm hook. 30 */ 31 32import fs from 'fs'; 33import path from 'path'; 34import { createRequire } from 'module'; 35import chalk from 'chalk'; 36 37const _require = createRequire(import.meta.url); 38 39const DEST_DIR = path.resolve('src/renderer/utils/webworker/src/pyodide'); 40const VERSION_FILE = path.join(DEST_DIR, '.pyodide-version'); 41 42// Files to exclude from the copy. 43const SKIP_EXTENSIONS = new Set(['.d.ts', '.map', '.html', '.md']); 44const SKIP_FILES = new Set(['package.json', 'README.md']); 45 46function shouldSkip(filename) { 47 if (SKIP_FILES.has(filename)) return true; 48 for (const ext of SKIP_EXTENSIONS) { 49 if (filename.endsWith(ext)) return true; 50 } 51 return false; 52} 53 54async function main() { 55 // Locate the pyodide package directory via Node's module resolution. 56 let pyodideDir; 57 try { 58 pyodideDir = path.dirname(_require.resolve('pyodide/package.json')); 59 } catch { 60 console.error( 61 chalk.red( 62 'pyodide not found in node_modules. Run `npm install` first.' 63 ) 64 ); 65 process.exit(1); 66 } 67 68 const version = JSON.parse( 69 fs.readFileSync(path.join(pyodideDir, 'package.json'), 'utf8') 70 ).version; 71 72 // Skip if this version was already installed. 73 if ( 74 fs.existsSync(VERSION_FILE) && 75 fs.readFileSync(VERSION_FILE, 'utf8').trim() === version 76 ) { 77 console.log(chalk.gray(`Pyodide ${version} already installed — skipping.`)); 78 return; 79 } 80 81 console.log( 82 chalk.blue.bold(`Installing Pyodide ${version} from node_modules…`) 83 ); 84 fs.mkdirSync(DEST_DIR, { recursive: true }); 85 86 const files = fs.readdirSync(pyodideDir); 87 for (const file of files) { 88 if (shouldSkip(file)) continue; 89 90 const src = path.join(pyodideDir, file); 91 const dest = path.join(DEST_DIR, file); 92 93 if (fs.statSync(src).isDirectory()) continue; 94 95 process.stdout.write(chalk.blue(` ${file}: `)); 96 fs.copyFileSync(src, dest); 97 console.log(chalk.green('copied')); 98 } 99 100 fs.writeFileSync(VERSION_FILE, version); 101 console.log( 102 chalk.green.bold(`\nPyodide ${version} ready at ${DEST_DIR}`) 103 ); 104} 105 106main().catch((err) => { 107 console.error(chalk.red('Fatal error:'), err); 108 process.exit(1); 109});