自定义Gulp.js插件:TypeError“路径必须是字符串。收到未定义”

时间:2017-02-10 14:32:57

标签: javascript gulp gulp-plugin

我在StackOverflow上找到了几个关于<select id="selector"> <option value="" disabled="disabled" selected="selected">Select a layout</option> <option value="1">One</option> <option value="2">Two</option> </select>的线程,尽管我无法将建议的解决方案应用到我的案例中。

我正在尝试构建一个连接到(付费)javascriptobfuscator.com服务的Gulp插件,并使用他们的TypeError: Path must be a string API来混淆我的JS。

Gulp任务看起来像:

POST

var gulp = require('gulp'), jso = require('./jsobfuscator'); gulp.task('jso', function() { // .jsx contain extendscript language, which as far as // the service is concerned, could be treated as .js return gulp.src('.src/app/jsx/photoshop.jsx') .pipe(jso()) .pipe(gulp.dest('./dist')) }); 文件包含以下代码:

jsobfuscator.js

当我运行gulp任务时,我显然从javascriptobfuscator代码得到了正确的响应(如下所示)但是我将文件传递到目的地的部分出了问题,因为我得到了:

var through = require('through2'),
    http = require('http'),
    gutil = require('gulp-util'),
    Readable = require('stream').Readable

module.exports = function() {
  /**
   * @this {Transform}
   */

    var transform = function(file, encoding, callback) {

        var that = this;

        var proj = {};
        proj.APIKey = "/* MyAPIKey*/";
        proj.APIPwd = "/* MyAPIPwd*/";
        proj.Name = "DoubleUSM";
        proj.ReorderCode = true;
        proj.ReplaceNames = true;
        proj.EncodeStrings = true;
        proj.MoveStrings = true;
        proj.MoveMembers = true;
        proj.DeepObfuscate = true;
        proj.SelfCompression = true;
        // Unsure about these two...
        proj.CompressionRatio = "Auto";
        proj.OptimizationMode = "Auto";

        var appJS = new Object();
        appJS.FileName = "app.js";
        appJS.FileCode = file.contents.toString('utf8');
        // Will try to implement multiple files later on
        proj.Items = [appJS];

        var postData = JSON.stringify(proj);

        // Length is OK
        gutil.log ("Length: " + Buffer.byteLength(postData, 'utf-8'))

        var options = {
            host: 'service.javascriptobfuscator.com',
            path: '/HttpApi.ashx',
            method: 'POST',
            headers: { 
                'Content-Type': 'text/json',
                'Content-Length': Buffer.byteLength(postData, 'utf-8')
            }
        };

        callback = function(response) {
            response.setEncoding('utf8');

            var str = '';
            response.on('data', function(chunk) {
                str += chunk;
            });

            response.on('end', function() {
                // I get the correct response here!
                gutil.log(JSON.stringify(JSON.parse(str), null, '  '));

                var resObj = JSON.parse(str);
                // Converting the received string into a Buffer
                var fileStream = new Readable();
                // resObj.Items[0].FileCode is where the obfuscated code belongs
                fileStream.push(resObj.Items[0].FileCode);
                fileStream.push(null);
                that.push(fileStream);
                callback();
            });
        }

        var req = http.request(options, callback);
        req.write(postData);
        req.end();
    };

    return through.obj(transform);
};

不可否认,我不是Gulp插件的专家 - 我正在尝试为自己的私人用途构建一个功能。看起来我很亲密,但我已经陷入了这个死胡同的一段时间,我需要更有经验的人的帮助。

提前致谢

半工作更新

按如下方式修改(master)* gulp jso [15:13:30] Using gulpfile ~/Dropbox/Developer/PROJECTS/DOUBLE USM/gulpfile.js [15:13:30] Starting 'jso'... [15:13:31] Lenght: 21897 [15:13:32] { "Type": "Succeed", "Items": [ { "FileName": "app.js", "FileCode": /* ... Long, horrible, properly obfuscated blob here... */ } ], "ErrorCode": null, "Message": null, "FileName": null, "LineNumber": null, "ExceptionToString": null } path.js:7 throw new TypeError('Path must be a string. Received ' + inspect(path)); ^ TypeError: Path must be a string. Received undefined at assertPath (path.js:7:11) at Object.resolve (path.js:1146:7) at DestroyableTransform.saveFile [as _transform] (/Users/davidebarranca/Dropbox/Developer/PROJECTS/DOUBLE USM/node_modules/vinyl-fs/lib/dest/index.js:36:26) at DestroyableTransform.Transform._read (/Users/davidebarranca/Dropbox/Developer/PROJECTS/DOUBLE USM/node_modules/vinyl-fs/node_modules/readable-stream/lib/_stream_transform.js:184:10) at DestroyableTransform.Transform._write (/Users/davidebarranca/Dropbox/Developer/PROJECTS/DOUBLE USM/node_modules/vinyl-fs/node_modules/readable-stream/lib/_stream_transform.js:172:12) at doWrite (/Users/davidebarranca/Dropbox/Developer/PROJECTS/DOUBLE USM/node_modules/vinyl-fs/node_modules/readable-stream/lib/_stream_writable.js:237:10) at writeOrBuffer (/Users/davidebarranca/Dropbox/Developer/PROJECTS/DOUBLE USM/node_modules/vinyl-fs/node_modules/readable-stream/lib/_stream_writable.js:227:5) at DestroyableTransform.Writable.write (/Users/davidebarranca/Dropbox/Developer/PROJECTS/DOUBLE USM/node_modules/vinyl-fs/node_modules/readable-stream/lib/_stream_writable.js:194:11) at DestroyableTransform.ondata (/Users/davidebarranca/Dropbox/Developer/PROJECTS/DOUBLE USM/node_modules/through2/node_modules/readable-stream/lib/_stream_readable.js:546:20) at emitOne (events.js:96:13) 回调,我终于可以写文件了:

response.on('end')

我不得不评论最后的response.on('end', function() { var resObj = JSON.parse(str); var fileStream = new Readable(); fileStream.push(resObj.Items[0].FileCode); fileStream.push(null); // Manually creating a new Vinyl file var jsFile = new Vinyl({ cwd: file.cwd, base: file.base, path: file.path, contents: fileStream }); return that.push(jsFile); // callback(); }); ,否则我会遇到指向callback()行的错误,response.setEncoding('utf8');未定义。

现在的问题似乎是任务,在某种程度上,永不终止。控制台显示response,文件已写入,控制台返回,但没有Starting 'jso'...,最糟糕的是,我完全之后无法链接更多gulp任务 ,所以,如果我:

Finished 'jso' after nn ms

我得到的唯一的事情是gulp.task('jso1', function() { return gulp.src('.src/app/jsx/photoshop.jsx') .pipe(jso()) .pipe(gulp.dest('./dist')) }); gulp.task('jso2', ['jso1'], function() { return gulp.src('.src/app/app.js') .pipe(jso()) .pipe(gulp.dest('./dist')) }); // then in the Terminal: $ gulp jso2 开始,显然有效,但从未完成; jso1永远不会运行。

1 个答案:

答案 0 :(得分:0)

许多小时的头部刮伤让我得到答案。简而言之,在我的Gulp插件中:

  1. 我必须在response.on('end')回调中返回一个新的Vinyl文件:文件的contents属性需要是来自服务器响应的流。
  2. 我的半工作解决方案的主要缺陷是我已经将同名(callback)赋予了两个非常不同的功能。一个是来自初始callback函数的transform;另一个是http.request回调。在callback()之后评论出最后一次return that.push(jsFile);电话会阻止整个Gulp任务结束。
  3. 完整的工作代码如下:

    var through  = require('through2'),
        http     = require('http'),
        gutil    = require('gulp-util'),
        Readable = require('stream').Readable,
        Vinyl    = require('vinyl');
    
    module.exports = function() {
    
        var transform = function(file, encoding, callback) {
    
            if (file.isNull()) { return callback(null, file) }
    
            var that = this;
    
            var proj = {};
            proj.APIKey = "/* MyAPIKey */";
            proj.APIPwd = "/* APIPwd */";
            proj.Name = "Project";
            proj.ReorderCode = true;
            proj.ReplaceNames = true;
            proj.EncodeStrings = true;
            proj.MoveStrings = true;
            proj.MoveMembers = true;
            proj.DeepObfuscate = true;
            proj.SelfCompression = true;
            proj.CompressionRatio = "Auto";
            proj.OptimizationMode = "Auto";
    
            var appJS = new Object();
            appJS.FileName = "app.js";
            appJS.FileCode = file.contents.toString('utf8');
    
            proj.Items = [appJS];
    
            var postData = JSON.stringify(proj);
    
            var options = {
                host: 'service.javascriptobfuscator.com',
                path: '/HttpApi.ashx',
                method: 'POST',
                headers: { 
                    'Content-Type': 'text/json',
                    'Content-Length': Buffer.byteLength(postData, 'utf-8')
                }
            };
    
            /* Renamed to avoid confusion with transform's callback */
            postCallback = function(response) {
    
                response.setEncoding('utf8');
                var str = '';
                response.on('data', function(chunk) {
                    str += chunk;
                });
    
                response.on('end', function() {
    
                    var resObj = JSON.parse(str);
                    var fileStream = new Readable();
                    fileStream.push(resObj.Items[0].FileCode);
                    fileStream.push(null);
    
                    /* Return a new Vinyl File */
                    var jsFile = new Vinyl({
                        cwd: file.cwd,
                        base: file.base,
                        path: file.path,
                        contents: fileStream
                    });
    
                    that.push(jsFile);
                    callback();
                });
            }
    
            var req = http.request(options, postCallback);
            req.write(postData);
            req.end();
    
        };
    
        return through.obj(transform);
    };
    

    也许有更好的方法可以在不创建新文件的情况下返回Vinyl文件。

    另一个改进是将所有源文件分组并对javascriptobfuscator API进行单个http调用(事实上可以将多个文件添加到proj.Items数组中),但我不知道如何分组源文件中的文件,将它们一次性传递给Gulp插件,然后稍后将它们拆分。