UNPKG

@selfage/generator_cli

Version:

Code generation for message, service, and database.

84 lines (83 loc) 13.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateMessage = generateMessage; const output_content_builder_1 = require("./output_content_builder"); const util_1 = require("./util"); let PRIMITIVE_TYPES = new Set(["string", "number", "boolean"]); function generateMessage(definitionModulePath, messageDefinition, definitionResolver, outputContentMap) { if (!messageDefinition.name) { throw new Error(`"name" field is missing on a message.`); } let loggingPrefix = `When generating message ${messageDefinition.name},`; let tsContentBuilder = output_content_builder_1.TsContentBuilder.get(outputContentMap, definitionModulePath); let fields = new Array(); let fieldDescriptors = new Array(); let usedIndexes = new Set(); if (messageDefinition.fields) { for (let field of messageDefinition.fields) { if (!field.name) { throw new Error(`${loggingPrefix} "name" is missing on a field.`); } if (!field.index) { throw new Error(`${loggingPrefix} "index" is missing on field ${field.name}.`); } if (usedIndexes.has(field.index)) { throw new Error(`${loggingPrefix} field ${field.name} has a duplicate index ${field.index}.`); } usedIndexes.add(field.index); if (!field.type) { throw new Error(`${loggingPrefix} "type" is missing on ${field.name}.`); } let typeDescriptorLine; if (PRIMITIVE_TYPES.has(field.type)) { tsContentBuilder.importFromMessageDescriptor("PrimitiveType"); typeDescriptorLine = `primitiveType: PrimitiveType.${field.type.toUpperCase()}`; } else { let definition = definitionResolver.resolve(loggingPrefix, field.type, field.import); if (definition.kind === "Enum") { let enumDescriptorName = (0, util_1.toUppercaseSnaked)(field.type); tsContentBuilder.importFromDefinition(field.import, field.type, enumDescriptorName); typeDescriptorLine = `enumType: ${enumDescriptorName}`; } else if (definition.kind === "Message") { let messageDescriptorName = (0, util_1.toUppercaseSnaked)(field.type); tsContentBuilder.importFromDefinition(field.import, field.type, messageDescriptorName); typeDescriptorLine = `messageType: ${messageDescriptorName}`; } else { throw new Error(`${loggingPrefix} a new definition needs to be handled for type ${field.type} of field ${field.name}.`); } } let fieldTypeName; let isArrayLine; if (field.isArray) { fieldTypeName = `Array<${field.type}>`; isArrayLine = `isArray: true`; } else { fieldTypeName = field.type; } fieldDescriptors.push(`{ name: '${field.name}', index: ${field.index}, ${typeDescriptorLine},${isArrayLine ? "\n " + isArrayLine + "," : ""} }`); if (!field.deprecated) { fields.push(` ${field.name}?: ${fieldTypeName},`); } } } tsContentBuilder.importFromMessageDescriptor("MessageDescriptor"); let descriptorName = (0, util_1.toUppercaseSnaked)(messageDefinition.name); tsContentBuilder.push(` export interface ${messageDefinition.name} {${fields.join("")} } export let ${descriptorName}: MessageDescriptor<${messageDefinition.name}> = { name: '${messageDefinition.name}', fields: [${fieldDescriptors.join(", ")}], }; `); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVzc2FnZV9nZW5lcmF0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJtZXNzYWdlX2dlbmVyYXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQVVBLDBDQXFHQztBQTdHRCxxRUFHa0M7QUFDbEMsaUNBQTJDO0FBRTNDLElBQUksZUFBZSxHQUFHLElBQUksR0FBRyxDQUFTLENBQUMsUUFBUSxFQUFFLFFBQVEsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDO0FBRXZFLFNBQWdCLGVBQWUsQ0FDN0Isb0JBQTRCLEVBQzVCLGlCQUFvQyxFQUNwQyxrQkFBc0MsRUFDdEMsZ0JBQW1EO0lBRW5ELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUM1QixNQUFNLElBQUksS0FBSyxDQUFDLHVDQUF1QyxDQUFDLENBQUM7SUFDM0QsQ0FBQztJQUVELElBQUksYUFBYSxHQUFHLDJCQUEyQixpQkFBaUIsQ0FBQyxJQUFJLEdBQUcsQ0FBQztJQUN6RSxJQUFJLGdCQUFnQixHQUFHLHlDQUFnQixDQUFDLEdBQUcsQ0FDekMsZ0JBQWdCLEVBQ2hCLG9CQUFvQixDQUNyQixDQUFDO0lBQ0YsSUFBSSxNQUFNLEdBQUcsSUFBSSxLQUFLLEVBQVUsQ0FBQztJQUNqQyxJQUFJLGdCQUFnQixHQUFHLElBQUksS0FBSyxFQUFVLENBQUM7SUFDM0MsSUFBSSxXQUFXLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztJQUNwQyxJQUFJLGlCQUFpQixDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQzdCLEtBQUssSUFBSSxLQUFLLElBQUksaUJBQWlCLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDM0MsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztnQkFDaEIsTUFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLGFBQWEsZ0NBQWdDLENBQUMsQ0FBQztZQUNwRSxDQUFDO1lBQ0QsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFD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QztnQkFDdEIsTUFBTSxDQUFDLElBQUksQ0FBQztJQUNoQixLQUFLLENBQUMsSUFBSSxNQUFNLGFBQWEsR0FBRyxDQUFDLENBQUM7WUFDaEMsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQsZ0JBQWdCLENBQUMsMkJBQTJCLENBQUMsbUJBQW1CLENBQUMsQ0FBQztJQUNsRSxJQUFJLGNBQWMsR0FBRyxJQUFBLHdCQUFpQixFQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQy9ELGdCQUFnQixDQUFDLElBQUksQ0FBQzttQkFDTCxpQkFBaUIsQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7OzthQUdoRCxjQUFjLHVCQUF1QixpQkFBaUIsQ0FBQyxJQUFJO1dBQzdELGlCQUFpQixDQUFDLElBQUk7YUFDcEIsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQzs7Q0FFdkMsQ0FBQyxDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE1lc3NhZ2VEZWZpbml0aW9uIH0gZnJvbSBcIi4vZGVmaW5pdGlvblwiO1xuaW1wb3J0IHsgRGVmaW5pdGlvblJlc29sdmVyIH0gZnJvbSBcIi4vZGVmaW5pdGlvbl9yZXNvbHZlclwiO1xuaW1wb3J0IHtcbiAgT3V0cHV0Q29udGVudEJ1aWxkZXIsXG4gIFRzQ29udGVudEJ1aWxkZXIsXG59IGZyb20gXCIuL291dHB1dF9jb250ZW50X2J1aWxkZXJcIjtcbmltcG9ydCB7IHRvVXBwZXJjYXNlU25ha2VkIH0gZnJvbSBcIi4vdXRpbFwiO1xuXG5sZXQgUFJJTUlUSVZFX1RZUEVTID0gbmV3IFNldDxzdHJpbmc+KFtcInN0cmluZ1wiLCBcIm51bWJlclwiLCBcImJvb2xlYW5cIl0pO1xuXG5leHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVNZXNzYWdlKFxuICBkZWZpbml0aW9uTW9kdWxlUGF0aDogc3RyaW5nLFxuICBtZXNzYWdlRGVmaW5pdGlvbjogTWVzc2FnZURlZmluaXRpb24sXG4gIGRlZmluaXRpb25SZXNvbHZlcjogRGVmaW5pdGlvblJlc29sdmVyLFxuICBvdXRwdXRDb250ZW50TWFwOiBNYXA8c3RyaW5nLCBPdXRwdXRDb250ZW50QnVpbGRlcj4sXG4pOiB2b2lkIHtcbiAgaWYgKCFtZXNzYWdlRGVmaW5pdGlvbi5uYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBcIm5hbWVcIiBmaWVsZCBpcyBtaXNzaW5nIG9uIGEgbWVzc2FnZS5gKTtcbiAgfVxuXG4gIGxldCBsb2dnaW5nUHJlZml4ID0gYFdoZW4gZ2VuZXJhdGluZyBtZXNzYWdlICR7bWVzc2FnZURlZmluaXRpb24ubmFtZX0sYDtcbiAgbGV0IHRzQ29udGVudEJ1aWxkZXIgPSBUc0NvbnRlbnRCdWlsZGVyLmdldChcbiAgICBvdXRwdXRDb250ZW50TWFwLFxuICAgIGRlZmluaXRpb25Nb2R1bGVQYXRoLFxuICApO1xuICBsZXQgZmllbGRzID0gbmV3IEFycmF5PHN0cmluZz4oKTtcbiAgbGV0IGZpZWxkRGVzY3JpcHRvcnMgPSBuZXcgQXJyYXk8c3RyaW5nPigpO1xuICBsZXQgdXNlZEluZGV4ZXMgPSBuZXcgU2V0PG51bWJlcj4oKTtcbiAgaWYgKG1lc3NhZ2VEZWZpbml0aW9uLmZpZWxkcykge1xuICAgIGZvciAobGV0IGZpZWxkIG9mIG1lc3NhZ2VEZWZpbml0aW9uLmZpZWxkcykge1xuICAgICAgaWYgKCFmaWVsZC5uYW1lKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgJHtsb2dnaW5nUHJlZml4fSBcIm5hbWVcIiBpcyBtaXNzaW5nIG9uIGEgZmllbGQuYCk7XG4gICAgICB9XG4gICAgICBpZiAoIWZpZWxkLmluZGV4KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgJHtsb2dnaW5nUHJlZml4fSBcImluZGV4XCIgaXMgbWlzc2luZyBvbiBmaWVsZCAke2ZpZWxkLm5hbWV9LmAsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBpZiAodXNlZEluZGV4ZXMuaGFzKGZpZWxkLmluZGV4KSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYCR7bG9nZ2luZ1ByZWZpeH0gZmllbGQgJHtmaWVsZC5uYW1lfSBoYXMgYSBkdXBsaWNhdGUgaW5kZXggJHtmaWVsZC5pbmRleH0uYCxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHVzZWRJbmRleGVzLmFkZChmaWVsZC5pbmRleCk7XG5cbiAgICAgIGlmICghZmllbGQudHlwZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bG9nZ2luZ1ByZWZpeH0gXCJ0eXBlXCIgaXMgbWlzc2luZyBvbiAke2ZpZWxkLm5hbWV9LmApO1xuICAgICAgfVxuICAgICAgbGV0IHR5cGVEZXNjcmlwdG9yTGluZTogc3RyaW5nO1xuICAgICAgaWYgKFBSSU1JVElWRV9UWVBFUy5oYXMoZmllbGQudHlwZSkpIHtcbiAgICAgICAgdHNDb250ZW50QnVpbGRlci5pbXBvcnRGcm9tTWVzc2FnZURlc2NyaXB0b3IoXCJQcmltaXRpdmVUeXBlXCIpO1xuICAgICAgICB0eXBlRGVzY3JpcHRvckxpbmUgPSBgcHJpbWl0aXZlVHlwZTogUHJpbWl0aXZlVHlwZS4ke2ZpZWxkLnR5cGUudG9VcHBlckNhc2UoKX1gO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbGV0IGRlZmluaXRpb24gPSBkZWZpbml0aW9uUmVzb2x2ZXIucmVzb2x2ZShcbiAgICAgICAgICBsb2dnaW5nUHJlZml4LFxuICAgICAgICAgIGZpZWxkLnR5cGUsXG4gICAgICAgICAgZmllbGQuaW1wb3J0LFxuICAgICAgICApO1xuICAgICAgICBpZiAoZGVmaW5pdGlvbi5raW5kID09PSBcIkVudW1cIikge1xuICAgICAgICAgIGxldCBlbnVtRGVzY3JpcHRvck5hbWUgPSB0b1VwcGVyY2FzZVNuYWtlZChmaWVsZC50eXBlKTtcbiAgICAgICAgICB0c0NvbnRlbnRCdWlsZGVyLmltcG9ydEZyb21EZWZpbml0aW9uKFxuICAgICAgICAgICAgZmllbGQuaW1wb3J0LFxuICAgICAgICAgICAgZmllbGQudHlwZSxcbiAgICAgICAgICAgIGVudW1EZXNjcmlwdG9yTmFtZSxcbiAgICAgICAgICApO1xuICAgICAgICAgIHR5cGVEZXNjcmlwdG9yTGluZSA9IGBlbnVtVHlwZTogJHtlbnVtRGVzY3JpcHRvck5hbWV9YDtcbiAgICAgICAgfSBlbHNlIGlmIChkZWZpbml0aW9uLmtpbmQgPT09IFwiTWVzc2FnZVwiKSB7XG4gICAgICAgICAgbGV0IG1lc3NhZ2VEZXNjcmlwdG9yTmFtZSA9IHRvVXBwZXJjYXNlU25ha2VkKGZpZWxkLnR5cGUpO1xuICAgICAgICAgIHRzQ29udGVudEJ1aWxkZXIuaW1wb3J0RnJvbURlZmluaXRpb24oXG4gICAgICAgICAgICBmaWVsZC5pbXBvcnQsXG4gICAgICAgICAgICBmaWVsZC50eXBlLFxuICAgICAgICAgICAgbWVzc2FnZURlc2NyaXB0b3JOYW1lLFxuICAgICAgICAgICk7XG4gICAgICAgICAgdHlwZURlc2NyaXB0b3JMaW5lID0gYG1lc3NhZ2VUeXBlOiAke21lc3NhZ2VEZXNjcmlwdG9yTmFtZX1gO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGAke2xvZ2dpbmdQcmVmaXh9IGEgbmV3IGRlZmluaXRpb24gbmVlZHMgdG8gYmUgaGFuZGxlZCBmb3IgdHlwZSAke2ZpZWxkLnR5cGV9IG9mIGZpZWxkICR7ZmllbGQubmFtZX0uYCxcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBsZXQgZmllbGRUeXBlTmFtZTogc3RyaW5nO1xuICAgICAgbGV0IGlzQXJyYXlMaW5lOiBzdHJpbmc7XG4gICAgICBpZiAoZmllbGQuaXNBcnJheSkge1xuICAgICAgICBmaWVsZFR5cGVOYW1lID0gYEFycmF5PCR7ZmllbGQudHlwZX0+YDtcbiAgICAgICAgaXNBcnJheUxpbmUgPSBgaXNBcnJheTogdHJ1ZWA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBmaWVsZFR5cGVOYW1lID0gZmllbGQudHlwZTtcbiAgICAgIH1cbiAgICAgIGZpZWxkRGVzY3JpcHRvcnMucHVzaChge1xuICAgIG5hbWU6ICcke2ZpZWxkLm5hbWV9JyxcbiAgICBpbmRleDogJHtmaWVsZC5pbmRleH0sXG4gICAgJHt0eXBlRGVzY3JpcHRvckxpbmV9LCR7aXNBcnJheUxpbmUgPyBcIlxcbiAgICBcIiArIGlzQXJyYXlMaW5lICsgXCIsXCIgOiBcIlwifVxuICB9YCk7XG4gICAgICBpZiAoIWZpZWxkLmRlcHJlY2F0ZWQpIHtcbiAgICAgICAgZmllbGRzLnB1c2goYFxuICAke2ZpZWxkLm5hbWV9PzogJHtmaWVsZFR5cGVOYW1lfSxgKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICB0c0NvbnRlbnRCdWlsZGVyLmltcG9ydEZyb21NZXNzYWdlRGVzY3JpcHRvcihcIk1lc3NhZ2VEZXNjcmlwdG9yXCIpO1xuICBsZXQgZGVzY3JpcHRvck5hbWUgPSB0b1VwcGVyY2FzZVNuYWtlZChtZXNzYWdlRGVmaW5pdGlvbi5uYW1lKTtcbiAgdHNDb250ZW50QnVpbGRlci5wdXNoKGBcbmV4cG9ydCBpbnRlcmZhY2UgJHttZXNzYWdlRGVmaW5pdGlvbi5uYW1lfSB7JHtmaWVsZHMuam9pbihcIlwiKX1cbn1cblxuZXhwb3J0IGxldCAke2Rlc2NyaXB0b3JOYW1lfTogTWVzc2FnZURlc2NyaXB0b3I8JHttZXNzYWdlRGVmaW5pdGlvbi5uYW1lfT4gPSB7XG4gIG5hbWU6ICcke21lc3NhZ2VEZWZpbml0aW9uLm5hbWV9JyxcbiAgZmllbGRzOiBbJHtmaWVsZERlc2NyaXB0b3JzLmpvaW4oXCIsIFwiKX1dLFxufTtcbmApO1xufVxuIl19