UNPKG

genezio

Version:

Command line utility to interact with Genezio infrastructure.

186 lines (185 loc) 9.85 kB
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var _GoBundler_instances, _GoBundler_getImportViewFromPath, _GoBundler_mapTypeToGoType, _GoBundler_getCastExpression, _GoBundler_createRouterFileForClass; import path from "path"; import Mustache from "mustache"; import { default as fsExtra } from "fs-extra"; // Utils import { createTemporaryFolder, writeToFile } from "../../utils/file.js"; import { debugLogger } from "../../utils/logging.js"; import { AstNodeType, } from "../../models/genezioModels.js"; import { checkIfGoIsInstalled } from "../../utils/go.js"; import { TriggerType } from "../../projectConfiguration/yaml/models.js"; import { UserError } from "../../errors.js"; export class GoBundler { constructor() { _GoBundler_instances.add(this); } async bundle(input) { // Create a temporary folder were we copy user code to prepare everything. const folderPath = input.projectConfiguration.workspace?.backend ?? input.genezioConfigurationFilePath; const inputTemporaryFolder = await createTemporaryFolder(); await fsExtra.copy(folderPath, inputTemporaryFolder); debugLogger.info(`Copy files in temp folder ${inputTemporaryFolder}`); // Create the router class const userClass = input.projectConfiguration.classes.find((c) => c.path == input.path); await __classPrivateFieldGet(this, _GoBundler_instances, "m", _GoBundler_createRouterFileForClass).call(this, userClass, input.ast, inputTemporaryFolder); checkIfGoIsInstalled(); // Compile the Go code on the server debugLogger.info("Compiling Go..."); input.path = inputTemporaryFolder; await this.compile(inputTemporaryFolder, input); debugLogger.info("Compiling Go finished."); return { ...input, path: inputTemporaryFolder, extra: { ...input.extra, entryFile: "bootstrap", }, }; } } _GoBundler_instances = new WeakSet(), _GoBundler_getImportViewFromPath = function _GoBundler_getImportViewFromPath(path) { if (!path) return { name: "", path: "", named: false }; const packageName = path.substring(path.lastIndexOf("/") + 1); const pathWithoutName = path.substring(0, path.lastIndexOf("/")); const packagePath = pathWithoutName.substring(pathWithoutName.lastIndexOf("/") + 1); if (packageName === packagePath) return { name: packageName, path: pathWithoutName, named: false }; return { name: packageName, path: pathWithoutName, named: true }; }, _GoBundler_mapTypeToGoType = function _GoBundler_mapTypeToGoType(type, ast, imports) { switch (type.type) { case AstNodeType.StringLiteral: return "string"; case AstNodeType.DoubleLiteral: return "float64"; case AstNodeType.BooleanLiteral: return "bool"; case AstNodeType.IntegerLiteral: return "int"; case AstNodeType.CustomNodeLiteral: for (const node of ast.body ?? []) { if (node.type === AstNodeType.StructLiteral) { const struct = node; if (struct.name === type.rawValue) { const importView = __classPrivateFieldGet(this, _GoBundler_instances, "m", _GoBundler_getImportViewFromPath).call(this, struct.path ?? ""); // check if import is already present if (!imports.find((i) => i.path === importView.path)) { imports.push(importView); } return importView.name + "." + struct.name; } } } return type.rawValue; case AstNodeType.ArrayType: return "[]" + __classPrivateFieldGet(this, _GoBundler_instances, "m", _GoBundler_mapTypeToGoType).call(this, type.generic, ast, imports); case AstNodeType.MapType: return `map[${__classPrivateFieldGet(this, _GoBundler_instances, "m", _GoBundler_mapTypeToGoType).call(this, type.genericKey, ast, imports)}]${__classPrivateFieldGet(this, _GoBundler_instances, "m", _GoBundler_mapTypeToGoType).call(this, type.genericValue, ast, imports)}`; case AstNodeType.AnyLiteral: return "interface{}"; } return "interface{}"; }, _GoBundler_getCastExpression = function _GoBundler_getCastExpression(index, parameter, ast, imports) { switch (parameter.type.type) { case AstNodeType.StringLiteral: case AstNodeType.DoubleLiteral: case AstNodeType.BooleanLiteral: if (parameter.optional) { return `var param${index} *${__classPrivateFieldGet(this, _GoBundler_instances, "m", _GoBundler_mapTypeToGoType).call(this, parameter.type, ast, imports)} if body.Params[${index}] == nil { param${index} = nil } else { paramValue${index} := body.Params[${index}].(${__classPrivateFieldGet(this, _GoBundler_instances, "m", _GoBundler_mapTypeToGoType).call(this, parameter.type, ast, imports)}) param${index} = &paramValue${index} }`; } return `param${index} := body.Params[${index}].(${__classPrivateFieldGet(this, _GoBundler_instances, "m", _GoBundler_mapTypeToGoType).call(this, parameter.type, ast, imports)})`; case AstNodeType.IntegerLiteral: if (parameter.optional) { return `var param${index} *${__classPrivateFieldGet(this, _GoBundler_instances, "m", _GoBundler_mapTypeToGoType).call(this, parameter.type, ast, imports)} if body.Params[${index}] == nil { param${index} = nil } else { paramValue${index} := body.Params[${index}].(float64) paramValueInt${index} := int(paramValue${index}) param${index} = &paramValueInt${index} }`; } return `paramFloat${index} := body.Params[${index}].(float64) param${index} := int(paramFloat${index})`; case AstNodeType.CustomNodeLiteral: if (parameter.type.rawValue === "GnzContext") { return `param${index} := ctx`; } // intentional fallthrough // eslint-disable-next-line no-fallthrough case AstNodeType.MapType: case AstNodeType.ArrayType: return `var param${index} ${parameter.optional ? "*" : ""}${__classPrivateFieldGet(this, _GoBundler_instances, "m", _GoBundler_mapTypeToGoType).call(this, parameter.type, ast, imports)} jsonMap, err := json.Marshal(body.Params[${index}]) if err != nil { ${this.generateErrorReturn()} } err = json.Unmarshal(jsonMap, &param${index}) if err != nil { ${this.generateErrorReturn()} }`; case AstNodeType.AnyLiteral: return `param${index} := body.Params[${index}]`; } return ""; }, _GoBundler_createRouterFileForClass = async function _GoBundler_createRouterFileForClass(classConfiguration, ast, folderPath) { const mainClass = ast.body?.find((element) => { return (element.type === AstNodeType.ClassDefinition && element.name === classConfiguration.name); }); const classConfigPath = path.dirname(classConfiguration.path); // Error check: User is using Windows but paths are unix style (possible when cloning projects from git) if (process.platform === "win32" && classConfigPath.includes("/")) { throw new UserError("Error: You are using Windows but your project contains unix style paths. Please use Windows style paths in genezio.yaml instead."); } const imports = []; const moustacheViewForMain = { imports: [], usesAuth: classConfiguration.methods.some((m) => m.auth), class: { name: mainClass.name, packageName: mainClass.path?.substring(mainClass.path.lastIndexOf("/") + 1), }, cronMethods: classConfiguration.methods .filter((m) => m.type === TriggerType.cron) .map((m) => ({ name: m.name, })), httpMethods: classConfiguration.methods .filter((m) => m.type === TriggerType.http) .map((m) => ({ name: m.name, })), jsonRpcMethods: classConfiguration.methods .filter((m) => m.type === TriggerType.jsonrpc) .map((m) => ({ name: m.name, auth: m.auth ?? false, isVoid: m.returnType.type === AstNodeType.VoidLiteral, parameters: m.parameters.map((p, index) => ({ index, last: index === m.parameters.length - 1, cast: __classPrivateFieldGet(this, _GoBundler_instances, "m", _GoBundler_getCastExpression).call(this, index, p, ast, imports), })), })), }; moustacheViewForMain.imports.push(...imports); const classImport = __classPrivateFieldGet(this, _GoBundler_instances, "m", _GoBundler_getImportViewFromPath).call(this, mainClass.path ?? ""); if (!moustacheViewForMain.imports.find((i) => i.path === classImport.path)) { moustacheViewForMain.imports.push(classImport); } const routerFileContent = Mustache.render(this.template, moustacheViewForMain); await writeToFile(folderPath, "main.go", routerFileContent); };