UNPKG

imba

Version:

Intuitive and powerful language for building webapps that fly

328 lines (286 loc) 8.11 kB
const imba1 = require('./bootstrap.compiler.js'); const imba2 = require('../src/compiler/compiler.mjs'); const chokidar = require('chokidar'); const fs = require('fs'); const np = require('path'); const esbuild = require('esbuild'); let helpers = imba2.helpers; let time = 0; let argv = helpers.parseArgs(process.argv.slice(2), { alias: { w: 'watch' } }) let meta = Symbol(); let compileCache = {}; let globalNames = { compiler: 'imbac' } let distdir = np.resolve(__dirname, '..', 'dist') // Create the dist directory fs.mkdirSync(distdir, { recursive: true }); for (let file of ["plugin.mjs", "plugin.cjs", "compiler.old.cjs"]) { let path = np.join(distdir, file); if (fs.existsSync(path)) fs.unlinkSync(path); } function plugin(build) { // console.log('setting up plugin',build,this); let options = this.options; let self = this; let watcher = this.watcher; let basedir = np.resolve(__dirname, '..'); let outdir = options.outdir || np.dirname(options.outfile); let distrel = './' + np.relative(distdir, outdir); let absoutdir = np.resolve(__dirname, '..', outdir); function relative(path) { let res = np.relative(absoutdir, np.resolve(basedir, path)).split('\\').join('/'); if (res[0] != '.') res = './' + res; return res; } build.onResolve({ filter: /^dist\// }, (p) => { return { path: relative(p.path), external: true } }); build.onResolve({ filter: /^imba\/runtime/ }, (p) => { return { path: np.resolve(basedir,'src','imba','runtime.mjs'), external: false } // return { path: relative(p.path), external: true } }); build.onResolve({ filter: /^compiler1?$/ }, (p) => { // find the output dir // console.log('resolve compiler?',p,options); let src = p.path == 'compiler1' ? "../scripts/bootstrap.compiler.js" : "./dist/compiler.cjs"; return { path: src, external: true } }); build.onLoad({ filter: /\.imba1$/ }, async (args) => { // console.log('loading imba1',args); if (watcher) watcher.add(args.path); let key = `${args.path}:${options.platform}` let raw = await fs.promises.readFile(args.path, 'utf8'); let cached = compileCache[key]; if (cached && cached.input == raw) { return { contents: cached.output }; } let target = { browser: 'web', worker: 'webworker' }[options.platform] || options.platform || 'web'; let t0 = Date.now(); let body = imba1.compile(raw, { target: target, filename: args.path, sourcePath: args.path }); time += (Date.now() - t0); compileCache[key] = { input: raw, output: body.js }; return { contents: body.js } }) build.onLoad({ filter: /\.imba$/ }, async (args) => { // console.log('loading imba',args); if (watcher) watcher.add(args.path); let raw = await fs.promises.readFile(args.path, 'utf8'); let key = `${args.path}:${options.platform}` let cached = compileCache[key]; if (cached && cached.input == raw) { // console.log('found cached version',key); return { contents: cached.output }; } let t0 = Date.now(); let body = imba2.compile(raw, Object.assign({ platform: options.platform || 'browser', format: 'esm', runtime: 'imba/runtime', sourcePath: args.path, }, self.imbaOptions)); time += (Date.now() - t0); compileCache[key] = { input: raw, output: body.js }; return { contents: body.js } }) build.onLoad({ filter: /\.(js|ts)/ }, async (args) => { // console.log('loading js',args); if (watcher) watcher.add(args.path); return; }) } async function universalise(result, o) { for (let file of result.outputFiles) { let bname = np.basename(file.path).split(".")[0]; let bytes = file.contents.length / 1000; console.log("output", file.path, bname,bytes.toFixed(2) + 'kb'); fs.writeFileSync(file.path, file.contents); if (o.format == 'esm' && file.path.indexOf('.mjs') >= 0) { let cjs = esbuild.transformSync(file.text, { format: 'cjs', minify: o.minify }); // && o.platform == 'node' let name = file.path.replace('.mjs', '.cjs'); console.log("transformed to cjs", name, cjs.code.length, file.text.length); fs.writeFileSync(name, cjs.code); } if (o.format == 'esm' && o.platform == 'browser' && globalNames[bname]) { let iife = esbuild.transformSync(file.text, { format: 'iife', minify: o.minify, globalName: globalNames[bname] }) let name = file.path.replace('.mjs', '.js'); if (true) { // name != file.path console.log("transformed to iife", name, globalNames[bname], iife.code.length, file.text.length); fs.writeFileSync(name, iife.code); } } } } async function bundle(o) { if (o instanceof Array) { for (let config of o) { await bundle(config) } return; } let input = o.entryPoints[0]; let entry = { options: o } let watcher = entry.watcher = argv.watch && chokidar.watch([]); entry.imbaOptions = o.options || {}; o.plugins = [{ name: 'imba', setup: plugin.bind(entry) }]; if (o.platform == 'node') { o.resolveExtensions = ['.node.imba', '.imba', '.imba1', '.ts', '.mjs', '.cjs', '.js', '.css', '.json']; } else { o.resolveExtensions = ['.web.imba', '.imba', '.imba1', '.ts', '.mjs', '.cjs', '.js', '.css', '.json']; o.nodePaths = [np.resolve(__dirname, '..', 'polyfills')] o.target = ['chrome88','edge79','safari15'] } if (!o.outdir && !o.outfile) { o.outdir = `dist/${o.platform}`; } o.target = o.target || ['es2020']; o.format = o.format || 'esm'; if (o.bundle == undefined) o.bundle = true; o.conditions = ["imba-core","imba"]; o.loader = { '.txt': 'text' } // o.incremental = !!watcher; o.logLevel = 'info'; o.charset = 'utf8'; o.pure = ['Symbol.for','Symbol']; o.minify = !argv.watch; o.supported = {bigint: true} o.define = {'process.env.NODE_ENV': "'production'"}; if (o.write == undefined) o.write = false; delete o.options; let context = await esbuild.context(o); let result = await context.rebuild(); await universalise(result, o); if (watcher) { watcher.on('change', async () => { console.log('rebuilding', input); let rebuilt = await context.rebuild(); await universalise(rebuilt, o); console.log('rebuilt', input); }) } else { context.dispose(); } } let aliases = { // 'imba/colors': '/Users/sindre/repos/imba/packages/imba/src/imba/utils/colors.imba', // 'imba': '/Users/sindre/repos/imba/packages/imba/src/imba/utils.imba' } let bundles = [ { entryPoints: ["src/imba/imba.imba"], outdir: "dist", platform: "browser", format: "esm", outExtension: { ".js": ".mjs" }, }, { entryPoints: ["compiler.imba"], outdir: "dist", treeShaking: true, alias: aliases, platform: "browser", format: "esm", outExtension: { ".js": ".mjs" } }, { entryPoints: ["src/imba/imba.imba"], outExtension: { ".js": ".node.js" }, format: "cjs", outdir: "dist", platform: "node", }, { entryPoints: ["src/imba/imba.imba"], outExtension: { ".js": ".node.mjs" }, format: "esm", outdir: "dist", external: ['get-port'], platform: "node", }, { entryPoints: [ "src/utils/colors.imba" ], outExtension: { ".js": ".mjs" }, minify: true, outdir: "dist", format: "esm", platform: "browser", }, { entryPoints: [ "src/utils/colors.imba" ], outExtension: { ".js": ".cjs" }, minify: true, outdir: "dist", format: "cjs", platform: "node", }, { entryPoints: [ "bin/imba.imba", "program.imba", "workers.imba" ], treeShaking: true, alias: aliases, outExtension: { ".js": ".imba.js" }, minify: true, external: ["chokidar", "esbuild"], outdir: ".", format: "cjs", platform: "node", }, { entryPoints: [ "program.imba" ], outExtension: { ".js": ".browser.imba.js" }, minify: true, external: ["chokidar", "esbuild"], outdir: ".", format: "esm", platform: "browser", }, { entryPoints: [ "src/utils/std/std.imba" ], outExtension: { ".js": ".mjs" }, minify: true, outdir: "dist", format: "esm", platform: "browser", }, { entryPoints: [ "src/utils/std/std.imba" ], outExtension: { ".js": ".cjs" }, minify: true, outdir: "dist", format: "cjs", platform: "node", }, ]; bundle(bundles)