Adding first pass of attachments updating.

This commit is contained in:
mike12345567 2022-10-12 17:34:17 +01:00
parent 33e31fe2e4
commit a2d12ef0a6
4 changed files with 71 additions and 27 deletions

View File

@ -32,7 +32,7 @@ const checkInitialised = () => {
} }
} }
export async function init(opts: PouchOptions) { export async function init(opts?: PouchOptions) {
PouchDB = pouch.getPouch(opts) PouchDB = pouch.getPouch(opts)
initialised = true initialised = true
} }
@ -40,7 +40,7 @@ export async function init(opts: PouchOptions) {
// NOTE: THIS IS A DANGEROUS FUNCTION - USE WITH CAUTION // NOTE: THIS IS A DANGEROUS FUNCTION - USE WITH CAUTION
// this function is prone to leaks, should only be used // this function is prone to leaks, should only be used
// in situations that using the function doWithDB does not work // in situations that using the function doWithDB does not work
export async function dangerousGetDB(dbName: string, opts: any) { export async function dangerousGetDB(dbName: string, opts?: any) {
checkInitialised() checkInitialised()
if (env.isTest()) { if (env.isTest()) {
dbList.add(dbName) dbList.add(dbName)

View File

@ -1,4 +1,4 @@
import { ATTACHMENT_DIR as attachmentDir } from "../../constants" import { ATTACHMENT_DIR as attachmentDir } from "../../../constants"
export const DB_EXPORT_FILE = "db.txt" export const DB_EXPORT_FILE = "db.txt"
export const ATTACHMENT_DIR = attachmentDir export const ATTACHMENT_DIR = attachmentDir
export const GLOBAL_DB_EXPORT_FILE = "global.txt" export const GLOBAL_DB_EXPORT_FILE = "global.txt"

View File

@ -1,4 +1,5 @@
import { db as dbCore } from "@budibase/backend-core" import { db as dbCore } from "@budibase/backend-core"
import { TABLE_ROW_PREFIX } from "../../../db/utils"
import { budibaseTempDir } from "../../../utilities/budibaseDir" import { budibaseTempDir } from "../../../utilities/budibaseDir"
import { DB_EXPORT_FILE, ATTACHMENT_DIR } from "./constants" import { DB_EXPORT_FILE, ATTACHMENT_DIR } from "./constants"
import { uploadDirectory } from "../../../utilities/fileSystem/utilities" import { uploadDirectory } from "../../../utilities/fileSystem/utilities"
@ -6,7 +7,7 @@ import { ObjectStoreBuckets, FieldTypes } from "../../../constants"
import { join } from "path" import { join } from "path"
import fs from "fs" import fs from "fs"
import sdk from "../../" import sdk from "../../"
import { CouchFindOptions, Row } from "@budibase/types" import { CouchFindOptions, RowAttachment } from "@budibase/types"
const uuid = require("uuid/v4") const uuid = require("uuid/v4")
const tar = require("tar") const tar = require("tar")
@ -18,6 +19,63 @@ type TemplateType = {
key?: string key?: string
} }
async function updateAttachmentColumns(
prodAppId: string,
db: PouchDB.Database
) {
// iterate through attachment documents and update them
const tables = await sdk.tables.getAllInternalTables(db)
for (let table of tables) {
const attachmentCols: string[] = []
for (let [key, column] of Object.entries(table.schema)) {
if (column.type === FieldTypes.ATTACHMENT) {
attachmentCols.push(key)
}
}
// no attachment columns, nothing to do
if (attachmentCols.length === 0) {
continue
}
// use the CouchDB Mango query API to lookup rows that have attachments
const params: CouchFindOptions = {
selector: {
_id: {
$regex: `^${TABLE_ROW_PREFIX}`,
},
},
}
attachmentCols.forEach(col => (params.selector[col] = { $exists: true }))
const { rows } = await dbCore.directCouchFind(db.name, params)
for (let row of rows) {
for (let column of attachmentCols) {
if (!Array.isArray(row[column])) {
continue
}
row[column] = row[column].map((attachment: RowAttachment) => {
// URL looks like: /prod-budi-app-assets/appId/attachments/file.csv
const urlParts = attachment.url.split("/")
// drop the first empty element
urlParts.shift()
// get the prefix
const prefix = urlParts.shift()
// remove the app ID
urlParts.shift()
// add new app ID
urlParts.unshift(prodAppId)
const key = urlParts.join("/")
return {
...attachment,
key,
url: `/${prefix}/${key}`,
}
})
}
}
// write back the updated attachments
await db.bulkDocs(rows)
}
}
/** /**
* This function manages temporary template files which are stored by Koa. * This function manages temporary template files which are stored by Koa.
* @param {Object} template The template object retrieved from the Koa context object. * @param {Object} template The template object retrieved from the Koa context object.
@ -67,28 +125,6 @@ export async function importApp(
if (!ok) { if (!ok) {
throw "Error loading database dump from template." throw "Error loading database dump from template."
} }
// iterate through attachment documents and update them await updateAttachmentColumns(prodAppId, db)
const tables = await sdk.tables.getAllInternalTables(db)
for (let table of tables) {
const attachmentCols: string[] = []
for (let [key, column] of Object.entries(table.schema)) {
if (column.type === FieldTypes.ATTACHMENT) {
attachmentCols.push(key)
}
}
// no attachment columns, nothing to do
if (attachmentCols.length === 0) {
continue
}
// use the CouchDB Mango query API to lookup rows that have attachments
const params: CouchFindOptions = { selector: {} }
attachmentCols.forEach(col => (params.selector[col] = { $exists: true }))
const { rows } = await dbCore.directCouchFind(db.name, params)
for (let row of rows) {
// TODO:
}
// write back the updated attachments
await db.bulkDocs(rows)
}
return ok return ok
} }

View File

@ -16,6 +16,14 @@ export enum FieldType {
INTERNAL = "internal", INTERNAL = "internal",
} }
export interface RowAttachment {
size: number
name: string
url: string
extension: string
key: string
}
export interface Row extends Document { export interface Row extends Document {
type?: string type?: string
tableId?: string tableId?: string