forked from tsai/budibase
13 changed files with 137 additions and 178 deletions
@ -0,0 +1,15 @@ |
|||||
|
const CouchDB = require("../../db/client") |
||||
|
const { generateLayoutID } = require("../../db/utils") |
||||
|
const compileStaticAssets = require("../../utilities/builder/compileStaticAssets") |
||||
|
|
||||
|
exports.save = async function(ctx) { |
||||
|
const db = new CouchDB(ctx.user.appId) |
||||
|
const appPackage = ctx.request.body |
||||
|
|
||||
|
// remove special doc props which couch will complain about
|
||||
|
delete appPackage.layout._css |
||||
|
appPackage.layout._id = appPackage.layout._id || generateLayoutID() |
||||
|
ctx.body = await db.put(appPackage.layout) |
||||
|
await compileStaticAssets(ctx.user.appId) |
||||
|
ctx.status = 200 |
||||
|
} |
||||
@ -1,19 +0,0 @@ |
|||||
const CouchDB = require("../../db/client") |
|
||||
const { generatePageID } = require("../../db/utils") |
|
||||
const compileStaticAssetsForPage = require("../../utilities/builder/compileStaticAssetsForPage") |
|
||||
|
|
||||
exports.save = async function(ctx) { |
|
||||
const db = new CouchDB(ctx.user.appId) |
|
||||
|
|
||||
const appPackage = ctx.request.body |
|
||||
|
|
||||
const page = await db.get(ctx.params.pageId) |
|
||||
await compileStaticAssetsForPage(ctx.user.appId, page.name, ctx.request.body) |
|
||||
|
|
||||
// remove special doc props which couch will complain about
|
|
||||
delete appPackage.page._css |
|
||||
delete appPackage.page._screens |
|
||||
appPackage.page._id = appPackage.page._id || generatePageID() |
|
||||
ctx.body = await db.put(appPackage.page) |
|
||||
ctx.status = 200 |
|
||||
} |
|
||||
@ -1,10 +1,10 @@ |
|||||
const Router = require("@koa/router") |
const Router = require("@koa/router") |
||||
const authorized = require("../../middleware/authorized") |
const authorized = require("../../middleware/authorized") |
||||
const { BUILDER } = require("../../utilities/security/permissions") |
const { BUILDER } = require("../../utilities/security/permissions") |
||||
const controller = require("../controllers/page") |
const controller = require("../controllers/layout") |
||||
|
|
||||
const router = Router() |
const router = Router() |
||||
|
|
||||
router.post("/api/pages/:pageId", authorized(BUILDER), controller.save) |
router.post("/api/layouts/:layoutId", authorized(BUILDER), controller.save) |
||||
|
|
||||
module.exports = router |
module.exports = router |
||||
@ -0,0 +1,83 @@ |
|||||
|
const { ensureDir, constants, copyFile, writeFile } = require("fs-extra") |
||||
|
const { join } = require("../centralPath") |
||||
|
const { budibaseAppsDir } = require("../budibaseDir") |
||||
|
const CouchDB = require("../../db") |
||||
|
const { getScreenParams, getLayoutParams } = require("../../db/utils") |
||||
|
|
||||
|
async function getAppPackage(appId) { |
||||
|
const db = new CouchDB(appId) |
||||
|
let params = { |
||||
|
include_docs: true, |
||||
|
} |
||||
|
let [screens, layouts] = await Promise.all([ |
||||
|
db.allDocs(getScreenParams(null, params)), |
||||
|
db.allDocs(getLayoutParams(null, params)), |
||||
|
]) |
||||
|
screens = screens.rows.map(row => row.doc) |
||||
|
layouts = layouts.rows.map(row => row.doc) |
||||
|
if (!screens) { |
||||
|
screens = [] |
||||
|
} |
||||
|
if (!layouts) { |
||||
|
layouts = [] |
||||
|
} |
||||
|
return { screens, layouts } |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Compile all the non-db static web assets that are required for the running of |
||||
|
* a budibase application. This includes CSS, the JSON structure of the DOM and |
||||
|
* the client library, a script responsible for reading the JSON structure |
||||
|
* and rendering the application. |
||||
|
* @param {string} appId - id of the application we want to compile static assets for |
||||
|
*/ |
||||
|
module.exports = async appId => { |
||||
|
const publicPath = join(budibaseAppsDir(), appId, "public") |
||||
|
const pkg = await getAppPackage(appId) |
||||
|
|
||||
|
await ensureDir(publicPath) |
||||
|
await buildCssBundle(publicPath, pkg) |
||||
|
await copyClientLib(publicPath) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Reads the _css property of all screens and the screen layouts, and creates a singular CSS |
||||
|
* bundle for the app at <appId>/public/bundle.css |
||||
|
* @param {String} publicPath - path to the public assets directory of the budibase application |
||||
|
* @param {Object} pkg - app package information |
||||
|
*/ |
||||
|
const buildCssBundle = async (publicPath, pkg) => { |
||||
|
let cssString = "" |
||||
|
|
||||
|
for (let screen of pkg.screens || []) { |
||||
|
if (!screen._css) continue |
||||
|
if (screen._css.trim().length === 0) { |
||||
|
delete screen._css |
||||
|
continue |
||||
|
} |
||||
|
cssString += screen._css |
||||
|
} |
||||
|
|
||||
|
if (pkg.layout._css) cssString += pkg.layout._css |
||||
|
|
||||
|
writeFile(join(publicPath, "bundle.css"), cssString) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Copy the budibase client library and sourcemap from NPM to <appId>/public/. |
||||
|
* The client library is then served as a static asset when the budibase application |
||||
|
* is running in preview or prod |
||||
|
* @param {String} publicPath - path to write the client library to |
||||
|
*/ |
||||
|
const copyClientLib = async publicPath => { |
||||
|
const sourcepath = require.resolve("@budibase/client") |
||||
|
const destPath = join(publicPath, "budibase-client.js") |
||||
|
|
||||
|
await copyFile(sourcepath, destPath, constants.COPYFILE_FICLONE) |
||||
|
|
||||
|
await copyFile( |
||||
|
sourcepath + ".map", |
||||
|
destPath + ".map", |
||||
|
constants.COPYFILE_FICLONE |
||||
|
) |
||||
|
} |
||||
@ -1,102 +0,0 @@ |
|||||
const { ensureDir, constants, copyFile, writeFile } = require("fs-extra") |
|
||||
const { join } = require("../centralPath") |
|
||||
const { budibaseAppsDir } = require("../budibaseDir") |
|
||||
|
|
||||
/** |
|
||||
* Compile all the non-db static web assets that are required for the running of |
|
||||
* a budibase application. This includes CSS, the JSON structure of the DOM and |
|
||||
* the client library, a script responsible for reading the JSON structure |
|
||||
* and rendering the application. |
|
||||
* @param {} appId - id of the application we want to compile static assets for |
|
||||
* @param {*} pageName - name of the page that the assets will be served for |
|
||||
* @param {*} pkg - app package information/metadata |
|
||||
*/ |
|
||||
module.exports = async (appId, pageName, pkg) => { |
|
||||
const pagePath = join(budibaseAppsDir(), appId, "public", pageName) |
|
||||
|
|
||||
pkg.screens = pkg.screens || [] |
|
||||
|
|
||||
await ensureDir(pagePath) |
|
||||
|
|
||||
await buildPageCssBundle(pagePath, pkg) |
|
||||
|
|
||||
await buildFrontendAppDefinition(pagePath, pkg) |
|
||||
|
|
||||
await copyClientLib(pagePath) |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Reads the _css property of a page and its screens, and creates a singular CSS |
|
||||
* bundle for the page at <appId>/public/<pageName>/bundle.css |
|
||||
* @param {String} publicPagePath - path to the public assets directory of the budibase application |
|
||||
* @param {Object} pkg - app package information |
|
||||
* @param {"main" | "unauthenticated"} pageName - the pagename of the page we are compiling CSS for. |
|
||||
*/ |
|
||||
const buildPageCssBundle = async (publicPagePath, pkg) => { |
|
||||
let cssString = "" |
|
||||
|
|
||||
for (let screen of pkg.screens || []) { |
|
||||
if (!screen._css) continue |
|
||||
if (screen._css.trim().length === 0) { |
|
||||
delete screen._css |
|
||||
continue |
|
||||
} |
|
||||
cssString += screen._css |
|
||||
} |
|
||||
|
|
||||
if (pkg.page._css) cssString += pkg.page._css |
|
||||
|
|
||||
writeFile(join(publicPagePath, "bundle.css"), cssString) |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Copy the budibase client library and sourcemap from NPM to <appId>/public/<pageName>. |
|
||||
* The client library is then served as a static asset when the budibase application |
|
||||
* is running in preview or prod |
|
||||
* @param {String} pagePath - path to write the client library to |
|
||||
*/ |
|
||||
const copyClientLib = async pagePath => { |
|
||||
const sourcepath = require.resolve("@budibase/client") |
|
||||
const destPath = join(pagePath, "budibase-client.js") |
|
||||
|
|
||||
await copyFile(sourcepath, destPath, constants.COPYFILE_FICLONE) |
|
||||
|
|
||||
await copyFile( |
|
||||
sourcepath + ".map", |
|
||||
destPath + ".map", |
|
||||
constants.COPYFILE_FICLONE |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Build the frontend definition for a budibase application. This includes all page and screen information, |
|
||||
* and is injected into the budibase client library to tell it how to start constructing |
|
||||
* the DOM from components defined in the frontendDefinition. |
|
||||
* @param {String} pagePath - path to the public folder of the page where the definition will be written |
|
||||
* @param {Object} pkg - app package information from which the frontendDefinition will be built. |
|
||||
*/ |
|
||||
const buildFrontendAppDefinition = async (pagePath, pkg) => { |
|
||||
const filename = join(pagePath, "clientFrontendDefinition.js") |
|
||||
|
|
||||
// Delete CSS code from the page and screens so it's not injected
|
|
||||
delete pkg.page._css |
|
||||
|
|
||||
for (let screen of pkg.screens) { |
|
||||
if (screen._css) { |
|
||||
delete pkg.page._css |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
const clientUiDefinition = JSON.stringify({ |
|
||||
page: pkg.page, |
|
||||
screens: pkg.screens, |
|
||||
libraries: ["@budibase/standard-components"], |
|
||||
}) |
|
||||
|
|
||||
await writeFile( |
|
||||
filename, |
|
||||
` |
|
||||
window['##BUDIBASE_FRONTEND_DEFINITION##'] = ${clientUiDefinition}; |
|
||||
` |
|
||||
) |
|
||||
} |
|
||||
Loading…
Reference in new issue