genezio
Version:
Command line utility to interact with Genezio infrastructure.
146 lines (145 loc) • 7.93 kB
JavaScript
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 _KotlinBundler_instances, _KotlinBundler_compile, _KotlinBundler_castParameterToPropertyType, _KotlinBundler_getProperCast, _KotlinBundler_createRouterFileForClass;
// Libs
import path from "path";
import Mustache from "mustache";
import { default as fsExtra } from "fs-extra";
import { log } from "../../utils/logging.js";
import { spawnSync } from "child_process";
// Kotlin stuff
import { checkIfKotlinReqsAreInstalled } from "../../utils/kotlin.js";
import { template } from "./kotlinMain.js";
import { castArrayRecursivelyInitial, castMapRecursivelyInitial, } from "../../utils/kotlinAstCasting.js";
// Utils
import { createTemporaryFolder, writeToFile } from "../../utils/file.js";
import { debugLogger } from "../../utils/logging.js";
import { TriggerType } from "../../projectConfiguration/yaml/models.js";
import { AstNodeType, } from "../../models/genezioModels.js";
import { UserError } from "../../errors.js";
import fs from "fs";
export class KotlinBundler {
constructor() {
_KotlinBundler_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.debug(`Copy files in temp folder ${inputTemporaryFolder}`);
// Create the router class
const userClass = input.projectConfiguration.classes.find((c) => c.path == input.path);
// If workspace.backend is defined we need to subtract it from the userClass.path
if (input.projectConfiguration.workspace?.backend) {
userClass.path = userClass.path.replace(input.projectConfiguration.workspace.backend, "");
}
await __classPrivateFieldGet(this, _KotlinBundler_instances, "m", _KotlinBundler_createRouterFileForClass).call(this, userClass, input.ast, inputTemporaryFolder);
checkIfKotlinReqsAreInstalled();
// Compile the Kotlin code locally
debugLogger.debug("Compiling Kotlin...");
await __classPrivateFieldGet(this, _KotlinBundler_instances, "m", _KotlinBundler_compile).call(this, inputTemporaryFolder);
debugLogger.debug("Compiling Kotlin finished.");
return {
...input,
path: path.join(inputTemporaryFolder, "final_build"),
};
}
}
_KotlinBundler_instances = new WeakSet(), _KotlinBundler_compile = async function _KotlinBundler_compile(folderPath) {
// Compile the Kotlin code locally
const gradlew = "." + path.sep + "gradlew" + (process.platform === "win32" ? ".bat" : "");
fs.chmod(`${folderPath}${path.sep}${"gradlew" + (process.platform === "win32" ? ".bat" : "")}`, 0o755, (err) => {
if (err) {
throw Error("Error while changing gradlew permissions");
}
});
const result = spawnSync(gradlew, ["--quiet", "fatJar"], {
cwd: folderPath,
});
if (result.status == null) {
log.info("There was an error while running the " +
gradlew +
" script, make sure you have the correct permissions.");
throw new UserError("Compilation error! Please check your code and try again.");
}
else if (result.status != 0) {
log.info(result.stderr.toString());
log.info(result.stdout.toString());
throw new UserError("Compilation error! Please check your code and try again.");
}
// Move the stand alone jar to its own folder
fsExtra.mkdirSync(path.join(folderPath, "final_build"));
const result_path = path.join(folderPath, "app", "build", "libs", "app-standalone.jar");
const destination_path = path.join(folderPath, "final_build", "app-standalone.jar");
fsExtra.moveSync(result_path, destination_path);
}, _KotlinBundler_castParameterToPropertyType = function _KotlinBundler_castParameterToPropertyType(node, variableName) {
let implementation = "";
switch (node.type) {
case AstNodeType.StringLiteral:
implementation += `${variableName}.jsonPrimitive.content`;
break;
case AstNodeType.DoubleLiteral:
implementation += `${variableName}.toDouble()`;
break;
case AstNodeType.BooleanLiteral:
implementation += `${variableName}.jsonPrimitive.content.toBoolean()`;
break;
case AstNodeType.IntegerLiteral:
implementation += `Integer.parseInt(${variableName}.jsonPrimitive.content)`;
break;
case AstNodeType.CustomNodeLiteral:
implementation += `Json.decodeFromJsonElement<${node.rawValue}>(${variableName})`;
break;
case AstNodeType.ArrayType:
implementation += castArrayRecursivelyInitial(node, variableName);
break;
case AstNodeType.MapType:
implementation += castMapRecursivelyInitial(node, variableName);
}
return implementation;
}, _KotlinBundler_getProperCast = function _KotlinBundler_getProperCast(mainClass, method, parameterType, index) {
const type = mainClass.methods
.find((m) => m.name == method.name)
.params.find((p) => p.name == parameterType.name);
return `${__classPrivateFieldGet(this, _KotlinBundler_instances, "m", _KotlinBundler_castParameterToPropertyType).call(this, type.paramType, `params!![${index}]`)}`;
}, _KotlinBundler_createRouterFileForClass = async function _KotlinBundler_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 moustacheViewForMain = {
packageName: classConfigPath.substring(classConfigPath.lastIndexOf(path.sep) + 1),
classFileName: path.basename(classConfiguration.path, path.extname(classConfiguration.path)),
className: classConfiguration.name,
jsonRpcMethods: classConfiguration.methods
.filter((m) => m.type === TriggerType.jsonrpc)
.map((m) => ({
name: m.name,
parameters: m.parameters.map((p, index) => ({
index,
cast: __classPrivateFieldGet(this, _KotlinBundler_instances, "m", _KotlinBundler_getProperCast).call(this, mainClass, m, p, index),
})),
})),
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,
})),
};
const routerFileContent = Mustache.render(template, moustacheViewForMain);
await writeToFile(folderPath, path.join(classConfigPath, "GeneratedCaller.kt"), routerFileContent);
};