|
|
|
@ -1,4 +1,3 @@ |
|
|
|
const CouchDB = require("../../../db") |
|
|
|
const linkRows = require("../../../db/linkedRows") |
|
|
|
const { |
|
|
|
generateRowID, |
|
|
|
@ -25,6 +24,7 @@ const { |
|
|
|
getFromMemoryDoc, |
|
|
|
} = require("../view/utils") |
|
|
|
const { cloneDeep } = require("lodash/fp") |
|
|
|
const { getAppDB } = require("@budibase/backend-core/context") |
|
|
|
const { finaliseRow, updateRelatedFormula } = require("./staticFormula") |
|
|
|
|
|
|
|
const CALCULATION_TYPES = { |
|
|
|
@ -76,8 +76,7 @@ async function getRawTableData(ctx, db, tableId) { |
|
|
|
} |
|
|
|
|
|
|
|
exports.patch = async ctx => { |
|
|
|
const appId = ctx.appId |
|
|
|
const db = new CouchDB(appId) |
|
|
|
const db = getAppDB() |
|
|
|
const inputs = ctx.request.body |
|
|
|
const tableId = inputs.tableId |
|
|
|
const isUserTable = tableId === InternalTables.USER_METADATA |
|
|
|
@ -116,14 +115,13 @@ exports.patch = async ctx => { |
|
|
|
|
|
|
|
// returned row is cleaned and prepared for writing to DB
|
|
|
|
row = await linkRows.updateLinks({ |
|
|
|
appId, |
|
|
|
eventType: linkRows.EventType.ROW_UPDATE, |
|
|
|
row, |
|
|
|
tableId: row.tableId, |
|
|
|
table, |
|
|
|
}) |
|
|
|
// check if any attachments removed
|
|
|
|
await cleanupAttachments(appId, table, { oldRow, row }) |
|
|
|
await cleanupAttachments(table, { oldRow, row }) |
|
|
|
|
|
|
|
if (isUserTable) { |
|
|
|
// the row has been updated, need to put it into the ctx
|
|
|
|
@ -132,15 +130,14 @@ exports.patch = async ctx => { |
|
|
|
return { row: ctx.body, table } |
|
|
|
} |
|
|
|
|
|
|
|
return finaliseRow(ctx.appId, table, row, { |
|
|
|
return finaliseRow(table, row, { |
|
|
|
oldTable: dbTable, |
|
|
|
updateFormula: true, |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
exports.save = async function (ctx) { |
|
|
|
const appId = ctx.appId |
|
|
|
const db = new CouchDB(appId) |
|
|
|
const db = getAppDB() |
|
|
|
let inputs = ctx.request.body |
|
|
|
inputs.tableId = ctx.params.tableId |
|
|
|
|
|
|
|
@ -162,21 +159,19 @@ exports.save = async function (ctx) { |
|
|
|
|
|
|
|
// make sure link rows are up to date
|
|
|
|
row = await linkRows.updateLinks({ |
|
|
|
appId, |
|
|
|
eventType: linkRows.EventType.ROW_SAVE, |
|
|
|
row, |
|
|
|
tableId: row.tableId, |
|
|
|
table, |
|
|
|
}) |
|
|
|
|
|
|
|
return finaliseRow(ctx.appId, table, row, { |
|
|
|
return finaliseRow(table, row, { |
|
|
|
oldTable: dbTable, |
|
|
|
updateFormula: true, |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
exports.fetchView = async ctx => { |
|
|
|
const appId = ctx.appId |
|
|
|
const viewName = ctx.params.viewName |
|
|
|
|
|
|
|
// if this is a table view being looked for just transfer to that
|
|
|
|
@ -185,7 +180,7 @@ exports.fetchView = async ctx => { |
|
|
|
return exports.fetch(ctx) |
|
|
|
} |
|
|
|
|
|
|
|
const db = new CouchDB(appId) |
|
|
|
const db = getAppDB() |
|
|
|
const { calculation, group, field } = ctx.query |
|
|
|
const viewInfo = await getView(db, viewName) |
|
|
|
let response |
|
|
|
@ -212,7 +207,7 @@ exports.fetchView = async ctx => { |
|
|
|
schema: {}, |
|
|
|
} |
|
|
|
} |
|
|
|
rows = await outputProcessing(ctx, table, response.rows) |
|
|
|
rows = await outputProcessing(table, response.rows) |
|
|
|
} |
|
|
|
|
|
|
|
if (calculation === CALCULATION_TYPES.STATS) { |
|
|
|
@ -239,27 +234,24 @@ exports.fetchView = async ctx => { |
|
|
|
} |
|
|
|
|
|
|
|
exports.fetch = async ctx => { |
|
|
|
const appId = ctx.appId |
|
|
|
const db = new CouchDB(appId) |
|
|
|
const db = getAppDB() |
|
|
|
|
|
|
|
const tableId = ctx.params.tableId |
|
|
|
let table = await db.get(tableId) |
|
|
|
let rows = await getRawTableData(ctx, db, tableId) |
|
|
|
return outputProcessing(ctx, table, rows) |
|
|
|
return outputProcessing(table, rows) |
|
|
|
} |
|
|
|
|
|
|
|
exports.find = async ctx => { |
|
|
|
const appId = ctx.appId |
|
|
|
const db = new CouchDB(appId) |
|
|
|
const db = getAppDB() |
|
|
|
const table = await db.get(ctx.params.tableId) |
|
|
|
let row = await findRow(ctx, db, ctx.params.tableId, ctx.params.rowId) |
|
|
|
row = await outputProcessing(ctx, table, row) |
|
|
|
let row = await findRow(ctx, ctx.params.tableId, ctx.params.rowId) |
|
|
|
row = await outputProcessing(table, row) |
|
|
|
return row |
|
|
|
} |
|
|
|
|
|
|
|
exports.destroy = async function (ctx) { |
|
|
|
const appId = ctx.appId |
|
|
|
const db = new CouchDB(appId) |
|
|
|
const db = getAppDB() |
|
|
|
const { _id, _rev } = ctx.request.body |
|
|
|
let row = await db.get(_id) |
|
|
|
|
|
|
|
@ -268,18 +260,17 @@ exports.destroy = async function (ctx) { |
|
|
|
} |
|
|
|
const table = await db.get(row.tableId) |
|
|
|
// update the row to include full relationships before deleting them
|
|
|
|
row = await outputProcessing(ctx, table, row, { squash: false }) |
|
|
|
row = await outputProcessing(table, row, { squash: false }) |
|
|
|
// now remove the relationships
|
|
|
|
await linkRows.updateLinks({ |
|
|
|
appId, |
|
|
|
eventType: linkRows.EventType.ROW_DELETE, |
|
|
|
row, |
|
|
|
tableId: row.tableId, |
|
|
|
}) |
|
|
|
// remove any attachments that were on the row from object storage
|
|
|
|
await cleanupAttachments(appId, table, { row }) |
|
|
|
await cleanupAttachments(table, { row }) |
|
|
|
// remove any static formula
|
|
|
|
await updateRelatedFormula(appId, table, row) |
|
|
|
await updateRelatedFormula(table, row) |
|
|
|
|
|
|
|
let response |
|
|
|
if (ctx.params.tableId === InternalTables.USER_METADATA) { |
|
|
|
@ -295,20 +286,18 @@ exports.destroy = async function (ctx) { |
|
|
|
} |
|
|
|
|
|
|
|
exports.bulkDestroy = async ctx => { |
|
|
|
const appId = ctx.appId |
|
|
|
const db = new CouchDB(appId) |
|
|
|
const db = getAppDB() |
|
|
|
const tableId = ctx.params.tableId |
|
|
|
const table = await db.get(tableId) |
|
|
|
let { rows } = ctx.request.body |
|
|
|
|
|
|
|
// before carrying out any updates, make sure the rows are ready to be returned
|
|
|
|
// they need to be the full rows (including previous relationships) for automations
|
|
|
|
rows = await outputProcessing(ctx, table, rows, { squash: false }) |
|
|
|
rows = await outputProcessing(table, rows, { squash: false }) |
|
|
|
|
|
|
|
// remove the relationships first
|
|
|
|
let updates = rows.map(row => |
|
|
|
linkRows.updateLinks({ |
|
|
|
appId, |
|
|
|
eventType: linkRows.EventType.ROW_DELETE, |
|
|
|
row, |
|
|
|
tableId: row.tableId, |
|
|
|
@ -327,8 +316,8 @@ exports.bulkDestroy = async ctx => { |
|
|
|
await db.bulkDocs(rows.map(row => ({ ...row, _deleted: true }))) |
|
|
|
} |
|
|
|
// remove any attachments that were on the rows from object storage
|
|
|
|
await cleanupAttachments(appId, table, { rows }) |
|
|
|
await updateRelatedFormula(appId, table, rows) |
|
|
|
await cleanupAttachments(table, { rows }) |
|
|
|
await updateRelatedFormula(table, rows) |
|
|
|
await Promise.all(updates) |
|
|
|
return { response: { ok: true }, rows } |
|
|
|
} |
|
|
|
@ -339,28 +328,27 @@ exports.search = async ctx => { |
|
|
|
return { rows: await exports.fetch(ctx) } |
|
|
|
} |
|
|
|
|
|
|
|
const appId = ctx.appId |
|
|
|
const { tableId } = ctx.params |
|
|
|
const db = new CouchDB(appId) |
|
|
|
const db = getAppDB() |
|
|
|
const { paginate, query, ...params } = ctx.request.body |
|
|
|
params.version = ctx.version |
|
|
|
params.tableId = tableId |
|
|
|
|
|
|
|
let response |
|
|
|
if (paginate) { |
|
|
|
response = await paginatedSearch(appId, query, params) |
|
|
|
response = await paginatedSearch(query, params) |
|
|
|
} else { |
|
|
|
response = await fullSearch(appId, query, params) |
|
|
|
response = await fullSearch(query, params) |
|
|
|
} |
|
|
|
|
|
|
|
// Enrich search results with relationships
|
|
|
|
if (response.rows && response.rows.length) { |
|
|
|
// enrich with global users if from users table
|
|
|
|
if (tableId === InternalTables.USER_METADATA) { |
|
|
|
response.rows = await getGlobalUsersFromMetadata(appId, response.rows) |
|
|
|
response.rows = await getGlobalUsersFromMetadata(response.rows) |
|
|
|
} |
|
|
|
const table = await db.get(tableId) |
|
|
|
response.rows = await outputProcessing(ctx, table, response.rows) |
|
|
|
response.rows = await outputProcessing(table, response.rows) |
|
|
|
} |
|
|
|
|
|
|
|
return response |
|
|
|
@ -368,25 +356,22 @@ exports.search = async ctx => { |
|
|
|
|
|
|
|
exports.validate = async ctx => { |
|
|
|
return validate({ |
|
|
|
appId: ctx.appId, |
|
|
|
tableId: ctx.params.tableId, |
|
|
|
row: ctx.request.body, |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
exports.fetchEnrichedRow = async ctx => { |
|
|
|
const appId = ctx.appId |
|
|
|
const db = new CouchDB(appId) |
|
|
|
const db = getAppDB() |
|
|
|
const tableId = ctx.params.tableId |
|
|
|
const rowId = ctx.params.rowId |
|
|
|
// need table to work out where links go in row
|
|
|
|
let [table, row] = await Promise.all([ |
|
|
|
db.get(tableId), |
|
|
|
findRow(ctx, db, tableId, rowId), |
|
|
|
findRow(ctx, tableId, rowId), |
|
|
|
]) |
|
|
|
// get the link docs
|
|
|
|
const linkVals = await linkRows.getLinkDocuments({ |
|
|
|
appId, |
|
|
|
tableId, |
|
|
|
rowId, |
|
|
|
}) |
|
|
|
@ -413,7 +398,7 @@ exports.fetchEnrichedRow = async ctx => { |
|
|
|
for (let [tableId, rows] of Object.entries(groups)) { |
|
|
|
// need to include the IDs in these rows for any links they may have
|
|
|
|
linkedRows = linkedRows.concat( |
|
|
|
await outputProcessing(ctx, tables[tableId], rows) |
|
|
|
await outputProcessing(tables[tableId], rows) |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
|