mirror of
https://github.com/hanzoai/protobuf.js.git
synced 2026-09-24 17:02:08 +00:00
237 lines
8.4 KiB
JavaScript
237 lines
8.4 KiB
JavaScript
"use strict";
|
|
var fs = require("fs"),
|
|
path = require("path"),
|
|
protobuf = require("protobufjs");
|
|
|
|
function basenameCompare(a, b) {
|
|
var aa = String(a).replace(/\.\w+$/, "").split(/(-?\d*\.?\d+)/g),
|
|
bb = String(b).replace(/\.\w+$/, "").split(/(-?\d*\.?\d+)/g);
|
|
for (var i = 0, k = Math.min(aa.length, bb.length); i < k; i++) {
|
|
var x = parseFloat(aa[i]) || aa[i].toLowerCase(),
|
|
y = parseFloat(bb[i]) || bb[i].toLowerCase();
|
|
if (x < y)
|
|
return -1;
|
|
if (x > y)
|
|
return 1;
|
|
}
|
|
return a.length < b.length ? -1 : 0;
|
|
}
|
|
|
|
exports.requireAll = function requireAll(dirname) {
|
|
dirname = path.join(__dirname, dirname);
|
|
var files = fs.readdirSync(dirname).sort(basenameCompare),
|
|
all = {};
|
|
files.forEach(function(file) {
|
|
var basename = path.basename(file, ".js"),
|
|
extname = path.extname(file);
|
|
if (extname === ".js")
|
|
all[basename] = require(path.join(dirname, file));
|
|
});
|
|
return all;
|
|
};
|
|
|
|
exports.traverse = function traverse(current, fn) {
|
|
fn(current);
|
|
if (current.fieldsArray)
|
|
current.fieldsArray.forEach(function(field) {
|
|
traverse(field, fn);
|
|
});
|
|
if (current.oneofsArray)
|
|
current.oneofsArray.forEach(function(oneof) {
|
|
traverse(oneof, fn);
|
|
});
|
|
if (current.methodsArray)
|
|
current.methodsArray.forEach(function(method) {
|
|
traverse(method, fn);
|
|
});
|
|
if (current.nestedArray)
|
|
current.nestedArray.forEach(function(nested) {
|
|
traverse(nested, fn);
|
|
});
|
|
};
|
|
|
|
exports.traverseResolved = function traverseResolved(current, fn) {
|
|
fn(current);
|
|
if (current.resolvedType)
|
|
traverseResolved(current.resolvedType, fn);
|
|
if (current.resolvedKeyType)
|
|
traverseResolved(current.resolvedKeyType, fn);
|
|
if (current.resolvedRequestType)
|
|
traverseResolved(current.resolvedRequestType, fn);
|
|
if (current.resolvedResponseType)
|
|
traverseResolved(current.resolvedResponseType, fn);
|
|
};
|
|
|
|
exports.isEsmWrapper = function isEsmWrapper(wrap) {
|
|
return wrap === "esm" || wrap === "es6";
|
|
};
|
|
|
|
var env = process.env; // eslint-disable-line no-process-env
|
|
var colorEnabled =
|
|
env.NO_COLOR === undefined &&
|
|
env.FORCE_COLOR !== "0" &&
|
|
(env.FORCE_COLOR !== undefined || process.stderr && process.stderr.isTTY);
|
|
|
|
exports.color = colorEnabled ? {
|
|
reset: "\x1b[0m",
|
|
bold: "\x1b[1m",
|
|
gray: "\x1b[90m",
|
|
green: "\x1b[32m",
|
|
white: "\x1b[37m"
|
|
} : {
|
|
reset: "",
|
|
bold: "",
|
|
gray: "",
|
|
green: "",
|
|
white: ""
|
|
};
|
|
|
|
exports.wrap = function(OUTPUT, options) {
|
|
var name = options.wrap || "default";
|
|
var wrap;
|
|
try {
|
|
// try built-in wrappers first
|
|
wrap = fs.readFileSync(path.join(__dirname, "wrappers", name + ".js")).toString("utf8");
|
|
} catch (e) {
|
|
// otherwise fetch the custom one
|
|
wrap = fs.readFileSync(path.resolve(process.cwd(), name)).toString("utf8");
|
|
}
|
|
wrap = wrap.replace(/\$DEPENDENCY/g, JSON.stringify(options.dependency || "protobufjs"));
|
|
wrap = wrap.replace(/( *)\$DEFAULT_EXPORT/g, function($0, $1) {
|
|
var defaultExport = options.defaultExport || "";
|
|
if (!defaultExport)
|
|
return $1;
|
|
defaultExport = defaultExport.replace(/\r?\n/g, "\n");
|
|
return $1.length ? defaultExport.replace(/^/mg, $1) : defaultExport;
|
|
});
|
|
wrap = wrap.replace(/( *)\$OUTPUT;/, function($0, $1) {
|
|
return $1.length ? OUTPUT.replace(/^/mg, $1) : OUTPUT;
|
|
});
|
|
if (options.lint !== "")
|
|
wrap = "/*" + String(options.lint).replace(/\*\//g, "* /") + "*/\n" + wrap;
|
|
return wrap.replace(/\r?\n/g, "\n");
|
|
};
|
|
|
|
exports.pad = function(str, len, l) {
|
|
while (str.length < len)
|
|
str = l ? str + " " : " " + str;
|
|
return str;
|
|
};
|
|
|
|
|
|
/**
|
|
* DFS to get all message dependencies, cache in filterMap.
|
|
* @param {Root} root The protobuf root instance
|
|
* @param {Message} message The message need to process.
|
|
* @param {Map} filterMap The result of message you need and their dependencies.
|
|
* @param {Map} flatMap A flag to record whether the message was searched.
|
|
* @returns {undefined} Does not return a value
|
|
*/
|
|
function dfsFilterMessageDependencies(root, message, filterMap, flatMap) {
|
|
if (message instanceof protobuf.Type) {
|
|
if (flatMap.get(`${message.fullName}`)) return;
|
|
flatMap.set(`${message.fullName}`, true);
|
|
for (var field of message.fieldsArray) {
|
|
if (field.resolvedType) {
|
|
// a nested message
|
|
if (field.resolvedType.parent.name === message.name) {
|
|
var nestedMessage = message.nested[field.resolvedType.name];
|
|
dfsFilterMessageDependencies(root, nestedMessage, filterMap, flatMap);
|
|
continue;
|
|
}
|
|
var packageName = field.resolvedType.parent.name;
|
|
var typeName = field.resolvedType.name;
|
|
var fullName = packageName ? `${packageName}.${typeName}` : typeName;
|
|
doFilterMessage(root, { messageNames: [fullName] }, filterMap, flatMap, packageName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* DFS to get all message you need and their dependencies, cache in filterMap.
|
|
* @param {Root} root The protobuf root instance
|
|
* @param {object} needMessageConfig Need message config:
|
|
* @param {string[]} needMessageConfig.messageNames The message names array in the root namespace you need to gen. example: [msg1, msg2]
|
|
* @param {Map} filterMap The result of message you need and their dependencies.
|
|
* @param {Map} flatMap A flag to record whether the message was searched.
|
|
* @param {string} currentPackageName Current package name
|
|
* @returns {undefined} Does not return a value
|
|
*/
|
|
function doFilterMessage(root, needMessageConfig, filterMap, flatMap, currentPackageName) {
|
|
var needMessageNames = needMessageConfig.messageNames;
|
|
|
|
for (var messageFullName of needMessageNames) {
|
|
var nameSplit = messageFullName.split(".");
|
|
var packageName = "";
|
|
var messageName = "";
|
|
if (nameSplit.length > 1) {
|
|
packageName = nameSplit[0];
|
|
messageName = nameSplit[1];
|
|
} else {
|
|
messageName = nameSplit[0];
|
|
}
|
|
|
|
// in Namespace
|
|
if (packageName) {
|
|
var ns = root.nested[packageName];
|
|
if (!ns || !(ns instanceof protobuf.Namespace)) {
|
|
throw new Error(`package not foud ${currentPackageName}.${messageName}`);
|
|
}
|
|
|
|
doFilterMessage(root, { messageNames: [messageName] }, filterMap, flatMap, packageName);
|
|
} else {
|
|
var message = root.nested[messageName];
|
|
|
|
if (currentPackageName) {
|
|
message = root.nested[currentPackageName].nested[messageName];
|
|
}
|
|
|
|
if (!message) {
|
|
throw new Error(`message not foud ${currentPackageName}.${messageName}`);
|
|
}
|
|
|
|
var set = filterMap.get(currentPackageName);
|
|
if (!filterMap.has(currentPackageName)) {
|
|
set = new Set();
|
|
filterMap.set(currentPackageName, set);
|
|
}
|
|
|
|
set.add(messageName);
|
|
|
|
// dfs to find all dependencies
|
|
dfsFilterMessageDependencies(root, message, filterMap, flatMap, currentPackageName);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* filter the message you need and their dependencies, all others will be delete from root.
|
|
* @param {Root} root Root the protobuf root instance
|
|
* @param {object} needMessageConfig Need message config:
|
|
* @param {string[]} needMessageConfig.messageNames Tthe message names array in the root namespace you need to gen. example: [msg1, msg2]
|
|
* @returns {boolean} True if a message should present in the generated files
|
|
*/
|
|
exports.filterMessage = function (root, needMessageConfig) {
|
|
var filterMap = new Map();
|
|
var flatMap = new Map();
|
|
doFilterMessage(root, needMessageConfig, filterMap, flatMap, "");
|
|
root._nestedArray = root._nestedArray.filter(ns => {
|
|
if (ns instanceof protobuf.Type || ns instanceof protobuf.Enum) {
|
|
return filterMap.get("").has(ns.name);
|
|
} else if (ns instanceof protobuf.Namespace) {
|
|
if (!filterMap.has(ns.name)) {
|
|
return false;
|
|
}
|
|
ns._nestedArray = ns._nestedArray.filter(nns => {
|
|
const nnsSet = filterMap.get(ns.name);
|
|
return nnsSet.has(nns.name);
|
|
});
|
|
|
|
return true;
|
|
}
|
|
return true;
|
|
});
|
|
};
|
|
|