const os = require('os'); const fs = require('fs'); const path = require('path'); const tmp = require('tmp-file'); const exec = require('./exec'); const through = require('through2'); const Sdk = require('./sdk'); const dateformat = require('dateformat'); const Vinyl = require('vinyl'); const PluginError = require('plugin-error'); const colors = require('ansi-colors'); const log = require('fancy-log'); const vfs = require('vinyl-fs'); class Haxe extends Sdk { getBin(name) { if (Sdk.System.isWindows) { return `${this.binPath}/${name}.exe`; } else if (Sdk.System.isLinux) { const binPath = `${this.binPath}/${name}`; fs.chmodSync(binPath, 0o755); return binPath; } return `` } get binPath() { return `${this.path}/haxe-${this.version}`; } get haxeBin() { return this.getBin('haxe'); } get haxelibBin() { return this.getBin('haxelib'); } constructor(version) { super(Haxe.ID, version || Haxe.VERSION); } get prepared() { try { return fs.existsSync(this.haxeBin); } catch (e) { return false; } } get link() { if (Sdk.System.isWindows) { return `https://github.com/HaxeFoundation/haxe/releases/download/${this.version}/haxe-${this.version}-win.zip`; } else if (Sdk.System.isLinux) { let arch = Sdk.System.archInt; return `https://github.com/HaxeFoundation/haxe/releases/download/${this.version}/haxe-${this.version}-linux${arch}.tar.gz`; } } haxe(args) { return exec('.', [this.haxeBin].concat(args).join(' ')); } haxelib(args) { const haxelibBin = this.haxelibBin; //return exec(this.binPath, [path.basename(haxelibBin)].concat(args).join(' ')); return exec('.', [haxelibBin].concat(args).join(' ')); } install(packages) { let promise = this.haxelib(['setup', `${this.path}/lib`]); const next = (args) => () => { log(this.tag, colors.cyan('haxelib', 'install'), colors.magenta(args[1])); return this.haxelib(args); }; if (!Array.isArray(packages)) { packages = Object.entries(packages).map(([k, v]) => ({name: k, version: v})); } for (let pack of packages) { const args = []; let version = null; if (typeof pack === 'string') { args.push('install', pack); } else if (typeof pack === 'object') { version = pack.version; if (version.substr(0, 3) === 'git') { pack.git = version; version = null; } if (pack.git) { args.push('git', pack.name, pack.git); if (pack.branch) args.push(pack.branch); } else { args.push('install', pack.name); if (version) args.push(version); } args.push('--always'); } let path = `${this.path}/lib/${args[1]}`; if (version) { path += `/${version.replace(/\./g, ',')}`; } else if (pack.git) { path += '/git'; } if (!fs.existsSync(path)) { promise = promise.then(next(args)); } } return promise; } upgrade() { let promise = this.haxelib(['setup', `${this.path}/lib`]); promise = promise.then(() => this.haxelib(['upgrade', '--always'])); return promise; } /** * * @param params * @returns {*} * * { * command: 'build', * platform: 'flash', * version: '1.0.0', * build: '1999.12.12 00:00', * values: {}, * outputFile: 'out.swf', * } */ openfl(params) { params = Object.assign({ build: dateformat(new Date(), 'yyyy-mm-dd HH:MM:ss'), macro: [], debug: false, }, params); const files = []; let stream = null; const bufferContents = (file, enc, callback) => { // ToDo: check file not stream files.push(file); callback(); }; const endStream = (callback) => { log(this.tag, colors.cyan(`openfl ${params.command} ${params.platform}`)); const args = ['-cwd', files[0].path, 'run', 'openfl', params.command, params.platform]; if (params.values) for (let key of Object.keys(params.values)) { const value = params.values[key]; if (value === true) { args.push(`-D${key}`); } else if (value) { args.push(`-D${key}="${value}"`); } } const buildDir = path.join(os.tmpdir(), 'build'); args.push(`--app-path=${buildDir}`); if (params.outputFile) { args.push(`--app-file=${params.outputFile}`); } if (params.version) args.push(`--meta-version=${params.version}`); //if (params.build) args.push(`--haxedef=BUILD="${params.build}"`); args.push(`--haxeflag="--macro CompilationOption.set('build','${params.build}')"`); let debug = null; if (params.debug) { debug = { host: 'localhost', port: 6000 + Math.floor(Math.random() * 1000), }; args.push(`--haxeflag="--macro CompilationOption.set('debug.address','${debug.host}')"`); args.push(`--haxeflag="--macro CompilationOption.set('debug.port','${debug.port}')"`); args.push('-debug'); } //console.log('haxelib', args.join(' ')); this.haxelib(args).then(() => { const result = { 'flash': `${buildDir}/flash/bin/*.swf`, 'html5': `${buildDir}/html5/bin/**/*`, 'linux': `${buildDir}/linux/bin/**/*`, }[params.platform]; vfs.src(result).pipe(through.obj((file, enc, cb) => { file.debug = debug; stream.push(file); cb(); }, (cb) => { callback(); cb(); })); //callback(); }).catch((error) => { stream.emit('error', new PluginError({plugin: this.name, message: error})); callback(); }); }; return stream = through.obj(bufferContents, endStream); } /** * * @param params * * { * platform: 'neko', * version: '1.0.0', * build: '1999.12.12 00:00', * values: {}, * lib: [], * src: [], * main: 'Main.hx', * outputFile: 'out.n', * debug: true, * } */ build(params) { params = Object.assign({ build: dateformat(new Date(), 'yyyy-mm-dd HH:MM:ss'), macro: [], debug: false, }, params); const files = []; let stream = null; const bufferContents = (file, enc, callback) => { // ToDo: check file not stream files.push(file); callback(); }; const endStream = (callback) => { log(this.tag, colors.cyan("haxe", params.platform), '=>', colors.magenta(params.outputFile)); const args = []; args.push('-main', params.main); for (const lib of params.lib) { args.push('-lib', lib); } for (const cp of params.cp) { args.push('-cp', cp); } for (const macro of params.macro) { args.push('--macro', `"${macro}"`); } if (params.values) for (let key of Object.keys(params.values)) { const value = params.values[key]; if (value === true) { args.push(`-D ${key}`); } else if (value) { args.push(`-D ${key}="${value}"`); } } const tmpFile = tmp.generateFile(); const dir = path.dirname(tmpFile.path); const name = path.basename(tmpFile.path); args.push(`-${params.platform}`, tmpFile.path); args.push(`--macro "CompilationOption.set('build','${params.build}')"`); let debug = null; if (params.debug) { debug = { host: 'localhost', port: 6000 + Math.floor(Math.random() * 1000), }; args.push(`--macro "CompilationOption.set('debug.address','${debug.host}')"`); args.push(`--macro "CompilationOption.set('debug.port','${debug.port}')"`); args.push('-debug'); } //console.log('haxe', args.join(' ')); this.haxe(args).then(() => { const out = new Vinyl({ path: params.outputFile, //contents: fs.createReadStream(tmpFile.path), contents: fs.readFileSync(tmpFile.path), }); out.debug = debug; stream.push(out); callback(); }).catch((error) => { stream.emit('error', new PluginError({plugin: this.name, message: error})); callback(); }); }; return stream = through.obj(bufferContents, endStream); } } Haxe.ID = 'haxe'; Haxe.VERSION_3_4_0 = '3.4.0'; Haxe.VERSION_3_4_2 = '3.4.2'; Haxe.VERSION_3_4_3 = '3.4.3'; Haxe.VERSION_3 = Haxe.VERSION_3_4_2; Haxe.VERSION = Haxe.VERSION_3; module.exports = Haxe;