Restore lost utility files

This commit is contained in:
pngwn 2020-01-21 15:54:00 +00:00
parent 3f9d708541
commit 705dd128d4
5 changed files with 433 additions and 0 deletions

View File

@ -0,0 +1,134 @@
const {
appPackageFolder
} = require("../createAppPackage");
const { componentLibraryInfo } = require("./componentLibraryInfo");
const {
stat, ensureDir, pathExists,
constants, copyFile, writeFile,
readFile
} = require("fs-extra");
const { join, resolve, dirname } = require("path");
const sqrl = require('squirrelly');
module.exports = async (config, appname, pages, appdefinition) => {
const appPath = appPackageFolder(config, appname);
await buildClientAppDefinition(
config, appname,
appdefinition,
appPath, pages, "main");
await buildClientAppDefinition(
config, appname,
appdefinition,
appPath, pages, "unauthenticated")
await buildIndexHtml(
config, appname, appPath,
pages, "main");
await buildIndexHtml(
config, appname, appPath,
pages, "unauthenticated");
await copyClientLib(appPath, "main");
await copyClientLib(appPath, "unauthenticated");
}
const publicPath = (appPath, pageName) => join(appPath, "public", pageName);
const rootPath = (config, appname) => config.useAppRootPath ? `/${appname}` : "";
const copyClientLib = async (appPath, pageName) => {
var sourcepath = require.resolve("@budibase/client");
var destPath = join(publicPath(appPath, pageName), "budibase-client.js");
await copyFile(sourcepath, destPath, constants.COPYFILE_FICLONE);
await copyFile(sourcepath + ".map", destPath + ".map", constants.COPYFILE_FICLONE);
}
const buildIndexHtml = async (config, appname, appPath, pages, pageName) => {
const appPublicPath = publicPath(appPath, pageName);
const appRootPath = rootPath(config, appname);
const stylesheetUrl = s =>
s.indexOf('http://') === 0 || s.indexOf('https://') === 0
? s
: `/${rootPath(config, appname)}/${s}`;
const templateObj = {
title: pages[pageName].index.title || "Budibase App",
favicon: `${appRootPath}/${pages[pageName].index.favicon || "/_shared/favicon.png"}`,
stylesheets: (pages.stylesheets || []).map(stylesheetUrl),
appRootPath
}
const indexHtmlTemplate = await readFile(
resolve(__dirname, "index.template.html"), "utf8");
const indexHtmlPath = join(appPublicPath, "index.html");
const indexHtml = sqrl.Render(indexHtmlTemplate, templateObj)
await writeFile(
indexHtmlPath,
indexHtml,
{flag:"w+"});
}
const buildClientAppDefinition = async (config, appname, appdefinition, appPath, pages, pageName) => {
const appPublicPath = publicPath(appPath, pageName);
const appRootPath = rootPath(config, appname);
const componentLibraries = [];
for(let lib of pages.componentLibraries) {
const info = await componentLibraryInfo(appPath, lib);
const libFile = info.components._lib || "index.js";
const source = join(info.libDir, libFile);
const moduleDir = join(appPublicPath, "lib", info.libDir.replace(appPath, ""));
const destPath = join(moduleDir, libFile);
await ensureDir(dirname(destPath));
componentLibraries.push({
importPath: destPath.replace(appPublicPath, "")
.replace(/\\/g, "/"),
libName: lib
});
let shouldCopy = !(await pathExists(destPath));
if(!shouldCopy) {
const destStat = await stat(destPath);
const sourceStat = await stat(source);
shouldCopy = destStat.ctimeMs !== sourceStat.ctimeMs;
}
if(shouldCopy) {
await copyFile(source, destPath, constants.COPYFILE_FICLONE);
}
}
const filename = join(appPublicPath, "clientAppDefinition.js");
const clientAppDefObj = {
hierarchy: appdefinition.hierarchy,
componentLibraries: componentLibraries,
appRootPath: appRootPath,
props: appdefinition.props[pageName]
}
await writeFile(filename,
`window['##BUDIBASE_APPDEFINITION##'] = ${JSON.stringify(clientAppDefObj)}`);
}

View File

@ -0,0 +1,67 @@
const {
readJSON, exists
} = require("fs-extra");
const {
resolve, join , dirname
} = require("path");
const getLibDir = (appPath, libname) => {
try {
const componentsFile = require.resolve(
join(libname, "components.json"),
{ paths: [appPath]});
return dirname(componentsFile);
} catch(e) {
console.log(e);
}
}
const getComponentsFilepath = libPath =>
resolve(libPath, "components.json");
module.exports.componentsFilepath = (appPath, libname) =>
getComponentsFilepath(getLibDir(appPath, libname));
module.exports.componentLibraryInfo = async (appPath, libname) => {
const libDir = getLibDir(appPath, libname);
const componentsPath = getComponentsFilepath(libDir);
if(!await exists(componentsPath)) {
const e = new Error(`could not find components definition file at ${componentsPath}`);
e.statusCode = 404;
throw e;
}
try {
const components = await readJSON(componentsPath);
const namespacedComponents = {_lib:components._lib};
for(let cname in components) {
if(cname === "_lib" || cname == "_generators") continue;
const namespacedName = `${libname}/${cname}`;
components[cname].name = namespacedName;
namespacedComponents[namespacedName] = components[cname];
}
const namespacedGenerators = {}
if(components._generators) {
namespacedGenerators._lib=components._generators._lib || "generators.js";
for(let gname in components._generators) {
if(gname === "_lib") continue;
const namespacedName = `${libname}/${gname}`;
components._generators[gname].name = namespacedName;
namespacedGenerators[namespacedName] = components._generators[gname];
}
}
return ({
components: namespacedComponents,
generators: namespacedGenerators,
libDir,
componentsPath
});
} catch(e) {
const err = `could not parse JSON - ${componentsPath} : ${e.message}`;
throw new Error(err);
}
}

View File

@ -0,0 +1,175 @@
const {
appPackageFolder,
appsFolder
} = require("../createAppPackage");
const {
readJSON, writeJSON, readdir,
stat, ensureDir, rename,
unlink, rmdir
} = require("fs-extra");
const {
join,dirname
} = require("path");
const { $ } = require("@budibase/core").common;
const {
keyBy, intersection, map
} = require("lodash/fp");
const {merge} = require("lodash");
const { componentLibraryInfo } = require("./componentLibraryInfo");
const savePackage = require("./savePackage");
const buildApp = require("./buildApp");
module.exports.savePackage = savePackage;
const getPages = async (appPath) => await readJSON(`${appPath}/pages.json`);
const getAppDefinition = async (appPath) => await readJSON(`${appPath}/appDefinition.json`);
module.exports.getPackageForBuilder = async (config, appname) => {
const appPath = appPackageFolder(config, appname);
const pages = await getPages(appPath);
return ({
appDefinition: await getAppDefinition(appPath),
accessLevels: await readJSON(`${appPath}/access_levels.json`),
pages,
components: await getComponents(appPath, pages),
screens: keyBy("name")(
await fetchscreens(appPath))
});
}
module.exports.getApps = async (config, master) => {
const dirs = await readdir(appsFolder(config));
return $(master.listApplications(), [
map(a => a.name),
intersection(dirs)
]);
}
const componentPath = (appPath, name) =>
join(appPath, "components", name + ".json");
module.exports.saveScreen = async (config, appname, component) => {
const appPath = appPackageFolder(config, appname);
const compPath = componentPath(appPath, component.name);
await ensureDir(dirname(compPath));
await writeJSON(
compPath,
component,
{encoding:"utf8", flag:"w", spaces:2});
}
module.exports.renameScreen = async (config, appname, oldName, newName) => {
const appPath = appPackageFolder(config, appname);
const oldComponentPath = componentPath(
appPath, oldName);
const newComponentPath = componentPath(
appPath, newName);
await ensureDir(dirname(newComponentPath));
await rename(
oldComponentPath,
newComponentPath);
}
module.exports.deleteScreen = async (config, appname, name) => {
const appPath = appPackageFolder(config, appname);
const componentFile = componentPath(appPath, name);
await unlink(componentFile);
const dir = dirname(componentFile);
if((await readdir(dir)).length === 0) {
await rmdir(dir);
}
}
module.exports.componentLibraryInfo = async (config, appname, lib) => {
const appPath = appPackageFolder(config, appname);
return await componentLibraryInfo(appPath, lib);
};
const getComponents = async (appPath, pages ,lib) => {
let libs;
if(!lib) {
pages = pages || await readJSON(
`${appPath}/pages.json`);
if(!pages.componentLibraries) return [];
libs = pages.componentLibraries;
} else {
libs = [lib];
}
const components = {};
const generators = {};
for(let l of libs) {
const info = await componentLibraryInfo(appPath, l);
merge(components, info.components);
merge(generators, info.generators);
}
if(components._lib) delete components._lib;
if(components._generators) delete components._generators;
return {components, generators};
}
const fetchscreens = async (appPath, relativePath = "") => {
const currentDir = join(appPath, "components", relativePath);
const contents = await readdir(currentDir);
const components = [];
for(let item of contents) {
const itemRelativePath = join(relativePath, item);
const itemFullPath = join(currentDir, item);
const stats = await stat(itemFullPath);
if(stats.isFile()) {
if(!item.endsWith(".json")) continue;
const component =
await readJSON(itemFullPath);
component.name = itemRelativePath
.substring(0, itemRelativePath.length - 5)
.replace(/\\/g, "/");
component.props = component.props || {};
components.push(component);
} else {
const childComponents = await fetchscreens(
appPath, join(relativePath, item)
);
for(let c of childComponents) {
components.push(c);
}
}
}
return components;
}
module.exports.getComponents = getComponents;

View File

@ -0,0 +1,32 @@
<!doctype html>
<html>
<head>
<meta charset='utf8'>
<meta name='viewport' content='width=device-width'>
<title>{{ title }}</title>
<link rel='icon' type='image/png' href='{{ favicon }}'>
<style>
html, body {
height: 100%;
width: 100%;
}
</style>
{{ each(options.stylesheets) }}
<link rel='stylesheet' href='{{ @this }}'>
{{ /each }}
<script src='{{ appRootPath }}/clientAppDefinition.js'></script>
<script src='{{ appRootPath }}/budibase-client.js'></script>
<script>
loadBudibase();
</script>
</head>
<body id="app">
</body>
</html>

View File

@ -0,0 +1,25 @@
const { appPackageFolder } = require("../createAppPackage");
const { writeJSON } = require("fs-extra");
const buildApp = require("./buildApp");
module.exports = async (config, appname, pkg) => {
const appPath = appPackageFolder(config, appname);
await writeJSON(
`${appPath}/appDefinition.json`,
pkg.appDefinition,
{spaces:2});
await writeJSON(
`${appPath}/access_levels.json`,
pkg.accessLevels,
{spaces:2});
await writeJSON(
`${appPath}/pages.json`,
pkg.pages,
{spaces:2});
await buildApp(
config, appname,
pkg.pages, pkg.appDefinition);
}