(core) Update Plugin API documentation

Summary: Updates to Plugin API documentation.

Test Plan: Tested manually in grist-help.

Reviewers: jarek

Reviewed By: jarek

Subscribers: jarek

Differential Revision: https://phab.getgrist.com/D3447
This commit is contained in:
George Gevoian 2022-05-24 13:22:41 -07:00
parent 3ad2d9212e
commit 3d3a5e334a
6 changed files with 100 additions and 30 deletions

View File

@ -69,7 +69,7 @@ export interface GristAPI {
} }
/** /**
* Allows getting information from and nteracting with the Grist document to which a plugin or widget is attached. * Allows getting information from and interacting with the Grist document to which a plugin or widget is attached.
*/ */
export interface GristDocAPI { export interface GristDocAPI {
/** /**
@ -83,19 +83,20 @@ export interface GristDocAPI {
listTables(): Promise<string[]>; listTables(): Promise<string[]>;
/** /**
* Returns a complete table of data in the format {colId: [values]}, including the 'id' column. * Returns a complete table of data as [[RowRecords]], including the
* Do not modify the returned arrays in-place, especially if used directly (not over RPC). * 'id' column. Do not modify the returned arrays in-place, especially if used
* TODO: return type is Promise{[colId: string]: CellValue[]}> but cannot be specified because * directly (not over RPC).
* ts-interface-builder does not properly support index-signature.
*/ */
fetchTable(tableId: string): Promise<any>; fetchTable(tableId: string): Promise<any>;
// TODO: return type is Promise{[colId: string]: CellValue[]}> but cannot be specified
// because ts-interface-builder does not properly support index-signature.
/** /**
* Applies an array of user actions. * Applies an array of user actions.
* TODO: return type should be Promise<ApplyUAResult>, but this requires importing modules from
* `app/common` which is not currently supported by the build.
*/ */
applyUserActions(actions: any[][], options?: any): Promise<any>; applyUserActions(actions: any[][], options?: any): Promise<any>;
// TODO: return type should be Promise<ApplyUAResult>, but this requires importing
// modules from `app/common` which is not currently supported by the build.
} }
/** /**
@ -104,15 +105,17 @@ export interface GristDocAPI {
export interface GristView { export interface GristView {
/** /**
* Like [[GristDocAPI.fetchTable]], but gets data for the custom section specifically, if there is any. * Like [[GristDocAPI.fetchTable]], but gets data for the custom section specifically, if there is any.
* TODO: return type is Promise{[colId: string]: CellValue[]}> but cannot be specified because
* ts-interface-builder does not properly support index-signature.
*/ */
fetchSelectedTable(): Promise<any>; fetchSelectedTable(): Promise<any>;
// TODO: return type is Promise{[colId: string]: CellValue[]}> but cannot be specified
// because ts-interface-builder does not properly support index-signature.
/** /**
* Similar TODO to `fetchSelectedTable()` for return type. * Fetches selected record by its `rowId`.
*/ */
fetchSelectedRecord(rowId: number): Promise<any>; fetchSelectedRecord(rowId: number): Promise<any>;
// TODO: return type is Promise{[colId: string]: CellValue}> but cannot be specified
// because ts-interface-builder does not properly support index-signature.
/** /**
* Allow custom widget to be listed as a possible source for linking with SELECT BY. * Allow custom widget to be listed as a possible source for linking with SELECT BY.

View File

@ -31,6 +31,11 @@ export const RowRecord = t.iface([], {
[t.indexKey]: "CellValue", [t.indexKey]: "CellValue",
}); });
export const RowRecords = t.iface([], {
"id": t.array("number"),
[t.indexKey]: t.array("CellValue"),
});
export const GristType = t.union(t.lit('Any'), t.lit('Attachments'), t.lit('Blob'), t.lit('Bool'), t.lit('Choice'), t.lit('ChoiceList'), t.lit('Date'), t.lit('DateTime'), t.lit('Id'), t.lit('Int'), t.lit('ManualSortPos'), t.lit('Numeric'), t.lit('PositionNumber'), t.lit('Ref'), t.lit('RefList'), t.lit('Text')); export const GristType = t.union(t.lit('Any'), t.lit('Attachments'), t.lit('Blob'), t.lit('Bool'), t.lit('Choice'), t.lit('ChoiceList'), t.lit('Date'), t.lit('DateTime'), t.lit('Id'), t.lit('Int'), t.lit('ManualSortPos'), t.lit('Numeric'), t.lit('PositionNumber'), t.lit('Ref'), t.lit('RefList'), t.lit('Text'));
const exportedTypeSuite: t.ITypeSuite = { const exportedTypeSuite: t.ITypeSuite = {
@ -38,6 +43,7 @@ const exportedTypeSuite: t.ITypeSuite = {
CellValue, CellValue,
BulkColValues, BulkColValues,
RowRecord, RowRecord,
RowRecords,
GristType, GristType,
}; };
export default exportedTypeSuite; export default exportedTypeSuite;

View File

@ -18,11 +18,73 @@ export const enum GristObjCode {
export type CellValue = number|string|boolean|null|[GristObjCode, ...unknown[]]; export type CellValue = number|string|boolean|null|[GristObjCode, ...unknown[]];
export interface BulkColValues { [colId: string]: CellValue[]; } export interface BulkColValues { [colId: string]: CellValue[]; }
/**
* Map of column ids to `CellValue`s.
*
* ### CellValue
*
* Each `CellValue` may either be a primitive (e.g. `true`, `123`, `"hello"`, `null`)
* or a tuple (JavaScript Array) representing a Grist object. The first element of the tuple
* is a string character representing the object code. For example, `["L", "foo", "bar"]`
* is a `CellValue` of a Choice List column, where `"L"` is the type, and `"foo"` and
* `"bar"` are the choices.
*
* ### Grist Object Types
*
* | Code | Type |
* | ---- | -------------- |
* | L | List |
* | l | LookUp |
* | O | Dict |
* | D | DateTime |
* | d | Date |
* | C | Censored |
* | R | Reference |
* | r | ReferenceList |
* | E | Exception |
* | P | Pending |
* | U | Unmarshallable |
* | V | Version |
*/
export interface RowRecord { export interface RowRecord {
id: number; id: number;
[colId: string]: CellValue; [colId: string]: CellValue;
} }
/**
* Map of column ids to `CellValue` arrays, where array indexes correspond to
* rows.
*
* ### CellValue
*
* Each `CellValue` may either be a primitive (e.g. `true`, `123`, `"hello"`, `null`)
* or a tuple (JavaScript Array) representing a Grist object. The first element of the tuple
* is a string character representing the object code. For example, `["L", "foo", "bar"]`
* is a `CellValue` of a Choice List column, where `"L"` is the type, and `"foo"` and
* `"bar"` are the choices.
*
* ### Grist Object Types
*
* | Code | Type |
* | ---- | -------------- |
* | L | List |
* | l | LookUp |
* | O | Dict |
* | D | DateTime |
* | d | Date |
* | C | Censored |
* | R | Reference |
* | r | ReferenceList |
* | E | Exception |
* | P | Pending |
* | U | Unmarshallable |
* | V | Version |
*/
export interface RowRecords {
id: number[];
[colId: string]: CellValue[];
}
export type GristType = 'Any' | 'Attachments' | 'Blob' | 'Bool' | 'Choice' | 'ChoiceList' | export type GristType = 'Any' | 'Attachments' | 'Blob' | 'Bool' | 'Choice' | 'ChoiceList' |
'Date' | 'DateTime' | 'Date' | 'DateTime' |
'Id' | 'Int' | 'ManualSortPos' | 'Numeric' | 'PositionNumber' | 'Ref' | 'RefList' | 'Text'; 'Id' | 'Int' | 'ManualSortPos' | 'Numeric' | 'PositionNumber' | 'Ref' | 'RefList' | 'Text';

View File

@ -3,14 +3,13 @@
*/ */
/** /**
* * Metadata and data for a table.
* Metadata and data for a table. This is documenting what is currently returned by the
* core plugins. Could be worth reconciling with:
* https://phab.getgrist.com/w/grist_data_format/
* Capitalization is python-style.
*
*/ */
export interface GristTable { export interface GristTable {
// This is documenting what is currently returned by the core plugins. Capitalization
// is python-style.
//
// TODO: could be worth reconciling with: https://phab.getgrist.com/w/grist_data_format/.
table_name: string | null; // currently allow names to be null table_name: string | null; // currently allow names to be null
column_metadata: GristColumn[]; column_metadata: GristColumn[];
table_data: any[][]; table_data: any[][];
@ -21,9 +20,7 @@ export interface GristTables {
} }
/** /**
*
* Metadata about a single column. * Metadata about a single column.
*
*/ */
export interface GristColumn { export interface GristColumn {
id: string; id: string;

View File

@ -37,20 +37,22 @@ export interface TableOperations {
/** /**
* General options for table operations. * General options for table operations.
* By default, string field values will be parsed based on the column type.
* This can be disabled.
*/ */
export interface OpOptions { export interface OpOptions {
parseStrings?: boolean; /** whether to parse strings based on the column type. */ /** Whether to parse strings based on the column type. Defaults to true. */
parseStrings?: boolean;
} }
/** /**
* Extra options for upserts. By default, add and update are true, * Extra options for upserts.
* onMany is first, and allowEmptyRequire is false.
*/ */
export interface UpsertOptions extends OpOptions { export interface UpsertOptions extends OpOptions {
add?: boolean; /** permit inserting a record */ /** Permit inserting a record. Defaults to true. */
update?: boolean; /** permit updating a record */ add?: boolean;
onMany?: 'none' | 'first' | 'all'; /** whether to update none, one, or all matching records */ /** Permit updating a record. Defaults to true. */
allowEmptyRequire?: boolean; /** allow "wildcard" operation */ update?: boolean;
/** Whether to update none, one, or all matching records. Defaults to "first". */
onMany?: 'none' | 'first' | 'all';
/** Allow "wildcard" operation. Defaults to false. */
allowEmptyRequire?: boolean;
} }

View File

@ -33,6 +33,7 @@ import { WidgetAPI } from './WidgetAPI';
export * from './TypeCheckers'; export * from './TypeCheckers';
export * from './FileParserAPI'; export * from './FileParserAPI';
export * from './GristAPI'; export * from './GristAPI';
export * from './GristData';
export * from './GristTable'; export * from './GristTable';
export * from './ImportSourceAPI'; export * from './ImportSourceAPI';
export * from './StorageAPI'; export * from './StorageAPI';
@ -78,7 +79,7 @@ export const setSelectedRows = viewApi.setSelectedRows;
* but decoding data by default, replacing e.g. ['D', timestamp] with * but decoding data by default, replacing e.g. ['D', timestamp] with
* a moment date. Option `keepEncoded` skips the decoding step. * a moment date. Option `keepEncoded` skips the decoding step.
*/ */
export async function fetchSelectedTable(options: {keepEncoded?: boolean} = {}) { export async function fetchSelectedTable(options: {keepEncoded?: boolean} = {}) {
const table = await viewApi.fetchSelectedTable(); const table = await viewApi.fetchSelectedTable();
return options.keepEncoded ? table : return options.keepEncoded ? table :
mapValues<any[], any[]>(table, (col) => col.map(decodeObject)); mapValues<any[], any[]>(table, (col) => col.map(decodeObject));
@ -305,10 +306,9 @@ export function mapColumnNamesBack(data: any, options?: {
* by some value within the row potentially changing. Handler may * by some value within the row potentially changing. Handler may
* in the future be called with null if the cursor moves away from * in the future be called with null if the cursor moves away from
* any row. * any row.
* TODO: currently this will be called even if the content of a different row
* changes.
*/ */
export function onRecord(callback: (data: RowRecord | null, mappings: WidgetColumnMap | null) => unknown) { export function onRecord(callback: (data: RowRecord | null, mappings: WidgetColumnMap | null) => unknown) {
// TODO: currently this will be called even if the content of a different row changes.
on('message', async function(msg) { on('message', async function(msg) {
if (!msg.tableId || !msg.rowId || msg.rowId === 'new') { return; } if (!msg.tableId || !msg.rowId || msg.rowId === 'new') { return; }
const rec = await docApi.fetchSelectedRecord(msg.rowId); const rec = await docApi.fetchSelectedRecord(msg.rowId);