// https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.13/dayjs.min.js const ColumnTypes = { NUMBER: 'number', TEXT: 'text', LONG_TEXT: 'long-text', CHECKBOX: 'checkbox', DATE: 'date', SINGLE_SELECT: 'single-select', MULTIPLE_SELECT: 'multiple-select', IMAGE: 'image', FILE: 'file', COLLABORATOR: 'collaborator', LINK: 'link', LINK_FORMULA: 'link-formula', FORMULA: 'formula', CREATOR: 'creator', CTIME: 'ctime', LAST_MODIFIER: 'last-modifier', MTIME: 'mtime', GEOLOCATION: 'geolocation', AUTO_NUMBER: 'auto-number', URL: 'url', } const DATE_FORMAT_MAP = { YYYY_MM_DD: 'YYYY-MM-DD', YYYY_MM_DD_HH_MM: 'YYYY-MM-DD HH:mm', YYYY_MM_DD_HH_MM_SS: 'YYYY-MM-DD HH:mm:ss' } const getDateDisplayString = (date, format) => { if (!date || typeof date !== 'string') { return ''; } const dateObj = dayjs(date); if (!dateObj.isValid()) return date; switch (format) { case 'D/M/YYYY': case 'DD/MM/YYYY': { const formatValue = dateObj.format('YYYY-MM-DD'); const formatValueList = formatValue.split('-'); return `${formatValueList[2]}/${formatValueList[1]}/${formatValueList[0]}`; } case 'D/M/YYYY HH:mm': case 'DD/MM/YYYY HH:mm': { const formatValues = dateObj.format('YYYY-MM-DD HH:mm'); const formatValuesList = formatValues.split(' '); const formatDateList = formatValuesList[0].split('-'); return `${formatDateList[2]}/${formatDateList[1]}/${formatDateList[0]} ${formatValuesList[1]}`; } case 'M/D/YYYY': return dateObj.format('M/D/YYYY'); case 'M/D/YYYY HH:mm': return dateObj.format('M/D/YYYY HH:mm'); case 'YYYY-MM-DD': return dateObj.format('YYYY-MM-DD'); case 'YYYY-MM-DD HH:mm': return dateObj.format('YYYY-MM-DD HH:mm'); case 'YYYY-MM-DD HH:mm:ss': { return dateObj.format('YYYY-MM-DD HH:mm:ss'); } case 'DD.MM.YYYY': return dateObj.format('DD.MM.YYYY'); case 'DD.MM.YYYY HH:mm': return dateObj.format('DD.MM.YYYY HH:mm'); default: // Compatible with older versions: if format is null, use defaultFormat return dateObj.format('YYYY-MM-DD'); } } const getAccessToken = (config) => { const { server, APIToken } = config; const url = server + '/api/v2.1/dtable/app-access-token/'; const headers = { 'Authorization': 'Token ' + APIToken }; return axios.get(url, { headers: headers }); } const isSingleOrMultiple = (type) => { return type === ColumnTypes.SINGLE_SELECT || type === ColumnTypes.MULTIPLE_SELECT; } const formatColumnOptionsToMap = (column) => { const { options = [] } = column.data || {}; let options_map = {}; options.forEach(option => { options_map[option.id] = option.name; }); return options_map; } const formatQueryResult = (result) => { const { metadata: columns, results: rows } = result; const columnMap = columns.reduce((keyMap, column) => { if (isSingleOrMultiple(column.type)) { column.options_map = formatColumnOptionsToMap(column); } if (column.type === ColumnTypes.LINK || column.type === ColumnTypes.LINK_FORMULA) { const { array_type, array_data } = column.data; if (isSingleOrMultiple(array_type)) { column.options_map = formatColumnOptionsToMap({ data: array_data }); } } keyMap[column.key] = column; return keyMap; }, {}); let formatRows = []; for (let i = 0; i < rows.length; i++) { const row = rows[i]; const formatRow = {}; formatRow['_id'] = row._id; Object.keys(row).forEach(key => { if (columnMap[key]) { const { name, type, options_map, data = {} } = columnMap[key]; let cellValue = row[key]; switch (type) { case ColumnTypes.SINGLE_SELECT: { cellValue = options_map[cellValue]; break; } case ColumnTypes.MULTIPLE_SELECT: { if (!Array.isArray(cellValue)) return []; cellValue = cellValue.map(key => options_map[key]); break; } case ColumnTypes.LINK: case ColumnTypes.LINK_FORMULA: { if (!Array.isArray(cellValue)) { cellValue = []; break; } const { array_type } = data; if (!isSingleOrMultiple(array_type)) { cellValue = cellValue.map(item => item.display_value); } else { cellValue = cellValue.map(item => options_map[item.display_value]); } break; } case ColumnTypes.DATE: { if (cellValue) { const { format } = data; cellValue = getDateDisplayString(cellValue, format); } break; } default: { cellValue = row[key]; break; } } formatRow[name] = cellValue; } }); formatRows.push(formatRow); } return formatRows; } class APIGateway { constructor({ token, server, dtable_uuid }) { this.token = token; this.dtable_uuid = dtable_uuid; this.baseURL = server[server.length - 1] === '/' ? `${server}api-gateway` : `${server}/api-gateway`; this.init(); } init() { this.req = axios.create({ baseURL: this.baseURL, headers: { 'Authorization': 'Token ' + this.token }, }); } async getDTable() { const url = `/api/v2/dtables/${this.dtable_uuid}/`; const res = await this.req.get(url); if (!res) { return {}; } return res.data || {}; } async getMetadata() { const url = `/api/v2/dtables/${this.dtable_uuid}/metadata/`; const res = await this.req.get(url); if (!res || !res.data) { return {}; } return res.data.metadata || {}; } async addTable(table_name, lang = 'en', columns = []) { const url = `/api/v2/dtables/${this.dtable_uuid}/tables/`; let data = { table_name, lang, }; if (columns) { data.columns = columns; } const res = await this.req.post(url, data); return (res && res.data) || {}; } async renameTable(table_name, new_table_name) { const url = `/api/v2/dtables/${this.dtable_uuid}/tables/`; const data = { table_name, new_table_name, }; const res = await this.req.put(url, data); return (res && res.data) || {}; } async deleteTable(table_name) { const url = `/api/v2/dtables/${this.dtable_uuid}/tables/`; const data = { table_name, }; const res = await this.req.delete(url, { data }); return (res && res.data) || {}; } async listViews(table_name) { const url = `/api/v2/dtables/${this.dtable_uuid}/views/`; const params = { table_name, }; const res = await this.req.get(url, { params }); if (!res || !res.data) { return []; } return res.data.views || []; } async getViewByName(table_name, view_name) { const url = `/api/v2/dtables/${this.dtable_uuid}/views/${view_name}/?table_name=${table_name}`; const res = await this.req.get(url); return (res && res.data) || {}; } async addView(table_name, view_name) { const url = `/api/v2/dtables/${this.dtable_uuid}/views/?table_name=${table_name}`; const data = { name: view_name, }; const res = await this.req.post(url, data); return (res && res.data) || {}; } async renameView(table_name, view_name, new_view_name) { const url = `/api/v2/dtables/${this.dtable_uuid}/views/${view_name}/?table_name=${table_name}`; const data = { name: new_view_name, } const res = await this.req.put(url, data); return (res && res.data) || {}; } async deleteView(table_name, view_name) { const url = `/api/v2/dtables/${this.dtable_uuid}/views/${view_name}/?table_name=${table_name}`; const res = await this.req.delete(url); return (res && res.data) || {}; } async listColumns(table_name, view_name) { const url = `/api/v2/dtables/${this.dtable_uuid}/columns/`; let params = { table_name, } if (view_name) { params.view_name = view_name; } const res = await this.req.get(url, { params }); if (!res || !res.data) { return []; } return res.data.columns || []; } async insertColumn(table_name, column_name, column_type, column_key, column_data) { const url = `/api/v2/dtables/${this.dtable_uuid}/columns/`; let data = { table_name, column_name, column_type, }; if (column_key) { data.anchor_column = column_key; } if (column_data) { data.column_data = column_data; } const res = await this.req.post(url, data); return (res && res.data) || {}; } async renameColumn(table_name, column_key, new_column_name) { const url = `/api/v2/dtables/${this.dtable_uuid}/columns/`; const data = { op_type: 'rename_column', column: column_key, table_name, new_column_name, }; const res = await this.req.put(url, data); return (res && res.data) || {}; } async resizeColumn(table_name, column_key, new_column_width) { const url = `/api/v2/dtables/${this.dtable_uuid}/columns/`; const data = { op_type: 'resize_column', column: column_key, table_name, new_column_width, }; const res = await this.req.put(url, data); return (res && res.data) || {}; } async freezeColumn(table_name, column_key, frozen) { const url = `/api/v2/dtables/${this.dtable_uuid}/columns/`; const data = { op_type: 'freeze_column', column: column_key, table_name, frozen, }; const res = await this.req.put(url, data); return (res && res.data) || {}; } async moveColumn(table_name, column_key, target_column_key) { const url = `/api/v2/dtables/${this.dtable_uuid}/columns/`; const data = { op_type: 'move_column', column: column_key, target_column: target_column_key, table_name, }; const res = await this.req.put(url, data); return (res && res.data) || {}; } async modifyColumnType(table_name, column_key, new_column_type) { const url = `/api/v2/dtables/${this.dtable_uuid}/columns/`; const data = { op_type: 'modify_column_type', column: column_key, table_name, new_column_type, }; const res = await this.req.put(url, data); return (res && res.data) || {}; } async addColumnOptions(table_name, column, options) { const url = `/api/v2/dtables/${this.dtable_uuid}/column-options/`; const data = { table_name, column, options }; const res = await this.req.post(url, data); return (res && res.data) || {}; } async addColumnCascadeSettings(table_name, child_column, parent_column, cascade_settings) { const url = `/api/v2/dtables/${this.dtable_uuid}/column-cascade-settings/`; const data = { table_name, child_column, parent_column, cascade_settings, }; const res = await this.req.post(url, data); return (res && res.data) || {}; } async deleteColumn(table_name, column_key) { const url = `/api/v2/dtables/${this.dtable_uuid}/columns/`; const data = { table_name, column: column_key, }; const res = await this.req.delete(url, { data }); return (res && res.data) || {}; } async listRows(table_name, view_name, order_by, desc, start, limit) { const url = `/api/v2/dtables/${this.dtable_uuid}/rows/`; let params = { table_name, convert_keys: true, convert_link_id: true, }; if (view_name) { params.view_name = view_name; } if (order_by) { params.order_by = order_by; params.direction = desc ? 'desc' : 'asc'; } if (start) { params.start = start; } if (limit) { params.limit = limit; } const res = await this.req.get(url, { params }); if (!res || !res.data) { return []; } return res.data.rows || []; } async getRow(table_name, row_id) { const url = `/api/v2/dtables/${this.dtable_uuid}/rows/${row_id}/`; const params = { table_name, convert_keys: true, }; const res = await this.req.get(url, { params }); return (res && res.data) || {}; } async appendRow(table_name, row_data, apply_default) { const url = `/api/v2/dtables/${this.dtable_uuid}/rows/`; let data = { table_name, rows: [row_data], }; if (typeof apply_default === 'boolean') { data.apply_default = apply_default; } const res = await this.req.post(url, data); if (!res || !res.data) { return {}; } return res.data.first_row || {}; } async batchAppendRows(table_name, rows_data, apply_default) { const url = `/api/v2/dtables/${this.dtable_uuid}/rows/`; let data = { table_name, rows: rows_data, }; if (typeof apply_default === 'boolean') { data.apply_default = apply_default; } const res = await this.req.post(url, data); if (!res || !res.data) { return {}; } return { inserted_row_count: res.data.inserted_row_count }; } async insertRow(table_name, row_data, _, apply_default) { // not support custom insert position yet return this.appendRow(table_name, row_data, apply_default); } async updateRow(table_name, row_id, row_data) { const url = `/api/v2/dtables/${this.dtable_uuid}/rows/`; const data = { table_name, updates: [{ row_id, row: row_data, }] }; const res = await this.req.put(url, data); return (res && res.data) || {}; } async batchUpdateRows(table_name, rows_data) { const url = `/api/v2/dtables/${this.dtable_uuid}/rows/`; const data = { table_name, updates: rows_data, }; const res = await this.req.put(url, data); return (res && res.data) || {}; } async deleteRow(table_name, row_id) { const url = `/api/v2/dtables/${this.dtable_uuid}/rows/`; const data = { table_name, row_ids: [row_id], }; const res = await this.req.delete(url, { data }); return (res && res.data) || {}; } async batchDeleteRows(table_name, row_ids) { const url = `/api/v2/dtables/${this.dtable_uuid}/rows/`; const data = { table_name, row_ids, }; const res = await this.req.delete(url, { data }); return (res && res.data) || {}; } async addLink(link_id, table_name, other_table_name, row_id, other_row_id) { const url = `/api/v2/dtables/${this.dtable_uuid}/links/`; const data = { link_id, table_name, other_table_name, other_rows_ids_map: { [row_id]: [other_row_id], }, }; const res = await this.req.post(url, data); return res && res.data; } async removeLink(link_id, table_name, other_table_name, row_id, other_row_id) { const url = `/api/v2/dtables/${this.dtable_uuid}/links/`; const data = { link_id, table_name, other_table_name, table_row_id: row_id, other_rows_ids_map: { [row_id]: [other_row_id], }, }; const res = await this.req.delete(url, { data }); return res && res.data; } async updateLink(link_id, table_name, other_table_name, row_id, other_rows_ids) { const url = `/api/v2/dtables/${this.dtable_uuid}/links/`; const data = { link_id, table_name, other_table_name, other_rows_ids_map: { [row_id]: other_rows_ids, }, }; const res = await this.req.put(url, data); return res && res.data; } async batchUpdateLinks(link_id, table_id, other_table_id, _, other_rows_ids_map) { const url = `/api/v2/dtables/${this.dtable_uuid}/links/`; const data = { link_id, table_id, other_table_id, other_rows_ids_map, }; const res = await this.req.put(url, data); return res && res.data; } async getLinkedRecords(table_id, link_column_key, rows) { const url = `/api/v2/dtables/${this.dtable_uuid}/query-links/`; const data = { table_id, link_column_key, rows, }; const res = await this.req.post(url, data); return (res && res.data) || {}; } async query(sql) { const url = `/api/v2/dtables/${this.dtable_uuid}/sql/`; const data = { sql, }; return this.req.post(url, data).then(response => { return Promise.resolve(formatQueryResult(response.data)); }); } } class Base { constructor(config) { this.config = config; this.appName = ''; this.accessToken = ''; this.dtableServer = ''; this.dtableSocket = ''; this.dtableDB = ''; this.lang = 'en'; this.req = null; this.apiGateway = null; } async auth() { const response = await getAccessToken(this.config); const { app_name, access_token, dtable_uuid, dtable_server = '', dtable_socket = '', dtable_db = '', use_api_gateway = true, } = response.data; this.appName = app_name; this.accessToken = access_token; this.dtableServer = dtable_server; this.dtableSocket = dtable_socket; this.dtableUuid = dtable_uuid; this.dtableDB = dtable_db; // api gateway entry if (use_api_gateway) { this.apiGateway = new APIGateway({ token: access_token, server: this.config.server, dtable_uuid, }); this.useApiGatewayWrapper(); } if (this.dtableServer) { this.req = axios.create({ baseURL: this.dtableServer, headers: { Authorization: 'Token ' + this.accessToken } }); this.req.interceptors.response.use(response => { const result = this.getResult(response); return result; }, error => { return Promise.reject(error); }); } if (!use_api_gateway && !this.dtableServer) { throw new Error('dtable_server is required when not using API Gateway.'); } } useApiGatewayWrapper() { [ // dtable this.getDTable, this.getMetadata, // table this.addTable, this.renameTable, this.deleteTable, // view this.listViews, this.getViewByName, this.addView, this.renameView, this.deleteView, // column this.listColumns, this.insertColumn, this.renameColumn, this.resizeColumn, this.freezeColumn, this.moveColumn, this.modifyColumnType, this.addColumnOptions, this.addColumnCascadeSettings, this.deleteColumn, // row this.listRows, this.getRow, this.appendRow, this.batchAppendRows, this.insertRow, this.updateRow, this.batchUpdateRows, this.deleteRow, this.batchDeleteRows, // link this.addLink, this.removeLink, this.updateLink, this.batchUpdateLinks, this.getLinkedRecords, // query this.query, ].forEach((func) => { if (func && Object.prototype.toString.call(func) === '[object Function]') { const funcName = func.name; this[funcName] = this.apiGatewayWrapper(func); } }); } apiGatewayWrapper(func) { return (...args) => { const funcName = func.name; const apiGatewayFunc = this.apiGateway && this.apiGateway[funcName]; if (apiGatewayFunc) { return apiGatewayFunc.apply(this.apiGateway, args); } return func.apply(this, args); } } getResult(response) { const { data, config } = response; const { method, url } = config; const paths = url.split('/'); const lastPath = paths[paths.length - 2]; let result = data; if (method === 'get') { // metadata if (lastPath === 'metadata') { result = data.metadata; return result; } // list views if (lastPath === 'views') { result = data.views; return result; } // list rows if (lastPath === 'rows') { result = data.rows; return result; } // list columns if (lastPath === 'columns') { result = data.columns; return result; } } return result; } getDTable() { const url = `/dtables/${this.dtableUuid}/?lang=${this.lang}`; return this.req.get(url); } getMetadata() { const url = `/api/v1/dtables/${this.dtableUuid}/metadata/`; return this.req.get(url); } async getTables() { const res = await this.getMetadata(); return (res && res.tables) || []; } async getTableByName(table_name) { const tables = await this.getTables(); if (!Array.isArray(tables) || tables.length === 0) { return {}; } return tables.find(table => table.name === table_name); } addTable(table_name, lang = 'en', columns = []) { const url = `/api/v1/dtables/${this.dtableUuid}/tables/`; let data = { table_name: table_name, lang: lang } if (columns) { data.columns = columns; } return this.req.post(url, data); } renameTable(old_name, new_name) { const url = `/api/v1/dtables/${this.dtableUuid}/tables/`; const data = { table_name: old_name, new_table_name: new_name } return this.req.put(url, { ...data }); } deleteTable(table_name) { const url = `/api/v1/dtables/${this.dtableUuid}/tables/`; const data = { table_name: table_name, } return this.req.delete(url, { data: data }); } listViews(table_name) { const url = `api/v1/dtables/${this.dtableUuid}/views/`; const params = { table_name: table_name, } return this.req.get(url, { params }); } getViewByName(table_name, view_name) { const url = `api/v1/dtables/${this.dtableUuid}/views/${view_name}/?table_name=` + table_name; return this.req.get(url) } addView(table_name, view_name) { const url = `api/v1/dtables/${this.dtableUuid}/views/?table_name=` + table_name; const data = { name: view_name }; return this.req.post(url, { ...data }); } renameView(table_name, view_name, new_view_name) { const url = `api/v1/dtables/${this.dtableUuid}/views/${view_name}/?table_name=` + table_name; const data = { name: new_view_name, } return this.req.put(url, { ...data }); } deleteView(table_name, view_name) { const url = `api/v1/dtables/${this.dtableUuid}/views/${view_name}/?table_name=` + table_name; return this.req.delete(url); } listColumns(table_name, view_name) { const url = `api/v1/dtables/${this.dtableUuid}/columns/`; const params = { table_name: table_name, view_name: view_name, } return this.req.get(url, { params }); } async getColumnByName(table_name, column_name) { const res = await this.listColumns(table_name); return res.find(col => col.name === column_name); } async getColumnsByType(table_name, column_type) { const res = await this.listColumns(table_name); return res.filter(col => col.type === column_type); } async getColumnLinkId(table_name, column_name) { const columns = await this.listColumns(table_name); const column = columns.find(column => column.name === column_name); if (!column) { return Promise.reject({ error_message: 'column is not exist', }); } if (column.type !== 'link') { return Promise.reject({ error_message: `The column ${column_name} is not a link colum` }); } return Promise.resolve(column.data['link_id']); } insertColumn(table_name, column_name, column_type, column_key, column_data) { const url = `api/v1/dtables/${this.dtableUuid}/columns/`; const data = { table_name: table_name, column_name: column_name, anchor_column: column_key, column_type: column_type, column_data: column_data }; return this.req.post(url, { ...data }); } renameColumn(table_name, column_key, new_column_name) { const url = `api/v1/dtables/${this.dtableUuid}/columns/`; const data = { op_type: 'rename_column', table_name: table_name, column: column_key, new_column_name: new_column_name, }; return this.req.put(url, { ...data }); } resizeColumn(table_name, column_key, new_column_width) { const url = `api/v1/dtables/${this.dtableUuid}/columns/`; const data = { op_type: 'resize_column', table_name: table_name, column: column_key, new_column_width: new_column_width, }; return this.req.put(url, { ...data }); } freezeColumn(table_name, column_key, frozen) { const url = `api/v1/dtables/${this.dtableUuid}/columns/`; const data = { op_type: 'freeze_column', table_name: table_name, column: column_key, frozen: frozen, }; return this.req.put(url, { ...data }); } moveColumn(table_name, column_key, target_column_key) { const url = `api/v1/dtables/${this.dtableUuid}/columns/`; const data = { op_type: 'move_column', table_name: table_name, column: column_key, target_column: target_column_key, }; return this.req.put(url, { ...data }); } modifyColumnType(table_name, column_key, new_column_type) { const url = `api/v1/dtables/${this.dtableUuid}/columns/`; const data = { op_type: 'modify_column_type', table_name: table_name, column: column_key, new_column_type: new_column_type, }; return this.req.put(url, { ...data }); } deleteColumn(table_name, column_key) { const url = `api/v1/dtables/${this.dtableUuid}/columns/`; const data = { table_name: table_name, column: column_key, }; return this.req.delete(url, { data: data }); } addColumnOptions(table_name, column, options) { const url = `api/v1/dtables/${this.dtableUuid}/column-options/`; const data = { table_name: table_name, column: column, options: options }; return this.req.post(url, { ...data }); } addColumnCascadeSettings(table_name, child_column, parent_column, cascade_settings) { const url = `api/v1/dtables/${this.dtableUuid}/column-cascade-settings/`; const data = { table_name: table_name, child_column: child_column, parent_column: parent_column, cascade_settings: cascade_settings, }; return this.req.post(url, { ...data }); } listRows(table_name, view_name, order_by, desc, start, limit) { const url = `api/v1/dtables/${this.dtableUuid}/rows/`; const params = { table_name: table_name, view_name: view_name, convert_link_id: true, }; params['direction'] = desc ? 'desc' : 'asc'; if (order_by) { params['order_by'] = order_by; } if (start) { params['start'] = start; } if (limit) { params['limit'] = limit; } return this.req.get(url, { params }); } appendRow(table_name, row_data, apply_default) { const url = `api/v1/dtables/${this.dtableUuid}/rows/`; let data = { table_name: table_name, row: row_data, }; if (typeof apply_default === 'boolean') { data.apply_default = apply_default; } return this.req.post(url, { ...data }); } insertRow(table_name, row_data, anchor_row_id, apply_default) { const url = `api/v1/dtables/${this.dtableUuid}/rows/`; let data = { table_name: table_name, row: row_data, anchor_row_id: anchor_row_id, }; if (typeof apply_default === 'boolean') { data.apply_default = apply_default; } return this.req.post(url, { ...data }); } deleteRow(table_name, row_id) { const url = `api/v1/dtables/${this.dtableUuid}/rows/`; const data = { table_name: table_name, row_id: row_id, }; return this.req.delete(url, { data: data }); } updateRow(table_name, row_id, row_data) { const url = `api/v1/dtables/${this.dtableUuid}/rows/`; const data = { table_name: table_name, row_id: row_id, row: row_data, }; return this.req.put(url, { ...data }); } getRow(table_name, row_id) { const url = `api/v1/dtables/${this.dtableUuid}/rows/${row_id}/`; const params = { table_name: table_name, }; return this.req.get(url, { params }); } batchAppendRows(table_name, rows_data, apply_default) { const url = `api/v1/dtables/${this.dtableUuid}/batch-append-rows/`; let data = { table_name: table_name, rows: rows_data, }; if (typeof apply_default === 'boolean') { data.apply_default = apply_default; } return this.req.post(url, { ...data }); } batchDeleteRows(table_name, row_ids) { const url = `api/v1/dtables/${this.dtableUuid}/batch-delete-rows/`; const data = { table_name: table_name, row_ids: row_ids, }; return this.req.delete(url, { data: data }); } batchUpdateRows(table_name, rows_data) { const url = `api/v1/dtables/${this.dtableUuid}/batch-update-rows/`; const data = { table_name: table_name, updates: rows_data, }; return this.req.put(url, { ...data }); } addLink(link_id, table_name, other_table_name, row_id, other_row_id) { const url = `api/v1/dtables/${this.dtableUuid}/links/`; const data = { link_id: link_id, table_name: table_name, other_table_name: other_table_name, table_row_id: row_id, other_table_row_id: other_row_id, }; return this.req.post(url, { ...data }); } updateLink(link_id, table_id, other_table_id, row_id, other_rows_ids) { const url = `api/v1/dtables/${this.dtableUuid}/links/`; const data = { link_id: link_id, table_name: table_id, other_table_name: other_table_id, row_id: row_id, other_rows_ids: other_rows_ids, }; return this.req.put(url, { ...data }); } removeLink(link_id, table_name, other_table_name, row_id, other_row_id) { const url = `api/v1/dtables/${this.dtableUuid}/links/`; const data = { link_id: link_id, table_name: table_name, other_table_name: other_table_name, table_row_id: row_id, other_table_row_id: other_row_id, }; return this.req.delete(url, { data: data }); } batchUpdateLinks(link_id, table_id, other_table_id, row_id_list, other_rows_ids_map) { const url = `api/v1/dtables/${this.dtableUuid}/batch-update-links/`; const data = { link_id: link_id, table_id: table_id, other_table_id: other_table_id, row_id_list: row_id_list, other_rows_ids_map: other_rows_ids_map, }; return this.req.put(url, { ...data }); } getLinkedRecords(table_id, link_column_key, rows) { const url = `api/v1/linked-records/${this.dtableUuid}/`; const data = { link_column: link_column_key, table_id, rows, }; const req = axios.create({ baseURL: this.dtableDB, headers: { Authorization: 'Token ' + this.accessToken } }); return req.post(url, { ...data }).then((response) => { return Promise.resolve((response && response.data) || {}); }); } query(sql) { const url = `api/v1/query/${this.dtableUuid}/`; const data = { sql: sql }; const req = axios.create({ baseURL: this.dtableDB, headers: { Authorization: 'Token ' + this.accessToken } }); return req.post(url, { ...data }).then(response => { return Promise.resolve(formatQueryResult(response.data)); }); } async queryAsync(sql) { const url = `api/v1/query/${this.dtableUuid}/`; const data = { sql: sql }; const req = axios.create({ baseURL: this.dtableDB, headers: { Authorization: 'Token ' + this.accessToken } }); return await req.post(url, { ...data }).then(response => { return Promise.resolve(formatQueryResult(response.data)); }); } }