Skip to content

Commit

Permalink
pbjs static target progress, uses customizable wrapper template [ci s…
Browse files Browse the repository at this point in the history
…kip]
  • Loading branch information
dcodeIO committed Dec 3, 2016
1 parent fce8276 commit 4885b82
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 72 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,10 @@ The `pbjs` command line utility can be used to bundle and translate between .pro
Consolidates imports and converts between file formats.
-t, --target Specifies the target format. [json, proto2, proto3]
Also accepts a path to require a custom target.
-p, --path Adds a directory to the include path.
-o, --out Saves to a file instead of writing to stdout.
usage: pbjs [options] file1.proto file2.json ...
Expand Down
23 changes: 14 additions & 9 deletions cli/pbjs.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ exports.main = function(args) {
alias: {
target : "t",
out : "o",
path : "p"
path : "p",
wrap : "w"
},
string: [ "target", "out", "path" ],
string: [ "target", "out", "path", "wrap" ],
default: {
target: "json"
}
});

var target = targets[argv.target],
files = argv._,
paths = typeof argv.path === 'string' ? [ argv.path ] : argv.path || [];
Expand All @@ -35,17 +37,18 @@ exports.main = function(args) {
"",
" -t, --target Specifies the target format. [" + Object.keys(targets).filter(function(key) { return !targets[key].private; }).join(', ') + "]",
" Also accepts a path to require a custom target.",
"",
" -p, --path Adds a directory to the include path.",
"",
" -o, --out Saves to a file instead of writing to stdout.",
"",
" -w, --wrap Specifies an alternative wrapper for the static target.",
"",
"usage: " + chalk.bold.green(path.basename(process.argv[1])) + " [options] file1.proto file2.json ..."
].join("\n"));
return 1;
}

if (!target)
target = require(path.resolve(process.cwd(), argv.target));

// Resolve glob expressions
for (var i = 0; i < files.length;) {
if (glob.hasMagic(files[i])) {
Expand All @@ -56,9 +59,13 @@ exports.main = function(args) {
++i;
}

// Require custom target
if (!target)
target = require(path.resolve(process.cwd(), argv.target));

var root = new protobuf.Root();

// Fall back to include paths when resolving imports
// Search include paths when resolving imports
root.resolvePath = function pbjsResolvePath(origin, target) {
var filepath = protobuf.util.resolvePath(origin, target);
if (fs.existsSync(filepath))
Expand All @@ -71,12 +78,10 @@ exports.main = function(args) {
return filepath;
};

var options = {};

root.load(files, function(err) {
if (err)
throw err;
target(root, options, function(err, output) {
target(root, argv, function(err, output) {
if (err)
throw err;
if (output !== "") {
Expand Down
1 change: 1 addition & 0 deletions cli/targets/json.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"use strict";
module.exports = json_target;

var protobuf = require("../..");
Expand Down
1 change: 1 addition & 0 deletions cli/targets/proto.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"use strict";
module.exports = proto_target;

proto_target.private = true;
Expand Down
1 change: 1 addition & 0 deletions cli/targets/proto2.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"use strict";
module.exports = proto2_target;

var protobuf = require("../..");
Expand Down
1 change: 1 addition & 0 deletions cli/targets/proto3.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"use strict";
module.exports = proto3_target;

var protobuf = require("../..");
Expand Down
73 changes: 38 additions & 35 deletions cli/targets/static.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
"use strict";
module.exports = static_target;

static_target.private = true;
// - Static code does not have any reflection or JSON features.
// - The default wrapper supports AMD, CommonJS and the global scope (as window.root), in this order.
// - You can specify a custom wrapper with the --wrap argument.
// - CommonJS modules depend on the minimal static runtime for reduced package size with browserify.
// - AMD and global scope depend on the full library for now.
// - Services aren't supported, yet.

// Currently, this target builds single file CommonJS modules.
// - There is no reflection and no message inheritance from Prototype.
// - Generated code is tailored for browerify build processes (minimal runtime).

// TBD:
// - Generate a single file or scaffold an entire project directory? Both?
// - Targets: ES5, ES6, TypeScript? CommonJS? AMD?
// - What about generating typescript definitions for non-ts targets?
var path = require("path"),
fs = require("fs");

var protobuf = require("../..");

Expand All @@ -26,14 +26,21 @@ var out = [];
var indent = 0;

function static_target(root, options, callback) {
tree = {};
if (options.wrap)
options.wrap = path.resolve(process.cwd(), options.wrap);
else
options.wrap = path.join(__dirname, "static.tpl");
try {
buildNamespace("module.exports", root);
callback(null, out.join('\n'));
var wrap = fs.readFileSync(options.wrap).toString("utf8");
++indent;
buildNamespace(null, root);
--indent;
callback(null, wrap.replace(/\r?\n%OUTPUT%/, out.join('\n')));
} catch (err) {
callback(err);
} finally {
out = [];
indent = 0;
}
}

Expand Down Expand Up @@ -63,17 +70,7 @@ function name(name) {
function buildNamespace(ref, ns) {
if (!ns)
return;
if (ns.name === "") { // root
push(name(ref) + " = (function() {");
++indent;
push('"use strict";');
push("");
push("// Minimal static codegen runtime");
push("var $runtime = require(\"protobufjs/runtime\");")
push("");
push("// Lazily resolved type references");
push("var $lazyTypes = [];");
} else {
if (ns.name !== "") {
push("");
push("/** @alias " + ns.fullName.substring(1) + " */");
push(name(ref) + "." + name(ns.name) + " = (function() {");
Expand All @@ -84,7 +81,7 @@ function buildNamespace(ref, ns) {
buildType(undefined, ns);
} else if (ns instanceof Service)
buildService(undefined, ns);
else {
else if (ns.name !== "") {
push("");
push("/** @alias " + (ns.name && ns.fullName.substring(1) || "exports") + " */");
push("var " + name(ns.name) + " = {};");
Expand All @@ -96,13 +93,12 @@ function buildNamespace(ref, ns) {
else if (nested instanceof Namespace)
buildNamespace(ns.name, nested);
});
push("");
if (ns.name === "") // root
push("return $runtime.resolve($root, $lazyTypes);");
else
if (ns.name !== "") {
push("");
push("return " + name(ns.name) + ";");
--indent;
push("})();");
--indent;
push("})();");
}
}

function buildFunction(type, functionName, gen, scope) {
Expand Down Expand Up @@ -235,17 +231,24 @@ function buildType(ref, type) {

function buildService(ref, service) {
push("");
push(name(ref) + "." + name(service.name) + " = {};"); // currently just an empty object
push(name(ref) + "." + name(service.name) + " = {};");
// TODO: Services are just empty objects currently
}

function buildEnum(ref, enm) {
push("");
push(ref + "." + enm.name + " = {");
pushComment([
enm.name + " values.",
"@exports " + enm.fullName.substring(1),
"@type {Object.<string,number>}"
]);
push(name(ref) + "." + name(enm.name) + " = {");
++indent;
push("");
Object.keys(enm.values).forEach(function(key) {
push(name(key) + ": " + enm.values[key].toString(10) + ",");
});
var keys = Object.keys(enm.values);
for (var i = 0; i < keys.length; ++i) {
push(name(keys[i]) + ": " + enm.values[keys[i]].toString(10) + (i < keys.length - 1 ? "," : ""));
}
--indent;
push("};");
}
37 changes: 37 additions & 0 deletions cli/targets/static.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
;(function(global, factory) {
/* AMD */ if (typeof define === 'function' && define.amd)
define(["protobuf"], factory);
/* CommonJS */ else if (typeof require === 'function' && typeof module === 'object' && module && module.exports)
module.exports = factory(require("protobufjs/runtime"));
/* Global */ else
global.root = factory(global.protobuf);
})(this, function($runtime) {
"use strict";
// Lazily resolved type references
var $lazyTypes = [];
// Exported root namespace
var $root = {};

%OUTPUT%

// Resolve lazy types
$lazyTypes.forEach(function(types) {
types.forEach(function(path, i) {
if (!path)
return;
path = path.split('.');
var ptr = $root;
while (path.length)
ptr = ptr[path.shift()];
types[i] = ptr;
});
});

return $root;
});
21 changes: 0 additions & 21 deletions runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,3 @@ runtime.Writer = require("./src/writer");
* @memberof runtime
*/
runtime.util = require("./src/util/runtime");

/**
* Resolves lazy type references.
* @param {Object} root Root object
* @param {string[][]} lazyTypes Lazy type references
* @returns {Object} `root`
*/
runtime.resolve = function resolve(root, lazyTypes) {
lazyTypes.forEach(function(types) {
types.forEach(function(path, i) {
if (!path)
return;
path = path.split('.');
var ptr = root;
while (path.length)
ptr = ptr[path.shift()];
types[i] = ptr;
});
});
return root;
};
35 changes: 28 additions & 7 deletions tests/data/package.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
module.exports = (function() {
"use strict";
;(function(global, factory) {

/* AMD */ if (typeof define === 'function' && define.amd)
define(["protobuf"], factory);

/* CommonJS */ else if (typeof require === 'function' && typeof module === 'object' && module && module.exports)
module.exports = factory(require("../../runtime"));

/* Global */ else
global.root = factory(global.protobuf);

// Minimal static codegen runtime
var $runtime = require("../../runtime");
})(this, function($runtime) {
"use strict";

// Lazily resolved type references
var $lazyTypes = [];

/** @alias exports */
// Exported root namespace
var $root = {};

/** @alias Package */
Expand Down Expand Up @@ -416,5 +424,18 @@ module.exports = (function() {
return Package;
})();

return $runtime.resolve($root, $lazyTypes);
})();
// Resolve lazy types
$lazyTypes.forEach(function(types) {
types.forEach(function(path, i) {
if (!path)
return;
path = path.split('.');
var ptr = $root;
while (path.length)
ptr = ptr[path.shift()];
types[i] = ptr;
});
});

return $root;
});

0 comments on commit 4885b82

Please sign in to comment.