nope-js-browser
Version:
NoPE Runtime for the Browser. For nodejs please use nope-js-node
256 lines (255 loc) • 10.3 kB
JavaScript
/**
* Helper file to perform all releated task to create a project,
* add services and modules to it.
*/
import { FOLDER_SPLIT, listFiles, createPath, createFile, replaceAll, insert, underscore, camelize, } from "../helpers/index.nodejs";
import { copyFile, readFile } from "fs/promises";
import { readFileSync } from "fs";
import { join, relative, resolve } from "path";
import * as handlebars from "handlebars";
import { existsSync } from "fs";
import { getNopeLogger } from "../index.browser";
import { simpleGit } from "simple-git";
const dirName = join(__dirname, "..", "..", "lib", "templates");
const INSERT_MARKER = " !! Insert-Marker: Don't remove this line !!";
const packageDirName = join(__dirname, "..", "..");
const packageJson = JSON.parse(readFileSync(join(packageDirName, "package.json")).toString("utf-8"));
const currentNopeVersion = packageJson.version;
function firstup(str) {
str = camelize(str);
return str[0].toUpperCase() + str.slice(1);
}
function toService(str) {
str = firstup(str);
if (str.endsWith("Service")) {
return str;
}
return str + "Service";
}
function toModule(str) {
str = firstup(str);
if (str.endsWith("Module")) {
return str;
}
return str + "Module";
}
function toInterface(str) {
str = toModule(str);
return "I" + str;
}
handlebars.registerHelper("underscore", function (str) {
return underscore(str, true);
});
handlebars.registerHelper("firstup", firstup);
handlebars.registerHelper("now", function () {
const now = new Date();
return (now.getDay().toString() +
"." +
now.getMonth().toString() +
"." +
now.getFullYear().toString());
});
handlebars.registerHelper("toService", toService);
handlebars.registerHelper("toModule", toModule);
handlebars.registerHelper("toInterface", toInterface);
export function generateDefaultProject() {
return {
type: "python",
version: "1.0",
name: "name",
dirName: "",
path: "",
modules: [],
services: [],
description: "",
author: {
forename: "",
surename: "",
mail: "",
},
depencies: [],
currentNopeVersion: currentNopeVersion,
};
}
/**
* Helper to define the relevant project files.
* @returns
*/
async function _getProjectTemplates(type) {
const files = await listFiles(join(dirName, "projects", type), ".handlebars");
return files;
}
async function _getProjectFilesToCopy(type) {
const files = await listFiles(join(dirName, "projects", type));
const filesToCopy = files.filter((item) => {
const isTemplate = item.includes(".handlebars");
return !isTemplate;
});
return filesToCopy;
}
function _relativePath(settings, type, path, dataForTemplate) {
const templatePath = dirName + FOLDER_SPLIT + type + FOLDER_SPLIT + settings.type;
const file = path.slice(templatePath.length);
const fileTemplate = replaceAll(file, FOLDER_SPLIT, "__FOLDER_SPLITTING_CHAR__");
const render = handlebars.compile(fileTemplate);
const result = render(dataForTemplate);
const ret = replaceAll(result, "__FOLDER_SPLITTING_CHAR__", FOLDER_SPLIT);
return ret;
}
async function _writeTemplate(path, templateFile, projectSettings, type, dataForTemplate, logger = null) {
const render = handlebars.compile(await readFile(templateFile, { encoding: "utf-8" }));
let filePath = path + _relativePath(projectSettings, type, templateFile, dataForTemplate);
if (templateFile.endsWith(".extend.handlebars")) {
filePath = filePath.slice(0, filePath.length - ".extend".length);
}
filePath = filePath.slice(0, filePath.length - ".handlebars".length);
const content = render(dataForTemplate);
if (templateFile.endsWith(".extend.handlebars") && existsSync(filePath)) {
const text = await readFile(filePath, { encoding: "utf-8" });
const idxToInsert = text.includes(INSERT_MARKER)
? text.indexOf(INSERT_MARKER) + INSERT_MARKER.length
: text.length;
const contentToStore = insert(text, idxToInsert, "\n".repeat(1) + content);
await createFile(filePath, contentToStore);
if (logger)
logger.info("updated\t", filePath);
}
else {
await createFile(join(filePath), content);
if (logger)
logger.info("created\t", filePath);
}
}
export async function createProject(projectSettings, dir, logger = null) {
var _a;
const path = await createPath(join(dir, projectSettings.name));
const filesToCopy = await _getProjectFilesToCopy(projectSettings.type);
const promises = filesToCopy.map(async (file) => {
const dest = await createFile(path + _relativePath(projectSettings, "projects", file, projectSettings), "");
await copyFile(file, dest);
if (logger)
logger.info("created\t", dest);
});
await promises;
// now we render the files.
for (const templateFile of await _getProjectTemplates(projectSettings.type)) {
await _writeTemplate(path, templateFile, projectSettings, "projects", projectSettings, logger);
}
projectSettings.path = resolve(process.cwd(), path);
await createFile(join(path, "nope.json"), JSON.stringify(projectSettings, undefined, 4));
const git = simpleGit(path);
// or await each step individually
await git.init();
const files = await listFiles(path);
const filesToCommit = files
.filter((file) => !file.includes(FOLDER_SPLIT + ".git" + FOLDER_SPLIT))
.map((file) => relative(path, file));
// await git.add(files);
await git.add(filesToCommit);
await git.commit("initial commit");
if ((_a = projectSettings.git) === null || _a === void 0 ? void 0 : _a.repo) {
await git.addRemote("origin", projectSettings.git.repo);
}
if (logger)
logger.info("created\t", join(path, "nope.json"));
}
export async function addServiceToProject(projectSettings, service, logger = null) {
let path = join(projectSettings.path, projectSettings.name);
// List the relevant templates.
const templates = await listFiles(join(dirName, "services", projectSettings.type), ".handlebars");
const settings = Object.assign({}, service, { project: projectSettings });
for (const templateFile of templates) {
await _writeTemplate(path, templateFile, projectSettings, "services", settings, logger);
}
const files = await listFiles(join(dirName, "services", projectSettings.type));
const filesToCopy = files.filter((item) => {
const isTemplate = item.includes(".handlebars");
return !isTemplate;
});
const promises = filesToCopy.map(async (file) => {
const dest = await createFile(path + _relativePath(projectSettings, "services", file, settings), "");
await copyFile(file, dest);
if (logger)
logger.info("created\t", dest);
});
await promises;
projectSettings.services.push(service);
await createFile(join(projectSettings.path, "nope.json"), JSON.stringify(projectSettings, undefined, 4));
}
export async function addModuleToProject(projectSettings, module, logger = null) {
let path = join(projectSettings.path, projectSettings.name);
// List the relevant templates.
const templates = await listFiles(join(dirName, "modules", projectSettings.type), ".handlebars");
const settings = Object.assign({}, module, {
project: projectSettings,
});
for (const templateFile of templates) {
await _writeTemplate(path, templateFile, projectSettings, "modules", settings, logger);
}
const files = await listFiles(join(dirName, "modules", projectSettings.type));
const filesToCopy = files.filter((item) => {
const isTemplate = item.includes(".handlebars");
return !isTemplate;
});
const promises = filesToCopy.map(async (file) => {
const dest = await createFile(path + _relativePath(projectSettings, "modules", file, settings), "");
await copyFile(file, dest);
if (logger)
logger.info("created\t", dest);
});
await promises;
projectSettings.modules.push(module);
await createFile(join(projectSettings.path, "nope.json"), JSON.stringify(projectSettings, undefined, 4));
}
if (require.main === module) {
const logger = getNopeLogger("tool");
async function main() {
const settings = {
author: {
mail: "m.karkowski@zema.de",
forename: "Martin",
surename: "Karkowski",
},
depencies: [],
description: "Minimal Description for the Test",
modules: [],
path: "./temp/",
services: [
{
name: "createDatabase",
},
],
name: "testPython",
dirName: "test_python",
version: "1.0",
type: "python",
currentNopeVersion: currentNopeVersion,
};
await createProject(settings, "../temp", logger);
await addServiceToProject(settings, {
name: "deleteDatabase",
}, logger);
await addModuleToProject(settings, {
methods: ["sayHello", "getTime"],
name: "HelloWorld",
events: [],
properties: ["lastGreetingMessage"],
}, logger);
// Now create a Typescript folder:
settings.type = "typescript";
settings.name = "testNodejs";
settings.name = "testNodejs";
settings.path = "./temp/";
await createProject(settings, "./temp", logger);
await addServiceToProject(settings, {
name: "deleteDatabase",
}, logger);
await addModuleToProject(settings, {
methods: ["sayHello", "getTime"],
name: "HelloWorld",
events: [],
properties: ["lastGreetingMessage"],
}, logger);
}
main().catch(console.error);
}