(core) Add PUT /records DocApi endpoint to AddOrUpdate records

Summary:
As designed in https://grist.quip.com/fZSrAnJKgO5j/Add-or-Update-Records-API

Current `POST /records` adds records, and `PATCH /records` updates them by row ID. This adds `PUT /records` to 'upsert' records, applying the AddOrUpdate user action. PUT was chosen because it's idempotent. Using a separate method (instead of inferring based on the request body) also cleanly separates validation, documentation, etc.

The name `require` for the new property was suggested by Paul because `where` isn't very clear when adding records.

Test Plan: New DocApi tests

Reviewers: jarek

Reviewed By: jarek

Differential Revision: https://phab.getgrist.com/D3251
This commit is contained in:
Alex Hall
2022-02-11 15:10:53 +02:00
parent 66eb0b91b8
commit 0de0cb0f4a
12 changed files with 220 additions and 48 deletions

View File

@@ -357,21 +357,35 @@ function parseColValues<T extends ColValues | BulkColValues>(
}
export function parseUserAction(ua: UserAction, docData: DocData): UserAction {
const actionType = ua[0] as string;
let parseBulk: boolean;
if (['AddRecord', 'UpdateRecord'].includes(actionType)) {
parseBulk = false;
} else if (['BulkAddRecord', 'BulkUpdateRecord', 'ReplaceTableData'].includes(actionType)) {
parseBulk = true;
} else {
return ua;
switch (ua[0]) {
case 'AddRecord':
case 'UpdateRecord':
return _parseUserActionColValues(ua, docData, false);
case 'BulkAddRecord':
case 'BulkUpdateRecord':
case 'ReplaceTableData':
return _parseUserActionColValues(ua, docData, true);
case 'AddOrUpdateRecord':
// Parse `require` (2) and `col_values` (3). The action looks like:
// ['AddOrUpdateRecord', table_id, require, col_values, options]
// (`col_values` is called `fields` in the API)
ua = _parseUserActionColValues(ua, docData, false, 2);
ua = _parseUserActionColValues(ua, docData, false, 3);
return ua;
default:
return ua;
}
}
// Returns a copy of the user action with one element parsed, by default the last one
function _parseUserActionColValues(ua: UserAction, docData: DocData, parseBulk: boolean, index?: number
): UserAction {
ua = ua.slice();
const tableId = ua[1] as string;
const lastIndex = ua.length - 1;
const colValues = ua[lastIndex] as ColValues | BulkColValues;
ua[lastIndex] = parseColValues(tableId, colValues, docData, parseBulk);
if (index === undefined) {
index = ua.length - 1;
}
const colValues = ua[index] as ColValues | BulkColValues;
ua[index] = parseColValues(tableId, colValues, docData, parseBulk);
return ua;
}