From 90a8435641a5226e6ed3bfc787b961fb1046fc0f Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 23 Nov 2020 14:07:18 +0000 Subject: [PATCH] Storing some work in commit, currently broken, further work needed - application needs cleaned up. --- .../server/src/api/controllers/application.js | 28 ++--- .../server/src/api/controllers/deploy/aws.js | 28 +++-- packages/server/src/api/controllers/layout.js | 15 +++ packages/server/src/api/controllers/page.js | 19 ---- .../src/api/controllers/static/index.js | 4 - .../static/templates/BudibaseApp.svelte | 3 +- packages/server/src/api/routes/index.js | 4 +- .../src/api/routes/{pages.js => layout.js} | 4 +- .../src/api/routes/tests/automation.spec.js | 1 - .../src/constants/{pages.js => layouts.js} | 8 +- packages/server/src/db/utils.js | 16 +-- .../utilities/builder/compileStaticAssets.js | 83 ++++++++++++++ .../builder/compileStaticAssetsForPage.js | 102 ------------------ 13 files changed, 137 insertions(+), 178 deletions(-) create mode 100644 packages/server/src/api/controllers/layout.js delete mode 100644 packages/server/src/api/controllers/page.js rename packages/server/src/api/routes/{pages.js => layout.js} (62%) rename packages/server/src/constants/{pages.js => layouts.js} (97%) create mode 100644 packages/server/src/utilities/builder/compileStaticAssets.js delete mode 100644 packages/server/src/utilities/builder/compileStaticAssetsForPage.js diff --git a/packages/server/src/api/controllers/application.js b/packages/server/src/api/controllers/application.js index 512299c5c8..095cb3b831 100644 --- a/packages/server/src/api/controllers/application.js +++ b/packages/server/src/api/controllers/application.js @@ -1,5 +1,5 @@ const CouchDB = require("../../db") -const compileStaticAssetsForPage = require("../../utilities/builder/compileStaticAssetsForPage") +const compileStaticAssets = require("../../utilities/builder/compileStaticAssets") const env = require("../../environment") const { existsSync } = require("fs-extra") const { budibaseAppsDir } = require("../../utilities/budibaseDir") @@ -14,16 +14,16 @@ const { generateAppID, DocumentTypes, SEPARATOR, - getPageParams, + getLayoutParams, getScreenParams, - generatePageID, + generateLayoutID, generateScreenID, } = require("../../db/utils") const { BUILTIN_LEVEL_IDS } = require("../../utilities/security/accessLevels") const { downloadExtractComponentLibraries, } = require("../../utilities/createAppPackage") -const { MAIN, UNAUTHENTICATED, PageTypes } = require("../../constants/pages") +const { MAIN, UNAUTHENTICATED, LayoutTypes } = require("../../constants/layouts") const { HOME_SCREEN } = require("../../constants/screens") const { cloneDeep } = require("lodash/fp") @@ -32,14 +32,14 @@ const APP_PREFIX = DocumentTypes.APP + SEPARATOR // utility function, need to do away with this async function getMainAndUnauthPage(db) { let pages = await db.allDocs( - getPageParams(null, { + getLayoutParams(null, { include_docs: true, }) ) pages = pages.rows.map(row => row.doc) - const mainPage = pages.find(page => page.name === PageTypes.MAIN) - const unauthPage = pages.find(page => page.name === PageTypes.UNAUTHENTICATED) + const mainPage = pages.find(page => page.name === LayoutTypes.MAIN) + const unauthPage = pages.find(page => page.name === LayoutTypes.UNAUTHENTICATED) return { mainPage, unauthPage } } @@ -194,11 +194,11 @@ const createEmptyAppPackage = async (ctx, app) => { fs.mkdirpSync(newAppFolder) const mainPage = cloneDeep(MAIN) - mainPage._id = generatePageID() + mainPage._id = generateLayoutID() mainPage.title = app.name const unauthPage = cloneDeep(UNAUTHENTICATED) - unauthPage._id = generatePageID() + unauthPage._id = generateLayoutID() unauthPage.title = app.name unauthPage.props._children[0].title = `Log in to ${app.name}` @@ -206,14 +206,6 @@ const createEmptyAppPackage = async (ctx, app) => { homeScreen._id = generateScreenID(mainPage._id) await db.bulkDocs([mainPage, unauthPage, homeScreen]) - await compileStaticAssetsForPage(app._id, "main", { - page: mainPage, - screens: [homeScreen], - }) - await compileStaticAssetsForPage(app._id, "unauthenticated", { - page: unauthPage, - screens: [], - }) - + await compileStaticAssets(app._id) return newAppFolder } diff --git a/packages/server/src/api/controllers/deploy/aws.js b/packages/server/src/api/controllers/deploy/aws.js index d478c4efde..5c788a9dcc 100644 --- a/packages/server/src/api/controllers/deploy/aws.js +++ b/packages/server/src/api/controllers/deploy/aws.js @@ -136,25 +136,21 @@ exports.uploadAppAssets = async function({ appId, bucket, accountId }) { const appAssetsPath = join(budibaseAppsDir(), appId, "public") - const appPages = fs.readdirSync(appAssetsPath) - let uploads = [] - for (let page of appPages) { - // Upload HTML, CSS and JS for each page of the web app - walkDir(join(appAssetsPath, page), function(filePath) { - const appAssetUpload = prepareUploadForS3({ - file: { - path: filePath, - name: [...filePath.split("/")].pop(), - }, - s3Key: filePath.replace(appAssetsPath, `assets/${appId}`), - s3, - metadata: { accountId }, - }) - uploads.push(appAssetUpload) + // Upload HTML, CSS and JS of the web app + walkDir(appAssetsPath, function(filePath) { + const appAssetUpload = prepareUploadForS3({ + file: { + path: filePath, + name: [...filePath.split("/")].pop(), + }, + s3Key: filePath.replace(appAssetsPath, `assets/${appId}`), + s3, + metadata: { accountId }, }) - } + uploads.push(appAssetUpload) + }) // Upload file attachments const db = new PouchDB(appId) diff --git a/packages/server/src/api/controllers/layout.js b/packages/server/src/api/controllers/layout.js new file mode 100644 index 0000000000..eae7b04d49 --- /dev/null +++ b/packages/server/src/api/controllers/layout.js @@ -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 +} diff --git a/packages/server/src/api/controllers/page.js b/packages/server/src/api/controllers/page.js deleted file mode 100644 index 4f3989ae90..0000000000 --- a/packages/server/src/api/controllers/page.js +++ /dev/null @@ -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 -} diff --git a/packages/server/src/api/controllers/static/index.js b/packages/server/src/api/controllers/static/index.js index b048bbd9fe..5676afb230 100644 --- a/packages/server/src/api/controllers/static/index.js +++ b/packages/server/src/api/controllers/static/index.js @@ -142,15 +142,11 @@ exports.performLocalFileProcessing = async function(ctx) { exports.serveApp = async function(ctx) { const App = require("./templates/BudibaseApp.svelte").default - const db = new CouchDB(ctx.params.appId) - const appInfo = await db.get(ctx.params.appId) const { head, html, css } = App.render({ title: appInfo.name, - pageName: - ctx.auth.authenticated === AuthTypes.APP ? "main" : "unauthenticated", production: env.CLOUD, appId: ctx.params.appId, }) diff --git a/packages/server/src/api/controllers/static/templates/BudibaseApp.svelte b/packages/server/src/api/controllers/static/templates/BudibaseApp.svelte index 7d6ad8141c..7668d7c7eb 100644 --- a/packages/server/src/api/controllers/static/templates/BudibaseApp.svelte +++ b/packages/server/src/api/controllers/static/templates/BudibaseApp.svelte @@ -3,14 +3,13 @@ export let favicon = "" export let appId - export let pageName = "" export let production export const PRODUCTION_ASSETS_URL = `https://${appId}.app.budi.live` function publicPath(path) { if (production) { - return `${PRODUCTION_ASSETS_URL}/assets/${appId}/${pageName}/${path}` + return `${PRODUCTION_ASSETS_URL}/assets/${appId}/${path}` } return `/assets/${path}` diff --git a/packages/server/src/api/routes/index.js b/packages/server/src/api/routes/index.js index 840f968eb3..43732298e1 100644 --- a/packages/server/src/api/routes/index.js +++ b/packages/server/src/api/routes/index.js @@ -1,5 +1,5 @@ const authRoutes = require("./auth") -const pageRoutes = require("./pages") +const layoutRoutes = require("./layout") const screenRoutes = require("./screen") const userRoutes = require("./user") const applicationRoutes = require("./application") @@ -19,7 +19,7 @@ const routingRoutes = require("./routing") exports.mainRoutes = [ deployRoutes, - pageRoutes, + layoutRoutes, screenRoutes, userRoutes, applicationRoutes, diff --git a/packages/server/src/api/routes/pages.js b/packages/server/src/api/routes/layout.js similarity index 62% rename from packages/server/src/api/routes/pages.js rename to packages/server/src/api/routes/layout.js index 43fb0e764c..b773dc7dae 100644 --- a/packages/server/src/api/routes/pages.js +++ b/packages/server/src/api/routes/layout.js @@ -1,10 +1,10 @@ const Router = require("@koa/router") const authorized = require("../../middleware/authorized") const { BUILDER } = require("../../utilities/security/permissions") -const controller = require("../controllers/page") +const controller = require("../controllers/layout") const router = Router() -router.post("/api/pages/:pageId", authorized(BUILDER), controller.save) +router.post("/api/layouts/:layoutId", authorized(BUILDER), controller.save) module.exports = router diff --git a/packages/server/src/api/routes/tests/automation.spec.js b/packages/server/src/api/routes/tests/automation.spec.js index 226bbad226..4c9bdb67cb 100644 --- a/packages/server/src/api/routes/tests/automation.spec.js +++ b/packages/server/src/api/routes/tests/automation.spec.js @@ -17,7 +17,6 @@ const AUTOMATION_ID = generateAutomationID() const TEST_AUTOMATION = { _id: AUTOMATION_ID, name: "My Automation", - pageId: "123123123", screenId: "kasdkfldsafkl", live: true, uiTree: { diff --git a/packages/server/src/constants/pages.js b/packages/server/src/constants/layouts.js similarity index 97% rename from packages/server/src/constants/pages.js rename to packages/server/src/constants/layouts.js index 5fe74d6123..065bcdf261 100644 --- a/packages/server/src/constants/pages.js +++ b/packages/server/src/constants/layouts.js @@ -1,4 +1,4 @@ -const PageTypes = { +const LayoutTypes = { MAIN: "main", UNAUTHENTICATED: "unauthenticated", } @@ -8,7 +8,7 @@ const MAIN = { title: "{{ name }}", favicon: "./_shared/favicon.png", stylesheets: [], - name: PageTypes.MAIN, + name: LayoutTypes.MAIN, props: { _id: "private-master-root", _component: "@budibase/standard-components/container", @@ -153,7 +153,7 @@ const UNAUTHENTICATED = { title: "{{ name }}", favicon: "./_shared/favicon.png", stylesheets: [], - name: PageTypes.UNAUTHENTICATED, + name: LayoutTypes.UNAUTHENTICATED, props: { _id: "public-master-root", _component: "@budibase/standard-components/container", @@ -218,4 +218,4 @@ const UNAUTHENTICATED = { }, } -module.exports = { MAIN, UNAUTHENTICATED, PageTypes } +module.exports = { MAIN, UNAUTHENTICATED, LayoutTypes } diff --git a/packages/server/src/db/utils.js b/packages/server/src/db/utils.js index c3b5866a2a..9d9e470ec1 100644 --- a/packages/server/src/db/utils.js +++ b/packages/server/src/db/utils.js @@ -13,7 +13,7 @@ const DocumentTypes = { ACCESS_LEVEL: "ac", WEBHOOK: "wh", INSTANCE: "inst", - PAGE: "page", + LAYOUT: "layout", SCREEN: "screen", } @@ -180,18 +180,18 @@ exports.getAccessLevelParams = (accessLevelId = null, otherProps = {}) => { } /** - * Generates a new page ID. - * @returns {string} The new page ID which the page doc can be stored under. + * Generates a new layout ID. + * @returns {string} The new layout ID which the layout doc can be stored under. */ -exports.generatePageID = () => { - return `${DocumentTypes.PAGE}${SEPARATOR}${newid()}` +exports.generateLayoutID = () => { + return `${DocumentTypes.LAYOUT}${SEPARATOR}${newid()}` } /** - * Gets parameters for retrieving pages, this is a utility function for the getDocParams function. + * Gets parameters for retrieving layout, this is a utility function for the getDocParams function. */ -exports.getPageParams = (pageId = null, otherProps = {}) => { - return getDocParams(DocumentTypes.PAGE, pageId, otherProps) +exports.getLayoutParams = (layoutId = null, otherProps = {}) => { + return getDocParams(DocumentTypes.LAYOUT, layoutId, otherProps) } /** diff --git a/packages/server/src/utilities/builder/compileStaticAssets.js b/packages/server/src/utilities/builder/compileStaticAssets.js new file mode 100644 index 0000000000..a64c2f0b98 --- /dev/null +++ b/packages/server/src/utilities/builder/compileStaticAssets.js @@ -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 /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 /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 + ) +} diff --git a/packages/server/src/utilities/builder/compileStaticAssetsForPage.js b/packages/server/src/utilities/builder/compileStaticAssetsForPage.js deleted file mode 100644 index c91ba24bb3..0000000000 --- a/packages/server/src/utilities/builder/compileStaticAssetsForPage.js +++ /dev/null @@ -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 /public//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 /public/. - * 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}; - ` - ) -}