budibase/packages/server/src/utilities/fileSystem/index.js

99 lines
3.6 KiB
JavaScript
Raw Normal View History

const { budibaseTempDir } = require("../budibaseDir")
const { isDev } = require("../index")
const fs = require("fs")
const { join } = require("path")
const uuid = require("uuid/v4")
const CouchDB = require("../../db")
const { ObjectStoreBuckets } = require("../../constants")
const { streamUpload, deleteFolder, downloadTarball } = require("./utilities")
const { downloadLibraries, newAppPublicPath } = require("./newApp")
/**
* The single stack system (Cloud and Builder) should not make use of the file system where possible,
* this file handles all of the file access for the system with the intention of limiting it all to one
* place. Keeping all of this logic in one place means that when we need to do file system access (like
* downloading a package or opening a temporary file) in can be done in way that we can confirm it shouldn't
* be done through an object store instead.
*/
/**
* Checks if the system is currently in development mode and if it is makes sure
* everything required to function is ready.
*/
exports.checkDevelopmentEnvironment = () => {
if (isDev() && !fs.existsSync(budibaseTempDir())) {
console.error(
"Please run a build before attempting to run server independently to fill 'tmp' directory."
)
process.exit(-1)
}
}
/**
* This function manages temporary template files which are stored by Koa.
* @param {Object} template The template object retrieved from the Koa context object.
* @returns {Object} Returns an fs read stream which can be loaded into the database.
*/
exports.getTemplateStream = async template => {
if (template.file) {
return fs.createReadStream(template.file.path)
} else {
const tmpPath = await exports.downloadTemplate(...template.key.split("/"))
return fs.createReadStream(join(tmpPath, "db", "dump.txt"))
}
}
/**
* Used to retrieve a handlebars file from the system which will be used as a template.
* This is allowable as the template handlebars files should be static and identical across
* the cluster.
* @param {string} path The path to the handlebars file which is to be loaded.
* @returns {string} The loaded handlebars file as a string - loaded as utf8.
*/
exports.loadHandlebarsFile = path => {
return fs.readFileSync(path, "utf8")
}
/**
* When return a file from the API need to write the file to the system temporarily so we
* can create a read stream to send.
* @param {string} contents the contents of the file which is to be returned from the API.
* @return {Object} the read stream which can be put into the koa context body.
*/
exports.apiFileReturn = contents => {
const path = join(budibaseTempDir(), uuid())
fs.writeFileSync(path, contents)
return fs.createReadStream(path)
}
exports.performBackup = async (appId, backupName) => {
const path = join(budibaseTempDir(), backupName)
const writeStream = fs.createWriteStream(path)
// perform couch dump
const instanceDb = new CouchDB(appId)
await instanceDb.dump(writeStream, {})
// write the file to the object store
await streamUpload(
ObjectStoreBuckets.BACKUPS,
join(appId, backupName),
fs.createReadStream(path)
)
return fs.createReadStream(path)
}
exports.createApp = async appId => {
await downloadLibraries(appId)
await newAppPublicPath(appId)
}
exports.deleteApp = async appId => {
await deleteFolder(ObjectStoreBuckets.APPS, `${appId}/`)
}
exports.downloadTemplate = async (type, name) => {
const DEFAULT_TEMPLATES_BUCKET =
"prod-budi-templates.s3-eu-west-1.amazonaws.com"
const templateUrl = `https://${DEFAULT_TEMPLATES_BUCKET}/templates/${type}/${name}.tar.gz`
return downloadTarball(templateUrl, ObjectStoreBuckets.TEMPLATES, type)
}