245 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			245 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| #!/usr/bin/env node
 | |
| var fs = require('fs');
 | |
| var path = require('path');
 | |
| 
 | |
| // These are the node packages we are going to wrap.
 | |
| var packages = {
 | |
|     assert: { skip: true },
 | |
|     async_hooks: { optional: true, skip: true },
 | |
|     buffer: { skip: true },
 | |
|     child_process: {
 | |
|         exec: { promisify: true, returnsObject: true, args: 1, cb:['stdout','stderr'] },
 | |
|         execFile: { promisify: true, returnsObject: true, args: 1, cb:['stdout','stderr'] },
 | |
|         fork: { promisify: false },
 | |
|         spawn: { promisify: false },
 | |
|     },
 | |
|     cluster: {
 | |
|         disconnect: { promisify: true, args: 0 },
 | |
|     },
 | |
|     console: { skip: true },
 | |
|     crypto: {
 | |
|         DEFAULT_ENCODING: { constant: false },
 | |
|         pseudoRandomBytes: { promisify: true, syncIfNoCallback: true, args: 1 },
 | |
|         randomBytes: { promisify: true, syncIfNoCallback: true, args: 1 },
 | |
|         randomFill: { args: 1 },
 | |
|     },
 | |
|     dns: {
 | |
|         // XXX: Resolver could be wrapped...
 | |
|         ADNAME: { skip: true },
 | |
|         lookup: { promisify: true, args: 1 },
 | |
|         lookupService: { promisify: true, args: 2, cb:['hostname','service'] },
 | |
|         resolve: { promisify: true, args: 1 },
 | |
|         resolve4: { promisify: true, args: 1 },
 | |
|         resolve6: { promisify: true, args: 1 },
 | |
|         resolveAny: { promisify: true, args: 1 },
 | |
|         resolveCname: { promisify: true, args: 1 },
 | |
|         resolveMx: { promisify: true, args: 1 },
 | |
|         resolveNaptr: { promisify: true, args: 1 },
 | |
|         resolveNs: { promisify: true, args: 1 },
 | |
|         resolvePtr: { promisify: true, args: 1 },
 | |
|         resolveSoa: { promisify: true, args: 1 },
 | |
|         resolveSrv: { promisify: true, args: 1 },
 | |
|         resolveTxt: { promisify: true, args: 1 },
 | |
|         reverse: { promisify: true, args: 1 },
 | |
|     },
 | |
|     domain: {
 | |
|         // XXX Domain#bind and Domain#intercept should be promisified
 | |
|     },
 | |
|     events: {
 | |
|         skip: true,
 | |
|     },
 | |
|     fs: {
 | |
|         access: { args: 1 },
 | |
|         appendFile: { args: 2 },
 | |
|         copyFile: { args: 2 },
 | |
|         exists: { promisify: true, noError: true },
 | |
|         mkdir: { args: 1 },
 | |
|         mkdtemp: { args: 1 },
 | |
|         open: { args: 2 },
 | |
|         read: { cb: ['read', 'buffer'] },
 | |
|         readdir: { args: 1 },
 | |
|         readlink: { args: 1 },
 | |
|         readFile: { args: 1 },
 | |
|         realpath: { args: 1 },
 | |
|         symlink: { args: 2 },
 | |
|         write: { cb: ['written', 'buffer'] },
 | |
|         writeFile: { args: 2 },
 | |
|     },
 | |
|     http: {
 | |
|         STATUS_CODES: { constant: true },
 | |
|         // XXX ClientRequest#setTimeout should be promisified
 | |
|         // XXX IncomingMessage#setTimeout should be promisified
 | |
|         // XXX Server#listen, Server#close, and Server#setTimeout
 | |
|         // should be promisified
 | |
|         // XXX ServerResponse#setTimeout should be promisified
 | |
|         request: { promisify: true, returnsObject: true, args: 1 },
 | |
|         get: { promisify: true, returnsObject: true, args: 1 },
 | |
|     },
 | |
|     http2: {
 | |
|         optional: true,
 | |
|     },
 | |
|     https: {
 | |
|         // XXX Server#listen, Server#close, and Server#setTimeout
 | |
|         // should be promisified
 | |
|         request: { promisify: true, returnsObject: true, args: 1 },
 | |
|         get: { promisify: true, returnsObject: true, args: 1 },
 | |
|     },
 | |
|     inspector: {
 | |
|         optional: true,
 | |
|         skip: true,
 | |
|     },
 | |
|     net: {
 | |
|         // XXX Server#listen, Server#close, Server#getConnections
 | |
|         // should be promisified
 | |
|         // XXX Socket#write, Socket#setTimeout should be promisified
 | |
|     },
 | |
|     os: { skip: true },
 | |
|     path: { skip: true },
 | |
|     perf_hooks: { optional: true, skip: true },
 | |
|     process: {
 | |
|         nextTick: { promisify: true, args: 0 }
 | |
|     },
 | |
|     punycode: { optional: true, skip: true },
 | |
|     querystring: { skip: true },
 | |
|     readline: {
 | |
|         // XXX Interface#question should be promisified
 | |
|     },
 | |
|     repl: { skip: true },
 | |
|     stream: {
 | |
|         super_: { skip: true },
 | |
|         // XXX Writable#write and Writable#end should be promisified
 | |
|         // XXX same for Duplex and Transform? inheritance unclear.
 | |
|         // what about _read/_write/_transform/_flush for implementers?
 | |
|     },
 | |
|     string_decoder: { skip: true },
 | |
|     timers: {
 | |
|         setImmediate: { promisify: true, callbackIsFirstArg: true, noError: true },
 | |
|         setTimeout: { promisify: true, callbackIsFirstArg: true, noError: true },
 | |
|     },
 | |
|     tls: {
 | |
|         connect: { promisify: true, returnsObject: true, args: 1 },
 | |
|         createServer: { promisify: true, returnsObject: true, args: 1 },
 | |
|     },
 | |
|     tty: {
 | |
|         skip: true
 | |
|         // should tty.ReadStream and tty.WriteStream be promisified?
 | |
|         // (process.stdin / process.stdout)
 | |
|     },
 | |
|     dgram: {
 | |
|         // note that createSocket takes a listener, not a callback
 | |
|         // XXX Socket#send and Socket#bind should be promisified
 | |
|     },
 | |
|     url: { skip: true },
 | |
|     util: {
 | |
|         pump: { promisify: true, args: 2 }
 | |
|     },
 | |
|     v8: { optional: true, skip: true },
 | |
|     vm: { skip: true },
 | |
|     zlib: {
 | |
|         codes: { constant: true },
 | |
|         deflate: { promisify: true, args: 1 },
 | |
|         deflateRaw: { promisify: true, args: 1 },
 | |
|         gzip: { promisify: true, args: 1 },
 | |
|         gunzip: { promisify: true, args: 1 },
 | |
|         inflate: { promisify: true, args: 1 },
 | |
|         inflateRaw: { promisify: true, args: 1 },
 | |
|         unzip: { promisify: true, args: 1 },
 | |
|     },
 | |
| };
 | |
| 
 | |
| var sorted = function(arr) {
 | |
|     var s = arr.slice(0);
 | |
|     s.sort();
 | |
|     return s;
 | |
| }
 | |
| 
 | |
| sorted(Object.keys(packages)).forEach(function(pkgname) {
 | |
|     var pkgopts = packages[pkgname] || {};
 | |
|     var script = [];
 | |
|     var emit = function(l) { script.push(l); };
 | |
|     var m;
 | |
|     if (pkgname==='process') {
 | |
|         m = process;
 | |
|     } else if (pkgopts.optional) {
 | |
|         // Package is not present in older versions of node.
 | |
|         emit('var '+pkgname+' = {};');
 | |
|         emit('try { '+pkgname+' = require("'+pkgname+'"); } catch (e) { }');
 | |
|         m = require(pkgname);
 | |
|     } else {
 | |
|         emit('var '+pkgname+' = require("'+pkgname+'");');
 | |
|         m = require(pkgname);
 | |
|     }
 | |
|     if (pkgopts.skip) {
 | |
|         emit('module.exports = '+pkgname+';');
 | |
|     } else {
 | |
|         emit('var promisify = require("./_promisify.js");');
 | |
|         emit('var bind = function(c, f) { return f && f.bind(c); };');
 | |
|         emit('Object.defineProperties(module.exports, {');
 | |
|         sorted(Object.keys(m)).forEach(function(prop) {
 | |
|             var opts = pkgopts[prop] || {};
 | |
|             // skip private properties
 | |
|             if (opts.skip !== undefined ? opts.skip : /^_/.test(prop)) {
 | |
|                 emit('  //'+prop+': // skipping');
 | |
|                 return;
 | |
|             }
 | |
|             var out = '  '+prop+': { enumerable: true, ';
 | |
|             // Is this a function?
 | |
|             var caps = /^[A-Z]/.test(prop);
 | |
|             var isFunction = typeof(m[prop]) === 'function';
 | |
|             var isConstant = opts.constant!==undefined ? opts.constant :
 | |
|                 isFunction ?
 | |
|                 (opts.bind !== undefined ? opts.bind===false : caps) :
 | |
|                 caps;
 | |
|             if (isConstant) {
 | |
|                 emit(out+'value: '+pkgname+'.'+prop+' },');
 | |
|                 return;
 | |
|             }
 | |
|             if (!isFunction) {
 | |
|                 // add getters & setters
 | |
|                 emit(out+'get: function() { return '+pkgname+'.'+prop+'; }, '+
 | |
|                      'set: function(v) { '+pkgname+'.'+prop+' = v; } },');
 | |
|                 return;
 | |
|             }
 | |
|             // Is this a async function?
 | |
|             var isAsync = (typeof(m[prop+'Sync']) === 'function');
 | |
|             if (opts.promisify) { isAsync = true; }
 | |
|             if (!isAsync || opts.promisify === false) {
 | |
|                 emit(out+'value: bind('+pkgname+', '+pkgname+'.'+prop+') },');
 | |
|                 return;
 | |
|             }
 | |
|             // OK, this is very likely an async function!
 | |
|             // number of mandatory options (may be additional optional args)
 | |
|             var nargs = opts.args!==undefined ? opts.args :
 | |
|                 (typeof(m[prop+'Sync']) === 'function') ?
 | |
|                 m[prop+'Sync'].length : m[prop].length;
 | |
|             var options = {}, emitOptions = false;
 | |
|             if (opts.cb) {
 | |
|                 options.pattern = opts.cb;
 | |
|                 emitOptions = true;
 | |
|             }
 | |
|             if (opts.noError) {
 | |
|                 options.noError = true;
 | |
|                 emitOptions = true;
 | |
|             }
 | |
|             if (opts.returnsObject) {
 | |
|                 options.returnsObject = true;
 | |
|                 emitOptions = true;
 | |
|             }
 | |
|             if (opts.callbackIsFirstArg) {
 | |
|                 options.callbackIsFirstArg = true;
 | |
|                 nargs = 0;
 | |
|                 emitOptions = true;
 | |
|             }
 | |
|             var optString = emitOptions ? ', '+JSON.stringify(options) : '';
 | |
|             emit(out+'value: promisify('+pkgname+', '+pkgname+'.'+prop+', '+nargs+optString+') },');
 | |
|             if (opts.syncIfNoCallback) {
 | |
|                 emit(out.replace(/:/,"Sync:")+'value: '+pkgname+'.'+prop+'.bind('+pkgname+') },');
 | |
|             }
 | |
|         });
 | |
|         emit('});');
 | |
|     }
 | |
|     // Write out this wrapped package!
 | |
|     fs.writeFileSync(path.join(__dirname,'..',pkgname+'.js'),
 | |
|                      script.join('\n'), 'utf-8');
 | |
| });
 |