1*033061beSJaap de Haanimport { build } from 'esbuild'; 2*033061beSJaap de Haanimport { cp, mkdir, readdir, readFile, rm, stat, writeFile } from 'node:fs/promises'; 3*033061beSJaap de Haanimport path from 'node:path'; 4*033061beSJaap de Haanimport { fileURLToPath } from 'node:url'; 5*033061beSJaap de Haan 6*033061beSJaap de Haanconst rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); 7*033061beSJaap de Haanconst nodeModulesDir = path.join(rootDir, 'node_modules'); 8*033061beSJaap de Haanconst vendorDir = path.join(rootDir, 'vendor'); 9*033061beSJaap de Haanconst fontDir = path.join(rootDir, 'font'); 10*033061beSJaap de Haan 11*033061beSJaap de Haanconst packages = [ 12*033061beSJaap de Haan { 13*033061beSJaap de Haan name: 'bpmn-js', 14*033061beSJaap de Haan globalName: 'BpmnJS', 15*033061beSJaap de Haan assetsDir: path.join('dist', 'assets'), 16*033061beSJaap de Haan fontsDir: path.join('dist', 'assets', 'bpmn-font', 'font'), 17*033061beSJaap de Haan fontFiles: ['bpmn.woff', 'bpmn.woff2'], 18*033061beSJaap de Haan outputs: [ 19*033061beSJaap de Haan { 20*033061beSJaap de Haan entryPoint: path.join(rootDir, 'build', 'vendor-entrypoints', 'bpmn-viewer.js'), 21*033061beSJaap de Haan outFile: path.join(vendorDir, 'bpmn-js', 'dist', 'bpmn-viewer.production.min.js'), 22*033061beSJaap de Haan }, 23*033061beSJaap de Haan { 24*033061beSJaap de Haan entryPoint: path.join(rootDir, 'build', 'vendor-entrypoints', 'bpmn-modeler.js'), 25*033061beSJaap de Haan outFile: path.join(vendorDir, 'bpmn-js', 'dist', 'bpmn-modeler.production.min.js'), 26*033061beSJaap de Haan }, 27*033061beSJaap de Haan ], 28*033061beSJaap de Haan }, 29*033061beSJaap de Haan { 30*033061beSJaap de Haan name: 'dmn-js', 31*033061beSJaap de Haan globalName: 'DmnJS', 32*033061beSJaap de Haan assetsDir: path.join('dist', 'assets'), 33*033061beSJaap de Haan fontsDir: path.join('dist', 'assets', 'dmn-font', 'font'), 34*033061beSJaap de Haan fontFiles: ['dmn.woff', 'dmn.woff2'], 35*033061beSJaap de Haan outputs: [ 36*033061beSJaap de Haan { 37*033061beSJaap de Haan entryPoint: path.join(rootDir, 'build', 'vendor-entrypoints', 'dmn-viewer.js'), 38*033061beSJaap de Haan outFile: path.join(vendorDir, 'dmn-js', 'dist', 'dmn-viewer.production.min.js'), 39*033061beSJaap de Haan }, 40*033061beSJaap de Haan { 41*033061beSJaap de Haan entryPoint: path.join(rootDir, 'build', 'vendor-entrypoints', 'dmn-modeler.js'), 42*033061beSJaap de Haan outFile: path.join(vendorDir, 'dmn-js', 'dist', 'dmn-modeler.production.min.js'), 43*033061beSJaap de Haan }, 44*033061beSJaap de Haan ], 45*033061beSJaap de Haan }, 46*033061beSJaap de Haan]; 47*033061beSJaap de Haan 48*033061beSJaap de Haanasync function pathExists(targetPath) { 49*033061beSJaap de Haan try { 50*033061beSJaap de Haan await stat(targetPath); 51*033061beSJaap de Haan return true; 52*033061beSJaap de Haan } catch { 53*033061beSJaap de Haan return false; 54*033061beSJaap de Haan } 55*033061beSJaap de Haan} 56*033061beSJaap de Haan 57*033061beSJaap de Haanasync function ensureInstalled(packageName) { 58*033061beSJaap de Haan const packagePath = path.join(nodeModulesDir, packageName, 'package.json'); 59*033061beSJaap de Haan 60*033061beSJaap de Haan if (!(await pathExists(packagePath))) { 61*033061beSJaap de Haan throw new Error( 62*033061beSJaap de Haan `Missing npm dependency ${packageName}. Run npm install before building vendor bundles.` 63*033061beSJaap de Haan ); 64*033061beSJaap de Haan } 65*033061beSJaap de Haan 66*033061beSJaap de Haan return packagePath; 67*033061beSJaap de Haan} 68*033061beSJaap de Haan 69*033061beSJaap de Haanasync function readPackageMetadata(packageName) { 70*033061beSJaap de Haan const packagePath = await ensureInstalled(packageName); 71*033061beSJaap de Haan return JSON.parse(await readFile(packagePath, 'utf8')); 72*033061beSJaap de Haan} 73*033061beSJaap de Haan 74*033061beSJaap de Haanfunction createBanner(metadata) { 75*033061beSJaap de Haan return `/*! ${metadata.name} - ${metadata.version} | generated for dokuwiki-plugin-bpmnio | ${metadata.license} */`; 76*033061beSJaap de Haan} 77*033061beSJaap de Haan 78*033061beSJaap de Haanasync function copyFileEnsuringDir(sourcePath, targetPath) { 79*033061beSJaap de Haan await mkdir(path.dirname(targetPath), { recursive: true }); 80*033061beSJaap de Haan await cp(sourcePath, targetPath, { force: true }); 81*033061beSJaap de Haan} 82*033061beSJaap de Haan 83*033061beSJaap de Haanasync function copyAssets(sourceDir, targetDir) { 84*033061beSJaap de Haan await mkdir(targetDir, { recursive: true }); 85*033061beSJaap de Haan 86*033061beSJaap de Haan for (const entry of await readdir(sourceDir, { withFileTypes: true })) { 87*033061beSJaap de Haan const sourcePath = path.join(sourceDir, entry.name); 88*033061beSJaap de Haan const normalizedPath = sourcePath.split(path.sep).join('/'); 89*033061beSJaap de Haan 90*033061beSJaap de Haan if (normalizedPath.includes('/font/')) { 91*033061beSJaap de Haan continue; 92*033061beSJaap de Haan } 93*033061beSJaap de Haan 94*033061beSJaap de Haan if (entry.isDirectory()) { 95*033061beSJaap de Haan await copyAssets(sourcePath, path.join(targetDir, entry.name)); 96*033061beSJaap de Haan continue; 97*033061beSJaap de Haan } 98*033061beSJaap de Haan 99*033061beSJaap de Haan const targetName = entry.name.endsWith('.css') 100*033061beSJaap de Haan ? entry.name.replace(/\.css$/u, '.less') 101*033061beSJaap de Haan : entry.name; 102*033061beSJaap de Haan 103*033061beSJaap de Haan await copyFileEnsuringDir(sourcePath, path.join(targetDir, targetName)); 104*033061beSJaap de Haan } 105*033061beSJaap de Haan} 106*033061beSJaap de Haan 107*033061beSJaap de Haanasync function copyFonts(sourceDir, files) { 108*033061beSJaap de Haan await mkdir(fontDir, { recursive: true }); 109*033061beSJaap de Haan 110*033061beSJaap de Haan for (const file of files) { 111*033061beSJaap de Haan await copyFileEnsuringDir(path.join(sourceDir, file), path.join(fontDir, file)); 112*033061beSJaap de Haan } 113*033061beSJaap de Haan} 114*033061beSJaap de Haan 115*033061beSJaap de Haanasync function cleanPackageOutput(packageName) { 116*033061beSJaap de Haan await rm(path.join(vendorDir, packageName), { recursive: true, force: true }); 117*033061beSJaap de Haan} 118*033061beSJaap de Haan 119*033061beSJaap de Haanasync function copyMetadata(packageName) { 120*033061beSJaap de Haan const sourceDir = path.join(nodeModulesDir, packageName); 121*033061beSJaap de Haan const targetDir = path.join(vendorDir, packageName); 122*033061beSJaap de Haan 123*033061beSJaap de Haan for (const file of ['LICENSE', 'README.md', 'package.json']) { 124*033061beSJaap de Haan const sourcePath = path.join(sourceDir, file); 125*033061beSJaap de Haan if (await pathExists(sourcePath)) { 126*033061beSJaap de Haan await copyFileEnsuringDir(sourcePath, path.join(targetDir, file)); 127*033061beSJaap de Haan } 128*033061beSJaap de Haan } 129*033061beSJaap de Haan} 130*033061beSJaap de Haan 131*033061beSJaap de Haanasync function buildBundle({ entryPoint, outFile, metadata, packageName }) { 132*033061beSJaap de Haan await mkdir(path.dirname(outFile), { recursive: true }); 133*033061beSJaap de Haan 134*033061beSJaap de Haan await build({ 135*033061beSJaap de Haan entryPoints: [entryPoint], 136*033061beSJaap de Haan outfile: outFile, 137*033061beSJaap de Haan bundle: true, 138*033061beSJaap de Haan minify: true, 139*033061beSJaap de Haan platform: 'browser', 140*033061beSJaap de Haan format: 'iife', 141*033061beSJaap de Haan target: ['es2019'], 142*033061beSJaap de Haan legalComments: 'inline', 143*033061beSJaap de Haan banner: { 144*033061beSJaap de Haan js: createBanner(metadata), 145*033061beSJaap de Haan }, 146*033061beSJaap de Haan define: { 147*033061beSJaap de Haan 'process.env.NODE_ENV': '"production"', 148*033061beSJaap de Haan global: 'window', 149*033061beSJaap de Haan }, 150*033061beSJaap de Haan logLevel: 'info', 151*033061beSJaap de Haan }); 152*033061beSJaap de Haan 153*033061beSJaap de Haan console.log(`Built ${packageName} bundle: ${path.relative(rootDir, outFile)}`); 154*033061beSJaap de Haan} 155*033061beSJaap de Haan 156*033061beSJaap de Haanasync function main() { 157*033061beSJaap de Haan for (const pkg of packages) { 158*033061beSJaap de Haan const metadata = await readPackageMetadata(pkg.name); 159*033061beSJaap de Haan const sourceDir = path.join(nodeModulesDir, pkg.name); 160*033061beSJaap de Haan const sourceAssetsDir = path.join(sourceDir, pkg.assetsDir); 161*033061beSJaap de Haan const sourceFontsDir = path.join(sourceDir, pkg.fontsDir); 162*033061beSJaap de Haan const targetAssetsDir = path.join(vendorDir, pkg.name, pkg.assetsDir); 163*033061beSJaap de Haan 164*033061beSJaap de Haan await cleanPackageOutput(pkg.name); 165*033061beSJaap de Haan await copyMetadata(pkg.name); 166*033061beSJaap de Haan await copyAssets(sourceAssetsDir, targetAssetsDir); 167*033061beSJaap de Haan await copyFonts(sourceFontsDir, pkg.fontFiles); 168*033061beSJaap de Haan 169*033061beSJaap de Haan for (const output of pkg.outputs) { 170*033061beSJaap de Haan await buildBundle({ 171*033061beSJaap de Haan entryPoint: output.entryPoint, 172*033061beSJaap de Haan outFile: output.outFile, 173*033061beSJaap de Haan metadata, 174*033061beSJaap de Haan packageName: pkg.name, 175*033061beSJaap de Haan }); 176*033061beSJaap de Haan } 177*033061beSJaap de Haan } 178*033061beSJaap de Haan 179*033061beSJaap de Haan const generatedMetadata = { 180*033061beSJaap de Haan generatedAt: new Date().toISOString(), 181*033061beSJaap de Haan packages: Object.fromEntries( 182*033061beSJaap de Haan await Promise.all( 183*033061beSJaap de Haan packages.map(async (pkg) => [pkg.name, (await readPackageMetadata(pkg.name)).version]) 184*033061beSJaap de Haan ) 185*033061beSJaap de Haan ), 186*033061beSJaap de Haan }; 187*033061beSJaap de Haan 188*033061beSJaap de Haan await writeFile( 189*033061beSJaap de Haan path.join(vendorDir, 'build-manifest.json'), 190*033061beSJaap de Haan `${JSON.stringify(generatedMetadata, null, 2)}\n` 191*033061beSJaap de Haan ); 192*033061beSJaap de Haan} 193*033061beSJaap de Haan 194*033061beSJaap de Haanmain().catch((error) => { 195*033061beSJaap de Haan console.error(error.message); 196*033061beSJaap de Haan process.exitCode = 1; 197*033061beSJaap de Haan}); 198