"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ApiError = exports.Client = void 0; /** * High-level API client. Each method maps to one REST endpoint of the * inkreach-teable backend, using the SELF-BUILT contract (not official teable). * * Base/table/field/record/view endpoints are compatible with official teable * open-api; workflow/automation endpoints use the project's own contract. */ const request_1 = require("./request"); Object.defineProperty(exports, "ApiError", { enumerable: true, get: function () { return request_1.ApiError; } }); class Client { cfg; constructor(cfg) { this.cfg = cfg; } get headers() { return this.cfg.token ? { Authorization: `Bearer ${this.cfg.token}` } : {}; } async call(method, p, body) { const res = await (0, request_1.request)(this.cfg.endpoint, p, { method, headers: this.headers, body }); return res.data; } // ---- auth / user ---- getMe() { // GET /api/auth/user — @TokenAccess() enabled, works with PAT. // (/api/auth/user/me is session-only and 403s for PAT.) return this.call('GET', '/api/auth/user'); } // ---- access tokens (PAT) ---- listAccessTokens() { return this.call('GET', '/api/access-token'); } createAccessToken(body) { return this.call('POST', '/api/access-token', body); } deleteAccessToken(id) { return this.call('DELETE', `/api/access-token/${id}`); } // ---- base ---- listBases() { // GET /api/base/access/all — lists bases the user can access. return this.call('GET', '/api/base/access/all'); } getBase(baseId) { return this.call('GET', `/api/base/${baseId}`); } // ---- table ---- listTables(baseId) { return this.call('GET', `/api/base/${baseId}/table`); } getTable(tableId) { return this.call('GET', `/api/table/${tableId}`); } createTable(baseId, body) { return this.call('POST', `/api/base/${baseId}/table`, body); } updateTable(tableId, body) { return this.call('PUT', `/api/table/${tableId}`, body); } deleteTable(tableId, baseId) { const base = baseId ?? this.cfg.baseId; return this.call('DELETE', `/api/base/${base}/table/${tableId}`); } // ---- field ---- listFields(tableId) { return this.call('GET', `/api/table/${tableId}/field`); } getField(tableId, fieldId) { return this.call('GET', `/api/table/${tableId}/field/${fieldId}`); } createField(tableId, body) { return this.call('POST', `/api/table/${tableId}/field`, body); } /** Rename/describe. NOTE: the update API accepts name/description only — * options (incl. select choice visibilityFilter) must go through convertField. */ updateField(tableId, fieldId, body) { return this.call('PATCH', `/api/table/${tableId}/field/${fieldId}`, body); } /** PUT convert: the ONLY API path that persists field options (choices, * visibilityFilter dependency config, etc.). Requires the field's current type. */ convertField(tableId, fieldId, body) { return this.call('PUT', `/api/table/${tableId}/field/${fieldId}/convert`, body); } deleteField(tableId, fieldId) { return this.call('DELETE', `/api/table/${tableId}/field/${fieldId}`); } /** Evaluate select-choice visibility dependency for one record+field. * GET /api/table/:tableId/select-visibility/:recordId/:fieldId */ getVisibleChoices(tableId, recordId, fieldId) { return this.call('GET', `/api/table/${tableId}/select-visibility/${recordId}/${fieldId}`); } // ---- record ---- getRecords(tableId, query) { const qs = query ? '?' + new URLSearchParams(this.flattenQuery(query)).toString() : ''; return this.call('GET', `/api/table/${tableId}/record${qs}`); } /** Flatten search[] tuple arrays into repeated query keys (Teable expects search[]=...). */ flattenQuery(query) { const out = {}; for (const [k, v] of Object.entries(query)) { if (v === undefined || v === null) continue; if (Array.isArray(v)) { v.forEach((item) => { out[`${k}[]`] = typeof item === 'object' ? JSON.stringify(item) : String(item); }); } else if (typeof v === 'object') { out[k] = JSON.stringify(v); } else if (k === 'search' && typeof v === 'string') { // The records list API expects `search[]=value` (tuple), not a plain // `search=value` string. https://github.com/colinhacks/zod out['search[]'] = v; } else { out[k] = String(v); } } return out; } getRecord(recordId, query) { const qs = query ? '?' + new URLSearchParams(this.flattenQuery(query)).toString() : ''; return this.call('GET', `/api/record/${recordId}${qs}`); } createRecord(tableId, body) { return this.call('POST', `/api/table/${tableId}/record`, body); } updateRecord(tableId, body) { return this.call('PATCH', `/api/table/${tableId}/record`, body); } updateRecordOne(recordId, body) { return this.call('PATCH', `/api/record/${recordId}`, body); } deleteRecords(tableId, recordIds) { const qs = recordIds.map((id) => `recordIds=${encodeURIComponent(id)}`).join('&'); return this.call('DELETE', `/api/table/${tableId}/record?${qs}`); } // ---- view ---- listViews(tableId) { return this.call('GET', `/api/table/${tableId}/view`); } getView(viewId) { return this.call('GET', `/api/view/${viewId}`); } createView(tableId, body) { return this.call('POST', `/api/table/${tableId}/view`, body); } updateView(viewId, body) { return this.call('PATCH', `/api/view/${viewId}`, body); } deleteView(viewId) { return this.call('DELETE', `/api/view/${viewId}`); } // ---- workflow (self-built contract) ---- listWorkflows(baseId) { return this.call('GET', `/api/base/${baseId}/workflow`); } getWorkflow(workflowId) { return this.call('GET', `/api/base/any/workflow/${workflowId}`); } /** * Get workflow by explicit baseId + workflowId. getWorkflow() above hits a * route that resolves base from the workflow itself, but some auth/permission * paths need the base-scoped route. Prefer this when baseId is known. */ getWorkflowInBase(baseId, workflowId) { return this.call('GET', `/api/base/${baseId}/workflow/${workflowId}`); } createWorkflow(baseId, body) { return this.call('POST', `/api/base/${baseId}/workflow`, body); } updateWorkflow(baseId, workflowId, body) { return this.call('PATCH', `/api/base/${baseId}/workflow/${workflowId}`, body); } deleteWorkflow(baseId, workflowId) { return this.call('DELETE', `/api/base/${baseId}/workflow/${workflowId}`); } activateWorkflow(baseId, workflowId) { return this.call('POST', `/api/base/${baseId}/workflow/${workflowId}/activate`); } deactivateWorkflow(baseId, workflowId) { return this.call('POST', `/api/base/${baseId}/workflow/${workflowId}/deactivate`); } testWorkflow(baseId, workflowId) { return this.call('POST', `/api/base/${baseId}/workflow/${workflowId}/test`); } /** PUT /node — whole-graph replacement (delete-all + create-all in a txn). */ replaceNodes(baseId, workflowId, body) { return this.call('PUT', `/api/base/${baseId}/workflow/${workflowId}/node`, body); } // ---- secrets ---- listSecrets(baseId, workflowId) { return this.call('GET', `/api/base/${baseId}/workflow/${workflowId}/secret`); } createSecret(baseId, workflowId, body) { return this.call('POST', `/api/base/${baseId}/workflow/${workflowId}/secret`, body); } updateSecret(baseId, workflowId, secretId, body) { return this.call('PATCH', `/api/base/${baseId}/workflow/${workflowId}/secret/${secretId}`, body); } deleteSecret(baseId, workflowId, secretId) { return this.call('DELETE', `/api/base/${baseId}/workflow/${workflowId}/secret/${secretId}`); } // ---- execution history ---- listExecutions(baseId, workflowId) { return this.call('GET', `/api/base/${baseId}/workflow/${workflowId}/execution`); } getExecution(baseId, workflowId, executionId) { return this.call('GET', `/api/base/${baseId}/workflow/${workflowId}/execution/${executionId}`); } rerunExecution(baseId, workflowId, executionId) { return this.call('POST', `/api/base/${baseId}/workflow/${workflowId}/execution/${executionId}/rerun`); } // ---- trigger (manual fire for testing) ---- fireButtonClick(tableId, recordId, fieldId) { return this.call('POST', `/api/table/${tableId}/record/${recordId}/${fieldId}/button-click`); } fireWebhook(baseId, workflowId, body) { // NOTE: real backend route is /api/webhook/{baseId}/{workflowId} (no /base/ /workflow/ segments) return this.call('POST', `/api/webhook/${baseId}/${workflowId}`, body); } // ---- SQL (read-only) ---- sql(baseId, sql) { return this.call('POST', `/api/base/${baseId}/sql`, { sql }); } // ---- plugin ---- getPlugins() { return this.call('GET', '/api/plugin'); } getPlugin(pluginId) { return this.call('GET', `/api/plugin/${encodeURIComponent(pluginId)}`); } updatePlugin(pluginId, body) { return this.call('PUT', `/api/plugin/${encodeURIComponent(pluginId)}`, body); } getCspOrigins() { return this.call('GET', '/api/plugin/csp-origins'); } registerPlugin(body) { return this.call('POST', '/api/plugin', body); } listPluginConfigs(baseId) { return this.call('GET', `/api/base/${baseId}/plugin-config`); } upsertPluginConfig(baseId, pluginId, body) { return this.call('PUT', `/api/base/${baseId}/plugin-config/${pluginId}`, body); } // ---- plugin installs ---- listInstalls(baseId) { return this.call('GET', `/api/base/${baseId}/plugin-installs`); } createInstall(baseId, body) { return this.call('POST', `/api/base/${baseId}/plugin-installs`, body); } deleteInstall(baseId, installId) { return this.call('DELETE', `/api/base/${baseId}/plugin-installs/${installId}`); } // ---- plugin developers ---- listDevelopers() { return this.call('GET', '/api/plugin-developers'); } addDeveloper(userIdOrEmail) { // Backend reads @Body('userId') or @Body('email'). Send whichever looks right. const isEmail = userIdOrEmail.includes('@'); const body = isEmail ? { email: userIdOrEmail } : { userId: userIdOrEmail }; return this.call('POST', '/api/plugin-developers', body); } removeDeveloper(userId) { return this.call('DELETE', `/api/plugin-developers/${encodeURIComponent(userId)}`); } } exports.Client = Client;