mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) DocApi meta endpoints: GET /tables and POST/PATCH /tables and /columns
Summary: Adds new API endpoints to list tables in a document and create or modify tables and columns. The request and response formats are designed to mirror the style of the existing `GET /columns` and `GET/POST/PATCH /records` endpoints. Discussion: https://grist.slack.com/archives/C0234CPPXPA/p1665139807125649?thread_ts=1628957179.010500&cid=C0234CPPXPA Test Plan: DocApi test Reviewers: jarek Reviewed By: jarek Subscribers: paulfitz Differential Revision: https://phab.getgrist.com/D3667
This commit is contained in:
@@ -10,6 +10,13 @@ export const NewRecord = t.iface([], {
|
||||
})),
|
||||
});
|
||||
|
||||
export const NewRecordWithStringId = t.iface([], {
|
||||
"id": t.opt("string"),
|
||||
"fields": t.opt(t.iface([], {
|
||||
[t.indexKey]: "CellValue",
|
||||
})),
|
||||
});
|
||||
|
||||
export const Record = t.iface([], {
|
||||
"id": "number",
|
||||
"fields": t.iface([], {
|
||||
@@ -17,6 +24,13 @@ export const Record = t.iface([], {
|
||||
}),
|
||||
});
|
||||
|
||||
export const RecordWithStringId = t.iface([], {
|
||||
"id": "string",
|
||||
"fields": t.iface([], {
|
||||
[t.indexKey]: "CellValue",
|
||||
}),
|
||||
});
|
||||
|
||||
export const AddOrUpdateRecord = t.iface([], {
|
||||
"require": t.intersection(t.iface([], {
|
||||
[t.indexKey]: "CellValue",
|
||||
@@ -46,14 +60,41 @@ export const MinimalRecord = t.iface([], {
|
||||
"id": "number",
|
||||
});
|
||||
|
||||
export const ColumnsPost = t.iface([], {
|
||||
"columns": t.tuple("NewRecordWithStringId", t.rest(t.array("NewRecordWithStringId"))),
|
||||
});
|
||||
|
||||
export const ColumnsPatch = t.iface([], {
|
||||
"columns": t.tuple("RecordWithStringId", t.rest(t.array("RecordWithStringId"))),
|
||||
});
|
||||
|
||||
export const TablePost = t.iface(["ColumnsPost"], {
|
||||
"id": t.opt("string"),
|
||||
});
|
||||
|
||||
export const TablesPost = t.iface([], {
|
||||
"tables": t.tuple("TablePost", t.rest(t.array("TablePost"))),
|
||||
});
|
||||
|
||||
export const TablesPatch = t.iface([], {
|
||||
"tables": t.tuple("RecordWithStringId", t.rest(t.array("RecordWithStringId"))),
|
||||
});
|
||||
|
||||
const exportedTypeSuite: t.ITypeSuite = {
|
||||
NewRecord,
|
||||
NewRecordWithStringId,
|
||||
Record,
|
||||
RecordWithStringId,
|
||||
AddOrUpdateRecord,
|
||||
RecordsPatch,
|
||||
RecordsPost,
|
||||
RecordsPut,
|
||||
RecordId,
|
||||
MinimalRecord,
|
||||
ColumnsPost,
|
||||
ColumnsPatch,
|
||||
TablePost,
|
||||
TablesPost,
|
||||
TablesPatch,
|
||||
};
|
||||
export default exportedTypeSuite;
|
||||
|
||||
@@ -11,6 +11,15 @@ export interface NewRecord {
|
||||
fields?: { [coldId: string]: CellValue };
|
||||
}
|
||||
|
||||
export interface NewRecordWithStringId {
|
||||
id?: string; // tableId or colId
|
||||
/**
|
||||
* Initial values of cells in record. Optional, if not set cells are left
|
||||
* blank.
|
||||
*/
|
||||
fields?: { [coldId: string]: CellValue };
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON schema for api /record endpoint. Used in PATCH method for updating existing records.
|
||||
*/
|
||||
@@ -19,6 +28,11 @@ export interface Record {
|
||||
fields: { [coldId: string]: CellValue };
|
||||
}
|
||||
|
||||
export interface RecordWithStringId {
|
||||
id: string; // tableId or colId
|
||||
fields: { [coldId: string]: CellValue };
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON schema for api /record endpoint. Used in PUT method for adding or updating records.
|
||||
*/
|
||||
@@ -65,3 +79,27 @@ export type RecordId = number;
|
||||
export interface MinimalRecord {
|
||||
id: number
|
||||
}
|
||||
|
||||
export interface ColumnsPost {
|
||||
columns: [NewRecordWithStringId, ...NewRecordWithStringId[]]; // at least one column is required
|
||||
}
|
||||
|
||||
export interface ColumnsPatch {
|
||||
columns: [RecordWithStringId, ...RecordWithStringId[]]; // at least one column is required
|
||||
}
|
||||
|
||||
/**
|
||||
* Creating tables requires a list of columns.
|
||||
* `fields` is not accepted because it's not generally sensible to set the metadata fields on new tables.
|
||||
*/
|
||||
export interface TablePost extends ColumnsPost {
|
||||
id?: string;
|
||||
}
|
||||
|
||||
export interface TablesPost {
|
||||
tables: [TablePost, ...TablePost[]]; // at least one table is required
|
||||
}
|
||||
|
||||
export interface TablesPatch {
|
||||
tables: [RecordWithStringId, ...RecordWithStringId[]]; // at least one table is required
|
||||
}
|
||||
|
||||
@@ -199,7 +199,9 @@ export async function handleSandboxErrorOnPlatform<T>(
|
||||
if (match) {
|
||||
platform.throwError('', `Invalid row id ${match[1]}`, 400);
|
||||
}
|
||||
match = message.match(/\[Sandbox] KeyError u?'(?:Table \w+ has no column )?(\w+)'/);
|
||||
match = message.match(
|
||||
/\[Sandbox] (?:KeyError u?'(?:Table \w+ has no column )?|ValueError No such table: )(\w+)/
|
||||
);
|
||||
if (match) {
|
||||
if (match[1] === tableId) {
|
||||
platform.throwError('', `Table not found "${tableId}"`, 404);
|
||||
|
||||
Reference in New Issue
Block a user