You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					245 lines
				
				8.9 KiB
			
		
		
			
		
	
	
					245 lines
				
				8.9 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								#!/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');
							 | 
						||
| 
								 | 
							
								});
							 |