2020-05-07 11:53:34 +02:00
|
|
|
const CouchDB = require("../../db")
|
2020-05-28 16:39:29 +02:00
|
|
|
const validateJs = require("validate.js")
|
2020-10-09 20:10:28 +02:00
|
|
|
const linkRows = require("../../db/linkedRows")
|
2020-10-09 10:47:37 +02:00
|
|
|
const {
|
2020-10-09 20:10:28 +02:00
|
|
|
getRowParams,
|
|
|
|
generateRowID,
|
2020-10-09 10:47:37 +02:00
|
|
|
DocumentTypes,
|
|
|
|
SEPARATOR,
|
2020-11-24 18:00:15 +01:00
|
|
|
ViewNames,
|
2020-10-09 10:47:37 +02:00
|
|
|
} = require("../../db/utils")
|
2020-11-24 18:00:15 +01:00
|
|
|
const usersController = require("./user")
|
2021-02-02 12:46:10 +01:00
|
|
|
const { coerceRowValues, enrichRows } = require("../../utilities")
|
2020-10-01 18:22:08 +02:00
|
|
|
|
2020-10-09 19:49:23 +02:00
|
|
|
const TABLE_VIEW_BEGINS_WITH = `all${SEPARATOR}${DocumentTypes.TABLE}${SEPARATOR}`
|
2020-05-04 18:13:57 +02:00
|
|
|
|
2020-10-15 13:09:41 +02:00
|
|
|
const CALCULATION_TYPES = {
|
|
|
|
SUM: "sum",
|
|
|
|
COUNT: "count",
|
2020-10-15 18:05:09 +02:00
|
|
|
STATS: "stats",
|
2020-10-15 13:09:41 +02:00
|
|
|
}
|
|
|
|
|
2020-09-08 19:03:41 +02:00
|
|
|
validateJs.extend(validateJs.validators.datetime, {
|
2020-10-14 16:13:22 +02:00
|
|
|
parse: function(value) {
|
2020-09-08 19:03:41 +02:00
|
|
|
return new Date(value).getTime()
|
|
|
|
},
|
|
|
|
// Input is a unix timestamp
|
2020-10-14 16:13:22 +02:00
|
|
|
format: function(value) {
|
2020-09-08 19:03:41 +02:00
|
|
|
return new Date(value).toISOString()
|
2020-09-09 17:27:46 +02:00
|
|
|
},
|
|
|
|
})
|
2020-09-08 19:03:41 +02:00
|
|
|
|
2020-12-09 11:52:18 +01:00
|
|
|
async function findRow(db, appId, tableId, rowId) {
|
|
|
|
let row
|
2020-12-08 18:33:08 +01:00
|
|
|
if (tableId === ViewNames.USERS) {
|
2020-12-09 11:52:18 +01:00
|
|
|
let ctx = {
|
|
|
|
params: {
|
|
|
|
userId: rowId,
|
|
|
|
},
|
|
|
|
user: {
|
|
|
|
appId,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
await usersController.find(ctx)
|
|
|
|
row = ctx.body
|
|
|
|
} else {
|
|
|
|
row = await db.get(rowId)
|
|
|
|
}
|
|
|
|
if (row.tableId !== tableId) {
|
|
|
|
throw "Supplied tableId does not match the rows tableId"
|
2020-12-08 18:33:08 +01:00
|
|
|
}
|
|
|
|
return row
|
|
|
|
}
|
|
|
|
|
2020-10-14 16:13:22 +02:00
|
|
|
exports.patch = async function(ctx) {
|
2020-10-29 11:28:27 +01:00
|
|
|
const appId = ctx.user.appId
|
|
|
|
const db = new CouchDB(appId)
|
2020-10-09 20:10:28 +02:00
|
|
|
let row = await db.get(ctx.params.id)
|
|
|
|
const table = await db.get(row.tableId)
|
2020-09-10 10:36:14 +02:00
|
|
|
const patchfields = ctx.request.body
|
|
|
|
|
2021-02-05 13:23:29 +01:00
|
|
|
// need to build up full patch fields before coerce
|
2020-09-29 17:40:59 +02:00
|
|
|
for (let key of Object.keys(patchfields)) {
|
2020-10-09 19:49:23 +02:00
|
|
|
if (!table.schema[key]) continue
|
2020-10-09 20:10:28 +02:00
|
|
|
row[key] = patchfields[key]
|
2020-09-10 10:36:14 +02:00
|
|
|
}
|
2020-09-10 22:11:05 +02:00
|
|
|
|
2021-02-05 13:23:29 +01:00
|
|
|
row = coerceRowValues(row, table)
|
|
|
|
|
2020-09-10 10:36:14 +02:00
|
|
|
const validateResult = await validate({
|
2020-10-09 20:10:28 +02:00
|
|
|
row,
|
2020-10-09 19:49:23 +02:00
|
|
|
table,
|
2020-09-10 10:36:14 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
if (!validateResult.valid) {
|
|
|
|
ctx.status = 400
|
|
|
|
ctx.body = {
|
|
|
|
status: 400,
|
|
|
|
errors: validateResult.errors,
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-10-09 20:10:28 +02:00
|
|
|
// returned row is cleaned and prepared for writing to DB
|
|
|
|
row = await linkRows.updateLinks({
|
2020-10-29 11:28:27 +01:00
|
|
|
appId,
|
2020-10-09 20:10:28 +02:00
|
|
|
eventType: linkRows.EventType.ROW_UPDATE,
|
|
|
|
row,
|
|
|
|
tableId: row.tableId,
|
2020-10-09 19:49:23 +02:00
|
|
|
table,
|
2020-09-29 12:55:18 +02:00
|
|
|
})
|
2020-12-08 18:33:08 +01:00
|
|
|
|
|
|
|
// Creation of a new user goes to the user controller
|
|
|
|
if (row.tableId === ViewNames.USERS) {
|
2021-02-05 13:23:29 +01:00
|
|
|
// the row has been updated, need to put it into the ctx
|
2021-02-21 11:20:05 +01:00
|
|
|
ctx.request.body = {
|
|
|
|
...row,
|
|
|
|
password: ctx.request.body.password
|
|
|
|
}
|
2020-12-08 18:33:08 +01:00
|
|
|
await usersController.update(ctx)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-10-09 20:10:28 +02:00
|
|
|
const response = await db.put(row)
|
|
|
|
row._rev = response.rev
|
|
|
|
row.type = "row"
|
2020-09-29 12:55:18 +02:00
|
|
|
|
2020-10-29 11:55:52 +01:00
|
|
|
ctx.eventEmitter && ctx.eventEmitter.emitRow(`row:update`, appId, row, table)
|
2020-10-09 20:10:28 +02:00
|
|
|
ctx.body = row
|
2020-09-10 10:36:14 +02:00
|
|
|
ctx.status = 200
|
2020-10-09 19:49:23 +02:00
|
|
|
ctx.message = `${table.name} updated successfully.`
|
2020-09-10 10:36:14 +02:00
|
|
|
}
|
|
|
|
|
2020-10-14 16:13:22 +02:00
|
|
|
exports.save = async function(ctx) {
|
2020-10-29 11:28:27 +01:00
|
|
|
const appId = ctx.user.appId
|
|
|
|
const db = new CouchDB(appId)
|
2020-10-09 20:10:28 +02:00
|
|
|
let row = ctx.request.body
|
|
|
|
row.tableId = ctx.params.tableId
|
2020-04-08 17:57:27 +02:00
|
|
|
|
2020-12-08 18:33:08 +01:00
|
|
|
// TODO: find usage of this and break out into own endpoint
|
2020-10-13 17:17:07 +02:00
|
|
|
if (ctx.request.body.type === "delete") {
|
|
|
|
await bulkDelete(ctx)
|
|
|
|
ctx.body = ctx.request.body.rows
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-12-08 18:33:08 +01:00
|
|
|
// if the row obj had an _id then it will have been retrieved
|
|
|
|
const existingRow = ctx.preExisting
|
|
|
|
if (existingRow) {
|
|
|
|
ctx.params.id = row._id
|
|
|
|
await exports.patch(ctx)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-10-09 20:10:28 +02:00
|
|
|
if (!row._rev && !row._id) {
|
|
|
|
row._id = generateRowID(row.tableId)
|
2020-05-14 16:12:30 +02:00
|
|
|
}
|
|
|
|
|
2020-10-09 20:10:28 +02:00
|
|
|
const table = await db.get(row.tableId)
|
2020-05-28 16:39:29 +02:00
|
|
|
|
2020-10-09 20:10:28 +02:00
|
|
|
row = coerceRowValues(row, table)
|
2020-10-02 15:14:58 +02:00
|
|
|
|
2020-05-28 16:39:29 +02:00
|
|
|
const validateResult = await validate({
|
2020-10-09 20:10:28 +02:00
|
|
|
row,
|
2020-10-09 19:49:23 +02:00
|
|
|
table,
|
2020-05-07 11:53:34 +02:00
|
|
|
})
|
2020-04-09 11:13:19 +02:00
|
|
|
|
2020-05-28 16:39:29 +02:00
|
|
|
if (!validateResult.valid) {
|
2020-04-22 17:35:20 +02:00
|
|
|
ctx.status = 400
|
2020-04-20 17:17:11 +02:00
|
|
|
ctx.body = {
|
|
|
|
status: 400,
|
2020-05-28 16:39:29 +02:00
|
|
|
errors: validateResult.errors,
|
2020-05-07 11:53:34 +02:00
|
|
|
}
|
|
|
|
return
|
2020-04-09 11:13:19 +02:00
|
|
|
}
|
|
|
|
|
2020-10-09 20:10:28 +02:00
|
|
|
// make sure link rows are up to date
|
|
|
|
row = await linkRows.updateLinks({
|
2020-10-29 11:28:27 +01:00
|
|
|
appId,
|
2020-10-14 16:06:48 +02:00
|
|
|
eventType: linkRows.EventType.ROW_SAVE,
|
2020-10-09 20:10:28 +02:00
|
|
|
row,
|
|
|
|
tableId: row.tableId,
|
2020-10-09 19:49:23 +02:00
|
|
|
table,
|
2020-09-30 16:41:52 +02:00
|
|
|
})
|
|
|
|
|
2020-11-24 18:00:15 +01:00
|
|
|
// Creation of a new user goes to the user controller
|
2020-12-08 18:33:08 +01:00
|
|
|
if (row.tableId === ViewNames.USERS) {
|
2021-02-05 13:23:29 +01:00
|
|
|
// the row has been updated, need to put it into the ctx
|
|
|
|
ctx.request.body = row
|
2020-12-08 18:33:08 +01:00
|
|
|
await usersController.create(ctx)
|
2020-04-22 17:35:20 +02:00
|
|
|
return
|
2020-04-09 11:13:19 +02:00
|
|
|
}
|
|
|
|
|
2020-10-09 20:10:28 +02:00
|
|
|
row.type = "row"
|
2020-12-08 18:33:08 +01:00
|
|
|
const response = await db.put(row)
|
2020-10-09 20:10:28 +02:00
|
|
|
row._rev = response.rev
|
2020-10-29 11:55:52 +01:00
|
|
|
ctx.eventEmitter && ctx.eventEmitter.emitRow(`row:save`, appId, row, table)
|
2020-10-09 20:10:28 +02:00
|
|
|
ctx.body = row
|
2020-04-22 17:35:20 +02:00
|
|
|
ctx.status = 200
|
2020-12-08 18:33:08 +01:00
|
|
|
ctx.message = `${table.name} saved successfully`
|
2020-04-09 11:13:19 +02:00
|
|
|
}
|
|
|
|
|
2020-10-14 16:13:22 +02:00
|
|
|
exports.fetchView = async function(ctx) {
|
2020-10-29 11:28:27 +01:00
|
|
|
const appId = ctx.user.appId
|
2020-10-01 18:22:08 +02:00
|
|
|
const viewName = ctx.params.viewName
|
|
|
|
|
2020-10-09 19:49:23 +02:00
|
|
|
// if this is a table view being looked for just transfer to that
|
2020-11-26 15:43:56 +01:00
|
|
|
if (viewName.startsWith(TABLE_VIEW_BEGINS_WITH)) {
|
2020-10-09 19:49:23 +02:00
|
|
|
ctx.params.tableId = viewName.substring(4)
|
2020-10-09 20:10:28 +02:00
|
|
|
await exports.fetchTableRows(ctx)
|
2020-10-01 18:22:08 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-12-08 18:33:08 +01:00
|
|
|
const db = new CouchDB(appId)
|
|
|
|
const { calculation, group, field } = ctx.query
|
2020-10-01 18:22:08 +02:00
|
|
|
const response = await db.query(`database/${viewName}`, {
|
2020-10-15 11:48:57 +02:00
|
|
|
include_docs: !calculation,
|
2020-08-18 18:14:26 +02:00
|
|
|
group,
|
2020-05-07 11:53:34 +02:00
|
|
|
})
|
2020-08-17 22:01:43 +02:00
|
|
|
|
2020-10-15 11:48:57 +02:00
|
|
|
if (!calculation) {
|
|
|
|
response.rows = response.rows.map(row => row.doc)
|
2021-02-02 15:55:52 +01:00
|
|
|
let table
|
|
|
|
try {
|
|
|
|
table = await db.get(ctx.params.tableId)
|
|
|
|
} catch (err) {
|
|
|
|
table = {
|
|
|
|
schema: {},
|
|
|
|
}
|
|
|
|
}
|
2021-02-01 19:08:06 +01:00
|
|
|
ctx.body = await enrichRows(appId, table, response.rows)
|
2020-10-15 11:48:57 +02:00
|
|
|
}
|
|
|
|
|
2020-10-15 13:09:41 +02:00
|
|
|
if (calculation === CALCULATION_TYPES.STATS) {
|
2020-08-24 12:46:28 +02:00
|
|
|
response.rows = response.rows.map(row => ({
|
|
|
|
group: row.key,
|
2020-09-02 12:52:32 +02:00
|
|
|
field,
|
2020-08-24 12:46:28 +02:00
|
|
|
...row.value,
|
|
|
|
avg: row.value.sum / row.value.count,
|
|
|
|
}))
|
2020-10-15 11:48:57 +02:00
|
|
|
ctx.body = response.rows
|
2020-08-17 22:01:43 +02:00
|
|
|
}
|
|
|
|
|
2020-10-15 13:09:41 +02:00
|
|
|
if (
|
|
|
|
calculation === CALCULATION_TYPES.COUNT ||
|
|
|
|
calculation === CALCULATION_TYPES.SUM
|
|
|
|
) {
|
|
|
|
ctx.body = response.rows.map(row => ({
|
|
|
|
group: row.key,
|
|
|
|
field,
|
|
|
|
value: row.value,
|
|
|
|
}))
|
2020-10-15 11:48:57 +02:00
|
|
|
}
|
2020-04-09 11:13:19 +02:00
|
|
|
}
|
|
|
|
|
2020-10-14 16:13:22 +02:00
|
|
|
exports.fetchTableRows = async function(ctx) {
|
2020-10-29 11:28:27 +01:00
|
|
|
const appId = ctx.user.appId
|
2021-02-01 19:08:06 +01:00
|
|
|
const db = new CouchDB(appId)
|
2020-11-26 15:43:56 +01:00
|
|
|
|
2020-12-08 18:33:08 +01:00
|
|
|
// special case for users, fetch through the user controller
|
2021-02-02 12:46:10 +01:00
|
|
|
let rows,
|
|
|
|
table = await db.get(ctx.params.tableId)
|
2020-12-08 18:33:08 +01:00
|
|
|
if (ctx.params.tableId === ViewNames.USERS) {
|
|
|
|
await usersController.fetch(ctx)
|
|
|
|
rows = ctx.body
|
|
|
|
} else {
|
|
|
|
const response = await db.allDocs(
|
|
|
|
getRowParams(ctx.params.tableId, null, {
|
|
|
|
include_docs: true,
|
|
|
|
})
|
|
|
|
)
|
|
|
|
rows = response.rows.map(row => row.doc)
|
2020-11-26 15:43:56 +01:00
|
|
|
}
|
2021-02-01 19:08:06 +01:00
|
|
|
ctx.body = await enrichRows(appId, table, rows)
|
2020-06-11 15:35:45 +02:00
|
|
|
}
|
|
|
|
|
2020-10-14 16:13:22 +02:00
|
|
|
exports.find = async function(ctx) {
|
2020-10-29 11:28:27 +01:00
|
|
|
const appId = ctx.user.appId
|
|
|
|
const db = new CouchDB(appId)
|
2020-12-09 11:52:18 +01:00
|
|
|
try {
|
2021-02-01 19:08:06 +01:00
|
|
|
const table = await db.get(ctx.params.tableId)
|
2020-12-09 11:52:18 +01:00
|
|
|
const row = await findRow(db, appId, ctx.params.tableId, ctx.params.rowId)
|
2021-02-01 19:08:06 +01:00
|
|
|
ctx.body = await enrichRows(appId, table, row)
|
2020-12-09 11:52:18 +01:00
|
|
|
} catch (err) {
|
|
|
|
ctx.throw(400, err)
|
2020-05-27 18:23:01 +02:00
|
|
|
}
|
2020-04-09 11:13:19 +02:00
|
|
|
}
|
|
|
|
|
2020-10-14 16:13:22 +02:00
|
|
|
exports.destroy = async function(ctx) {
|
2020-10-29 11:28:27 +01:00
|
|
|
const appId = ctx.user.appId
|
|
|
|
const db = new CouchDB(appId)
|
2020-10-09 20:10:28 +02:00
|
|
|
const row = await db.get(ctx.params.rowId)
|
|
|
|
if (row.tableId !== ctx.params.tableId) {
|
|
|
|
ctx.throw(400, "Supplied tableId doesn't match the row's tableId")
|
2020-05-27 18:23:01 +02:00
|
|
|
return
|
|
|
|
}
|
2020-10-09 20:10:28 +02:00
|
|
|
await linkRows.updateLinks({
|
2020-10-29 11:28:27 +01:00
|
|
|
appId,
|
2020-10-09 20:10:28 +02:00
|
|
|
eventType: linkRows.EventType.ROW_DELETE,
|
|
|
|
row,
|
|
|
|
tableId: row.tableId,
|
2020-09-29 12:55:18 +02:00
|
|
|
})
|
2020-10-09 20:10:28 +02:00
|
|
|
ctx.body = await db.remove(ctx.params.rowId, ctx.params.revId)
|
2020-09-29 17:40:59 +02:00
|
|
|
ctx.status = 200
|
2020-09-29 12:55:18 +02:00
|
|
|
|
2020-10-09 20:10:28 +02:00
|
|
|
// for automations include the row that was deleted
|
|
|
|
ctx.row = row
|
2020-10-29 11:28:27 +01:00
|
|
|
ctx.eventEmitter && ctx.eventEmitter.emitRow(`row:delete`, appId, row)
|
2020-05-07 11:53:34 +02:00
|
|
|
}
|
2020-05-28 16:39:29 +02:00
|
|
|
|
2020-10-14 16:13:22 +02:00
|
|
|
exports.validate = async function(ctx) {
|
2020-05-28 16:39:29 +02:00
|
|
|
const errors = await validate({
|
2020-10-29 11:28:27 +01:00
|
|
|
appId: ctx.user.appId,
|
2020-10-09 19:49:23 +02:00
|
|
|
tableId: ctx.params.tableId,
|
2020-10-09 20:10:28 +02:00
|
|
|
row: ctx.request.body,
|
2020-05-28 16:39:29 +02:00
|
|
|
})
|
|
|
|
ctx.status = 200
|
|
|
|
ctx.body = errors
|
|
|
|
}
|
|
|
|
|
2020-10-29 11:28:27 +01:00
|
|
|
async function validate({ appId, tableId, row, table }) {
|
2020-10-09 19:49:23 +02:00
|
|
|
if (!table) {
|
2020-10-29 11:28:27 +01:00
|
|
|
const db = new CouchDB(appId)
|
2020-10-09 19:49:23 +02:00
|
|
|
table = await db.get(tableId)
|
2020-05-28 16:39:29 +02:00
|
|
|
}
|
|
|
|
const errors = {}
|
2020-10-09 19:49:23 +02:00
|
|
|
for (let fieldName of Object.keys(table.schema)) {
|
2020-09-14 15:35:03 +02:00
|
|
|
const res = validateJs.single(
|
2020-10-09 20:10:28 +02:00
|
|
|
row[fieldName],
|
2020-10-09 19:49:23 +02:00
|
|
|
table.schema[fieldName].constraints
|
2020-09-14 15:35:03 +02:00
|
|
|
)
|
2020-05-28 16:39:29 +02:00
|
|
|
if (res) errors[fieldName] = res
|
|
|
|
}
|
|
|
|
return { valid: Object.keys(errors).length === 0, errors }
|
|
|
|
}
|
2020-09-29 12:55:18 +02:00
|
|
|
|
2020-10-14 16:13:22 +02:00
|
|
|
exports.fetchEnrichedRow = async function(ctx) {
|
2020-10-29 11:28:27 +01:00
|
|
|
const appId = ctx.user.appId
|
|
|
|
const db = new CouchDB(appId)
|
2020-10-09 19:49:23 +02:00
|
|
|
const tableId = ctx.params.tableId
|
2020-10-09 20:10:28 +02:00
|
|
|
const rowId = ctx.params.rowId
|
2020-10-29 11:28:27 +01:00
|
|
|
if (appId == null || tableId == null || rowId == null) {
|
2020-09-29 12:55:18 +02:00
|
|
|
ctx.status = 400
|
|
|
|
ctx.body = {
|
|
|
|
status: 400,
|
|
|
|
error:
|
|
|
|
"Cannot handle request, URI params have not been successfully prepared.",
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2020-10-09 20:10:28 +02:00
|
|
|
// need table to work out where links go in row
|
2020-12-09 11:52:18 +01:00
|
|
|
let [table, row] = await Promise.all([
|
|
|
|
db.get(tableId),
|
|
|
|
findRow(db, appId, tableId, rowId),
|
|
|
|
])
|
2020-09-29 17:40:59 +02:00
|
|
|
// get the link docs
|
2020-10-09 20:10:28 +02:00
|
|
|
const linkVals = await linkRows.getLinkDocuments({
|
2020-10-29 11:28:27 +01:00
|
|
|
appId,
|
2020-10-09 19:49:23 +02:00
|
|
|
tableId,
|
2020-10-09 20:10:28 +02:00
|
|
|
rowId,
|
2020-09-29 12:55:18 +02:00
|
|
|
})
|
2020-10-09 20:10:28 +02:00
|
|
|
// look up the actual rows based on the ids
|
2020-09-30 13:00:56 +02:00
|
|
|
const response = await db.allDocs({
|
2020-09-29 17:40:59 +02:00
|
|
|
include_docs: true,
|
2020-09-30 16:37:38 +02:00
|
|
|
keys: linkVals.map(linkVal => linkVal.id),
|
2020-09-29 17:40:59 +02:00
|
|
|
})
|
2020-10-09 20:10:28 +02:00
|
|
|
// need to include the IDs in these rows for any links they may have
|
2021-02-01 19:08:06 +01:00
|
|
|
let linkedRows = await enrichRows(
|
2020-10-29 11:28:27 +01:00
|
|
|
appId,
|
2021-02-01 19:08:06 +01:00
|
|
|
table,
|
2021-02-02 12:46:10 +01:00
|
|
|
response.rows.map(row => row.doc)
|
2020-09-30 16:37:38 +02:00
|
|
|
)
|
2020-10-09 20:10:28 +02:00
|
|
|
// insert the link rows in the correct place throughout the main row
|
2020-10-09 19:49:23 +02:00
|
|
|
for (let fieldName of Object.keys(table.schema)) {
|
|
|
|
let field = table.schema[fieldName]
|
2020-09-30 16:37:38 +02:00
|
|
|
if (field.type === "link") {
|
2020-10-09 20:10:28 +02:00
|
|
|
row[fieldName] = linkedRows.filter(
|
|
|
|
linkRow => linkRow.tableId === field.tableId
|
2020-09-30 16:37:38 +02:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
2020-10-09 20:10:28 +02:00
|
|
|
ctx.body = row
|
2020-09-29 12:55:18 +02:00
|
|
|
ctx.status = 200
|
|
|
|
}
|
2020-10-07 11:45:26 +02:00
|
|
|
|
2020-10-13 17:17:07 +02:00
|
|
|
async function bulkDelete(ctx) {
|
2020-10-29 11:28:27 +01:00
|
|
|
const appId = ctx.user.appId
|
2020-10-13 17:17:07 +02:00
|
|
|
const { rows } = ctx.request.body
|
2020-10-29 11:28:27 +01:00
|
|
|
const db = new CouchDB(appId)
|
2020-10-13 17:17:07 +02:00
|
|
|
|
|
|
|
const linkUpdates = rows.map(row =>
|
|
|
|
linkRows.updateLinks({
|
2020-10-29 11:28:27 +01:00
|
|
|
appId,
|
2020-10-13 17:17:07 +02:00
|
|
|
eventType: linkRows.EventType.ROW_DELETE,
|
|
|
|
row,
|
|
|
|
tableId: row.tableId,
|
|
|
|
})
|
|
|
|
)
|
|
|
|
|
|
|
|
await db.bulkDocs(rows.map(row => ({ ...row, _deleted: true })))
|
|
|
|
await Promise.all(linkUpdates)
|
|
|
|
|
|
|
|
rows.forEach(row => {
|
2020-10-29 11:28:27 +01:00
|
|
|
ctx.eventEmitter && ctx.eventEmitter.emitRow(`row:delete`, appId, row)
|
2020-10-13 17:17:07 +02:00
|
|
|
})
|
|
|
|
}
|