Cancellation & Cleanup
AbortSignal / Request Cancellation
All public methods accept an optional AbortSignal as their last parameter. Use this to cancel in-flight requests when the user navigates away or a component unmounts:
1const controller = new AbortController();23// Cancel on unmount / navigation4window.addEventListener('beforeunload', () => controller.abort());56const result = await sdk.listRecords('tasks', {}, controller.signal);
When cancelled, the SDK re-throws the native DOMException with name === 'AbortError'. Check for this before checking NetworkError:
1try {2 const result = await sdk.listRecords('tasks', {}, signal);3} catch (error) {4 if (error instanceof DOMException && error.name === 'AbortError') {5 return; // intentionally cancelled — no action needed6 }7 if (error instanceof WorkAppsSDK.NetworkError) {8 // genuine connection failure9 }10}
The signal is also respected during retry backoff delays — if the signal fires while the SDK is waiting before a retry, the delay is cancelled immediately.
destroy()
Call destroy() when done to abort all in-flight requests and clear event handlers:
1sdk.destroy();
Pending promises reject with AbortError. After destroy(), the maintenance event handlers (onMaintenanceStart, onMaintenanceEnd) are cleared.
Event Handler Cleanup
sdk.on() returns an unsubscribe function. Use it to remove individual handlers without keeping a reference to them:
1const unsubscribe = sdk.on('maintenanceStart', (status) => {2 showBanner(status?.message);3});45// Later, when cleaning up:6unsubscribe();
See Maintenance Mode for full event handler patterns.
Finding types: All SDK TypeScript types are listed below. If you use an IDE with TypeScript support, these are also available from the SDK module itself via
import type { RecordData, ListOptions } from 'https://sdk.workapps.tech/v1.js'.
TypeScript Types
1// System fields present on all records returned from the server.2// Use RecordInput (Record<string, unknown>) when sending data to createRecord or updateRecord.3type RecordData = Record<string, unknown> & {4 id: string;5 created_by?: string;6 updated_by?: string;7 created_at: string;8 updated_at: string;9};1011type ListResponse<T> = {12 data: T[];13 meta: { hasMore: boolean; cursor: string | null; total?: number };14};1516type SingleResponse<T> = { data: T };1718type Filter = Record<string, Partial<Record<FilterOperator, FilterValue>>>;19type FilterOperator = 'eq' | 'neq' | 'in' | 'contains' | 'gt' | 'gte' | 'lt' | 'lte';20type FilterValue = string | number | boolean | (string | number)[];2122type ListOptions = {23 filter?: Filter;24 sort?: string;25 pageSize?: number;26 cursor?: string;27};2829type PaginateOptions = Omit<ListOptions, 'cursor'> & {30 maxPages?: number;31 maxRecords?: number;32 signal?: AbortSignal;33};3435type RetryConfig = {36 maxRetries?: number;37 baseDelayMs?: number;38};3940type SchemaEntity = {41 key: string;42 name: string;43 display_field: string | null;44 fields: SchemaField[];45};4647type SchemaField = {48 key: string;49 name: string;50 type: string;51 required: boolean;52 read_only: boolean;53 options?: string[] | null;54 sort_order: number;55};5657type BootstrapData = {58 user: { id: string; name: string; email: string };59 role: 'viewer' | 'editor' | 'admin';60 app: { id: string; name: string; type: string };61 limits: Record<string, number>;62};6364type StatusData = {65 status: 'ok' | 'maintenance';66 message?: string;67 estimatedSeconds?: number;68};6970type RecordInput = Record<string, unknown>;7172type BulkUpdateItem = {73 id: string;74 data: RecordInput;75};7677type FileUploadRequest = {78 fieldKey: string;79 fileName: string;80 mimeType?: string;81 sizeBytes: number;82};8384type FileUploadResponse = {85 fileId: string;86 uploadUrl: string;87 headers: Record<string, string>;88};8990type FileDownloadResponse = {91 url: string; // Pre-signed download URL — valid for ~1 hour92 fileName: string; // Original file name as uploaded93 mimeType: string | null;94 expiresAt: string; // ISO 8601 expiry timestamp95};9697type BulkCreateResponse = {98 data: RecordData[];99 error?: { code: string; message: string; details: Record<string, Record<string, string[]>> };100};101102type BulkUpdateResponse = {103 data: RecordData[];104 error?: { code: string; message: string; details: Record<string, Record<string, string[]>> };105};106107type BulkDeleteResponse = {108 data: { deleted: string[] };109 error?: { code: string; message: string; details: Record<string, Record<string, string[]>> };110};