mirror of
https://github.com/n8n-io/n8n.git
synced 2026-10-18 05:59:42 +02:00
Co-authored-by: Matsu <matias.huhta@n8n.io> Co-authored-by: Bernhard Wittmann <bernhard.wittmann@n8n.io> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Co-authored-by: Elias Meire <elias@meire.dev> Co-authored-by: n8n-assistant[bot] <n8n-assistant[bot]@users.noreply.github.com> Co-authored-by: João Almeida <jg.almeida56@gmail.com> Co-authored-by: Savelii <savelii.sychov@n8n.io> Co-authored-by: Rick Gale <richardgale90@gmail.com> Co-authored-by: Emilia <100027345+sovietspaceship@users.noreply.github.com> Co-authored-by: oleg <me@olegivaniv.com> Co-authored-by: RomanDavydchuk <roman.davydchuk@n8n.io> Co-authored-by: Stephen Wright <sjw948@gmail.com> Co-authored-by: Yuliia Pominchuk <31064937+yuliia-pominchuk@users.noreply.github.com> Co-authored-by: Shireen Missi <94372015+ShireenMissi@users.noreply.github.com> Co-authored-by: Miguel Ángel Moreno <1411774+miguelsaddress@users.noreply.github.com> Co-authored-by: Anne Aguirre <anne.aguirre@n8n.io> Co-authored-by: Dimitri Lavrenük <20122620+dlavrenuek@users.noreply.github.com> Co-authored-by: Kai <kai.hartlage@n8n.io> Co-authored-by: Luigi Gubello <27034386+luigigubello@users.noreply.github.com> Co-authored-by: Danny Martini <danny@n8n.io> Co-authored-by: MHMD <45968454+dou-mhmd@users.noreply.github.com> Co-authored-by: Mutasem Aldmour <4711238+mutdmour@users.noreply.github.com> Co-authored-by: Iván Ovejero <ivov.src@gmail.com> Co-authored-by: Charlie Kolb <charlie@n8n.io>
168 lines
4.1 KiB
TypeScript
168 lines
4.1 KiB
TypeScript
import type {
|
|
IDataObject,
|
|
IExecuteFunctions,
|
|
IHookFunctions,
|
|
IHttpRequestMethods,
|
|
ILoadOptionsFunctions,
|
|
IRequestOptions,
|
|
IWebhookFunctions,
|
|
JsonObject,
|
|
} from 'n8n-workflow';
|
|
import { NodeApiError, NodeOperationError } from 'n8n-workflow';
|
|
|
|
import { assertNoQueryDelimiters } from '../../utils/query-escaping';
|
|
|
|
export async function quickbaseApiRequest(
|
|
this: IExecuteFunctions | ILoadOptionsFunctions | IHookFunctions | IWebhookFunctions,
|
|
method: IHttpRequestMethods,
|
|
resource: string,
|
|
|
|
body: any = {},
|
|
qs: IDataObject = {},
|
|
option: IDataObject = {},
|
|
): Promise<any> {
|
|
const credentials = await this.getCredentials('quickbaseApi');
|
|
|
|
if (!credentials.hostname) {
|
|
throw new NodeOperationError(this.getNode(), 'Hostname must be defined');
|
|
}
|
|
|
|
if (!credentials.userToken) {
|
|
throw new NodeOperationError(this.getNode(), 'User Token must be defined');
|
|
}
|
|
|
|
try {
|
|
const options: IRequestOptions = {
|
|
headers: {
|
|
'QB-Realm-Hostname': credentials.hostname,
|
|
Authorization: `QB-USER-TOKEN ${credentials.userToken}`,
|
|
'Content-Type': 'application/json',
|
|
},
|
|
method,
|
|
body,
|
|
qs,
|
|
uri: `https://api.quickbase.com/v1${resource}`,
|
|
json: true,
|
|
};
|
|
|
|
if (Object.keys(body as IDataObject).length === 0) {
|
|
delete options.body;
|
|
}
|
|
|
|
if (Object.keys(qs).length === 0) {
|
|
delete options.qs;
|
|
}
|
|
|
|
if (Object.keys(option).length !== 0) {
|
|
Object.assign(options, option);
|
|
}
|
|
|
|
return await this.helpers?.request(options);
|
|
} catch (error) {
|
|
throw new NodeApiError(this.getNode(), error as JsonObject);
|
|
}
|
|
}
|
|
|
|
export async function getFieldsObject(
|
|
this: IHookFunctions | ILoadOptionsFunctions | IExecuteFunctions,
|
|
tableId: string,
|
|
): Promise<any> {
|
|
const fieldsLabelKey: { [key: string]: number } = {};
|
|
const fieldsIdKey: { [key: number]: string } = {};
|
|
const data = await quickbaseApiRequest.call(this, 'GET', '/fields', {}, { tableId });
|
|
for (const field of data) {
|
|
fieldsLabelKey[field.label] = field.id;
|
|
fieldsIdKey[field.id] = field.label;
|
|
}
|
|
return { fieldsLabelKey, fieldsIdKey };
|
|
}
|
|
|
|
export async function quickbaseApiRequestAllItems(
|
|
this: IHookFunctions | ILoadOptionsFunctions | IExecuteFunctions,
|
|
method: IHttpRequestMethods,
|
|
resource: string,
|
|
|
|
body: any = {},
|
|
query: IDataObject = {},
|
|
): Promise<any> {
|
|
const returnData: IDataObject[] = [];
|
|
|
|
let responseData = [];
|
|
|
|
if (method === 'POST') {
|
|
body.options = {
|
|
skip: 0,
|
|
top: 100,
|
|
};
|
|
} else {
|
|
query.skip = 0;
|
|
query.top = 100;
|
|
}
|
|
|
|
let metadata;
|
|
|
|
do {
|
|
const {
|
|
data,
|
|
fields,
|
|
metadata: meta,
|
|
} = await quickbaseApiRequest.call(this, method, resource, body, query);
|
|
|
|
metadata = meta;
|
|
|
|
const fieldsIdKey: { [key: string]: string } = {};
|
|
|
|
for (const field of fields) {
|
|
fieldsIdKey[field.id] = field.label;
|
|
}
|
|
|
|
for (const record of data) {
|
|
const recordData: IDataObject = {};
|
|
for (const [key, value] of Object.entries(record as IDataObject)) {
|
|
recordData[fieldsIdKey[key]] = (value as IDataObject).value;
|
|
}
|
|
responseData.push(recordData);
|
|
}
|
|
|
|
if (method === 'POST') {
|
|
body.options.skip += body.options.top;
|
|
} else {
|
|
//@ts-ignore
|
|
query.skip += query.top;
|
|
}
|
|
returnData.push.apply(returnData, responseData);
|
|
responseData = [];
|
|
} while (returnData.length < metadata.totalRecords);
|
|
|
|
return returnData;
|
|
}
|
|
|
|
/**
|
|
* Replaces `$1`, `$2`, … in a Quick Base query with the matching parameter.
|
|
* The query language documents no way to escape a quote or a brace inside a
|
|
* value, so a parameter that contains one is rejected.
|
|
*/
|
|
export function applyWhereParameters(
|
|
this: IExecuteFunctions,
|
|
where: string,
|
|
parameters: IDataObject[],
|
|
itemIndex: number,
|
|
) {
|
|
if (!where || parameters.length === 0) return where;
|
|
|
|
return where.replace(/\$(\d+)/g, (_match, index: string) => {
|
|
const position = Number(index) - 1;
|
|
if (position < 0 || position >= parameters.length) {
|
|
throw new NodeOperationError(
|
|
this.getNode(),
|
|
`'Where' references parameter $${index}, but only ${parameters.length} parameter(s) were provided`,
|
|
{ itemIndex },
|
|
);
|
|
}
|
|
|
|
const { value } = parameters[position];
|
|
assertNoQueryDelimiters.call(this, 'Where Parameters', value, ["'", '"', '{', '}'], itemIndex);
|
|
return String(value);
|
|
});
|
|
}
|