#!/usr/bin/node // Make a standalone and self-contained JS application for node.js/jxcore // Version 1.5.5 var TOP='/home/sbosse/proj/jam/js'; global.TOP=TOP; global.PATH=[process.cwd(),TOP]; global.MODE='makeapp'; global.TARGET='node'; // | 'browser' var Fs = require('fs'); var Modules = []; // modu.Modules; var Objects = []; // modu.Objects; var Files = []; // modu.Files; var FilesEmbedded = {}; var Main = undefined; var Bundle = 'bundle.js'; var shift=0; function FileExtension(filename) { return filename.split('.').pop(); } function search(index,module) { if (module.indexOf('/')==-1) return module; if (PATH.length==index) return module; var path=PATH[index]; if (Fs.existsSync(path+'/'+module+'.js')) return path+'/'+module+'.js'; else if (Fs.existsSync(path+'/'+module)) return path+'/'+module; else return search(index+1,module); } var CoreModule={}; CoreModule['crypto']='crypto'; CoreModule['util']='util'; CoreModule['http']='http'; CoreModule['fs']='fs'; CoreModule['stream']='stream'; CoreModule['url']='url'; CoreModule['os']='os'; CoreModule['net']='net'; CoreModule['zlib']='zlib'; CoreModule['path']='path'; CoreModule['dgram']='dgram'; CoreModule['child_process']='child_process'; CoreModule['events']='events'; CoreModule['string_decoder']='string_decoder'; CoreModule['assert']='assert'; CoreModule['buffer']='buffer'; Require = function (module) { var file,filepath,_Require=Require,_Modules=Modules,_Objects=Objects; try { if (CoreModule[module]!=undefined) module=CoreModule[module]; if (module=='') return undefined; if (Modules[module]) return Modules[module]; else if (Objects[module]) return Objects[module]; file=search(0,module); try { filepath=Fs.realpathSync(file); Files.push([module,filepath]); } catch (e) {filepath=''}; if (FileExtension(filepath)=='json') { console.log('Require: Loading '+module); var Object = require(file); Require = _Require; Modules = _Modules; Objects = _Objects; Objects[module]=Object; return Object; } else { console.log('Require: Loading '+module); var Module = require(file); Require = _Require; Modules = _Modules; Objects = _Objects; Modules[module]=Module; return Module; } } catch (e) { var more=''; if (e.name==='SyntaxError' && filepath) { var src=Fs.readFileSync(filepath,'utf8'); var Esprima = Require('parser/esprima'); try { var ast = Esprima.parse(src, { tolerant: true, loc:true }); if (ast.errors && ast.errors.length>0) more = ', '+ast.errors[0]; } catch (e) { if (e.lineNumber) more = ', in line '+e.lineNumber; } } if (e.stack) console.log(e.stack); console.log('Require import of '+module+' failed: '+e+more); process.exit(-1); } } global.Require=Require; FileEmbedd = function (path,format) { var fullpath=search(0,path); console.log('*'+path); try { FilesEmbedded[path]=Fs.readFileSync(fullpath,format); console.log('#'+path+':'+FilesEmbedded[path].length+' bytes'); } catch (e) { console.log('FileEmbedd failed for: '+fullpath) FilesEmbedded[path]=undefined}; } global.FileEmbedd=FileEmbedd; FileEmbedded = function (path,format) { if (FilesEmbedded[path]) return FilesEmbedded[path]; else { FileEmbedd(path,format); return FilesEmbedded[path]; } } global.FileEmbedded = FileEmbedded; var Base64 = require(TOP+'/os/base64'); var Comp = require(TOP+'/com/compat'); var exit=false; var argv=[]; Comp.args.parse(process.argv,[ ['-exit',0,function (arg) { if (!Main) exit=true; else argv.push(arg);}], ['-o',1,function (arg) { if (!Main) Bundle=arg; else argv.push(arg);}], [function (arg) { if (!Main) Main=arg; argv.push(arg); }] ],2); if (Main) Require(Main); //Files=Files.slice(0,8); var NL = '\n'; var coremodules = ""; for(var m in CoreModule) { coremodules = coremodules + "CoreModule['"+m+"']='"+CoreModule[m]+"';"+NL; } var header= 'var CoreModule = {};'+NL+ coremodules+NL+ 'var BundleModuleCode=[];'+NL+ 'var BundleObjectCode=[];'+NL+ 'var BundleModules = [];'+NL+ 'function _isdir(path) {'+NL+ ' var stats=Fs.statSync(path);'+NL+ ' return stats && stats.isDirectory()};'+NL+ 'function _search(index,file) {'+NL+ ' if (PATH.length==index) return file;'+NL+ ' var path=PATH[index];'+NL+ ' if (Fs.existsSync(path+"/"+file+".js")) return path+"/"+file+".js";'+NL+ ' else if (Fs.existsSync(path+"/"+file) && !_isdir(path+"/"+fil)) return path+"/"+file;'+NL+ ' else return _search(index+1,file);'+NL+ ' }'+NL+ 'var Fs = require("fs");'+NL+ "if (typeof __dirname == 'undefined') __dirname = '';"+NL+ "if (typeof __filename == 'undefined') __filename = '"+Main+"';"+NL+ "if (typeof global == 'undefined') global={};"+NL+ 'PATH=[process.cwd(),".","'+TOP+'"];'+NL+ 'function search(index,file) {'+NL+ ' if (file.indexOf("/")==-1) return file;'+NL+ ' if (PATH.length==index) return file;'+NL+ ' var path=PATH[index];'+NL+ ' if (Fs.existsSync(path+"/"+file+".js")) return path+"/"+file+".js";'+NL+ ' else if (Fs.existsSync(path+"/"+file)) return path+"/"+file;'+NL+ ' else return search(index+1,file);'+NL+ ' }'+NL+ 'function Require(modupath) { '+NL+ ' var file,filepath;'+NL+ ' if (BundleModules[modupath]) return BundleModules[modupath];'+NL+ ' var exports={}; var module={exports:exports};'+NL+ ' if (CoreModule[modupath]!=undefined) modupath=CoreModule[modupath];'+NL+ " if (modupath=='') return undefined;"+NL+ ' if (BundleModuleCode[modupath]) BundleModuleCode[modupath](module,exports);'+NL+ ' else if (BundleObjectCode[modupath]) BundleObjectCode[modupath](module,exports);'+NL+ ' else { try { file=search(0,modupath); module = require(file)}'+NL+ ' catch (e) { var more="";'+NL+ ' if ((e.name==="SyntaxError"||e.name==="TypeError") && file) {'+NL+ ' var src=Fs.readFileSync(file,"utf8");'+NL+ ' var Esprima = Require("parser/esprima");'+NL+ ' try {'+NL+ ' var ast = Esprima.parse(src, { tolerant: true, loc:true });'+NL+ ' if (ast.errors && ast.errors.length>0) more = ", "+ast.errors[0];'+NL+ ' } catch (e) {'+NL+ ' if (e.lineNumber) more = ", in line "+e.lineNumber;'+NL+ ' }'+NL+ ' }'+NL+ ' console.log("Require import of "+file+" failed: "+e+more);'+NL+ ' // if (e.stack) console.log(e.stack);'+NL+ ' throw e; // process.exit(-1);'+NL+ ' }}'+NL+ ' BundleModules[modupath]=module.exports||module;'+NL+ ' return module.exports||module;};'+NL+ 'FilesEmbedded=global.FilesEmbedded = {};'+NL+ 'FileEmbedd=global.FileEmbedd = function (path,format) {};'+NL+ 'FileEmbedded=global.FileEmbedded = function (path,format) {return FilesEmbedded[path](format);};'+NL+ "global.TARGET='"+global.TARGET+"';"+NL; var trailer= "var Base64=Require('os/base64');"+NL+ "module.exports=Require('"+Main+"');"+NL; var code = ''; for (var file in Files) { var modupath=Files[file][0]; var path=Files[file][1]; console.log('+'+path); if (FileExtension(path)=='json') code=code+"BundleObjectCode['"+modupath+"']=function (module,exports){\nexports="+Fs.readFileSync(path,'utf8')+'};\n'; else code=code+"BundleModuleCode['"+modupath+"']=function (module,exports){\n"+Fs.readFileSync(path,'utf8')+'};\n'; } for (var file in FilesEmbedded) { var data = FilesEmbedded[file]; if (!data) code=code+"FilesEmbedded['"+file+"']=undefined"; else { console.log('+'+file); if (typeof data == 'string') code=code+"FilesEmbedded['"+file+"']=function (format){return Base64.decode('"+Base64.encode(data)+"')};\n"; else code=code+"FilesEmbedded['"+file+"']=function (format){return Base64.decodeBuf('"+Base64.encodeBuf(data)+"')};\n"; } } console.log('Writing bundled JS file '+Bundle); var shebang = '#!/usr/bin/env pl3'; // breaks non-pl3 systems! Fs.writeFileSync(Bundle, (shebang?shebang:'')+NL+header+NL+code+NL+trailer, 'utf8'); if (shebang) Fs.chmodSync(Bundle,0755); console.log('Finished. Exit ..'); if (exit) process.exit();