proto-gen-dts
Version:
proto generate typescript dictionary type file
328 lines (260 loc) • 12.4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _stanUtils = require("stan-utils");
var _protobufjs = require("protobufjs");
var _util = require("./util");
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
var dtsTemplate = "<%= comment %>\ndeclare namespace <%= namespace %> {\n<%= content %>\n}";
var interfaceTemplate = "<%= comment %>\nexport interface <%= name %> {\n<%= content %>\n}";
var enumTemplate = "<%= comment %>\nexport enum <%= name %> {\n<%= content %>\n}";
var serviceTemplate = "<%= comment %>\nexport interface <%= name %>Service {\n<%= content %>\n}";
var serviceFNTemplate = "<%= comment %>\n<%= name %><R extends <%= requestType %>, O>(r: R, o?: O): Promise<<%= responseType %>>,";
var dtsExecutor = _stanUtils.lodash.template(dtsTemplate);
var interfaceExecutor = _stanUtils.lodash.template(interfaceTemplate);
var enumExecutor = _stanUtils.lodash.template(enumTemplate);
var serviceExecutor = _stanUtils.lodash.template(serviceTemplate);
var serviceFNExecutor = _stanUtils.lodash.template(serviceFNTemplate);
/**
* Parsed proto content to dts content
* @description Nested message names will be spliced by _
* @param namespace {Namespace}
* @param filename {string}
* @param visitor {Visitor}
* @returns dts content
*/
function parseNamespace(namespace, filename, visitor) {
var _visitor$EmitTSNamesp;
var moduleName = namespace.name;
var parsedNestedList = []; // record generation history to prevent repeated generation
var hasGenMap = {
enums: new Map(),
services: new Map(),
interfaces: new Map()
}; // construct the name of the message embedded in the message
function replaceNamespacePrefix(name, field) {
var _namespace$lookup;
var _filename = (_namespace$lookup = namespace.lookup(name)) === null || _namespace$lookup === void 0 ? void 0 : _namespace$lookup.filename; // not current namespace types
if (_filename !== filename) {
var arr = name.split('.'); // other files, search from the GoogleProtoFilesRoot
var lastNamespaceIndex = arr.findIndex(function (_, index) {
return !(0, _util.isNamespace)((0, _util.getNamespaceRoot)(namespace).lookup(arr.slice(0, index + 1).join('.')));
});
if (!lastNamespaceIndex) {
return name;
}
return [arr.slice(0, lastNamespaceIndex).join('.'), arr.slice(lastNamespaceIndex).join('_')].filter(String).join('.');
}
if (field && !name.includes('.')) {
if ((0, _util.isNamespace)(field.parent)) {
return name;
}
name = "".concat((0, _util.getReflectionParentName)(field), "_").concat(name);
}
return name.replace(new RegExp("^".concat(moduleName, "_")), '').replace(/\./g, '_');
} // gen common
function genComment(str) {
if (!str) return '';
var lines = str.replace(/\r\n/g, '/n').split('\n');
return lines.map(function (v) {
return "// ".concat(v);
}).join('\n');
} // process interface
function processType(name, nested) {
var comment = genComment(nested.comment);
var schema = {
name: name,
comment: comment,
fieldList: nested.fieldsArray.reduce(function (acc, field) {
var childrenNested = (0, _util.getParentLookup)({
field: field,
root: namespace,
type: field.type
});
var endPrefix = field.repeated ? '[]' : '';
acc.push({
key: field.name,
reflection: childrenNested,
comment: genComment(field.comment),
isRequired: (0, _util.getFieldIsRequired)(field),
isArray: field.repeated,
isMap: field instanceof _protobufjs.MapField,
value: field instanceof _protobufjs.MapField ? "Record<".concat((0, _util.protoTypeToTSType)(field.keyType), ", ").concat(childrenNested ? replaceNamespacePrefix(field.type, childrenNested) : (0, _util.protoTypeToTSType)(field.type) || replaceNamespacePrefix(field.type), ">;") : "".concat(childrenNested ? replaceNamespacePrefix(field.type, childrenNested) : (0, _util.protoTypeToTSType)(field.type) || replaceNamespacePrefix(field.type)).concat(endPrefix, ";")
});
return acc;
}, [])
};
function parse() {
var content;
if (visitor !== null && visitor !== void 0 && visitor.TSMessageDeclaration) {
content = visitor.TSMessageDeclaration(schema, nested);
}
if (content === false) return '';
if (content) return content;
return interfaceExecutor({
name: name,
comment: comment,
content: nested.fieldsArray.reduce(function (acc, field) {
var childrenNested = (0, _util.getParentLookup)({
field: field,
root: namespace,
type: field.type
});
if (field.comment) {
acc.push(genComment(field.comment));
}
var endPrefix = field.repeated ? '[]' : '';
var fieldContent = "".concat(field.name).concat((0, _util.getFieldIsRequired)(field) ? '' : '?', ": ");
if (field instanceof _protobufjs.MapField) {
fieldContent += "Record<".concat((0, _util.protoTypeToTSType)(field.keyType), ", ").concat(childrenNested ? replaceNamespacePrefix(field.type, childrenNested) : (0, _util.protoTypeToTSType)(field.type) || replaceNamespacePrefix(field.type), ">;");
} else {
fieldContent += "".concat(childrenNested ? replaceNamespacePrefix(field.type, childrenNested) : (0, _util.protoTypeToTSType)(field.type) || replaceNamespacePrefix(field.type)).concat(endPrefix, ";");
}
acc.push(fieldContent);
return acc;
}, []).join('\n')
});
}
parsedNestedList.push(parse());
return schema;
} // process enum
function processEnum(name, nested) {
var comment = genComment(nested.comment);
var schema = {
name: name,
comment: comment,
fieldList: Object.keys(nested.values).map(function (key) {
var _nested$comments;
return {
key: key,
value: nested.values[key],
comment: genComment((_nested$comments = nested.comments) === null || _nested$comments === void 0 ? void 0 : _nested$comments[key])
};
})
};
function parse() {
var content;
if (visitor !== null && visitor !== void 0 && visitor.TSEnumDeclaration) {
content = visitor.TSEnumDeclaration(schema, nested);
}
if (content === false) return '';
if (content) return content;
return enumExecutor({
name: name,
comment: comment,
content: Object.keys(nested.values).reduce(function (acc, field) {
var _nested$comments2;
if ((_nested$comments2 = nested.comments) !== null && _nested$comments2 !== void 0 && _nested$comments2[field]) {
acc.push(genComment(nested.comments[field]));
}
acc.push("".concat(field, " = ").concat(nested.values[field], ","));
return acc;
}, []).join('\n')
});
}
parsedNestedList.push(parse());
return schema;
} // process service
function processService(name, nested) {
var comment = genComment(nested.comment);
function handleFieldItemObj(field) {
return {
name: field.name,
requestType: replaceNamespacePrefix(field.requestType),
responseType: replaceNamespacePrefix(field.responseType),
options: field.options,
comment: genComment(field.comment) + ( // services options as remark
field.options ? Object.keys(field.options).reduce(function (acc, k) {
acc.push("// svr options: ".concat(k, " = ").concat(field.options[k]));
return acc;
}, ['\n']).join('\n') : '')
};
}
var schema = {
name: name,
comment: comment,
fieldList: nested.methodsArray.map(handleFieldItemObj)
};
function parse() {
var content;
if (visitor !== null && visitor !== void 0 && visitor.TSServiceDeclaration) {
content = visitor.TSServiceDeclaration(schema, nested);
}
if (content === false) return '';
if (content) return content;
return serviceExecutor({
name: name,
comment: comment,
content: nested.methodsArray.reduce(function (acc, field) {
var content;
if (visitor !== null && visitor !== void 0 && visitor.TSServiceItemDeclaration) {
content = visitor.TSServiceItemDeclaration(handleFieldItemObj(field), field);
}
if (content === false) return acc;
if (content) {
acc.push(content);
return acc;
}
acc.push(serviceFNExecutor({
name: field.name,
requestType: replaceNamespacePrefix(field.requestType),
responseType: replaceNamespacePrefix(field.responseType),
comment: genComment(field.comment) + ( // services options as remark
field.options ? Object.keys(field.options).reduce(function (acc, k) {
acc.push("// svr options: ".concat(k, " = ").concat(field.options[k]));
return acc;
}, ['\n']).join('\n') : '')
}));
return acc;
}, []).join('\n')
});
}
parsedNestedList.push(parse());
return schema;
} // parse proto reflection obj
function processNested(nested) {
// it's not that the content in the current file is not generated
// because the dependent modules will generate separate files
if (nested.filename && nested.filename !== filename) return;
var messageName = replaceNamespacePrefix(nested.name, nested);
if (nested instanceof _protobufjs.Type) {
if (hasGenMap.interfaces.has(messageName)) return;
hasGenMap.interfaces.set(messageName, processType(messageName, nested)); // nested message
eachNested(nested.nested);
} else if (nested instanceof _protobufjs.Enum) {
if (hasGenMap.enums.has(messageName)) return;
hasGenMap.enums.set(messageName, processEnum(messageName, nested));
} else if (nested instanceof _protobufjs.Service) {
if (hasGenMap.services.has(messageName)) return;
hasGenMap.services.set(messageName, processService(messageName, nested)); // nested message
eachNested(nested.nested);
} else if (nested instanceof _protobufjs.Namespace) {
var parsed = parseNamespace(nested, filename, visitor);
parsedNestedList.push(parsed.replace('declare namespace', 'namespace'));
}
}
function eachNested(nested) {
Object.keys(nested || {}).forEach(function (type) {
return processNested(nested[type]);
});
}
eachNested(namespace.nested);
var comment = genComment(namespace.comment);
visitor === null || visitor === void 0 ? void 0 : (_visitor$EmitTSNamesp = visitor.EmitTSNamespaceDeclaration) === null || _visitor$EmitTSNamesp === void 0 ? void 0 : _visitor$EmitTSNamesp.call(visitor, _objectSpread({
namespace: namespace,
comment: comment,
filename: filename,
moduleName: moduleName
}, hasGenMap));
return (0, _util.formatTS)(dtsExecutor({
namespace: moduleName,
comment: comment,
content: parsedNestedList.join('\n\n')
}));
}
var _default = parseNamespace;
exports.default = _default;