Merge branch 'master' of github.com:rgeorgel/n8n

This commit is contained in:
Ricardo Georgel 2021-07-20 18:26:40 -03:00
commit d35fc0bd43
183 changed files with 40091 additions and 34042 deletions

View file

@ -31,6 +31,14 @@ jobs:
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
-
name: Install dependencies
run: |
apt update -y
echo 'tzdata tzdata/Areas select Europe' | debconf-set-selections
echo 'tzdata tzdata/Zones/Europe select Paris' | debconf-set-selections
DEBIAN_FRONTEND="noninteractive" apt-get install -y graphicsmagick
shell: bash
-
name: npm install and build
run: |

View file

@ -2,6 +2,16 @@
This list shows all the versions which include breaking changes and how to upgrade.
## 0.131.0
### What changed?
For the Pipedrive regular node, the `deal:create` operation now requires an organization ID or person ID, in line with upcoming changes to the Pipedrive API.
### When is action necessary?
If you are using the `deal:create` operation in the Pipedrive regular node, set an organization ID or a person ID.
## 0.130.0
### What changed?

View file

@ -42,6 +42,7 @@ interface INodeSpecialCases {
interface INodeSpecialCase {
ignoredProperties?: string[];
capResults?: number;
keepOnlyProperties?: string[];
}
type ExecutionStatus = 'success' | 'error' | 'warning' | 'running';

View file

@ -45,6 +45,10 @@ import {
LoggerProxy,
} from 'n8n-workflow';
import {
pick,
} from 'lodash';
export class ExecuteBatch extends Command {
static description = '\nExecutes multiple workflows once';
@ -166,6 +170,8 @@ export class ExecuteBatch extends Command {
'429',
'econnrefused',
'missing a required parameter',
'insufficient credit balance',
'request timed out',
];
errorMessage = errorMessage.toLowerCase();
@ -600,6 +606,8 @@ export class ExecuteBatch extends Command {
nodeEdgeCases[node.name].capResults = parseInt(parts[1], 10);
} else if (parts[0] === 'IGNORED_PROPERTIES') {
nodeEdgeCases[node.name].ignoredProperties = parts[1].split(',').map(property => property.trim());
} else if (parts[0] === 'KEEP_ONLY_PROPERTIES') {
nodeEdgeCases[node.name].keepOnlyProperties = parts[1].split(',').map(property => property.trim());
}
}
});
@ -701,6 +709,11 @@ export class ExecuteBatch extends Command {
nodeEdgeCases[nodeName].ignoredProperties!.forEach(ignoredProperty => delete executionData.json[ignoredProperty]);
}
let keepOnlyFields = [] as string[];
if (nodeEdgeCases[nodeName] !== undefined && nodeEdgeCases[nodeName].keepOnlyProperties !== undefined) {
keepOnlyFields = nodeEdgeCases[nodeName].keepOnlyProperties!;
}
executionData.json = keepOnlyFields.length > 0 ? pick(executionData.json, keepOnlyFields) : executionData.json;
const jsonProperties = executionData.json;
const nodeOutputAttributes = Object.keys(jsonProperties);

View file

@ -1,6 +1,6 @@
{
"name": "n8n",
"version": "0.129.0",
"version": "0.130.0",
"description": "n8n Workflow Automation Tool",
"license": "SEE LICENSE IN LICENSE.md",
"homepage": "https://n8n.io",
@ -109,8 +109,8 @@
"lodash.get": "^4.4.2",
"mysql2": "~2.2.0",
"n8n-core": "~0.77.0",
"n8n-editor-ui": "~0.98.0",
"n8n-nodes-base": "~0.126.0",
"n8n-editor-ui": "~0.99.0",
"n8n-nodes-base": "~0.127.0",
"n8n-workflow": "~0.63.0",
"oauth-1.0a": "^2.2.6",
"open": "^7.0.0",

View file

@ -927,32 +927,37 @@ class App {
// Returns the node icon
this.app.get([`/${this.restEndpoint}/node-icon/:nodeType`, `/${this.restEndpoint}/node-icon/:scope/:nodeType`], async (req: express.Request, res: express.Response): Promise<void> => {
const nodeTypeName = `${req.params.scope ? `${req.params.scope}/` : ''}${req.params.nodeType}`;
try {
const nodeTypeName = `${req.params.scope ? `${req.params.scope}/` : ''}${req.params.nodeType}`;
const nodeTypes = NodeTypes();
const nodeType = nodeTypes.getByName(nodeTypeName);
const nodeTypes = NodeTypes();
const nodeType = nodeTypes.getByName(nodeTypeName);
if (nodeType === undefined) {
res.status(404).send('The nodeType is not known.');
return;
if (nodeType === undefined) {
res.status(404).send('The nodeType is not known.');
return;
}
if (nodeType.description.icon === undefined) {
res.status(404).send('No icon found for node.');
return;
}
if (!nodeType.description.icon.startsWith('file:')) {
res.status(404).send('Node does not have a file icon.');
return;
}
const filepath = nodeType.description.icon.substr(5);
const maxAge = 7 * 24 * 60 * 60 * 1000; // 7 days
res.setHeader('Cache-control', `private max-age=${maxAge}`);
res.sendFile(filepath);
} catch (error) {
// Error response
return ResponseHelper.sendErrorResponse(res, error);
}
if (nodeType.description.icon === undefined) {
res.status(404).send('No icon found for node.');
return;
}
if (!nodeType.description.icon.startsWith('file:')) {
res.status(404).send('Node does not have a file icon.');
return;
}
const filepath = nodeType.description.icon.substr(5);
const maxAge = 7 * 24 * 60 * 60 * 1000; // 7 days
res.setHeader('Cache-control', `private max-age=${maxAge}`);
res.sendFile(filepath);
});
@ -1316,70 +1321,75 @@ class App {
// Verify and store app code. Generate access tokens and store for respective credential.
this.app.get(`/${this.restEndpoint}/oauth1-credential/callback`, async (req: express.Request, res: express.Response) => {
const { oauth_verifier, oauth_token, cid } = req.query;
if (oauth_verifier === undefined || oauth_token === undefined) {
const errorResponse = new ResponseHelper.ResponseError('Insufficient parameters for OAuth1 callback. Received following query parameters: ' + JSON.stringify(req.query), undefined, 503);
return ResponseHelper.sendErrorResponse(res, errorResponse);
}
const result = await Db.collections.Credentials!.findOne(cid as any); // tslint:disable-line:no-any
if (result === undefined) {
const errorResponse = new ResponseHelper.ResponseError('The credential is not known.', undefined, 404);
return ResponseHelper.sendErrorResponse(res, errorResponse);
}
let encryptionKey = undefined;
encryptionKey = await UserSettings.getEncryptionKey();
if (encryptionKey === undefined) {
const errorResponse = new ResponseHelper.ResponseError('No encryption key got found to decrypt the credentials!', undefined, 503);
return ResponseHelper.sendErrorResponse(res, errorResponse);
}
// Decrypt the currently saved credentials
const workflowCredentials: IWorkflowCredentials = {
[result.type as string]: {
[result.name as string]: result as ICredentialsEncrypted,
},
};
const mode: WorkflowExecuteMode = 'internal';
const credentialsHelper = new CredentialsHelper(workflowCredentials, encryptionKey);
const decryptedDataOriginal = credentialsHelper.getDecrypted(result.name, result.type, mode, true);
const oauthCredentials = credentialsHelper.applyDefaultsAndOverwrites(decryptedDataOriginal, result.type, mode);
const options: OptionsWithUrl = {
method: 'POST',
url: _.get(oauthCredentials, 'accessTokenUrl') as string,
qs: {
oauth_token,
oauth_verifier,
},
};
let oauthToken;
try {
oauthToken = await requestPromise(options);
const { oauth_verifier, oauth_token, cid } = req.query;
if (oauth_verifier === undefined || oauth_token === undefined) {
const errorResponse = new ResponseHelper.ResponseError('Insufficient parameters for OAuth1 callback. Received following query parameters: ' + JSON.stringify(req.query), undefined, 503);
return ResponseHelper.sendErrorResponse(res, errorResponse);
}
const result = await Db.collections.Credentials!.findOne(cid as any); // tslint:disable-line:no-any
if (result === undefined) {
const errorResponse = new ResponseHelper.ResponseError('The credential is not known.', undefined, 404);
return ResponseHelper.sendErrorResponse(res, errorResponse);
}
let encryptionKey = undefined;
encryptionKey = await UserSettings.getEncryptionKey();
if (encryptionKey === undefined) {
const errorResponse = new ResponseHelper.ResponseError('No encryption key got found to decrypt the credentials!', undefined, 503);
return ResponseHelper.sendErrorResponse(res, errorResponse);
}
// Decrypt the currently saved credentials
const workflowCredentials: IWorkflowCredentials = {
[result.type as string]: {
[result.name as string]: result as ICredentialsEncrypted,
},
};
const mode: WorkflowExecuteMode = 'internal';
const credentialsHelper = new CredentialsHelper(workflowCredentials, encryptionKey);
const decryptedDataOriginal = credentialsHelper.getDecrypted(result.name, result.type, mode, true);
const oauthCredentials = credentialsHelper.applyDefaultsAndOverwrites(decryptedDataOriginal, result.type, mode);
const options: OptionsWithUrl = {
method: 'POST',
url: _.get(oauthCredentials, 'accessTokenUrl') as string,
qs: {
oauth_token,
oauth_verifier,
},
};
let oauthToken;
try {
oauthToken = await requestPromise(options);
} catch (error) {
const errorResponse = new ResponseHelper.ResponseError('Unable to get access tokens!', undefined, 404);
return ResponseHelper.sendErrorResponse(res, errorResponse);
}
// Response comes as x-www-form-urlencoded string so convert it to JSON
const oauthTokenJson = querystring.parse(oauthToken);
decryptedDataOriginal.oauthTokenData = oauthTokenJson;
const credentials = new Credentials(result.name, result.type, result.nodesAccess);
credentials.setData(decryptedDataOriginal, encryptionKey);
const newCredentialsData = credentials.getDataToSave() as unknown as ICredentialsDb;
// Add special database related data
newCredentialsData.updatedAt = this.getCurrentDate();
// Save the credentials in DB
await Db.collections.Credentials!.update(cid as any, newCredentialsData); // tslint:disable-line:no-any
res.sendFile(pathResolve(__dirname, '../../templates/oauth-callback.html'));
} catch (error) {
const errorResponse = new ResponseHelper.ResponseError('Unable to get access tokens!', undefined, 404);
return ResponseHelper.sendErrorResponse(res, errorResponse);
// Error response
return ResponseHelper.sendErrorResponse(res, error);
}
// Response comes as x-www-form-urlencoded string so convert it to JSON
const oauthTokenJson = querystring.parse(oauthToken);
decryptedDataOriginal.oauthTokenData = oauthTokenJson;
const credentials = new Credentials(result.name, result.type, result.nodesAccess);
credentials.setData(decryptedDataOriginal, encryptionKey);
const newCredentialsData = credentials.getDataToSave() as unknown as ICredentialsDb;
// Add special database related data
newCredentialsData.updatedAt = this.getCurrentDate();
// Save the credentials in DB
await Db.collections.Credentials!.update(cid as any, newCredentialsData); // tslint:disable-line:no-any
res.sendFile(pathResolve(__dirname, '../../templates/oauth-callback.html'));
});
@ -1478,111 +1488,116 @@ class App {
// Verify and store app code. Generate access tokens and store for respective credential.
this.app.get(`/${this.restEndpoint}/oauth2-credential/callback`, async (req: express.Request, res: express.Response) => {
// realmId it's currently just use for the quickbook OAuth2 flow
const { code, state: stateEncoded } = req.query;
if (code === undefined || stateEncoded === undefined) {
const errorResponse = new ResponseHelper.ResponseError('Insufficient parameters for OAuth2 callback. Received following query parameters: ' + JSON.stringify(req.query), undefined, 503);
return ResponseHelper.sendErrorResponse(res, errorResponse);
}
let state;
try {
state = JSON.parse(Buffer.from(stateEncoded as string, 'base64').toString());
} catch (error) {
const errorResponse = new ResponseHelper.ResponseError('Invalid state format returned', undefined, 503);
return ResponseHelper.sendErrorResponse(res, errorResponse);
}
const result = await Db.collections.Credentials!.findOne(state.cid);
if (result === undefined) {
const errorResponse = new ResponseHelper.ResponseError('The credential is not known.', undefined, 404);
return ResponseHelper.sendErrorResponse(res, errorResponse);
}
// realmId it's currently just use for the quickbook OAuth2 flow
const { code, state: stateEncoded } = req.query;
let encryptionKey = undefined;
encryptionKey = await UserSettings.getEncryptionKey();
if (encryptionKey === undefined) {
const errorResponse = new ResponseHelper.ResponseError('No encryption key got found to decrypt the credentials!', undefined, 503);
return ResponseHelper.sendErrorResponse(res, errorResponse);
}
if (code === undefined || stateEncoded === undefined) {
const errorResponse = new ResponseHelper.ResponseError('Insufficient parameters for OAuth2 callback. Received following query parameters: ' + JSON.stringify(req.query), undefined, 503);
return ResponseHelper.sendErrorResponse(res, errorResponse);
}
// Decrypt the currently saved credentials
const workflowCredentials: IWorkflowCredentials = {
[result.type as string]: {
[result.name as string]: result as ICredentialsEncrypted,
},
};
const mode: WorkflowExecuteMode = 'internal';
const credentialsHelper = new CredentialsHelper(workflowCredentials, encryptionKey);
const decryptedDataOriginal = credentialsHelper.getDecrypted(result.name, result.type, mode, true);
const oauthCredentials = credentialsHelper.applyDefaultsAndOverwrites(decryptedDataOriginal, result.type, mode);
let state;
try {
state = JSON.parse(Buffer.from(stateEncoded as string, 'base64').toString());
} catch (error) {
const errorResponse = new ResponseHelper.ResponseError('Invalid state format returned', undefined, 503);
return ResponseHelper.sendErrorResponse(res, errorResponse);
}
const token = new csrf();
if (decryptedDataOriginal.csrfSecret === undefined || !token.verify(decryptedDataOriginal.csrfSecret as string, state.token)) {
const errorResponse = new ResponseHelper.ResponseError('The OAuth2 callback state is invalid!', undefined, 404);
return ResponseHelper.sendErrorResponse(res, errorResponse);
}
const result = await Db.collections.Credentials!.findOne(state.cid);
if (result === undefined) {
const errorResponse = new ResponseHelper.ResponseError('The credential is not known.', undefined, 404);
return ResponseHelper.sendErrorResponse(res, errorResponse);
}
let options = {};
let encryptionKey = undefined;
encryptionKey = await UserSettings.getEncryptionKey();
if (encryptionKey === undefined) {
const errorResponse = new ResponseHelper.ResponseError('No encryption key got found to decrypt the credentials!', undefined, 503);
return ResponseHelper.sendErrorResponse(res, errorResponse);
}
const oAuth2Parameters = {
clientId: _.get(oauthCredentials, 'clientId') as string,
clientSecret: _.get(oauthCredentials, 'clientSecret', '') as string | undefined,
accessTokenUri: _.get(oauthCredentials, 'accessTokenUrl', '') as string,
authorizationUri: _.get(oauthCredentials, 'authUrl', '') as string,
redirectUri: `${WebhookHelpers.getWebhookBaseUrl()}${this.restEndpoint}/oauth2-credential/callback`,
scopes: _.split(_.get(oauthCredentials, 'scope', 'openid,') as string, ','),
};
if (_.get(oauthCredentials, 'authentication', 'header') as string === 'body') {
options = {
body: {
client_id: _.get(oauthCredentials, 'clientId') as string,
client_secret: _.get(oauthCredentials, 'clientSecret', '') as string,
// Decrypt the currently saved credentials
const workflowCredentials: IWorkflowCredentials = {
[result.type as string]: {
[result.name as string]: result as ICredentialsEncrypted,
},
};
delete oAuth2Parameters.clientSecret;
const mode: WorkflowExecuteMode = 'internal';
const credentialsHelper = new CredentialsHelper(workflowCredentials, encryptionKey);
const decryptedDataOriginal = credentialsHelper.getDecrypted(result.name, result.type, mode, true);
const oauthCredentials = credentialsHelper.applyDefaultsAndOverwrites(decryptedDataOriginal, result.type, mode);
const token = new csrf();
if (decryptedDataOriginal.csrfSecret === undefined || !token.verify(decryptedDataOriginal.csrfSecret as string, state.token)) {
const errorResponse = new ResponseHelper.ResponseError('The OAuth2 callback state is invalid!', undefined, 404);
return ResponseHelper.sendErrorResponse(res, errorResponse);
}
let options = {};
const oAuth2Parameters = {
clientId: _.get(oauthCredentials, 'clientId') as string,
clientSecret: _.get(oauthCredentials, 'clientSecret', '') as string | undefined,
accessTokenUri: _.get(oauthCredentials, 'accessTokenUrl', '') as string,
authorizationUri: _.get(oauthCredentials, 'authUrl', '') as string,
redirectUri: `${WebhookHelpers.getWebhookBaseUrl()}${this.restEndpoint}/oauth2-credential/callback`,
scopes: _.split(_.get(oauthCredentials, 'scope', 'openid,') as string, ','),
};
if (_.get(oauthCredentials, 'authentication', 'header') as string === 'body') {
options = {
body: {
client_id: _.get(oauthCredentials, 'clientId') as string,
client_secret: _.get(oauthCredentials, 'clientSecret', '') as string,
},
};
delete oAuth2Parameters.clientSecret;
}
await this.externalHooks.run('oauth2.callback', [oAuth2Parameters]);
const oAuthObj = new clientOAuth2(oAuth2Parameters);
const queryParameters = req.originalUrl.split('?').splice(1, 1).join('');
const oauthToken = await oAuthObj.code.getToken(`${oAuth2Parameters.redirectUri}?${queryParameters}`, options);
if (Object.keys(req.query).length > 2) {
_.set(oauthToken.data, 'callbackQueryString', _.omit(req.query, 'state', 'code'));
}
if (oauthToken === undefined) {
const errorResponse = new ResponseHelper.ResponseError('Unable to get access tokens!', undefined, 404);
return ResponseHelper.sendErrorResponse(res, errorResponse);
}
if (decryptedDataOriginal.oauthTokenData) {
// Only overwrite supplied data as some providers do for example just return the
// refresh_token on the very first request and not on subsequent ones.
Object.assign(decryptedDataOriginal.oauthTokenData, oauthToken.data);
} else {
// No data exists so simply set
decryptedDataOriginal.oauthTokenData = oauthToken.data;
}
_.unset(decryptedDataOriginal, 'csrfSecret');
const credentials = new Credentials(result.name, result.type, result.nodesAccess);
credentials.setData(decryptedDataOriginal, encryptionKey);
const newCredentialsData = credentials.getDataToSave() as unknown as ICredentialsDb;
// Add special database related data
newCredentialsData.updatedAt = this.getCurrentDate();
// Save the credentials in DB
await Db.collections.Credentials!.update(state.cid, newCredentialsData);
res.sendFile(pathResolve(__dirname, '../../templates/oauth-callback.html'));
} catch (error) {
// Error response
return ResponseHelper.sendErrorResponse(res, error);
}
await this.externalHooks.run('oauth2.callback', [oAuth2Parameters]);
const oAuthObj = new clientOAuth2(oAuth2Parameters);
const queryParameters = req.originalUrl.split('?').splice(1, 1).join('');
const oauthToken = await oAuthObj.code.getToken(`${oAuth2Parameters.redirectUri}?${queryParameters}`, options);
if (Object.keys(req.query).length > 2) {
_.set(oauthToken.data, 'callbackQueryString', _.omit(req.query, 'state', 'code'));
}
if (oauthToken === undefined) {
const errorResponse = new ResponseHelper.ResponseError('Unable to get access tokens!', undefined, 404);
return ResponseHelper.sendErrorResponse(res, errorResponse);
}
if (decryptedDataOriginal.oauthTokenData) {
// Only overwrite supplied data as some providers do for example just return the
// refresh_token on the very first request and not on subsequent ones.
Object.assign(decryptedDataOriginal.oauthTokenData, oauthToken.data);
} else {
// No data exists so simply set
decryptedDataOriginal.oauthTokenData = oauthToken.data;
}
_.unset(decryptedDataOriginal, 'csrfSecret');
const credentials = new Credentials(result.name, result.type, result.nodesAccess);
credentials.setData(decryptedDataOriginal, encryptionKey);
const newCredentialsData = credentials.getDataToSave() as unknown as ICredentialsDb;
// Add special database related data
newCredentialsData.updatedAt = this.getCurrentDate();
// Save the credentials in DB
await Db.collections.Credentials!.update(state.cid, newCredentialsData);
res.sendFile(pathResolve(__dirname, '../../templates/oauth-callback.html'));
});

View file

@ -1,6 +1,6 @@
{
"name": "n8n-editor-ui",
"version": "0.98.0",
"version": "0.99.0",
"description": "Workflow Editor UI for n8n",
"license": "SEE LICENSE IN LICENSE.md",
"homepage": "https://n8n.io",

View file

@ -395,6 +395,7 @@ export default mixins(
this.$showError(error, 'Problem deleting the workflow', 'There was a problem deleting the workflow:');
return;
}
this.$store.commit('setStateDirty', false);
// Reset tab title since workflow is deleted.
this.$titleReset();
this.$showMessage({

View file

@ -0,0 +1,35 @@
import {
ICredentialType,
NodePropertyTypes,
} from 'n8n-workflow';
export class ElasticsearchApi implements ICredentialType {
name = 'elasticsearchApi';
displayName = 'Elasticsearch API';
documentationUrl = 'elasticsearch';
properties = [
{
displayName: 'Username',
name: 'username',
type: 'string' as NodePropertyTypes,
default: '',
},
{
displayName: 'Password',
name: 'password',
type: 'string' as NodePropertyTypes,
typeOptions: {
password: true,
},
default: '',
},
{
displayName: 'Base URL',
name: 'baseUrl',
type: 'string' as NodePropertyTypes,
default: '',
placeholder: 'https://abc.elastic-cloud.com:9243',
description: 'Referred to as \'endpoint\' in the Elasticsearch dashboard.',
},
];
}

File diff suppressed because it is too large Load diff

View file

@ -162,196 +162,204 @@ export class Affinity implements INodeType {
const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string;
for (let i = 0; i < length; i++) {
if (resource === 'list') {
//https://api-docs.affinity.co/#get-a-specific-list
if (operation === 'get') {
const listId = this.getNodeParameter('listId', i) as string;
responseData = await affinityApiRequest.call(this, 'GET', `/lists/${listId}`, {}, qs);
}
//https://api-docs.affinity.co/#get-all-lists
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
responseData = await affinityApiRequest.call(this, 'GET', `/lists`, {}, qs);
if (returnAll === false) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.splice(0, limit);
try {
if (resource === 'list') {
//https://api-docs.affinity.co/#get-a-specific-list
if (operation === 'get') {
const listId = this.getNodeParameter('listId', i) as string;
responseData = await affinityApiRequest.call(this, 'GET', `/lists/${listId}`, {}, qs);
}
//https://api-docs.affinity.co/#get-all-lists
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
responseData = await affinityApiRequest.call(this, 'GET', `/lists`, {}, qs);
if (returnAll === false) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.splice(0, limit);
}
}
}
}
if (resource === 'listEntry') {
//https://api-docs.affinity.co/#create-a-new-list-entry
if (operation === 'create') {
const listId = this.getNodeParameter('listId', i) as string;
const entityId = this.getNodeParameter('entityId', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IDataObject = {
entity_id: parseInt(entityId, 10),
};
Object.assign(body, additionalFields);
responseData = await affinityApiRequest.call(this, 'POST', `/lists/${listId}/list-entries`, body);
}
//https://api-docs.affinity.co/#get-a-specific-list-entry
if (operation === 'get') {
const listId = this.getNodeParameter('listId', i) as string;
const listEntryId = this.getNodeParameter('listEntryId', i) as string;
responseData = await affinityApiRequest.call(this, 'GET', `/lists/${listId}/list-entries/${listEntryId}`, {}, qs);
}
//https://api-docs.affinity.co/#get-all-list-entries
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const listId = this.getNodeParameter('listId', i) as string;
if (returnAll === true) {
responseData = await affinityApiRequestAllItems.call(this, 'list_entries', 'GET', `/lists/${listId}/list-entries`, {}, qs);
} else {
qs.page_size = this.getNodeParameter('limit', i) as number;
responseData = await affinityApiRequest.call(this, 'GET', `/lists/${listId}/list-entries`, {}, qs);
responseData = responseData.list_entries;
if (resource === 'listEntry') {
//https://api-docs.affinity.co/#create-a-new-list-entry
if (operation === 'create') {
const listId = this.getNodeParameter('listId', i) as string;
const entityId = this.getNodeParameter('entityId', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IDataObject = {
entity_id: parseInt(entityId, 10),
};
Object.assign(body, additionalFields);
responseData = await affinityApiRequest.call(this, 'POST', `/lists/${listId}/list-entries`, body);
}
//https://api-docs.affinity.co/#get-a-specific-list-entry
if (operation === 'get') {
const listId = this.getNodeParameter('listId', i) as string;
const listEntryId = this.getNodeParameter('listEntryId', i) as string;
responseData = await affinityApiRequest.call(this, 'GET', `/lists/${listId}/list-entries/${listEntryId}`, {}, qs);
}
//https://api-docs.affinity.co/#get-all-list-entries
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const listId = this.getNodeParameter('listId', i) as string;
if (returnAll === true) {
responseData = await affinityApiRequestAllItems.call(this, 'list_entries', 'GET', `/lists/${listId}/list-entries`, {}, qs);
} else {
qs.page_size = this.getNodeParameter('limit', i) as number;
responseData = await affinityApiRequest.call(this, 'GET', `/lists/${listId}/list-entries`, {}, qs);
responseData = responseData.list_entries;
}
}
//https://api-docs.affinity.co/#delete-a-specific-list-entry
if (operation === 'delete') {
const listId = this.getNodeParameter('listId', i) as string;
const listEntryId = this.getNodeParameter('listEntryId', i) as string;
responseData = await affinityApiRequest.call(this, 'DELETE', `/lists/${listId}/list-entries/${listEntryId}`, {}, qs);
}
}
//https://api-docs.affinity.co/#delete-a-specific-list-entry
if (operation === 'delete') {
const listId = this.getNodeParameter('listId', i) as string;
const listEntryId = this.getNodeParameter('listEntryId', i) as string;
responseData = await affinityApiRequest.call(this, 'DELETE', `/lists/${listId}/list-entries/${listEntryId}`, {}, qs);
}
}
if (resource === 'person') {
//https://api-docs.affinity.co/#create-a-new-person
if (operation === 'create') {
const firstName = this.getNodeParameter('firstName', i) as string;
const lastName = this.getNodeParameter('lastName', i) as string;
const emails = this.getNodeParameter('emails', i) as string[];
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IPerson = {
first_name: firstName,
last_name: lastName,
emails,
};
if (additionalFields.organizations) {
body.organization_ids = additionalFields.organizations as number[];
if (resource === 'person') {
//https://api-docs.affinity.co/#create-a-new-person
if (operation === 'create') {
const firstName = this.getNodeParameter('firstName', i) as string;
const lastName = this.getNodeParameter('lastName', i) as string;
const emails = this.getNodeParameter('emails', i) as string[];
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IPerson = {
first_name: firstName,
last_name: lastName,
emails,
};
if (additionalFields.organizations) {
body.organization_ids = additionalFields.organizations as number[];
}
responseData = await affinityApiRequest.call(this, 'POST', '/persons', body);
}
responseData = await affinityApiRequest.call(this, 'POST', '/persons', body);
}
//https://api-docs.affinity.co/#update-a-person
if (operation === 'update') {
const personId = this.getNodeParameter('personId', i) as number;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const emails = this.getNodeParameter('emails', i) as string[];
const body: IPerson = {
emails,
};
if (updateFields.firstName) {
body.first_name = updateFields.firstName as string;
//https://api-docs.affinity.co/#update-a-person
if (operation === 'update') {
const personId = this.getNodeParameter('personId', i) as number;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const emails = this.getNodeParameter('emails', i) as string[];
const body: IPerson = {
emails,
};
if (updateFields.firstName) {
body.first_name = updateFields.firstName as string;
}
if (updateFields.lastName) {
body.last_name = updateFields.lastName as string;
}
if (updateFields.organizations) {
body.organization_ids = updateFields.organizations as number[];
}
responseData = await affinityApiRequest.call(this, 'PUT', `/persons/${personId}`, body);
}
if (updateFields.lastName) {
body.last_name = updateFields.lastName as string;
//https://api-docs.affinity.co/#get-a-specific-person
if (operation === 'get') {
const personId = this.getNodeParameter('personId', i) as number;
const options = this.getNodeParameter('options', i) as IDataObject;
if (options.withInteractionDates) {
qs.with_interaction_dates = options.withInteractionDates as boolean;
}
responseData = await affinityApiRequest.call(this, 'GET', `/persons/${personId}`, {}, qs);
}
if (updateFields.organizations) {
body.organization_ids = updateFields.organizations as number[];
//https://api-docs.affinity.co/#search-for-persons
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const options = this.getNodeParameter('options', i) as IDataObject;
if (options.term) {
qs.term = options.term as string;
}
if (options.withInteractionDates) {
qs.with_interaction_dates = options.withInteractionDates as boolean;
}
if (returnAll === true) {
responseData = await affinityApiRequestAllItems.call(this, 'persons', 'GET', '/persons', {}, qs);
} else {
qs.page_size = this.getNodeParameter('limit', i) as number;
responseData = await affinityApiRequest.call(this, 'GET', '/persons', {}, qs);
responseData = responseData.persons;
}
}
responseData = await affinityApiRequest.call(this, 'PUT', `/persons/${personId}`, body);
}
//https://api-docs.affinity.co/#get-a-specific-person
if (operation === 'get') {
const personId = this.getNodeParameter('personId', i) as number;
const options = this.getNodeParameter('options', i) as IDataObject;
if (options.withInteractionDates) {
qs.with_interaction_dates = options.withInteractionDates as boolean;
}
responseData = await affinityApiRequest.call(this, 'GET', `/persons/${personId}`, {}, qs);
}
//https://api-docs.affinity.co/#search-for-persons
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const options = this.getNodeParameter('options', i) as IDataObject;
if (options.term) {
qs.term = options.term as string;
}
if (options.withInteractionDates) {
qs.with_interaction_dates = options.withInteractionDates as boolean;
}
if (returnAll === true) {
responseData = await affinityApiRequestAllItems.call(this, 'persons', 'GET', '/persons', {}, qs);
} else {
qs.page_size = this.getNodeParameter('limit', i) as number;
responseData = await affinityApiRequest.call(this, 'GET', '/persons', {}, qs);
responseData = responseData.persons;
//https://api-docs.affinity.co/#delete-a-person
if (operation === 'delete') {
const personId = this.getNodeParameter('personId', i) as number;
responseData = await affinityApiRequest.call(this, 'DELETE', `/persons/${personId}`, {}, qs);
}
}
//https://api-docs.affinity.co/#delete-a-person
if (operation === 'delete') {
const personId = this.getNodeParameter('personId', i) as number;
responseData = await affinityApiRequest.call(this, 'DELETE', `/persons/${personId}`, {}, qs);
}
}
if (resource === 'organization') {
//https://api-docs.affinity.co/#create-a-new-organization
if (operation === 'create') {
const name = this.getNodeParameter('name', i) as string;
const domain = this.getNodeParameter('domain', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IOrganization = {
name,
domain,
};
if (additionalFields.persons) {
body.person_ids = additionalFields.persons as number[];
if (resource === 'organization') {
//https://api-docs.affinity.co/#create-a-new-organization
if (operation === 'create') {
const name = this.getNodeParameter('name', i) as string;
const domain = this.getNodeParameter('domain', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IOrganization = {
name,
domain,
};
if (additionalFields.persons) {
body.person_ids = additionalFields.persons as number[];
}
responseData = await affinityApiRequest.call(this, 'POST', '/organizations', body);
}
responseData = await affinityApiRequest.call(this, 'POST', '/organizations', body);
}
//https://api-docs.affinity.co/#update-an-organization
if (operation === 'update') {
const organizationId = this.getNodeParameter('organizationId', i) as number;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const body: IOrganization = {};
if (updateFields.name) {
body.name = updateFields.name as string;
//https://api-docs.affinity.co/#update-an-organization
if (operation === 'update') {
const organizationId = this.getNodeParameter('organizationId', i) as number;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const body: IOrganization = {};
if (updateFields.name) {
body.name = updateFields.name as string;
}
if (updateFields.domain) {
body.domain = updateFields.domain as string;
}
if (updateFields.persons) {
body.person_ids = updateFields.persons as number[];
}
responseData = await affinityApiRequest.call(this, 'PUT', `/organizations/${organizationId}`, body);
}
if (updateFields.domain) {
body.domain = updateFields.domain as string;
//https://api-docs.affinity.co/#get-a-specific-organization
if (operation === 'get') {
const organizationId = this.getNodeParameter('organizationId', i) as number;
const options = this.getNodeParameter('options', i) as IDataObject;
if (options.withInteractionDates) {
qs.with_interaction_dates = options.withInteractionDates as boolean;
}
responseData = await affinityApiRequest.call(this, 'GET', `/organizations/${organizationId}`, {}, qs);
}
if (updateFields.persons) {
body.person_ids = updateFields.persons as number[];
//https://api-docs.affinity.co/#search-for-organizations
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const options = this.getNodeParameter('options', i) as IDataObject;
if (options.term) {
qs.term = options.term as string;
}
if (options.withInteractionDates) {
qs.with_interaction_dates = options.withInteractionDates as boolean;
}
if (returnAll === true) {
responseData = await affinityApiRequestAllItems.call(this, 'organizations', 'GET', '/organizations', {}, qs);
} else {
qs.page_size = this.getNodeParameter('limit', i) as number;
responseData = await affinityApiRequest.call(this, 'GET', '/organizations', {}, qs);
responseData = responseData.organizations;
}
}
responseData = await affinityApiRequest.call(this, 'PUT', `/organizations/${organizationId}`, body);
}
//https://api-docs.affinity.co/#get-a-specific-organization
if (operation === 'get') {
const organizationId = this.getNodeParameter('organizationId', i) as number;
const options = this.getNodeParameter('options', i) as IDataObject;
if (options.withInteractionDates) {
qs.with_interaction_dates = options.withInteractionDates as boolean;
}
responseData = await affinityApiRequest.call(this, 'GET', `/organizations/${organizationId}`, {}, qs);
}
//https://api-docs.affinity.co/#search-for-organizations
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const options = this.getNodeParameter('options', i) as IDataObject;
if (options.term) {
qs.term = options.term as string;
}
if (options.withInteractionDates) {
qs.with_interaction_dates = options.withInteractionDates as boolean;
}
if (returnAll === true) {
responseData = await affinityApiRequestAllItems.call(this, 'organizations', 'GET', '/organizations', {}, qs);
} else {
qs.page_size = this.getNodeParameter('limit', i) as number;
responseData = await affinityApiRequest.call(this, 'GET', '/organizations', {}, qs);
responseData = responseData.organizations;
//https://api-docs.affinity.co/#delete-an-organization
if (operation === 'delete') {
const organizationId = this.getNodeParameter('organizationId', i) as number;
responseData = await affinityApiRequest.call(this, 'DELETE', `/organizations/${organizationId}`, {}, qs);
}
}
//https://api-docs.affinity.co/#delete-an-organization
if (operation === 'delete') {
const organizationId = this.getNodeParameter('organizationId', i) as number;
responseData = await affinityApiRequest.call(this, 'DELETE', `/organizations/${organizationId}`, {}, qs);
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];

View file

@ -489,43 +489,51 @@ export class Airtable implements INodeType {
let bulkSize = 10;
for (let i = 0; i < items.length; i++) {
addAllFields = this.getNodeParameter('addAllFields', i) as boolean;
options = this.getNodeParameter('options', i, {}) as IDataObject;
bulkSize = options.bulkSize as number || bulkSize;
try {
addAllFields = this.getNodeParameter('addAllFields', i) as boolean;
options = this.getNodeParameter('options', i, {}) as IDataObject;
bulkSize = options.bulkSize as number || bulkSize;
const row: IDataObject = {};
const row: IDataObject = {};
if (addAllFields === true) {
// Add all the fields the item has
row.fields = { ...items[i].json };
// tslint:disable-next-line: no-any
delete (row.fields! as any).id;
} else {
// Add only the specified fields
row.fields = {} as IDataObject;
if (addAllFields === true) {
// Add all the fields the item has
row.fields = { ...items[i].json };
// tslint:disable-next-line: no-any
delete (row.fields! as any).id;
} else {
// Add only the specified fields
row.fields = {} as IDataObject;
fields = this.getNodeParameter('fields', i, []) as string[];
fields = this.getNodeParameter('fields', i, []) as string[];
for (const fieldName of fields) {
// @ts-ignore
row.fields[fieldName] = items[i].json[fieldName];
}
}
rows.push(row);
if (rows.length === bulkSize || i === items.length - 1) {
if (options.typecast === true) {
body['typecast'] = true;
for (const fieldName of fields) {
// @ts-ignore
row.fields[fieldName] = items[i].json[fieldName];
}
}
body['records'] = rows;
rows.push(row);
responseData = await apiRequest.call(this, requestMethod, endpoint, body, qs);
if (rows.length === bulkSize || i === items.length - 1) {
if (options.typecast === true) {
body['typecast'] = true;
}
returnData.push(...responseData.records);
// empty rows
rows.length = 0;
body['records'] = rows;
responseData = await apiRequest.call(this, requestMethod, endpoint, body, qs);
returnData.push(...responseData.records);
// empty rows
rows.length = 0;
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
@ -537,28 +545,36 @@ export class Airtable implements INodeType {
const bulkSize = options.bulkSize as number || 10;
for (let i = 0; i < items.length; i++) {
let id: string;
try {
let id: string;
id = this.getNodeParameter('id', i) as string;
id = this.getNodeParameter('id', i) as string;
rows.push(id);
rows.push(id);
if (rows.length === bulkSize || i === items.length - 1) {
endpoint = `${application}/${table}`;
if (rows.length === bulkSize || i === items.length - 1) {
endpoint = `${application}/${table}`;
// Make one request after another. This is slower but makes
// sure that we do not run into the rate limit they have in
// place and so block for 30 seconds. Later some global
// functionality in core should make it easy to make requests
// according to specific rules like not more than 5 requests
// per seconds.
qs.records = rows;
// Make one request after another. This is slower but makes
// sure that we do not run into the rate limit they have in
// place and so block for 30 seconds. Later some global
// functionality in core should make it easy to make requests
// according to specific rules like not more than 5 requests
// per seconds.
qs.records = rows;
responseData = await apiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = await apiRequest.call(this, requestMethod, endpoint, body, qs);
returnData.push(...responseData.records);
// empty rows
rows.length = 0;
returnData.push(...responseData.records);
// empty rows
rows.length = 0;
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
@ -566,37 +582,44 @@ export class Airtable implements INodeType {
// ----------------------------------
// list
// ----------------------------------
try {
requestMethod = 'GET';
endpoint = `${application}/${table}`;
requestMethod = 'GET';
endpoint = `${application}/${table}`;
returnAll = this.getNodeParameter('returnAll', 0) as boolean;
returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const downloadAttachments = this.getNodeParameter('downloadAttachments', 0) as boolean;
const downloadAttachments = this.getNodeParameter('downloadAttachments', 0) as boolean;
const additionalOptions = this.getNodeParameter('additionalOptions', 0, {}) as IDataObject;
const additionalOptions = this.getNodeParameter('additionalOptions', 0, {}) as IDataObject;
for (const key of Object.keys(additionalOptions)) {
if (key === 'sort' && (additionalOptions.sort as IDataObject).property !== undefined) {
qs[key] = (additionalOptions[key] as IDataObject).property;
} else {
qs[key] = additionalOptions[key];
for (const key of Object.keys(additionalOptions)) {
if (key === 'sort' && (additionalOptions.sort as IDataObject).property !== undefined) {
qs[key] = (additionalOptions[key] as IDataObject).property;
} else {
qs[key] = additionalOptions[key];
}
}
}
if (returnAll === true) {
responseData = await apiRequestAllItems.call(this, requestMethod, endpoint, body, qs);
} else {
qs.maxRecords = this.getNodeParameter('limit', 0) as number;
responseData = await apiRequest.call(this, requestMethod, endpoint, body, qs);
}
if (returnAll === true) {
responseData = await apiRequestAllItems.call(this, requestMethod, endpoint, body, qs);
} else {
qs.maxRecords = this.getNodeParameter('limit', 0) as number;
responseData = await apiRequest.call(this, requestMethod, endpoint, body, qs);
}
returnData.push.apply(returnData, responseData.records);
returnData.push.apply(returnData, responseData.records);
if (downloadAttachments === true) {
const downloadFieldNames = (this.getNodeParameter('downloadFieldNames', 0) as string).split(',');
const data = await downloadRecordAttachments.call(this, responseData.records, downloadFieldNames);
return [data];
if (downloadAttachments === true) {
const downloadFieldNames = (this.getNodeParameter('downloadFieldNames', 0) as string).split(',');
const data = await downloadRecordAttachments.call(this, responseData.records, downloadFieldNames);
return [data];
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
} else {
throw error;
}
}
} else if (operation === 'read') {
@ -619,10 +642,17 @@ export class Airtable implements INodeType {
// functionality in core should make it easy to make requests
// according to specific rules like not more than 5 requests
// per seconds.
try {
responseData = await apiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = await apiRequest.call(this, requestMethod, endpoint, body, qs);
returnData.push(responseData);
returnData.push(responseData);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
} else if (operation === 'update') {
@ -640,60 +670,68 @@ export class Airtable implements INodeType {
let bulkSize = 10;
for (let i = 0; i < items.length; i++) {
updateAllFields = this.getNodeParameter('updateAllFields', i) as boolean;
options = this.getNodeParameter('options', i, {}) as IDataObject;
bulkSize = options.bulkSize as number || bulkSize;
try {
updateAllFields = this.getNodeParameter('updateAllFields', i) as boolean;
options = this.getNodeParameter('options', i, {}) as IDataObject;
bulkSize = options.bulkSize as number || bulkSize;
const row: IDataObject = {};
row.fields = {} as IDataObject;
const row: IDataObject = {};
row.fields = {} as IDataObject;
if (updateAllFields === true) {
// Update all the fields the item has
row.fields = { ...items[i].json };
// remove id field
// tslint:disable-next-line: no-any
delete (row.fields! as any).id;
if (updateAllFields === true) {
// Update all the fields the item has
row.fields = { ...items[i].json };
// remove id field
// tslint:disable-next-line: no-any
delete (row.fields! as any).id;
if (options.ignoreFields && options.ignoreFields !== '') {
const ignoreFields = (options.ignoreFields as string).split(',').map(field => field.trim()).filter(field => !!field);
if (ignoreFields.length) {
// From: https://stackoverflow.com/questions/17781472/how-to-get-a-subset-of-a-javascript-objects-properties
row.fields = Object.entries(items[i].json)
.filter(([key]) => !ignoreFields.includes(key))
.reduce((obj, [key, val]) => Object.assign(obj, { [key]: val }), {});
if (options.ignoreFields && options.ignoreFields !== '') {
const ignoreFields = (options.ignoreFields as string).split(',').map(field => field.trim()).filter(field => !!field);
if (ignoreFields.length) {
// From: https://stackoverflow.com/questions/17781472/how-to-get-a-subset-of-a-javascript-objects-properties
row.fields = Object.entries(items[i].json)
.filter(([key]) => !ignoreFields.includes(key))
.reduce((obj, [key, val]) => Object.assign(obj, { [key]: val }), {});
}
}
} else {
fields = this.getNodeParameter('fields', i, []) as string[];
for (const fieldName of fields) {
// @ts-ignore
row.fields[fieldName] = items[i].json[fieldName];
}
}
} else {
fields = this.getNodeParameter('fields', i, []) as string[];
for (const fieldName of fields) {
// @ts-ignore
row.fields[fieldName] = items[i].json[fieldName];
row.id = this.getNodeParameter('id', i) as string;
rows.push(row);
if (rows.length === bulkSize || i === items.length - 1) {
endpoint = `${application}/${table}`;
// Make one request after another. This is slower but makes
// sure that we do not run into the rate limit they have in
// place and so block for 30 seconds. Later some global
// functionality in core should make it easy to make requests
// according to specific rules like not more than 5 requests
// per seconds.
const data = { records: rows, typecast: (options.typecast) ? true : false };
responseData = await apiRequest.call(this, requestMethod, endpoint, data, qs);
returnData.push(...responseData.records);
// empty rows
rows.length = 0;
}
}
row.id = this.getNodeParameter('id', i) as string;
rows.push(row);
if (rows.length === bulkSize || i === items.length - 1) {
endpoint = `${application}/${table}`;
// Make one request after another. This is slower but makes
// sure that we do not run into the rate limit they have in
// place and so block for 30 seconds. Later some global
// functionality in core should make it easy to make requests
// according to specific rules like not more than 5 requests
// per seconds.
const data = { records: rows, typecast: (options.typecast) ? true : false };
responseData = await apiRequest.call(this, requestMethod, endpoint, data, qs);
returnData.push(...responseData.records);
// empty rows
rows.length = 0;
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
@ -703,4 +741,4 @@ export class Airtable implements INodeType {
return [this.helpers.returnJsonArray(returnData)];
}
}
}

View file

@ -97,84 +97,92 @@ export class Amqp implements INodeType {
};
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const credentials = this.getCredentials('amqp');
if (!credentials) {
throw new NodeOperationError(this.getNode(), 'Credentials are mandatory!');
}
try {
const credentials = this.getCredentials('amqp');
if (!credentials) {
throw new NodeOperationError(this.getNode(), 'Credentials are mandatory!');
}
const sink = this.getNodeParameter('sink', 0, '') as string;
const applicationProperties = this.getNodeParameter('headerParametersJson', 0, {}) as string | object;
const options = this.getNodeParameter('options', 0, {}) as IDataObject;
const containerId = options.containerId as string;
const containerReconnect = options.reconnect as boolean || true;
const containerReconnectLimit = options.reconnectLimit as number || 50;
const sink = this.getNodeParameter('sink', 0, '') as string;
const applicationProperties = this.getNodeParameter('headerParametersJson', 0, {}) as string | object;
const options = this.getNodeParameter('options', 0, {}) as IDataObject;
const containerId = options.containerId as string;
const containerReconnect = options.reconnect as boolean || true;
const containerReconnectLimit = options.reconnectLimit as number || 50;
let headerProperties: Dictionary<any>; // tslint:disable-line:no-any
if (typeof applicationProperties === 'string' && applicationProperties !== '') {
headerProperties = JSON.parse(applicationProperties);
} else {
headerProperties = applicationProperties as object;
}
let headerProperties: Dictionary<any>; // tslint:disable-line:no-any
if (typeof applicationProperties === 'string' && applicationProperties !== '') {
headerProperties = JSON.parse(applicationProperties);
} else {
headerProperties = applicationProperties as object;
}
if (sink === '') {
throw new NodeOperationError(this.getNode(), 'Queue or Topic required!');
}
if (sink === '') {
throw new NodeOperationError(this.getNode(), 'Queue or Topic required!');
}
const container = create_container();
const container = create_container();
/*
Values are documentet here: https://github.com/amqp/rhea#container
*/
const connectOptions: ContainerOptions = {
host: credentials.hostname,
hostname: credentials.hostname,
port: credentials.port,
reconnect: containerReconnect,
reconnect_limit: containerReconnectLimit,
username: credentials.username ? credentials.username : undefined,
password: credentials.password ? credentials.password : undefined,
transport: credentials.transportType ? credentials.transportType : undefined,
container_id: containerId ? containerId : undefined,
id: containerId ? containerId : undefined,
};
const conn = container.connect(connectOptions);
/*
Values are documentet here: https://github.com/amqp/rhea#container
*/
const connectOptions: ContainerOptions = {
host: credentials.hostname,
hostname: credentials.hostname,
port: credentials.port,
reconnect: containerReconnect,
reconnect_limit: containerReconnectLimit,
username: credentials.username ? credentials.username : undefined,
password: credentials.password ? credentials.password : undefined,
transport: credentials.transportType ? credentials.transportType : undefined,
container_id: containerId ? containerId : undefined,
id: containerId ? containerId : undefined,
};
const conn = container.connect(connectOptions);
const sender = conn.open_sender(sink);
const sender = conn.open_sender(sink);
const responseData: IDataObject[] = await new Promise((resolve) => {
container.once('sendable', (context: EventContext) => {
const returnData = [];
const responseData: IDataObject[] = await new Promise((resolve) => {
container.once('sendable', (context: EventContext) => {
const returnData = [];
const items = this.getInputData();
for (let i = 0; i < items.length; i++) {
const item = items[i];
const items = this.getInputData();
for (let i = 0; i < items.length; i++) {
const item = items[i];
let body: IDataObject | string = item.json;
const sendOnlyProperty = options.sendOnlyProperty as string;
let body: IDataObject | string = item.json;
const sendOnlyProperty = options.sendOnlyProperty as string;
if (sendOnlyProperty) {
body = body[sendOnlyProperty] as string;
if (sendOnlyProperty) {
body = body[sendOnlyProperty] as string;
}
if (options.dataAsObject !== true) {
body = JSON.stringify(body);
}
const result = context.sender?.send({
application_properties: headerProperties,
body,
});
returnData.push({ id: result?.id });
}
if (options.dataAsObject !== true) {
body = JSON.stringify(body);
}
const result = context.sender?.send({
application_properties: headerProperties,
body,
});
returnData.push({ id: result?.id });
}
resolve(returnData);
resolve(returnData);
});
});
});
sender.close();
conn.close();
sender.close();
conn.close();
return [this.helpers.returnJsonArray(responseData)];
return [this.helpers.returnJsonArray(responseData)];
} catch (error) {
if (this.continueOnFail()) {
return [this.helpers.returnJsonArray({ error: error.message })];
}else{
throw error;
}
}
}
}

View file

@ -420,10 +420,17 @@ export class ApiTemplateIo implements INodeType {
// ----------------------------------
for (let i = 0; i < length; i++) {
try {
responseData = await apiTemplateIoApiRequest.call(this, 'GET', '/account-information');
responseData = await apiTemplateIoApiRequest.call(this, 'GET', '/account-information');
returnData.push(responseData);
returnData.push(responseData);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({json:{ error: error.message }});
continue;
}
throw error;
}
}
}
@ -442,52 +449,60 @@ export class ApiTemplateIo implements INodeType {
// https://docs.apitemplate.io/reference/api-reference.html#create-an-image-jpeg-and-png
for (let i = 0; i < length; i++) {
const jsonParameters = this.getNodeParameter('jsonParameters', i) as boolean;
try {
const jsonParameters = this.getNodeParameter('jsonParameters', i) as boolean;
const options = this.getNodeParameter('options', i) as IDataObject;
const options = this.getNodeParameter('options', i) as IDataObject;
const qs = {
template_id: this.getNodeParameter('imageTemplateId', i),
};
const body = { overrides: [] } as IDataObject;
if (jsonParameters === false) {
const overrides = (this.getNodeParameter('overridesUi', i) as IDataObject || {}).overrideValues as IDataObject[] || [];
if (overrides.length !== 0) {
const data: IDataObject[] = [];
for (const override of overrides) {
const properties = (override.propertiesUi as IDataObject || {}).propertyValues as IDataObject[] || [];
data.push(properties.reduce((obj, value) => Object.assign(obj, { [`${value.key}`]: value.value }), {}));
}
body.overrides = data;
}
} else {
const overrideJson = this.getNodeParameter('overridesJson', i) as string;
if (overrideJson !== '') {
const data = validateJSON(overrideJson);
if (data === undefined) {
throw new NodeOperationError(this.getNode(), 'A valid JSON must be provided.');
}
body.overrides = data;
}
}
responseData = await apiTemplateIoApiRequest.call(this, 'POST', '/create', qs, body);
if (download === true) {
const binaryProperty = this.getNodeParameter('binaryProperty', i) as string;
const data = await downloadImage.call(this, responseData.download_url);
const fileName = responseData.download_url.split('/').pop();
const binaryData = await this.helpers.prepareBinaryData(data, options.fileName || fileName);
responseData = {
json: responseData,
binary: {
[binaryProperty]: binaryData,
},
const qs = {
template_id: this.getNodeParameter('imageTemplateId', i),
};
const body = { overrides: [] } as IDataObject;
if (jsonParameters === false) {
const overrides = (this.getNodeParameter('overridesUi', i) as IDataObject || {}).overrideValues as IDataObject[] || [];
if (overrides.length !== 0) {
const data: IDataObject[] = [];
for (const override of overrides) {
const properties = (override.propertiesUi as IDataObject || {}).propertyValues as IDataObject[] || [];
data.push(properties.reduce((obj, value) => Object.assign(obj, { [`${value.key}`]: value.value }), {}));
}
body.overrides = data;
}
} else {
const overrideJson = this.getNodeParameter('overridesJson', i) as string;
if (overrideJson !== '') {
const data = validateJSON(overrideJson);
if (data === undefined) {
throw new NodeOperationError(this.getNode(), 'A valid JSON must be provided.');
}
body.overrides = data;
}
}
responseData = await apiTemplateIoApiRequest.call(this, 'POST', '/create', qs, body);
if (download === true) {
const binaryProperty = this.getNodeParameter('binaryProperty', i) as string;
const data = await downloadImage.call(this, responseData.download_url);
const fileName = responseData.download_url.split('/').pop();
const binaryData = await this.helpers.prepareBinaryData(data, options.fileName || fileName);
responseData = {
json: responseData,
binary: {
[binaryProperty]: binaryData,
},
};
}
returnData.push(responseData);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({json:{ error: error.message }});
continue;
}
throw error;
}
returnData.push(responseData);
}
if (download === true) {
@ -511,45 +526,53 @@ export class ApiTemplateIo implements INodeType {
const download = this.getNodeParameter('download', 0) as boolean;
for (let i = 0; i < length; i++) {
const jsonParameters = this.getNodeParameter('jsonParameters', i) as boolean;
try {
const jsonParameters = this.getNodeParameter('jsonParameters', i) as boolean;
const options = this.getNodeParameter('options', i) as IDataObject;
const options = this.getNodeParameter('options', i) as IDataObject;
const qs = {
template_id: this.getNodeParameter('pdfTemplateId', i),
};
let data;
if (jsonParameters === false) {
const properties = (this.getNodeParameter('propertiesUi', i) as IDataObject || {}).propertyValues as IDataObject[] || [];
if (properties.length === 0) {
throw new NodeOperationError(this.getNode(), 'The parameter properties cannot be empty');
}
data = properties.reduce((obj, value) => Object.assign(obj, { [`${value.key}`]: value.value }), {});
} else {
const propertiesJson = this.getNodeParameter('propertiesJson', i) as string;
data = validateJSON(propertiesJson);
if (data === undefined) {
throw new NodeOperationError(this.getNode(), 'A valid JSON must be provided.');
}
}
responseData = await apiTemplateIoApiRequest.call(this, 'POST', '/create', qs, data);
if (download === true) {
const binaryProperty = this.getNodeParameter('binaryProperty', i) as string;
const data = await downloadImage.call(this, responseData.download_url);
const fileName = responseData.download_url.split('/').pop();
const binaryData = await this.helpers.prepareBinaryData(data, options.fileName || fileName);
responseData = {
json: responseData,
binary: {
[binaryProperty]: binaryData,
},
const qs = {
template_id: this.getNodeParameter('pdfTemplateId', i),
};
let data;
if (jsonParameters === false) {
const properties = (this.getNodeParameter('propertiesUi', i) as IDataObject || {}).propertyValues as IDataObject[] || [];
if (properties.length === 0) {
throw new NodeOperationError(this.getNode(), 'The parameter properties cannot be empty');
}
data = properties.reduce((obj, value) => Object.assign(obj, { [`${value.key}`]: value.value }), {});
} else {
const propertiesJson = this.getNodeParameter('propertiesJson', i) as string;
data = validateJSON(propertiesJson);
if (data === undefined) {
throw new NodeOperationError(this.getNode(), 'A valid JSON must be provided.');
}
}
responseData = await apiTemplateIoApiRequest.call(this, 'POST', '/create', qs, data);
if (download === true) {
const binaryProperty = this.getNodeParameter('binaryProperty', i) as string;
const data = await downloadImage.call(this, responseData.download_url);
const fileName = responseData.download_url.split('/').pop();
const binaryData = await this.helpers.prepareBinaryData(data, options.fileName || fileName);
responseData = {
json: responseData,
binary: {
[binaryProperty]: binaryData,
},
};
}
returnData.push(responseData);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({json:{ error: error.message }});
continue;
}
throw error;
}
returnData.push(responseData);
}
if (download === true) {
return this.prepareOutputData(returnData as unknown as INodeExecutionData[]);

View file

@ -1842,417 +1842,425 @@ export class Asana implements INodeType {
let responseData;
for (let i = 0; i < items.length; i++) {
body = {};
qs = {};
try {
body = {};
qs = {};
if (resource === 'subtask') {
if (operation === 'create') {
// ----------------------------------
// subtask:create
// ----------------------------------
if (resource === 'subtask') {
if (operation === 'create') {
// ----------------------------------
// subtask:create
// ----------------------------------
const taskId = this.getNodeParameter('taskId', i) as string;
const taskId = this.getNodeParameter('taskId', i) as string;
requestMethod = 'POST';
endpoint = `/tasks/${taskId}/subtasks`;
requestMethod = 'POST';
endpoint = `/tasks/${taskId}/subtasks`;
body.name = this.getNodeParameter('name', i) as string;
body.name = this.getNodeParameter('name', i) as string;
const otherProperties = this.getNodeParameter('otherProperties', i) as IDataObject;
Object.assign(body, otherProperties);
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = responseData.data;
}
if (operation === 'getAll') {
// ----------------------------------
// subtask:getAll
// ----------------------------------
const taskId = this.getNodeParameter('taskId', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const options = this.getNodeParameter('options', i) as IDataObject;
requestMethod = 'GET';
endpoint = `/tasks/${taskId}/subtasks`;
Object.assign(qs, options);
if (qs.opt_fields) {
const fields = qs.opt_fields as string[];
if (fields.includes('*')) {
qs.opt_fields = getTaskFields().map((e) => snakeCase(e)).join(',');
} else {
qs.opt_fields = (qs.opt_fields as string[]).join(',');
}
}
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = responseData.data;
if (returnAll === false) {
const limit = this.getNodeParameter('limit', i) as boolean;
responseData = responseData.splice(0, limit);
}
}
}
if (resource === 'task') {
if (operation === 'create') {
// ----------------------------------
// task:create
// ----------------------------------
requestMethod = 'POST';
endpoint = '/tasks';
body.name = this.getNodeParameter('name', i) as string;
// body.notes = this.getNodeParameter('taskNotes', 0) as string;
body.workspace = this.getNodeParameter('workspace', i) as string;
const otherProperties = this.getNodeParameter('otherProperties', i) as IDataObject;
Object.assign(body, otherProperties);
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = responseData.data;
} else if (operation === 'delete') {
// ----------------------------------
// task:delete
// ----------------------------------
requestMethod = 'DELETE';
endpoint = '/tasks/' + this.getNodeParameter('id', i) as string;
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = responseData.data;
} else if (operation === 'get') {
// ----------------------------------
// task:get
// ----------------------------------
requestMethod = 'GET';
endpoint = '/tasks/' + this.getNodeParameter('id', i) as string;
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = responseData.data;
} else if (operation === 'getAll') {
// ----------------------------------
// task:getAll
// ----------------------------------
const filters = this.getNodeParameter('filters', i) as IDataObject;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
requestMethod = 'GET';
endpoint = `/tasks`;
Object.assign(qs, filters);
if (qs.opt_fields) {
const fields = qs.opt_fields as string[];
if (fields.includes('*')) {
qs.opt_fields = getTaskFields().map((e) => snakeCase(e)).join(',');
} else {
qs.opt_fields = (qs.opt_fields as string[]).join(',');
}
}
if (qs.modified_since) {
qs.modified_since = moment.tz(qs.modified_since as string, timezone).format();
}
if (qs.completed_since) {
qs.completed_since = moment.tz(qs.completed_since as string, timezone).format();
}
if (returnAll) {
responseData = await asanaApiRequestAllItems.call(this, requestMethod, endpoint, body, qs);
} else {
qs.limit = this.getNodeParameter('limit', i) as boolean;
const otherProperties = this.getNodeParameter('otherProperties', i) as IDataObject;
Object.assign(body, otherProperties);
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = responseData.data;
}
} else if (operation === 'move') {
// ----------------------------------
// task:move
// ----------------------------------
if (operation === 'getAll') {
// ----------------------------------
// subtask:getAll
// ----------------------------------
const taskId = this.getNodeParameter('taskId', i) as string;
const sectionId = this.getNodeParameter('section', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
requestMethod = 'POST';
const options = this.getNodeParameter('options', i) as IDataObject;
endpoint = `/sections/${sectionId}/addTask`;
requestMethod = 'GET';
endpoint = `/tasks/${taskId}/subtasks`;
body.task = this.getNodeParameter('id', i) as string;
Object.assign(qs, options);
Object.assign(body);
if (qs.opt_fields) {
const fields = qs.opt_fields as string[];
if (fields.includes('*')) {
qs.opt_fields = getTaskFields().map((e) => snakeCase(e)).join(',');
} else {
qs.opt_fields = (qs.opt_fields as string[]).join(',');
}
}
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = { success: true };
responseData = responseData.data;
} else if (operation === 'update') {
// ----------------------------------
// task:update
// ----------------------------------
requestMethod = 'PUT';
endpoint = '/tasks/' + this.getNodeParameter('id', i) as string;
const otherProperties = this.getNodeParameter('otherProperties', i) as IDataObject;
Object.assign(body, otherProperties);
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = responseData.data;
} else if (operation === 'search') {
// ----------------------------------
// tasksearch
// ----------------------------------
const workspaceId = this.getNodeParameter('workspace', i) as string;
requestMethod = 'GET';
endpoint = `/workspaces/${workspaceId}/tasks/search`;
const searchTaskProperties = this.getNodeParameter('searchTaskProperties', i) as IDataObject;
Object.assign(qs, searchTaskProperties);
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = responseData.data;
}
}
if (resource === 'taskComment') {
if (operation === 'add') {
// ----------------------------------
// taskComment:add
// ----------------------------------
const taskId = this.getNodeParameter('id', i) as string;
const isTextHtml = this.getNodeParameter('isTextHtml', i) as boolean;
if (!isTextHtml) {
body.text = this.getNodeParameter('text', i) as string;
} else {
body.html_text = this.getNodeParameter('text', i) as string;
if (returnAll === false) {
const limit = this.getNodeParameter('limit', i) as boolean;
responseData = responseData.splice(0, limit);
}
}
requestMethod = 'POST';
endpoint = `/tasks/${taskId}/stories`;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
Object.assign(body, additionalFields);
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = responseData.data;
}
if (resource === 'task') {
if (operation === 'create') {
// ----------------------------------
// task:create
// ----------------------------------
if (operation === 'remove') {
// ----------------------------------
// taskComment:remove
// ----------------------------------
requestMethod = 'POST';
endpoint = '/tasks';
const commentId = this.getNodeParameter('id', i) as string;
body.name = this.getNodeParameter('name', i) as string;
// body.notes = this.getNodeParameter('taskNotes', 0) as string;
body.workspace = this.getNodeParameter('workspace', i) as string;
requestMethod = 'DELETE';
const otherProperties = this.getNodeParameter('otherProperties', i) as IDataObject;
Object.assign(body, otherProperties);
endpoint = `/stories/${commentId}`;
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = responseData.data;
responseData = { success: true };
}
}
if (resource === 'taskTag') {
if (operation === 'add') {
} else if (operation === 'delete') {
// ----------------------------------
// task:delete
// ----------------------------------
// ----------------------------------
// taskTag:add
// ----------------------------------
requestMethod = 'DELETE';
const taskId = this.getNodeParameter('id', i) as string;
endpoint = '/tasks/' + this.getNodeParameter('id', i) as string;
requestMethod = 'POST';
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
endpoint = `/tasks/${taskId}/addTag`;
responseData = responseData.data;
body.tag = this.getNodeParameter('tag', i) as string;
} else if (operation === 'get') {
// ----------------------------------
// task:get
// ----------------------------------
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
requestMethod = 'GET';
responseData = { success: true };
}
endpoint = '/tasks/' + this.getNodeParameter('id', i) as string;
if (operation === 'remove') {
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
// ----------------------------------
// taskTag:remove
// ----------------------------------
responseData = responseData.data;
const taskId = this.getNodeParameter('id', i) as string;
} else if (operation === 'getAll') {
// ----------------------------------
// task:getAll
// ----------------------------------
requestMethod = 'POST';
const filters = this.getNodeParameter('filters', i) as IDataObject;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
endpoint = `/tasks/${taskId}/removeTag`;
requestMethod = 'GET';
endpoint = `/tasks`;
body.tag = this.getNodeParameter('tag', i) as string;
Object.assign(qs, filters);
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
if (qs.opt_fields) {
const fields = qs.opt_fields as string[];
if (fields.includes('*')) {
qs.opt_fields = getTaskFields().map((e) => snakeCase(e)).join(',');
} else {
qs.opt_fields = (qs.opt_fields as string[]).join(',');
}
}
responseData = { success: true };
}
}
if (resource === 'taskProject') {
if (operation === 'add') {
if (qs.modified_since) {
qs.modified_since = moment.tz(qs.modified_since as string, timezone).format();
}
// ----------------------------------
// taskProject:add
// ----------------------------------
if (qs.completed_since) {
qs.completed_since = moment.tz(qs.completed_since as string, timezone).format();
}
const taskId = this.getNodeParameter('id', i) as string;
if (returnAll) {
responseData = await asanaApiRequestAllItems.call(this, requestMethod, endpoint, body, qs);
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
} else {
qs.limit = this.getNodeParameter('limit', i) as boolean;
requestMethod = 'POST';
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
endpoint = `/tasks/${taskId}/addProject`;
responseData = responseData.data;
}
body.project = this.getNodeParameter('project', i) as string;
} else if (operation === 'move') {
// ----------------------------------
// task:move
// ----------------------------------
Object.assign(body, additionalFields);
const sectionId = this.getNodeParameter('section', i) as string;
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
requestMethod = 'POST';
responseData = { success: true };
}
endpoint = `/sections/${sectionId}/addTask`;
if (operation === 'remove') {
body.task = this.getNodeParameter('id', i) as string;
// ----------------------------------
// taskProject:remove
// ----------------------------------
Object.assign(body);
const taskId = this.getNodeParameter('id', i) as string;
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
requestMethod = 'POST';
responseData = { success: true };
endpoint = `/tasks/${taskId}/removeProject`;
} else if (operation === 'update') {
// ----------------------------------
// task:update
// ----------------------------------
body.project = this.getNodeParameter('project', i) as string;
requestMethod = 'PUT';
endpoint = '/tasks/' + this.getNodeParameter('id', i) as string;
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
const otherProperties = this.getNodeParameter('otherProperties', i) as IDataObject;
Object.assign(body, otherProperties);
responseData = { success: true };
}
}
if (resource === 'user') {
if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
const userId = this.getNodeParameter('userId', i) as string;
responseData = responseData.data;
requestMethod = 'GET';
endpoint = `/users/${userId}`;
} else if (operation === 'search') {
// ----------------------------------
// tasksearch
// ----------------------------------
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = responseData.data;
const workspaceId = this.getNodeParameter('workspace', i) as string;
} else if (operation === 'getAll') {
// ----------------------------------
// getAll
// ----------------------------------
requestMethod = 'GET';
endpoint = `/workspaces/${workspaceId}/tasks/search`;
const workspaceId = this.getNodeParameter('workspace', i) as string;
requestMethod = 'GET';
endpoint = `/workspaces/${workspaceId}/users`;
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = responseData.data;
}
}
if (resource === 'project') {
if (operation === 'get') {
// ----------------------------------
// project:get
// ----------------------------------
const projectId = this.getNodeParameter('id', i) as string;
requestMethod = 'GET';
endpoint = `/projects/${projectId}`;
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = responseData.data;
}
if (operation === 'getAll') {
// ----------------------------------
// project:getAll
// ----------------------------------
const workspaceId = this.getNodeParameter('workspace', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
requestMethod = 'GET';
endpoint = `/projects`;
if (additionalFields.team) {
qs.team = additionalFields.team;
} else {
qs.workspace = workspaceId;
}
if (additionalFields.archived) {
qs.archived = additionalFields.archived as boolean;
}
if (returnAll) {
responseData = await asanaApiRequestAllItems.call(this, requestMethod, endpoint, body, qs);
} else {
qs.limit = this.getNodeParameter('limit', i) as boolean;
const searchTaskProperties = this.getNodeParameter('searchTaskProperties', i) as IDataObject;
Object.assign(qs, searchTaskProperties);
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = responseData.data;
}
}
}
if (resource === 'taskComment') {
if (operation === 'add') {
// ----------------------------------
// taskComment:add
// ----------------------------------
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData);
const taskId = this.getNodeParameter('id', i) as string;
const isTextHtml = this.getNodeParameter('isTextHtml', i) as boolean;
if (!isTextHtml) {
body.text = this.getNodeParameter('text', i) as string;
} else {
body.html_text = this.getNodeParameter('text', i) as string;
}
requestMethod = 'POST';
endpoint = `/tasks/${taskId}/stories`;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
Object.assign(body, additionalFields);
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = responseData.data;
}
if (operation === 'remove') {
// ----------------------------------
// taskComment:remove
// ----------------------------------
const commentId = this.getNodeParameter('id', i) as string;
requestMethod = 'DELETE';
endpoint = `/stories/${commentId}`;
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = { success: true };
}
}
if (resource === 'taskTag') {
if (operation === 'add') {
// ----------------------------------
// taskTag:add
// ----------------------------------
const taskId = this.getNodeParameter('id', i) as string;
requestMethod = 'POST';
endpoint = `/tasks/${taskId}/addTag`;
body.tag = this.getNodeParameter('tag', i) as string;
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = { success: true };
}
if (operation === 'remove') {
// ----------------------------------
// taskTag:remove
// ----------------------------------
const taskId = this.getNodeParameter('id', i) as string;
requestMethod = 'POST';
endpoint = `/tasks/${taskId}/removeTag`;
body.tag = this.getNodeParameter('tag', i) as string;
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = { success: true };
}
}
if (resource === 'taskProject') {
if (operation === 'add') {
// ----------------------------------
// taskProject:add
// ----------------------------------
const taskId = this.getNodeParameter('id', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
requestMethod = 'POST';
endpoint = `/tasks/${taskId}/addProject`;
body.project = this.getNodeParameter('project', i) as string;
Object.assign(body, additionalFields);
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = { success: true };
}
if (operation === 'remove') {
// ----------------------------------
// taskProject:remove
// ----------------------------------
const taskId = this.getNodeParameter('id', i) as string;
requestMethod = 'POST';
endpoint = `/tasks/${taskId}/removeProject`;
body.project = this.getNodeParameter('project', i) as string;
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = { success: true };
}
}
if (resource === 'user') {
if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
const userId = this.getNodeParameter('userId', i) as string;
requestMethod = 'GET';
endpoint = `/users/${userId}`;
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = responseData.data;
} else if (operation === 'getAll') {
// ----------------------------------
// getAll
// ----------------------------------
const workspaceId = this.getNodeParameter('workspace', i) as string;
requestMethod = 'GET';
endpoint = `/workspaces/${workspaceId}/users`;
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = responseData.data;
}
}
if (resource === 'project') {
if (operation === 'get') {
// ----------------------------------
// project:get
// ----------------------------------
const projectId = this.getNodeParameter('id', i) as string;
requestMethod = 'GET';
endpoint = `/projects/${projectId}`;
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = responseData.data;
}
if (operation === 'getAll') {
// ----------------------------------
// project:getAll
// ----------------------------------
const workspaceId = this.getNodeParameter('workspace', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
requestMethod = 'GET';
endpoint = `/projects`;
if (additionalFields.team) {
qs.team = additionalFields.team;
} else {
qs.workspace = workspaceId;
}
if (additionalFields.archived) {
qs.archived = additionalFields.archived as boolean;
}
if (returnAll) {
responseData = await asanaApiRequestAllItems.call(this, requestMethod, endpoint, body, qs);
} else {
qs.limit = this.getNodeParameter('limit', i) as boolean;
responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs);
responseData = responseData.data;
}
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData);
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}

View file

@ -172,39 +172,46 @@ export class AwsLambda implements INodeType {
const returnData: IDataObject[] = [];
for (let i = 0; i < items.length; i++) {
const params = {
FunctionName: this.getNodeParameter('function', i) as string,
InvocationType: this.getNodeParameter('invocationType', i) as string,
Payload: this.getNodeParameter('payload', i) as string,
Qualifier: this.getNodeParameter('qualifier', i) as string,
};
try {
const params = {
FunctionName: this.getNodeParameter('function', i) as string,
InvocationType: this.getNodeParameter('invocationType', i) as string,
Payload: this.getNodeParameter('payload', i) as string,
Qualifier: this.getNodeParameter('qualifier', i) as string,
};
const responseData = await awsApiRequestREST.call(
this,
'lambda',
'POST',
`/2015-03-31/functions/${params.FunctionName}/invocations?Qualifier=${params.Qualifier}`,
params.Payload,
{
'X-Amz-Invocation-Type': params.InvocationType,
'Content-Type': 'application/x-amz-json-1.0',
},
);
const responseData = await awsApiRequestREST.call(
this,
'lambda',
'POST',
`/2015-03-31/functions/${params.FunctionName}/invocations?Qualifier=${params.Qualifier}`,
params.Payload,
{
'X-Amz-Invocation-Type': params.InvocationType,
'Content-Type': 'application/x-amz-json-1.0',
},
);
if (responseData !== null && responseData.errorMessage !== undefined) {
let errorMessage = responseData.errorMessage;
if (responseData !== null && responseData.errorMessage !== undefined) {
let errorMessage = responseData.errorMessage;
if (responseData.stackTrace) {
errorMessage += `\n\nStack trace:\n${responseData.stackTrace}`;
if (responseData.stackTrace) {
errorMessage += `\n\nStack trace:\n${responseData.stackTrace}`;
}
throw new NodeApiError(this.getNode(), responseData);
} else {
returnData.push({
result: responseData,
} as IDataObject);
}
throw new NodeApiError(this.getNode(), responseData);
} else {
returnData.push({
result: responseData,
} as IDataObject);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];

View file

@ -140,15 +140,23 @@ export class AwsSns implements INodeType {
const returnData: IDataObject[] = [];
for (let i = 0; i < items.length; i++) {
const params = [
'TopicArn=' + this.getNodeParameter('topic', i) as string,
'Subject=' + this.getNodeParameter('subject', i) as string,
'Message=' + this.getNodeParameter('message', i) as string,
];
try {
const params = [
'TopicArn=' + this.getNodeParameter('topic', i) as string,
'Subject=' + this.getNodeParameter('subject', i) as string,
'Message=' + this.getNodeParameter('message', i) as string,
];
const responseData = await awsApiRequestSOAP.call(this, 'sns', 'GET', '/?Action=Publish&' + params.join('&'));
returnData.push({MessageId: responseData.PublishResponse.PublishResult.MessageId} as IDataObject);
const responseData = await awsApiRequestSOAP.call(this, 'sns', 'GET', '/?Action=Publish&' + params.join('&'));
returnData.push({MessageId: responseData.PublishResponse.PublishResult.MessageId} as IDataObject);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];

View file

@ -213,63 +213,71 @@ export class AwsComprehend implements INodeType {
const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string;
for (let i = 0; i < items.length; i++) {
if (resource === 'text') {
//https://docs.aws.amazon.com/comprehend/latest/dg/API_DetectDominantLanguage.html
if (operation === 'detectDominantLanguage') {
const text = this.getNodeParameter('text', i) as string;
const simple = this.getNodeParameter('simple', i) as boolean;
try {
if (resource === 'text') {
//https://docs.aws.amazon.com/comprehend/latest/dg/API_DetectDominantLanguage.html
if (operation === 'detectDominantLanguage') {
const text = this.getNodeParameter('text', i) as string;
const simple = this.getNodeParameter('simple', i) as boolean;
const body: IDataObject = {
Text: text,
};
const action = 'Comprehend_20171127.DetectDominantLanguage';
responseData = await awsApiRequestREST.call(this, 'comprehend', 'POST', '', JSON.stringify(body), { 'x-amz-target': action, 'Content-Type': 'application/x-amz-json-1.1' });
const body: IDataObject = {
Text: text,
};
const action = 'Comprehend_20171127.DetectDominantLanguage';
responseData = await awsApiRequestREST.call(this, 'comprehend', 'POST', '', JSON.stringify(body), { 'x-amz-target': action, 'Content-Type': 'application/x-amz-json-1.1' });
if (simple === true) {
responseData = responseData.Languages.reduce((accumulator: { [key: string]: number }, currentValue: IDataObject) => {
accumulator[currentValue.LanguageCode as string] = currentValue.Score as number;
return accumulator;
}, {});
if (simple === true) {
responseData = responseData.Languages.reduce((accumulator: { [key: string]: number }, currentValue: IDataObject) => {
accumulator[currentValue.LanguageCode as string] = currentValue.Score as number;
return accumulator;
}, {});
}
}
//https://docs.aws.amazon.com/comprehend/latest/dg/API_DetectSentiment.html
if (operation === 'detectSentiment') {
const action = 'Comprehend_20171127.DetectSentiment';
const text = this.getNodeParameter('text', i) as string;
const languageCode = this.getNodeParameter('languageCode', i) as string;
const body: IDataObject = {
Text: text,
LanguageCode: languageCode,
};
responseData = await awsApiRequestREST.call(this, 'comprehend', 'POST', '', JSON.stringify(body), { 'x-amz-target': action, 'Content-Type': 'application/x-amz-json-1.1' });
}
//https://docs.aws.amazon.com/comprehend/latest/dg/API_DetectEntities.html
if (operation === 'detectEntities') {
const action = 'Comprehend_20171127.DetectEntities';
const text = this.getNodeParameter('text', i) as string;
const languageCode = this.getNodeParameter('languageCode', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IDataObject = {
Text: text,
LanguageCode: languageCode,
};
if (additionalFields.endpointArn) {
body.EndpointArn = additionalFields.endpointArn;
}
responseData = await awsApiRequestREST.call(this, 'comprehend', 'POST', '', JSON.stringify(body), { 'x-amz-target': action, 'Content-Type': 'application/x-amz-json-1.1' });
responseData = responseData.Entities;
}
}
//https://docs.aws.amazon.com/comprehend/latest/dg/API_DetectSentiment.html
if (operation === 'detectSentiment') {
const action = 'Comprehend_20171127.DetectSentiment';
const text = this.getNodeParameter('text', i) as string;
const languageCode = this.getNodeParameter('languageCode', i) as string;
const body: IDataObject = {
Text: text,
LanguageCode: languageCode,
};
responseData = await awsApiRequestREST.call(this, 'comprehend', 'POST', '', JSON.stringify(body), { 'x-amz-target': action, 'Content-Type': 'application/x-amz-json-1.1' });
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
}
//https://docs.aws.amazon.com/comprehend/latest/dg/API_DetectEntities.html
if (operation === 'detectEntities') {
const action = 'Comprehend_20171127.DetectEntities';
const text = this.getNodeParameter('text', i) as string;
const languageCode = this.getNodeParameter('languageCode', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IDataObject = {
Text: text,
LanguageCode: languageCode,
};
if (additionalFields.endpointArn) {
body.EndpointArn = additionalFields.endpointArn;
}
responseData = await awsApiRequestREST.call(this, 'comprehend', 'POST', '', JSON.stringify(body), { 'x-amz-target': action, 'Content-Type': 'application/x-amz-json-1.1' });
responseData = responseData.Entities;
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];

View file

@ -0,0 +1,374 @@
import {
IExecuteFunctions,
} from 'n8n-core';
import {
IDataObject,
ILoadOptionsFunctions,
INodeExecutionData,
INodeType,
INodeTypeDescription,
NodeParameterValue,
} from 'n8n-workflow';
import {
awsApiRequest,
awsApiRequestAllItems,
} from './GenericFunctions';
import {
itemFields,
itemOperations,
} from './ItemDescription';
import {
FieldsUiValues,
IAttributeNameUi,
IAttributeValueUi,
IRequestBody,
PutItemUi,
} from './types';
import {
adjustExpressionAttributeName,
adjustExpressionAttributeValues,
adjustPutItem,
decodeItem,
simplify,
} from './utils';
export class AwsDynamoDB implements INodeType {
description: INodeTypeDescription = {
displayName: 'AWS DynamoDB',
name: 'awsDynamoDb',
icon: 'file:dynamodb.svg',
group: ['transform'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Consume the AWS DynamoDB API',
defaults: {
name: 'AWS DynamoDB',
color: '#2273b9',
},
inputs: ['main'],
outputs: ['main'],
credentials: [
{
name: 'aws',
required: true,
},
],
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
options: [
{
name: 'Item',
value: 'item',
},
],
default: 'item',
},
...itemOperations,
...itemFields,
],
};
methods = {
loadOptions: {
async getTables(this: ILoadOptionsFunctions) {
const headers = {
'Content-Type': 'application/x-amz-json-1.0',
'X-Amz-Target': 'DynamoDB_20120810.ListTables',
};
const responseData = await awsApiRequest.call(this, 'dynamodb', 'POST', '/', {}, headers);
return responseData.TableNames.map((table: string) => ({ name: table, value: table }));
},
},
};
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const items = this.getInputData();
const resource = this.getNodeParameter('resource', 0);
const operation = this.getNodeParameter('operation', 0);
let responseData;
const returnData: IDataObject[] = [];
for (let i = 0; i < items.length; i++) {
try {
if (resource === 'item') {
if (operation === 'upsert') {
// ----------------------------------
// upsert
// ----------------------------------
// https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html
const eavUi = this.getNodeParameter('additionalFields.eavUi.eavValues', i, []) as IAttributeValueUi[];
const conditionExpession = this.getNodeParameter('conditionExpression', i, '') as string;
const eanUi = this.getNodeParameter('additionalFields.eanUi.eanValues', i, []) as IAttributeNameUi[];
const body: IRequestBody = {
TableName: this.getNodeParameter('tableName', i) as string,
};
const expressionAttributeValues = adjustExpressionAttributeValues(eavUi);
if (Object.keys(expressionAttributeValues).length) {
body.ExpressionAttributeValues = expressionAttributeValues;
}
const expressionAttributeName = adjustExpressionAttributeName(eanUi);
if (Object.keys(expressionAttributeName).length) {
body.expressionAttributeNames = expressionAttributeName;
}
if (conditionExpession) {
body.ConditionExpression = conditionExpession;
}
const dataToSend = this.getNodeParameter('dataToSend', 0) as 'defineBelow' | 'autoMapInputData';
const item: { [key: string]: string } = {};
if (dataToSend === 'autoMapInputData') {
const incomingKeys = Object.keys(items[i].json);
const rawInputsToIgnore = this.getNodeParameter('inputsToIgnore', i) as string;
const inputsToIgnore = rawInputsToIgnore.split(',').map(c => c.trim());
for (const key of incomingKeys) {
if (inputsToIgnore.includes(key)) continue;
item[key] = items[i].json[key] as string;
}
body.Item = adjustPutItem(item as PutItemUi);
} else {
const fields = this.getNodeParameter('fieldsUi.fieldValues', i, []) as FieldsUiValues;
fields.forEach(({ fieldId, fieldValue }) => item[fieldId] = fieldValue);
body.Item = adjustPutItem(item as PutItemUi);
}
const headers = {
'Content-Type': 'application/x-amz-json-1.0',
'X-Amz-Target': 'DynamoDB_20120810.PutItem',
};
responseData = await awsApiRequest.call(this, 'dynamodb', 'POST', '/', body, headers);
responseData = item;
} else if (operation === 'delete') {
// ----------------------------------
// delete
// ----------------------------------
// https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DeleteItem.html
// tslint:disable-next-line: no-any
const body: { [key: string]: any } = {
TableName: this.getNodeParameter('tableName', i) as string,
Key: {},
ReturnValues: this.getNodeParameter('returnValues', 0) as string,
};
const eavUi = this.getNodeParameter('additionalFields.eavUi.eavValues', i, []) as IAttributeValueUi[];
const eanUi = this.getNodeParameter('additionalFields.eanUi.eanValues', i, []) as IAttributeNameUi[];
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const simple = this.getNodeParameter('simple', 0, false) as boolean;
const items = this.getNodeParameter('keysUi.keyValues', i, []) as [{ key: string, type: string, value: string }];
for (const item of items) {
let value = item.value as NodeParameterValue;
// All data has to get send as string even numbers
// @ts-ignore
value = ![null, undefined].includes(value) ? value?.toString() : '';
body.Key[item.key as string] = { [item.type as string]: value };
}
const expressionAttributeValues = adjustExpressionAttributeValues(eavUi);
if (Object.keys(expressionAttributeValues).length) {
body.ExpressionAttributeValues = expressionAttributeValues;
}
const expressionAttributeName = adjustExpressionAttributeName(eanUi);
if (Object.keys(expressionAttributeName).length) {
body.expressionAttributeNames = expressionAttributeName;
}
const headers = {
'Content-Type': 'application/x-amz-json-1.0',
'X-Amz-Target': 'DynamoDB_20120810.DeleteItem',
};
if (additionalFields.conditionExpression) {
body.ConditionExpression = additionalFields.conditionExpression as string;
}
responseData = await awsApiRequest.call(this, 'dynamodb', 'POST', '/', body, headers);
if (!Object.keys(responseData).length) {
responseData = { success: true };
} else if (simple === true) {
responseData = decodeItem(responseData.Attributes);
}
} else if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
// https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_GetItem.html
const tableName = this.getNodeParameter('tableName', 0) as string;
const simple = this.getNodeParameter('simple', 0, false) as boolean;
const select = this.getNodeParameter('select', 0) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const eanUi = this.getNodeParameter('additionalFields.eanUi.eanValues', i, []) as IAttributeNameUi[];
// tslint:disable-next-line: no-any
const body: { [key: string]: any } = {
TableName: tableName,
Key: {},
Select: select,
};
Object.assign(body, additionalFields);
const expressionAttributeName = adjustExpressionAttributeName(eanUi);
if (Object.keys(expressionAttributeName).length) {
body.expressionAttributeNames = expressionAttributeName;
}
if (additionalFields.readType) {
body.ConsistentRead = additionalFields.readType === 'stronglyConsistentRead';
}
if (additionalFields.projectionExpression) {
body.ProjectionExpression = additionalFields.projectionExpression as string;
}
const items = this.getNodeParameter('keysUi.keyValues', i, []) as IDataObject[];
for (const item of items) {
let value = item.value as NodeParameterValue;
// All data has to get send as string even numbers
// @ts-ignore
value = ![null, undefined].includes(value) ? value?.toString() : '';
body.Key[item.key as string] = { [item.type as string]: value };
}
const headers = {
'X-Amz-Target': 'DynamoDB_20120810.GetItem',
'Content-Type': 'application/x-amz-json-1.0',
};
responseData = await awsApiRequest.call(this, 'dynamodb', 'POST', '/', body, headers);
responseData = responseData.Item;
if (simple && responseData) {
responseData = decodeItem(responseData);
}
} else if (operation === 'getAll') {
// ----------------------------------
// getAll
// ----------------------------------
// https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html
const eavUi = this.getNodeParameter('eavUi.eavValues', i, []) as IAttributeValueUi[];
const simple = this.getNodeParameter('simple', 0, false) as boolean;
const select = this.getNodeParameter('select', 0) as string;
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const eanUi = this.getNodeParameter('additionalFields.eanUi.eanValues', i, []) as IAttributeNameUi[];
const body: IRequestBody = {
TableName: this.getNodeParameter('tableName', i) as string,
KeyConditionExpression: this.getNodeParameter('keyConditionExpression', i) as string,
ExpressionAttributeValues: adjustExpressionAttributeValues(eavUi),
};
const {
indexName,
projectionExpression,
} = this.getNodeParameter('options', i) as {
indexName: string;
projectionExpression: string;
};
const expressionAttributeName = adjustExpressionAttributeName(eanUi);
if (Object.keys(expressionAttributeName).length) {
body.expressionAttributeNames = expressionAttributeName;
}
if (indexName) {
body.IndexName = indexName;
}
if (projectionExpression && select !== 'COUNT') {
body.ProjectionExpression = projectionExpression;
}
if (select) {
body.Select = select;
}
const headers = {
'Content-Type': 'application/json',
'X-Amz-Target': 'DynamoDB_20120810.Query',
};
if (returnAll === true && select !== 'COUNT') {
responseData = await awsApiRequestAllItems.call(this, 'dynamodb', 'POST', '/', body, headers);
} else {
body.Limit = this.getNodeParameter('limit', 0, 1) as number;
responseData = await awsApiRequest.call(this, 'dynamodb', 'POST', '/', body, headers);
if (select !== 'COUNT') {
responseData = responseData.Items;
}
}
if (simple === true) {
responseData = responseData.map(simplify);
}
}
Array.isArray(responseData)
? returnData.push(...responseData)
: returnData.push(responseData);
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];
}
}

View file

@ -0,0 +1,108 @@
import {
URL,
} from 'url';
import {
sign,
} from 'aws4';
import {
IExecuteFunctions,
IHookFunctions,
ILoadOptionsFunctions,
IWebhookFunctions,
} from 'n8n-core';
import {
ICredentialDataDecryptedObject,
IDataObject,
INodeExecutionData,
} from 'n8n-workflow';
import {
IRequestBody,
} from './types';
function getEndpointForService(service: string, credentials: ICredentialDataDecryptedObject): string {
let endpoint;
if (service === 'lambda' && credentials.lambdaEndpoint) {
endpoint = credentials.lambdaEndpoint;
} else if (service === 'sns' && credentials.snsEndpoint) {
endpoint = credentials.snsEndpoint;
} else {
endpoint = `https://${service}.${credentials.region}.amazonaws.com`;
}
return (endpoint as string).replace('{region}', credentials.region as string);
}
export async function awsApiRequest(this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions | IWebhookFunctions, service: string, method: string, path: string, body?: object | IRequestBody, headers?: object): Promise<any> { // tslint:disable-line:no-any
const credentials = this.getCredentials('aws');
if (credentials === undefined) {
throw new Error('No credentials got returned!');
}
// Concatenate path and instantiate URL object so it parses correctly query strings
const endpoint = new URL(getEndpointForService(service, credentials) + path);
const options = sign({
uri: endpoint,
service,
region: credentials.region,
method,
path: '/',
headers: { ...headers },
body: JSON.stringify(body),
}, {
accessKeyId: credentials.accessKeyId,
secretAccessKey: credentials.secretAccessKey,
});
try {
return JSON.parse(await this.helpers.request!(options));
} catch (error) {
const errorMessage = (error.response && error.response.body.message) || (error.response && error.response.body.Message) || error.message;
if (error.statusCode === 403) {
if (errorMessage === 'The security token included in the request is invalid.') {
throw new Error('The AWS credentials are not valid!');
} else if (errorMessage.startsWith('The request signature we calculated does not match the signature you provided')) {
throw new Error('The AWS credentials are not valid!');
}
}
throw new Error(`AWS error response [${error.statusCode}]: ${errorMessage}`);
}
}
export async function awsApiRequestAllItems(this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions | IWebhookFunctions, service: string, method: string, path: string, body?: IRequestBody, headers?: object): Promise<any> { // tslint:disable-line:no-any
const returnData: IDataObject[] = [];
let responseData;
do {
responseData = await awsApiRequest.call(this, service, method, path, body, headers);
if (responseData.LastEvaluatedKey) {
body!.ExclusiveStartKey = responseData.LastEvaluatedKey;
}
returnData.push(...responseData.Items);
} while (
responseData.LastEvaluatedKey !== undefined
);
return returnData;
}
export function copyInputItem(item: INodeExecutionData, properties: string[]): IDataObject {
// Prepare the data to insert and copy it to be returned
let newItem: IDataObject;
newItem = {};
for (const property of properties) {
if (item.json[property] === undefined) {
newItem[property] = null;
} else {
newItem[property] = JSON.parse(JSON.stringify(item.json[property]));
}
}
return newItem;
}

View file

@ -0,0 +1,920 @@
import {
INodeProperties,
} from 'n8n-workflow';
export const itemOperations = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
displayOptions: {
show: {
resource: [
'item',
],
},
},
options: [
{
name: 'Create or Update',
value: 'upsert',
description: 'Create a new record, or update the current one if it already exists (upsert/put)',
},
{
name: 'Delete',
value: 'delete',
description: 'Delete an item',
},
{
name: 'Get',
value: 'get',
description: 'Get an item',
},
{
name: 'Get All',
value: 'getAll',
description: 'Get all items',
},
],
default: 'upsert',
},
] as INodeProperties[];
export const itemFields = [
// ----------------------------------
// all
// ----------------------------------
{
displayName: 'Table Name',
name: 'tableName',
description: 'Table to operate on',
type: 'options',
required: true,
displayOptions: {
show: {
resource: [
'item',
],
},
},
default: [],
typeOptions: {
loadOptionsMethod: 'getTables',
},
},
// ----------------------------------
// upsert
// ----------------------------------
{
displayName: 'Data to Send',
name: 'dataToSend',
type: 'options',
options: [
{
name: 'Auto-map Input Data to Columns',
value: 'autoMapInputData',
description: 'Use when node input properties match destination column names',
},
{
name: 'Define Below for Each Column',
value: 'defineBelow',
description: 'Set the value for each destination column',
},
],
displayOptions: {
show: {
operation: [
'upsert',
],
},
},
default: 'defineBelow',
description: 'Whether to insert the input data this node receives in the new row',
},
{
displayName: 'Inputs to Ignore',
name: 'inputsToIgnore',
type: 'string',
displayOptions: {
show: {
operation: [
'upsert',
],
dataToSend: [
'autoMapInputData',
],
},
},
default: '',
required: false,
description: 'List of input properties to avoid sending, separated by commas. Leave empty to send all properties.',
placeholder: 'Enter properties...',
},
{
displayName: 'Fields to Send',
name: 'fieldsUi',
placeholder: 'Add Field',
type: 'fixedCollection',
typeOptions: {
multipleValueButtonText: 'Add Field to Send',
multipleValues: true,
},
displayOptions: {
show: {
operation: [
'upsert',
],
dataToSend: [
'defineBelow',
],
},
},
default: {},
options: [
{
displayName: 'Field',
name: 'fieldValues',
values: [
{
displayName: 'Field ID',
name: 'fieldId',
type: 'string',
default: '',
},
{
displayName: 'Field Value',
name: 'fieldValue',
type: 'string',
default: '',
},
],
},
],
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: [
'item',
],
operation: [
'upsert',
],
},
},
options: [
{
displayName: 'Expression Attribute Values',
name: 'eavUi',
description: 'Substitution tokens for attribute names in an expression.<br>Only needed when the parameter "condition expression" is set',
placeholder: 'Add Attribute Value',
type: 'fixedCollection',
default: '',
required: true,
typeOptions: {
multipleValues: true,
minValue: 1,
},
options: [
{
name: 'eavValues',
displayName: 'Expression Attribute Vaue',
values: [
{
displayName: 'Attribute',
name: 'attribute',
type: 'string',
default: '',
},
{
displayName: 'Type',
name: 'type',
type: 'options',
options: [
{
name: 'Number',
value: 'N',
},
{
name: 'String',
value: 'S',
},
],
default: 'S',
},
{
displayName: 'Value',
name: 'value',
type: 'string',
default: '',
},
],
},
],
},
{
displayName: 'Condition Expression',
name: 'conditionExpression',
type: 'string',
default: '',
description: 'A condition that must be satisfied in order for a conditional upsert to succeed. <a target="_blank" href="https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html">View details</a>',
},
{
displayName: 'Expression Attribute Names',
name: 'eanUi',
placeholder: 'Add Expression',
type: 'fixedCollection',
default: '',
typeOptions: {
multipleValues: true,
},
options: [
{
name: 'eanValues',
displayName: 'Expression',
values: [
{
displayName: 'Key',
name: 'key',
type: 'string',
default: '',
},
{
displayName: 'Value',
name: 'value',
type: 'string',
default: '',
},
],
},
],
description: 'One or more substitution tokens for attribute names in an expression. <a target="_blank" href="https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html">View details</a>',
},
],
},
// ----------------------------------
// delete
// ----------------------------------
{
displayName: 'Return',
name: 'returnValues',
type: 'options',
displayOptions: {
show: {
resource: [
'item',
],
operation: [
'delete',
],
},
},
options: [
{
name: 'Attribute Values',
value: 'ALL_OLD',
description: 'The content of the old item is returned',
},
{
name: 'Nothing',
value: 'NONE',
description: 'Nothing is returned',
},
],
default: 'NONE',
description: 'Use ReturnValues if you want to get the item attributes as they appeared before they were deleted',
},
{
displayName: 'Keys',
name: 'keysUi',
type: 'fixedCollection',
placeholder: 'Add Key',
default: {},
typeOptions: {
multipleValues: true,
},
displayOptions: {
show: {
resource: [
'item',
],
operation: [
'delete',
],
},
},
options: [
{
displayName: 'Key',
name: 'keyValues',
values: [
{
displayName: 'Key',
name: 'key',
type: 'string',
default: '',
},
{
displayName: 'Type',
name: 'type',
type: 'options',
options: [
{
name: 'Binary',
value: 'B',
},
{
name: 'Number',
value: 'N',
},
{
name: 'String',
value: 'S',
},
],
default: 'S',
},
{
displayName: 'Value',
name: 'value',
type: 'string',
default: '',
},
],
},
],
description: 'Item\'s primary key. For example, with a simple primary key, you only need to provide a value for the partition key.<br>For a composite primary key, you must provide values for both the partition key and the sort key',
},
{
displayName: 'Simple',
name: 'simple',
type: 'boolean',
displayOptions: {
show: {
resource: [
'item',
],
operation: [
'delete',
],
returnValues: [
'ALL_OLD',
],
},
},
default: true,
description: 'Whether to return a simplified version of the response instead of the raw data',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: [
'item',
],
operation: [
'delete',
],
},
},
options: [
{
displayName: 'Condition Expression',
name: 'conditionExpression',
type: 'string',
default: '',
description: 'A condition that must be satisfied in order for a conditional delete to succeed',
},
{
displayName: 'Expression Attribute Names',
name: 'eanUi',
placeholder: 'Add Expression',
type: 'fixedCollection',
default: '',
typeOptions: {
multipleValues: true,
},
options: [
{
name: 'eanValues',
displayName: 'Expression',
values: [
{
displayName: 'Key',
name: 'key',
type: 'string',
default: '',
},
{
displayName: 'Value',
name: 'value',
type: 'string',
default: '',
},
],
},
],
description: 'One or more substitution tokens for attribute names in an expression. Check <a href="https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html" target="_blank">Info</a>',
},
{
displayName: 'Expression Attribute Values',
name: 'expressionAttributeUi',
description: 'Substitution tokens for attribute names in an expression.<br>Only needed when the parameter "condition expression" is set',
placeholder: 'Add Attribute Value',
type: 'fixedCollection',
default: '',
required: true,
typeOptions: {
multipleValues: true,
minValue: 1,
},
options: [
{
name: 'expressionAttributeValues',
displayName: 'Expression Attribute Vaue',
values: [
{
displayName: 'Attribute',
name: 'attribute',
type: 'string',
default: '',
},
{
displayName: 'Type',
name: 'type',
type: 'options',
options: [
{
name: 'Number',
value: 'N',
},
{
name: 'String',
value: 'S',
},
],
default: 'S',
},
{
displayName: 'Value',
name: 'value',
type: 'string',
default: '',
},
],
},
],
},
],
},
// ----------------------------------
// get
// ----------------------------------
{
displayName: 'Select',
name: 'select',
type: 'options',
displayOptions: {
show: {
resource: [
'item',
],
operation: [
'get',
],
},
},
options: [
{
name: 'All Attributes',
value: 'ALL_ATTRIBUTES',
},
{
name: 'All Projected Attributes',
value: 'ALL_PROJECTED_ATTRIBUTES',
},
{
name: 'Specific Attributes',
value: 'SPECIFIC_ATTRIBUTES',
description: 'Select them in Attributes to Select under Additional Fields',
},
],
default: 'ALL_ATTRIBUTES',
},
{
displayName: 'Simple',
name: 'simple',
type: 'boolean',
displayOptions: {
show: {
resource: [
'item',
],
operation: [
'get',
],
select: [
'ALL_PROJECTED_ATTRIBUTES',
'ALL_ATTRIBUTES',
],
},
},
default: true,
description: 'Whether to return a simplified version of the response instead of the raw data',
},
{
displayName: 'Keys',
name: 'keysUi',
type: 'fixedCollection',
placeholder: 'Add Key',
default: {},
typeOptions: {
multipleValues: true,
},
displayOptions: {
show: {
resource: [
'item',
],
operation: [
'get',
],
},
},
options: [
{
displayName: 'Key',
name: 'keyValues',
values: [
{
displayName: 'Key',
name: 'key',
type: 'string',
default: '',
},
{
displayName: 'Type',
name: 'type',
type: 'options',
options: [
{
name: 'Binary',
value: 'B',
},
{
name: 'Number',
value: 'N',
},
{
name: 'String',
value: 'S',
},
],
default: 'S',
},
{
displayName: 'Value',
name: 'value',
type: 'string',
default: '',
},
],
},
],
description: 'Item\'s primary key. For example, with a simple primary key, you only need to provide a value for the partition key.<br>For a composite primary key, you must provide values for both the partition key and the sort key',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: [
'item',
],
operation: [
'get',
],
},
},
options: [
{
displayName: 'Attributes to Select',
name: 'projectionExpression',
type: 'string',
placeholder: 'id, name',
default: '',
},
{
displayName: 'Expression Attribute Names',
name: 'eanUi',
placeholder: 'Add Expression',
type: 'fixedCollection',
default: '',
typeOptions: {
multipleValues: true,
},
options: [
{
name: 'eanValues',
displayName: 'Expression',
values: [
{
displayName: 'Key',
name: 'key',
type: 'string',
default: '',
},
{
displayName: 'Value',
name: 'value',
type: 'string',
default: '',
},
],
},
],
description: 'One or more substitution tokens for attribute names in an expression. <a href="https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html" target="_blank">View details</a>',
},
{
displayName: 'Read Type',
name: 'readType',
type: 'options',
options: [
{
name: 'Strongly consistent read',
value: 'stronglyConsistentRead',
},
{
name: 'Eventually consistent read',
value: 'eventuallyConsistentRead',
},
],
default: 'eventuallyConsistentRead',
description: 'Type of read to perform on the table. <a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadConsistency.html" target="_blank">View details</a>',
},
],
},
// ----------------------------------
// Get All
// ----------------------------------
{
displayName: 'Key Condition Expression',
name: 'keyConditionExpression',
description: 'Condition to determine the items to be retrieved. The condition must perform an equality test<br>on a single partition key value, in this format: <code>partitionKeyName = :partitionkeyval</code>',
placeholder: 'id = :id',
default: '',
type: 'string',
required: true,
displayOptions: {
show: {
resource: [
'item',
],
operation: [
'getAll',
],
},
},
},
{
displayName: 'Expression Attribute Values',
name: 'eavUi',
description: 'Substitution tokens for attribute names in an expression',
placeholder: 'Add Attribute Value',
type: 'fixedCollection',
default: '',
required: true,
typeOptions: {
multipleValues: true,
minValue: 1,
},
displayOptions: {
show: {
resource: [
'item',
],
operation: [
'getAll',
],
},
},
options: [
{
name: 'eavValues',
displayName: 'Expression Attribute Vaue',
values: [
{
displayName: 'Attribute',
name: 'attribute',
type: 'string',
default: '',
},
{
displayName: 'Type',
name: 'type',
type: 'options',
options: [
{
name: 'Number',
value: 'N',
},
{
name: 'String',
value: 'S',
},
],
default: 'S',
},
{
displayName: 'Value',
name: 'value',
type: 'string',
default: '',
},
],
},
],
},
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
resource: [
'item',
],
operation: [
'getAll',
],
},
},
default: false,
description: 'Whether to return all results or only up to a given limit',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
displayOptions: {
show: {
operation: [
'getAll',
],
returnAll: [
false,
],
},
},
typeOptions: {
minValue: 1,
maxValue: 100,
},
default: 50,
description: 'How many results to return',
},
{
displayName: 'Select',
name: 'select',
type: 'options',
displayOptions: {
show: {
resource: [
'item',
],
operation: [
'getAll',
],
},
},
options: [
{
name: 'All Attributes',
value: 'ALL_ATTRIBUTES',
},
{
name: 'All Projected Attributes',
value: 'ALL_PROJECTED_ATTRIBUTES',
},
{
name: 'Count',
value: 'COUNT',
},
{
name: 'Specific Attributes',
value: 'SPECIFIC_ATTRIBUTES',
description: 'Select them in Attributes to Select under Additional Fields',
},
],
default: 'ALL_ATTRIBUTES',
},
{
displayName: 'Simple',
name: 'simple',
type: 'boolean',
displayOptions: {
show: {
resource: [
'item',
],
operation: [
'getAll',
],
select: [
'ALL_PROJECTED_ATTRIBUTES',
'ALL_ATTRIBUTES',
'SPECIFIC_ATTRIBUTES',
],
},
},
default: true,
description: 'Whether to return a simplified version of the response instead of the raw data',
},
{
displayName: 'Options',
name: 'options',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: [
'item',
],
operation: [
'getAll',
],
},
},
options: [
{
displayName: 'Index Name',
name: 'indexName',
description: 'Name of the index to query. It can be any <br>secondary local or global index on the table.',
type: 'string',
default: '',
},
{
displayName: 'Attributes to Select',
name: 'projectionExpression',
type: 'string',
default: '',
description: 'Text that identifies one or more attributes to retrieve from the table.<br>These attributes can include scalars, sets, or elements of a JSON document. The attributes<br>in the expression must be separated by commas',
},
{
displayName: 'Filter Expression',
name: 'filterExpression',
type: 'string',
default: '',
description: 'Text that contains conditions that DynamoDB applies after the Query operation,<br>but before the data is returned. Items that do not satisfy the FilterExpression criteria</br>are not returned',
},
{
displayName: 'Expression Attribute Names',
name: 'eanUi',
placeholder: 'Add Expression',
type: 'fixedCollection',
default: '',
typeOptions: {
multipleValues: true,
},
options: [
{
name: 'eanValues',
displayName: 'Expression',
values: [
{
displayName: 'Key',
name: 'key',
type: 'string',
default: '',
},
{
displayName: 'Value',
name: 'value',
type: 'string',
default: '',
},
],
},
],
description: 'One or more substitution tokens for attribute names in an expression. Check <a target="_blank" href="https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html">Info</a>',
},
],
},
] as INodeProperties[];

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg viewBox="-40 -35 340 340" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid">
<g>
<path d="M165.258,288.501 L168.766,288.501 L226.027,259.867 L226.98,258.52 L226.98,29.964 L226.027,28.61 L168.766,0 L165.215,0 L165.258,288.501" fill="#5294CF"/>
<path d="M90.741,288.501 L87.184,288.501 L29.972,259.867 L28.811,257.87 L28.222,31.128 L29.972,28.61 L87.184,0 L90.785,0 L90.741,288.501" fill="#1F5B98"/>
<path d="M87.285,0 L168.711,0 L168.711,288.501 L87.285,288.501 L87.285,0 Z" fill="#2D72B8"/>
<path d="M256,137.769 L254.065,137.34 L226.437,134.764 L226.027,134.968 L168.715,132.676 L87.285,132.676 L29.972,134.968 L29.972,91.264 L29.912,91.296 L29.972,91.168 L87.285,77.888 L168.715,77.888 L226.027,91.168 L247.096,102.367 L247.096,95.167 L256,94.193 L255.078,92.395 L226.886,72.236 L226.027,72.515 L168.715,54.756 L87.285,54.756 L29.972,72.515 L29.972,28.61 L0,63.723 L0,94.389 L0.232,94.221 L8.904,95.167 L8.904,102.515 L0,107.28 L0,137.793 L0.232,137.769 L8.904,137.897 L8.904,150.704 L1.422,150.816 L0,150.68 L0,181.205 L8.904,185.993 L8.904,193.426 L0.373,194.368 L0,194.088 L0,224.749 L29.972,259.867 L29.972,215.966 L87.285,233.725 L168.715,233.725 L226.196,215.914 L226.96,216.249 L254.781,196.387 L256,194.408 L247.096,193.426 L247.096,186.142 L245.929,185.676 L226.886,195.941 L226.196,197.381 L168.715,210.584 L168.715,210.6 L87.285,210.6 L87.285,210.584 L29.972,197.325 L29.972,153.461 L87.285,155.745 L87.285,155.801 L168.715,155.801 L226.027,153.461 L227.332,154.061 L254.111,151.755 L256,150.832 L247.096,150.704 L247.096,137.897 L256,137.769" fill="#1A476F"/>
<path d="M226.027,215.966 L226.027,259.867 L256,224.749 L256,194.288 L226.2,215.914 L226.027,215.966" fill="#2D72B8"/>
<path d="M226.027,197.421 L226.2,197.381 L256,181.353 L256,150.704 L226.027,153.461 L226.027,197.421" fill="#2D72B8"/>
<path d="M226.2,91.208 L226.027,91.168 L226.027,134.968 L256,137.769 L256,107.135 L226.2,91.208" fill="#2D72B8"/>
<path d="M226.2,72.687 L256,94.193 L256,63.731 L226.027,28.61 L226.027,72.515 L226.2,72.575 L226.2,72.687" fill="#2D72B8"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -0,0 +1,79 @@
export interface IRequestBody {
[key: string]: string | IAttributeValue | undefined | boolean | object | number;
TableName: string;
Key?: object;
IndexName?: string;
ProjectionExpression?: string;
KeyConditionExpression?: string;
ExpressionAttributeValues?: IAttributeValue;
ConsistentRead?: boolean;
FilterExpression?: string;
Limit?: number;
ExclusiveStartKey?: IAttributeValue;
}
export interface IAttributeValue {
[attribute: string]: IAttributeValueValue;
}
interface IAttributeValueValue {
[type: string]: string | string[] | IAttributeValue[];
}
export interface IAttributeValueUi {
attribute: string;
type: AttributeValueType;
value: string;
}
export interface IAttributeNameUi {
key: string;
value: string;
}
type AttributeValueType =
| 'B' // binary
| 'BOOL' // boolean
| 'BS' // binary set
| 'L' // list
| 'M' // map
| 'N' // number
| 'NULL'
| 'NS' // number set
| 'S' // string
| 'SS'; // string set
export type PartitionKey = {
details: {
name: string;
type: string;
value: string;
},
};
export enum EAttributeValueType {
S = 'S', SS = 'SS', M = 'M', L = 'L', NS = 'NS', N = 'N', BOOL = 'BOOL', B = 'B', BS = 'BS', NULL = 'NULL',
}
export interface IExpressionAttributeValue {
attribute: string;
type: EAttributeValueType;
value: string;
}
export type FieldsUiValues = Array<{
fieldId: string;
fieldValue: string;
}>;
export type PutItemUi = {
attribute: string;
type: 'S' | 'N';
value: string;
};
export type AdjustedPutItem = {
[attribute: string]: {
[type: string]: string
}
};

View file

@ -0,0 +1,134 @@
import {
IDataObject,
INodeExecutionData,
} from 'n8n-workflow';
import {
AdjustedPutItem,
AttributeValueType,
EAttributeValueType,
IAttributeNameUi,
IAttributeValue,
IAttributeValueUi,
IAttributeValueValue,
PutItemUi,
} from './types';
const addColon = (attribute: string) => attribute = attribute.charAt(0) === ':' ? attribute : `:${attribute}`;
const addPound = (key: string) => key = key.charAt(0) === '#' ? key : `#${key}`;
export function adjustExpressionAttributeValues(eavUi: IAttributeValueUi[]) {
const eav: IAttributeValue = {};
eavUi.forEach(({ attribute, type, value }) => {
eav[addColon(attribute)] = { [type]: value } as IAttributeValueValue;
});
return eav;
}
export function adjustExpressionAttributeName(eanUi: IAttributeNameUi[]) {
// tslint:disable-next-line: no-any
const ean: { [key: string]: any } = {};
eanUi.forEach(({ key, value }) => {
ean[addPound(key)] = { value } as IAttributeValueValue;
});
return ean;
}
export function adjustPutItem(putItemUi: PutItemUi) {
const adjustedPutItem: AdjustedPutItem = {};
Object.entries(putItemUi).forEach(([attribute, value]) => {
let type: string;
if (typeof value === 'boolean') {
type = 'BOOL';
} else if (typeof value === 'object' && !Array.isArray(value) && value !== null) {
type = 'M';
// @ts-ignore
} else if (isNaN(value)) {
type = 'S';
} else {
type = 'N';
}
adjustedPutItem[attribute] = { [type]: value.toString() };
});
return adjustedPutItem;
}
export function simplify(item: IAttributeValue): IDataObject {
const output: IDataObject = {};
for (const [attribute, value] of Object.entries(item)) {
const [type, content] = Object.entries(value)[0] as [AttributeValueType, string];
output[attribute] = decodeAttribute(type, content);
}
return output;
}
function decodeAttribute(type: AttributeValueType, attribute: string) {
switch (type) {
case 'BOOL':
return Boolean(attribute);
case 'N':
return Number(attribute);
case 'S':
return String(attribute);
case 'SS':
case 'NS':
return attribute;
default:
return null;
}
}
// tslint:disable-next-line: no-any
export function validateJSON(input: any): object {
try {
return JSON.parse(input);
} catch (error) {
throw new Error('Items must be a valid JSON');
}
}
export function copyInputItem(item: INodeExecutionData, properties: string[]): IDataObject {
// Prepare the data to insert and copy it to be returned
let newItem: IDataObject;
newItem = {};
for (const property of properties) {
if (item.json[property] === undefined) {
newItem[property] = null;
} else {
newItem[property] = JSON.parse(JSON.stringify(item.json[property]));
}
}
return newItem;
}
export function mapToAttributeValues(item: IDataObject): void {
for (const key of Object.keys(item)) {
if (!key.startsWith(':')) {
item[`:${key}`] = item[key];
delete item[key];
}
}
}
export function decodeItem(item: IAttributeValue): IDataObject {
const _item: IDataObject = {};
for (const entry of Object.entries(item)) {
const [attribute, value]: [string, object] = entry;
const [type, content]: [string, object] = Object.entries(value)[0];
_item[attribute] = decodeAttribute(type as EAttributeValueType, content as unknown as string);
}
return _item;
}

View file

@ -383,129 +383,137 @@ export class AwsRekognition implements INodeType {
const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string;
for (let i = 0; i < items.length; i++) {
if (resource === 'image') {
//https://docs.aws.amazon.com/rekognition/latest/dg/API_DetectModerationLabels.html#API_DetectModerationLabels_RequestSyntax
if (operation === 'analyze') {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
try {
if (resource === 'image') {
//https://docs.aws.amazon.com/rekognition/latest/dg/API_DetectModerationLabels.html#API_DetectModerationLabels_RequestSyntax
if (operation === 'analyze') {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
let action = undefined;
let action = undefined;
const body: IDataObject = {};
const body: IDataObject = {};
const type = this.getNodeParameter('type', 0) as string;
const type = this.getNodeParameter('type', 0) as string;
if (type === 'detectModerationLabels') {
action = 'RekognitionService.DetectModerationLabels';
if (type === 'detectModerationLabels') {
action = 'RekognitionService.DetectModerationLabels';
// property = 'ModerationLabels';
// property = 'ModerationLabels';
if (additionalFields.minConfidence) {
body['MinConfidence'] = additionalFields.minConfidence as number;
}
}
if (type === 'detectFaces') {
action = 'RekognitionService.DetectFaces';
// TODO: Add a later point make it possible to activate via option.
// If activated add an index to each of the found faces/tages/...
// to not loose the reference to the image it got found on if
// multilpe ones got supplied.
// property = 'FaceDetails';
if (additionalFields.attributes) {
body['Attributes'] = additionalFields.attributes as string;
}
}
if (type === 'detectLabels') {
action = 'RekognitionService.DetectLabels';
if (additionalFields.minConfidence) {
body['MinConfidence'] = additionalFields.minConfidence as number;
if (additionalFields.minConfidence) {
body['MinConfidence'] = additionalFields.minConfidence as number;
}
}
if (additionalFields.maxLabels) {
body['MaxLabels'] = additionalFields.maxLabels as number;
}
}
if (type === 'detectFaces') {
action = 'RekognitionService.DetectFaces';
if (type === 'recognizeCelebrity') {
action = 'RekognitionService.RecognizeCelebrities';
}
// TODO: Add a later point make it possible to activate via option.
// If activated add an index to each of the found faces/tages/...
// to not loose the reference to the image it got found on if
// multilpe ones got supplied.
// property = 'FaceDetails';
if (type === 'detectText') {
action = 'RekognitionService.DetectText';
body.Filters = {};
const box = (additionalFields.regionsOfInterestUi as IDataObject || {}).regionsOfInterestValues as IDataObject[] || [];
if (box.length !== 0) {
//@ts-ignore
body.Filters.RegionsOfInterest = box.map((box: IDataObject) => {
return { BoundingBox: keysTPascalCase(box) };
});
if (additionalFields.attributes) {
body['Attributes'] = additionalFields.attributes as string;
}
}
const wordFilter = additionalFields.wordFilterUi as IDataObject || {};
if (Object.keys(wordFilter).length !== 0) {
//@ts-ignore
body.Filters.WordFilter = keysTPascalCase(wordFilter);
}
if (type === 'detectLabels') {
action = 'RekognitionService.DetectLabels';
const binaryData = this.getNodeParameter('binaryData', 0) as boolean;
if (binaryData) {
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', 0) as string;
if (items[i].binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
if (additionalFields.minConfidence) {
body['MinConfidence'] = additionalFields.minConfidence as number;
}
if ((items[i].binary as IBinaryKeyData)[binaryPropertyName] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property "${binaryPropertyName}" does not exists on item!`);
if (additionalFields.maxLabels) {
body['MaxLabels'] = additionalFields.maxLabels as number;
}
}
const binaryPropertyData = (items[i].binary as IBinaryKeyData)[binaryPropertyName];
if (type === 'recognizeCelebrity') {
action = 'RekognitionService.RecognizeCelebrities';
}
Object.assign(body, {
Image: {
Bytes: binaryPropertyData.data,
},
});
if (type === 'detectText') {
action = 'RekognitionService.DetectText';
} else {
body.Filters = {};
const bucket = this.getNodeParameter('bucket', i) as string;
const box = (additionalFields.regionsOfInterestUi as IDataObject || {}).regionsOfInterestValues as IDataObject[] || [];
const name = this.getNodeParameter('name', i) as string;
Object.assign(body, {
Image: {
S3Object: {
Bucket: bucket,
Name: name,
},
},
});
if (additionalFields.version) {
if (box.length !== 0) {
//@ts-ignore
body.Image.S3Object.Version = additionalFields.version as string;
body.Filters.RegionsOfInterest = box.map((box: IDataObject) => {
return { BoundingBox: keysTPascalCase(box) };
});
}
const wordFilter = additionalFields.wordFilterUi as IDataObject || {};
if (Object.keys(wordFilter).length !== 0) {
//@ts-ignore
body.Filters.WordFilter = keysTPascalCase(wordFilter);
}
const binaryData = this.getNodeParameter('binaryData', 0) as boolean;
if (binaryData) {
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', 0) as string;
if (items[i].binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
}
if ((items[i].binary as IBinaryKeyData)[binaryPropertyName] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property "${binaryPropertyName}" does not exists on item!`);
}
const binaryPropertyData = (items[i].binary as IBinaryKeyData)[binaryPropertyName];
Object.assign(body, {
Image: {
Bytes: binaryPropertyData.data,
},
});
} else {
const bucket = this.getNodeParameter('bucket', i) as string;
const name = this.getNodeParameter('name', i) as string;
Object.assign(body, {
Image: {
S3Object: {
Bucket: bucket,
Name: name,
},
},
});
if (additionalFields.version) {
//@ts-ignore
body.Image.S3Object.Version = additionalFields.version as string;
}
}
responseData = await awsApiRequestREST.call(this, 'rekognition', 'POST', '', JSON.stringify(body), {}, { 'X-Amz-Target': action, 'Content-Type': 'application/x-amz-json-1.1' });
}
responseData = await awsApiRequestREST.call(this, 'rekognition', 'POST', '', JSON.stringify(body), {}, { 'X-Amz-Target': action, 'Content-Type': 'application/x-amz-json-1.1' });
}
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData);
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData);
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];

File diff suppressed because it is too large Load diff

View file

@ -934,376 +934,383 @@ export class AwsSes implements INodeType {
const operation = this.getNodeParameter('operation', 0) as string;
for (let i = 0; i < items.length; i++) {
try {
if (resource === 'customVerificationEmail') {
if (resource === 'customVerificationEmail') {
if (operation === 'create') {
if (operation === 'create') {
const failureRedirectionURL = this.getNodeParameter('failureRedirectionURL', i) as string;
const failureRedirectionURL = this.getNodeParameter('failureRedirectionURL', i) as string;
const email = this.getNodeParameter('fromEmailAddress', i) as string;
const email = this.getNodeParameter('fromEmailAddress', i) as string;
const successRedirectionURL = this.getNodeParameter('successRedirectionURL', i) as string;
const successRedirectionURL = this.getNodeParameter('successRedirectionURL', i) as string;
const templateContent = this.getNodeParameter('templateContent', i) as string;
const templateContent = this.getNodeParameter('templateContent', i) as string;
const templateName = this.getNodeParameter('templateName', i) as string;
const templateName = this.getNodeParameter('templateName', i) as string;
const templateSubject = this.getNodeParameter('templateSubject', i) as string;
const templateSubject = this.getNodeParameter('templateSubject', i) as string;
const params = [
`Action=CreateCustomVerificationEmailTemplate`,
`FailureRedirectionURL=${failureRedirectionURL}`,
`FromEmailAddress=${email}`,
`SuccessRedirectionURL=${successRedirectionURL}`,
`TemplateContent=${templateContent}`,
`TemplateName=${templateName}`,
`TemplateSubject=${templateSubject}`,
];
const params = [
`Action=CreateCustomVerificationEmailTemplate`,
`FailureRedirectionURL=${failureRedirectionURL}`,
`FromEmailAddress=${email}`,
`SuccessRedirectionURL=${successRedirectionURL}`,
`TemplateContent=${templateContent}`,
`TemplateName=${templateName}`,
`TemplateSubject=${templateSubject}`,
];
responseData = await awsApiRequestSOAP.call(this, 'email', 'POST', '', params.join('&'));
responseData = await awsApiRequestSOAP.call(this, 'email', 'POST', '', params.join('&'));
responseData = responseData.CreateCustomVerificationEmailTemplateResponse;
}
if (operation === 'delete') {
const templateName = this.getNodeParameter('templateName', i) as string;
const params = [
`Action=DeleteCustomVerificationEmailTemplate`,
`TemplateName=${templateName}`,
];
responseData = await awsApiRequestSOAP.call(this, 'email', 'POST', '', params.join('&'));
responseData = responseData.DeleteCustomVerificationEmailTemplateResponse;
}
if (operation === 'get') {
const templateName = this.getNodeParameter('templateName', i) as string;
const params = [
`TemplateName=${templateName}`,
];
responseData = await awsApiRequestSOAP.call(this, 'email', 'POST', '/?Action=GetCustomVerificationEmailTemplate&' + params.join('&'));
responseData = responseData.GetCustomVerificationEmailTemplateResponse;
}
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
if (returnAll === true) {
responseData = await awsApiRequestSOAPAllItems.call(this, 'ListCustomVerificationEmailTemplatesResponse.ListCustomVerificationEmailTemplatesResult.CustomVerificationEmailTemplates.member', 'email', 'POST', '/?Action=ListCustomVerificationEmailTemplates');
} else {
const limit = this.getNodeParameter('limit', i) as number;
responseData = await awsApiRequestSOAP.call(this, 'email', 'GET', `/?Action=ListCustomVerificationEmailTemplates&MaxResults=${limit}`);
responseData = responseData.ListCustomVerificationEmailTemplatesResponse.ListCustomVerificationEmailTemplatesResult.CustomVerificationEmailTemplates.member;
}
}
if (operation === 'send') {
const email = this.getNodeParameter('email', i) as string[];
const templateName = this.getNodeParameter('templateName', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const params = [
`Action=SendCustomVerificationEmail`,
`TemplateName=${templateName}`,
`EmailAddress=${email}`,
];
if (additionalFields.configurationSetName) {
params.push(`ConfigurationSetName=${additionalFields.configurationSetName}`);
responseData = responseData.CreateCustomVerificationEmailTemplateResponse;
}
responseData = await awsApiRequestSOAP.call(this, 'email', 'POST', '', params.join('&'));
if (operation === 'delete') {
responseData = responseData.SendCustomVerificationEmailResponse;
}
const templateName = this.getNodeParameter('templateName', i) as string;
if (operation === 'update') {
const params = [
`Action=DeleteCustomVerificationEmailTemplate`,
`TemplateName=${templateName}`,
];
const templateName = this.getNodeParameter('templateName', i) as string;
responseData = await awsApiRequestSOAP.call(this, 'email', 'POST', '', params.join('&'));
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const params = [
`Action=UpdateCustomVerificationEmailTemplate`,
`TemplateName=${templateName}`,
];
if (updateFields.FailureRedirectionURL) {
params.push(`FailureRedirectionURL=${updateFields.FailureRedirectionURL}`);
responseData = responseData.DeleteCustomVerificationEmailTemplateResponse;
}
if (updateFields.email) {
params.push(`FromEmailAddress=${updateFields.email}`);
if (operation === 'get') {
const templateName = this.getNodeParameter('templateName', i) as string;
const params = [
`TemplateName=${templateName}`,
];
responseData = await awsApiRequestSOAP.call(this, 'email', 'POST', '/?Action=GetCustomVerificationEmailTemplate&' + params.join('&'));
responseData = responseData.GetCustomVerificationEmailTemplateResponse;
}
if (updateFields.successRedirectionURL) {
params.push(`SuccessRedirectionURL=${updateFields.successRedirectionURL}`);
}
if (operation === 'getAll') {
if (updateFields.templateContent) {
params.push(`TemplateContent=${updateFields.templateContent}`);
}
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
if (updateFields.templateSubject) {
params.push(`TemplateSubject=${updateFields.templateSubject}`);
}
if (returnAll === true) {
responseData = await awsApiRequestSOAPAllItems.call(this, 'ListCustomVerificationEmailTemplatesResponse.ListCustomVerificationEmailTemplatesResult.CustomVerificationEmailTemplates.member', 'email', 'POST', '/?Action=ListCustomVerificationEmailTemplates');
responseData = await awsApiRequestSOAP.call(this, 'email', 'POST', '', params.join('&'));
} else {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.UpdateCustomVerificationEmailTemplateResponse;
}
}
responseData = await awsApiRequestSOAP.call(this, 'email', 'GET', `/?Action=ListCustomVerificationEmailTemplates&MaxResults=${limit}`);
if (resource === 'email') {
if (operation === 'send') {
const toAddresses = this.getNodeParameter('toAddresses', i) as string[];
const message = this.getNodeParameter('body', i) as string;
const subject = this.getNodeParameter('subject', i) as string;
const fromEmail = this.getNodeParameter('fromEmail', i) as string;
const isBodyHtml = this.getNodeParameter('isBodyHtml', i) as boolean;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const params = [
`Message.Subject.Data=${subject}`,
`Source=${fromEmail}`,
];
if (isBodyHtml) {
params.push(`Message.Body.Html.Data=${encodeURI(message)}`);
} else {
params.push(`Message.Body.Text.Data=${encodeURI(message)}`);
}
if (toAddresses.length) {
setParameter(params, 'Destination.ToAddresses.member', toAddresses);
} else {
throw new NodeOperationError(this.getNode(), 'At least one "To Address" has to be added!');
}
if (additionalFields.configurationSetName) {
params.push(`ConfigurationSetName=${additionalFields.configurationSetName}`);
}
if (additionalFields.returnPath) {
params.push(`ReturnPath=${additionalFields.returnPath}`);
}
if (additionalFields.returnPathArn) {
params.push(`ReturnPathArn=${additionalFields.returnPathArn}`);
}
if (additionalFields.sourceArn) {
params.push(`SourceArn=${additionalFields.sourceArn}`);
}
if (additionalFields.replyToAddresses) {
setParameter(params, 'ReplyToAddresses.member', additionalFields.replyToAddresses as string[]);
}
if (additionalFields.bccAddresses) {
setParameter(params, 'Destination.BccAddresses.member', additionalFields.bccAddresses as string[]);
}
if (additionalFields.ccAddresses) {
setParameter(params, 'Destination.CcAddresses.member', additionalFields.ccAddresses as string[]);
}
responseData = await awsApiRequestSOAP.call(this, 'email', 'POST', '/?Action=SendEmail&' + params.join('&'));
}
if (operation === 'sendTemplate') {
const toAddresses = this.getNodeParameter('toAddresses', i) as string[];
const template = this.getNodeParameter('templateName', i) as string;
const fromEmail = this.getNodeParameter('fromEmail', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const templateDataUi = this.getNodeParameter('templateDataUi', i) as IDataObject;
const params = [
`Template=${template}`,
`Source=${fromEmail}`,
];
if (toAddresses.length) {
setParameter(params, 'Destination.ToAddresses.member', toAddresses);
} else {
throw new NodeOperationError(this.getNode(), 'At least one "To Address" has to be added!');
}
if (additionalFields.configurationSetName) {
params.push(`ConfigurationSetName=${additionalFields.configurationSetName}`);
}
if (additionalFields.returnPath) {
params.push(`ReturnPath=${additionalFields.returnPath}`);
}
if (additionalFields.returnPathArn) {
params.push(`ReturnPathArn=${additionalFields.returnPathArn}`);
}
if (additionalFields.sourceArn) {
params.push(`SourceArn=${additionalFields.sourceArn}`);
}
if (additionalFields.replyToAddresses) {
setParameter(params, 'ReplyToAddresses.member', additionalFields.replyToAddresses as string[]);
}
if (additionalFields.bccAddresses) {
setParameter(params, 'Destination.BccAddresses.member', additionalFields.bccAddresses as string[]);
}
if (additionalFields.ccAddresses) {
setParameter(params, 'Destination.CcAddresses.member', additionalFields.ccAddresses as string[]);
}
if (templateDataUi) {
const templateDataValues = (templateDataUi as IDataObject).templateDataValues as IDataObject[];
const templateData: IDataObject = {};
if (templateDataValues !== undefined) {
for (const templateDataValue of templateDataValues) {
//@ts-ignore
templateData[templateDataValue.key] = templateDataValue.value;
}
params.push(`TemplateData=${JSON.stringify(templateData)}`);
responseData = responseData.ListCustomVerificationEmailTemplatesResponse.ListCustomVerificationEmailTemplatesResult.CustomVerificationEmailTemplates.member;
}
}
responseData = await awsApiRequestSOAP.call(this, 'email', 'POST', '/?Action=SendTemplatedEmail&' + params.join('&'));
if (operation === 'send') {
responseData = responseData.SendTemplatedEmailResponse;
}
}
const email = this.getNodeParameter('email', i) as string[];
if (resource === 'template') {
const templateName = this.getNodeParameter('templateName', i) as string;
if (operation === 'create') {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const templateName = this.getNodeParameter('templateName', i) as string;
const params = [
`Action=SendCustomVerificationEmail`,
`TemplateName=${templateName}`,
`EmailAddress=${email}`,
];
const subjectPart = this.getNodeParameter('subjectPart', i) as string;
if (additionalFields.configurationSetName) {
params.push(`ConfigurationSetName=${additionalFields.configurationSetName}`);
}
const htmlPart = this.getNodeParameter('htmlPart', i) as string;
responseData = await awsApiRequestSOAP.call(this, 'email', 'POST', '', params.join('&'));
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const params = [
`Template.TemplateName=${templateName}`,
`Template.SubjectPart=${subjectPart}`,
`Template.HtmlPart=<h1>${htmlPart}</h1>`,
];
if (additionalFields.textPart) {
params.push(`Template.TextPart=${additionalFields.textPart}`);
responseData = responseData.SendCustomVerificationEmailResponse;
}
responseData = await awsApiRequestSOAP.call(this, 'email', 'POST', '/?Action=CreateTemplate&' + params.join('&'));
if (operation === 'update') {
responseData = responseData.CreateTemplateResponse;
}
const templateName = this.getNodeParameter('templateName', i) as string;
if (operation === 'delete') {
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const templateName = this.getNodeParameter('templateName', i) as string;
const params = [
`Action=UpdateCustomVerificationEmailTemplate`,
`TemplateName=${templateName}`,
];
const params = [
`TemplateName=${templateName}`,
];
if (updateFields.FailureRedirectionURL) {
params.push(`FailureRedirectionURL=${updateFields.FailureRedirectionURL}`);
}
responseData = await awsApiRequestSOAP.call(this, 'email', 'POST', '/?Action=DeleteTemplate&' + params.join('&'));
if (updateFields.email) {
params.push(`FromEmailAddress=${updateFields.email}`);
}
responseData = responseData.DeleteTemplateResponse;
}
if (updateFields.successRedirectionURL) {
params.push(`SuccessRedirectionURL=${updateFields.successRedirectionURL}`);
}
if (operation === 'get') {
if (updateFields.templateContent) {
params.push(`TemplateContent=${updateFields.templateContent}`);
}
const templateName = this.getNodeParameter('templateName', i) as string;
if (updateFields.templateSubject) {
params.push(`TemplateSubject=${updateFields.templateSubject}`);
}
const params = [
`TemplateName=${templateName}`,
];
responseData = await awsApiRequestSOAP.call(this, 'email', 'POST', '', params.join('&'));
responseData = await awsApiRequestSOAP.call(this, 'email', 'POST', '/?Action=GetTemplate&' + params.join('&'));
responseData = responseData.GetTemplateResponse;
}
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
if (returnAll === true) {
responseData = await awsApiRequestSOAPAllItems.call(this, 'ListTemplatesResponse.ListTemplatesResult.TemplatesMetadata.member', 'email', 'POST', '/?Action=ListTemplates');
} else {
const limit = this.getNodeParameter('limit', i) as number;
responseData = await awsApiRequestSOAP.call(this, 'email', 'GET', `/?Action=ListTemplates&MaxItems=${limit}`);
responseData = responseData.ListTemplatesResponse.ListTemplatesResult.TemplatesMetadata.member;
responseData = responseData.UpdateCustomVerificationEmailTemplateResponse;
}
}
if (operation === 'update') {
if (resource === 'email') {
const templateName = this.getNodeParameter('templateName', i) as string;
if (operation === 'send') {
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const toAddresses = this.getNodeParameter('toAddresses', i) as string[];
const params = [
`Template.TemplateName=${templateName}`,
];
const message = this.getNodeParameter('body', i) as string;
if (updateFields.textPart) {
params.push(`Template.TextPart=${updateFields.textPart}`);
const subject = this.getNodeParameter('subject', i) as string;
const fromEmail = this.getNodeParameter('fromEmail', i) as string;
const isBodyHtml = this.getNodeParameter('isBodyHtml', i) as boolean;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const params = [
`Message.Subject.Data=${subject}`,
`Source=${fromEmail}`,
];
if (isBodyHtml) {
params.push(`Message.Body.Html.Data=${encodeURI(message)}`);
} else {
params.push(`Message.Body.Text.Data=${encodeURI(message)}`);
}
if (toAddresses.length) {
setParameter(params, 'Destination.ToAddresses.member', toAddresses);
} else {
throw new NodeOperationError(this.getNode(), 'At least one "To Address" has to be added!');
}
if (additionalFields.configurationSetName) {
params.push(`ConfigurationSetName=${additionalFields.configurationSetName}`);
}
if (additionalFields.returnPath) {
params.push(`ReturnPath=${additionalFields.returnPath}`);
}
if (additionalFields.returnPathArn) {
params.push(`ReturnPathArn=${additionalFields.returnPathArn}`);
}
if (additionalFields.sourceArn) {
params.push(`SourceArn=${additionalFields.sourceArn}`);
}
if (additionalFields.replyToAddresses) {
setParameter(params, 'ReplyToAddresses.member', additionalFields.replyToAddresses as string[]);
}
if (additionalFields.bccAddresses) {
setParameter(params, 'Destination.BccAddresses.member', additionalFields.bccAddresses as string[]);
}
if (additionalFields.ccAddresses) {
setParameter(params, 'Destination.CcAddresses.member', additionalFields.ccAddresses as string[]);
}
responseData = await awsApiRequestSOAP.call(this, 'email', 'POST', '/?Action=SendEmail&' + params.join('&'));
}
if (updateFields.subjectPart) {
params.push(`Template.SubjectPart=${updateFields.subjectPart}`);
if (operation === 'sendTemplate') {
const toAddresses = this.getNodeParameter('toAddresses', i) as string[];
const template = this.getNodeParameter('templateName', i) as string;
const fromEmail = this.getNodeParameter('fromEmail', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const templateDataUi = this.getNodeParameter('templateDataUi', i) as IDataObject;
const params = [
`Template=${template}`,
`Source=${fromEmail}`,
];
if (toAddresses.length) {
setParameter(params, 'Destination.ToAddresses.member', toAddresses);
} else {
throw new NodeOperationError(this.getNode(), 'At least one "To Address" has to be added!');
}
if (additionalFields.configurationSetName) {
params.push(`ConfigurationSetName=${additionalFields.configurationSetName}`);
}
if (additionalFields.returnPath) {
params.push(`ReturnPath=${additionalFields.returnPath}`);
}
if (additionalFields.returnPathArn) {
params.push(`ReturnPathArn=${additionalFields.returnPathArn}`);
}
if (additionalFields.sourceArn) {
params.push(`SourceArn=${additionalFields.sourceArn}`);
}
if (additionalFields.replyToAddresses) {
setParameter(params, 'ReplyToAddresses.member', additionalFields.replyToAddresses as string[]);
}
if (additionalFields.bccAddresses) {
setParameter(params, 'Destination.BccAddresses.member', additionalFields.bccAddresses as string[]);
}
if (additionalFields.ccAddresses) {
setParameter(params, 'Destination.CcAddresses.member', additionalFields.ccAddresses as string[]);
}
if (templateDataUi) {
const templateDataValues = (templateDataUi as IDataObject).templateDataValues as IDataObject[];
const templateData: IDataObject = {};
if (templateDataValues !== undefined) {
for (const templateDataValue of templateDataValues) {
//@ts-ignore
templateData[templateDataValue.key] = templateDataValue.value;
}
params.push(`TemplateData=${JSON.stringify(templateData)}`);
}
}
responseData = await awsApiRequestSOAP.call(this, 'email', 'POST', '/?Action=SendTemplatedEmail&' + params.join('&'));
responseData = responseData.SendTemplatedEmailResponse;
}
if (updateFields.subjectPart) {
params.push(`Template.HtmlPart=${updateFields.htmlPart}`);
}
responseData = await awsApiRequestSOAP.call(this, 'email', 'POST', '/?Action=UpdateTemplate&' + params.join('&'));
responseData = responseData.UpdateTemplateResponse;
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
if (responseData !== undefined) {
returnData.push(responseData as IDataObject);
if (resource === 'template') {
if (operation === 'create') {
const templateName = this.getNodeParameter('templateName', i) as string;
const subjectPart = this.getNodeParameter('subjectPart', i) as string;
const htmlPart = this.getNodeParameter('htmlPart', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const params = [
`Template.TemplateName=${templateName}`,
`Template.SubjectPart=${subjectPart}`,
`Template.HtmlPart=<h1>${htmlPart}</h1>`,
];
if (additionalFields.textPart) {
params.push(`Template.TextPart=${additionalFields.textPart}`);
}
responseData = await awsApiRequestSOAP.call(this, 'email', 'POST', '/?Action=CreateTemplate&' + params.join('&'));
responseData = responseData.CreateTemplateResponse;
}
if (operation === 'delete') {
const templateName = this.getNodeParameter('templateName', i) as string;
const params = [
`TemplateName=${templateName}`,
];
responseData = await awsApiRequestSOAP.call(this, 'email', 'POST', '/?Action=DeleteTemplate&' + params.join('&'));
responseData = responseData.DeleteTemplateResponse;
}
if (operation === 'get') {
const templateName = this.getNodeParameter('templateName', i) as string;
const params = [
`TemplateName=${templateName}`,
];
responseData = await awsApiRequestSOAP.call(this, 'email', 'POST', '/?Action=GetTemplate&' + params.join('&'));
responseData = responseData.GetTemplateResponse;
}
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
if (returnAll === true) {
responseData = await awsApiRequestSOAPAllItems.call(this, 'ListTemplatesResponse.ListTemplatesResult.TemplatesMetadata.member', 'email', 'POST', '/?Action=ListTemplates');
} else {
const limit = this.getNodeParameter('limit', i) as number;
responseData = await awsApiRequestSOAP.call(this, 'email', 'GET', `/?Action=ListTemplates&MaxItems=${limit}`);
responseData = responseData.ListTemplatesResponse.ListTemplatesResult.TemplatesMetadata.member;
}
}
if (operation === 'update') {
const templateName = this.getNodeParameter('templateName', i) as string;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const params = [
`Template.TemplateName=${templateName}`,
];
if (updateFields.textPart) {
params.push(`Template.TextPart=${updateFields.textPart}`);
}
if (updateFields.subjectPart) {
params.push(`Template.SubjectPart=${updateFields.subjectPart}`);
}
if (updateFields.subjectPart) {
params.push(`Template.HtmlPart=${updateFields.htmlPart}`);
}
responseData = await awsApiRequestSOAP.call(this, 'email', 'POST', '/?Action=UpdateTemplate&' + params.join('&'));
responseData = responseData.UpdateTemplateResponse;
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
if (responseData !== undefined) {
returnData.push(responseData as IDataObject);
}
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}

View file

@ -316,84 +316,92 @@ export class AwsSqs implements INodeType {
const operation = this.getNodeParameter('operation', 0) as string;
for (let i = 0; i < items.length; i++) {
const queueUrl = this.getNodeParameter('queue', i) as string;
const queuePath = new URL(queueUrl).pathname;
const params = [
'Version=2012-11-05',
`Action=${pascalCase(operation)}`,
];
const options = this.getNodeParameter('options', i, {}) as IDataObject;
const sendInputData = this.getNodeParameter('sendInputData', i) as boolean;
const message = sendInputData ? JSON.stringify(items[i].json) : this.getNodeParameter('message', i) as string;
params.push(`MessageBody=${message}`);
if (options.delaySeconds) {
params.push(`DelaySeconds=${options.delaySeconds}`);
}
const queueType = this.getNodeParameter('queueType', i, {}) as string;
if (queueType === 'fifo') {
const messageDeduplicationId = this.getNodeParameter('options.messageDeduplicationId', i, '') as string;
if (messageDeduplicationId) {
params.push(`MessageDeduplicationId=${messageDeduplicationId}`);
}
const messageGroupId = this.getNodeParameter('messageGroupId', i) as string;
if (messageGroupId) {
params.push(`MessageGroupId=${messageGroupId}`);
}
}
let attributeCount = 0;
// Add string values
(this.getNodeParameter('options.messageAttributes.string', i, []) as INodeParameters[]).forEach((attribute) => {
attributeCount++;
params.push(`MessageAttribute.${attributeCount}.Name=${attribute.name}`);
params.push(`MessageAttribute.${attributeCount}.Value.StringValue=${attribute.value}`);
params.push(`MessageAttribute.${attributeCount}.Value.DataType=String`);
});
// Add binary values
(this.getNodeParameter('options.messageAttributes.binary', i, []) as INodeParameters[]).forEach((attribute) => {
attributeCount++;
const dataPropertyName = attribute.dataPropertyName as string;
const item = items[i];
if (item.binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data set. So message attribute cannot be added!');
}
if (item.binary[dataPropertyName] === undefined) {
throw new NodeOperationError(this.getNode(), `The binary property "${dataPropertyName}" does not exist. So message attribute cannot be added!`);
}
const binaryData = item.binary[dataPropertyName].data;
params.push(`MessageAttribute.${attributeCount}.Name=${attribute.name}`);
params.push(`MessageAttribute.${attributeCount}.Value.BinaryValue=${binaryData}`);
params.push(`MessageAttribute.${attributeCount}.Value.DataType=Binary`);
});
// Add number values
(this.getNodeParameter('options.messageAttributes.number', i, []) as INodeParameters[]).forEach((attribute) => {
attributeCount++;
params.push(`MessageAttribute.${attributeCount}.Name=${attribute.name}`);
params.push(`MessageAttribute.${attributeCount}.Value.StringValue=${attribute.value}`);
params.push(`MessageAttribute.${attributeCount}.Value.DataType=Number`);
});
let responseData;
try {
responseData = await awsApiRequestSOAP.call(this, 'sqs', 'GET', `${queuePath}?${params.join('&')}`);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
const queueUrl = this.getNodeParameter('queue', i) as string;
const queuePath = new URL(queueUrl).pathname;
const result = responseData.SendMessageResponse.SendMessageResult;
returnData.push(result as IDataObject);
const params = [
'Version=2012-11-05',
`Action=${pascalCase(operation)}`,
];
const options = this.getNodeParameter('options', i, {}) as IDataObject;
const sendInputData = this.getNodeParameter('sendInputData', i) as boolean;
const message = sendInputData ? JSON.stringify(items[i].json) : this.getNodeParameter('message', i) as string;
params.push(`MessageBody=${message}`);
if (options.delaySeconds) {
params.push(`DelaySeconds=${options.delaySeconds}`);
}
const queueType = this.getNodeParameter('queueType', i, {}) as string;
if (queueType === 'fifo') {
const messageDeduplicationId = this.getNodeParameter('options.messageDeduplicationId', i, '') as string;
if (messageDeduplicationId) {
params.push(`MessageDeduplicationId=${messageDeduplicationId}`);
}
const messageGroupId = this.getNodeParameter('messageGroupId', i) as string;
if (messageGroupId) {
params.push(`MessageGroupId=${messageGroupId}`);
}
}
let attributeCount = 0;
// Add string values
(this.getNodeParameter('options.messageAttributes.string', i, []) as INodeParameters[]).forEach((attribute) => {
attributeCount++;
params.push(`MessageAttribute.${attributeCount}.Name=${attribute.name}`);
params.push(`MessageAttribute.${attributeCount}.Value.StringValue=${attribute.value}`);
params.push(`MessageAttribute.${attributeCount}.Value.DataType=String`);
});
// Add binary values
(this.getNodeParameter('options.messageAttributes.binary', i, []) as INodeParameters[]).forEach((attribute) => {
attributeCount++;
const dataPropertyName = attribute.dataPropertyName as string;
const item = items[i];
if (item.binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data set. So message attribute cannot be added!');
}
if (item.binary[dataPropertyName] === undefined) {
throw new NodeOperationError(this.getNode(), `The binary property "${dataPropertyName}" does not exist. So message attribute cannot be added!`);
}
const binaryData = item.binary[dataPropertyName].data;
params.push(`MessageAttribute.${attributeCount}.Name=${attribute.name}`);
params.push(`MessageAttribute.${attributeCount}.Value.BinaryValue=${binaryData}`);
params.push(`MessageAttribute.${attributeCount}.Value.DataType=Binary`);
});
// Add number values
(this.getNodeParameter('options.messageAttributes.number', i, []) as INodeParameters[]).forEach((attribute) => {
attributeCount++;
params.push(`MessageAttribute.${attributeCount}.Name=${attribute.name}`);
params.push(`MessageAttribute.${attributeCount}.Value.StringValue=${attribute.value}`);
params.push(`MessageAttribute.${attributeCount}.Value.DataType=Number`);
});
let responseData;
try {
responseData = await awsApiRequestSOAP.call(this, 'sqs', 'GET', `${queuePath}?${params.join('&')}`);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
const result = responseData.SendMessageResponse.SendMessageResult;
returnData.push(result as IDataObject);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.description });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];

View file

@ -340,60 +340,66 @@ export class Beeminder implements INodeType {
for (let i = 0; i < length; i++) {
try {
if (resource === 'datapoint') {
const goalName = this.getNodeParameter('goalName', i) as string;
if (operation === 'create') {
const value = this.getNodeParameter('value', i) as number;
const options = this.getNodeParameter('additionalFields', i) as INodeParameters;
const data: IDataObject = {
value,
goalName,
};
Object.assign(data, options);
if (resource === 'datapoint') {
const goalName = this.getNodeParameter('goalName', i) as string;
if (operation === 'create') {
const value = this.getNodeParameter('value', i) as number;
const options = this.getNodeParameter('additionalFields', i) as INodeParameters;
const data: IDataObject = {
value,
goalName,
};
Object.assign(data, options);
if (data.timestamp) {
data.timestamp = moment.tz(data.timestamp, timezone).unix();
if (data.timestamp) {
data.timestamp = moment.tz(data.timestamp, timezone).unix();
}
results = await createDatapoint.call(this, data);
}
results = await createDatapoint.call(this, data);
}
else if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const options = this.getNodeParameter('options', i) as INodeParameters;
const data: IDataObject = {
goalName,
};
Object.assign(data, options);
else if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const options = this.getNodeParameter('options', i) as INodeParameters;
const data: IDataObject = {
goalName,
};
Object.assign(data, options);
if (returnAll === false) {
data.count = this.getNodeParameter('limit', 0) as number;
}
if (returnAll === false) {
data.count = this.getNodeParameter('limit', 0) as number;
}
results = await getAllDatapoints.call(this, data);
}
else if (operation === 'update') {
const datapointId = this.getNodeParameter('datapointId', i) as string;
const options = this.getNodeParameter('updateFields', i) as INodeParameters;
const data: IDataObject = {
goalName,
datapointId,
};
Object.assign(data, options);
if (data.timestamp) {
data.timestamp = moment.tz(data.timestamp, timezone).unix();
results = await getAllDatapoints.call(this, data);
}
else if (operation === 'update') {
const datapointId = this.getNodeParameter('datapointId', i) as string;
const options = this.getNodeParameter('updateFields', i) as INodeParameters;
const data: IDataObject = {
goalName,
datapointId,
};
Object.assign(data, options);
if (data.timestamp) {
data.timestamp = moment.tz(data.timestamp, timezone).unix();
}
results = await updateDatapoint.call(this, data);
}
else if (operation === 'delete') {
const datapointId = this.getNodeParameter('datapointId', i) as string;
const data: IDataObject = {
goalName,
datapointId,
};
results = await deleteDatapoint.call(this, data);
}
results = await updateDatapoint.call(this, data);
}
else if (operation === 'delete') {
const datapointId = this.getNodeParameter('datapointId', i) as string;
const data: IDataObject = {
goalName,
datapointId,
};
results = await deleteDatapoint.call(this, data);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
if (Array.isArray(results)) {
returnData.push.apply(returnData, results as IDataObject[]);
} else {

View file

@ -141,81 +141,89 @@ export class Bitly implements INodeType {
const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string;
for (let i = 0; i < length; i++) {
if (resource === 'link') {
if (operation === 'create') {
const longUrl = this.getNodeParameter('longUrl', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IDataObject = {
long_url: longUrl,
};
if (additionalFields.title) {
body.title = additionalFields.title as string;
}
if (additionalFields.domain) {
body.domain = additionalFields.domain as string;
}
if (additionalFields.group) {
body.group = additionalFields.group as string;
}
if (additionalFields.tags) {
body.tags = additionalFields.tags as string[];
}
const deeplinks = (this.getNodeParameter('deeplink', i) as IDataObject).deeplinkUi as IDataObject[];
if (deeplinks) {
for (const deeplink of deeplinks) {
//@ts-ignore
body.deeplinks.push({
app_uri_path: deeplink.appUriPath,
install_type: deeplink.installType,
install_url: deeplink.installUrl,
app_id: deeplink.appId,
});
try {
if (resource === 'link') {
if (operation === 'create') {
const longUrl = this.getNodeParameter('longUrl', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IDataObject = {
long_url: longUrl,
};
if (additionalFields.title) {
body.title = additionalFields.title as string;
}
}
responseData = await bitlyApiRequest.call(this, 'POST', '/bitlinks', body);
}
if (operation === 'update') {
const linkId = this.getNodeParameter('id', i) as string;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const body: IDataObject = {};
if (updateFields.longUrl) {
body.long_url = updateFields.longUrl as string;
}
if (updateFields.title) {
body.title = updateFields.title as string;
}
if (updateFields.archived !== undefined) {
body.archived = updateFields.archived as boolean;
}
if (updateFields.group) {
body.group = updateFields.group as string;
}
if (updateFields.tags) {
body.tags = updateFields.tags as string[];
}
const deeplinks = (this.getNodeParameter('deeplink', i) as IDataObject).deeplinkUi as IDataObject[];
if (deeplinks) {
for (const deeplink of deeplinks) {
//@ts-ignore
body.deeplinks.push({
app_uri_path: deeplink.appUriPath,
install_type: deeplink.installType,
install_url: deeplink.installUrl,
app_id: deeplink.appId,
});
if (additionalFields.domain) {
body.domain = additionalFields.domain as string;
}
if (additionalFields.group) {
body.group = additionalFields.group as string;
}
if (additionalFields.tags) {
body.tags = additionalFields.tags as string[];
}
const deeplinks = (this.getNodeParameter('deeplink', i) as IDataObject).deeplinkUi as IDataObject[];
if (deeplinks) {
for (const deeplink of deeplinks) {
//@ts-ignore
body.deeplinks.push({
app_uri_path: deeplink.appUriPath,
install_type: deeplink.installType,
install_url: deeplink.installUrl,
app_id: deeplink.appId,
});
}
}
responseData = await bitlyApiRequest.call(this, 'POST', '/bitlinks', body);
}
if (operation === 'update') {
const linkId = this.getNodeParameter('id', i) as string;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const body: IDataObject = {};
if (updateFields.longUrl) {
body.long_url = updateFields.longUrl as string;
}
if (updateFields.title) {
body.title = updateFields.title as string;
}
if (updateFields.archived !== undefined) {
body.archived = updateFields.archived as boolean;
}
if (updateFields.group) {
body.group = updateFields.group as string;
}
if (updateFields.tags) {
body.tags = updateFields.tags as string[];
}
const deeplinks = (this.getNodeParameter('deeplink', i) as IDataObject).deeplinkUi as IDataObject[];
if (deeplinks) {
for (const deeplink of deeplinks) {
//@ts-ignore
body.deeplinks.push({
app_uri_path: deeplink.appUriPath,
install_type: deeplink.installType,
install_url: deeplink.installUrl,
app_id: deeplink.appId,
});
}
}
responseData = await bitlyApiRequest.call(this, 'PATCH', `/bitlinks/${linkId}`, body);
}
if (operation === 'get') {
const linkId = this.getNodeParameter('id', i) as string;
responseData = await bitlyApiRequest.call(this, 'GET', `/bitlinks/${linkId}`);
}
responseData = await bitlyApiRequest.call(this, 'PATCH', `/bitlinks/${linkId}`, body);
}
if (operation === 'get') {
const linkId = this.getNodeParameter('id', i) as string;
responseData = await bitlyApiRequest.call(this, 'GET', `/bitlinks/${linkId}`);
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];

View file

@ -89,396 +89,404 @@ export class Box implements INodeType {
const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string;
for (let i = 0; i < length; i++) {
if (resource === 'file') {
// https://developer.box.com/reference/post-files-id-copy
if (operation === 'copy') {
const fileId = this.getNodeParameter('fileId', i) as string;
const parentId = this.getNodeParameter('parentId', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IDataObject = {};
if (additionalFields.name) {
body.name = additionalFields.name as string;
}
if (parentId) {
body.parent = { id: parentId };
} else {
body.parent = { id: 0 };
}
if (additionalFields.fields) {
qs.fields = additionalFields.fields as string;
}
if (additionalFields.version) {
body.version = additionalFields.version as string;
}
responseData = await boxApiRequest.call(this, 'POST', `/files/${fileId}/copy`, body, qs);
returnData.push(responseData as IDataObject);
}
// https://developer.box.com/reference/delete-files-id
if (operation === 'delete') {
const fileId = this.getNodeParameter('fileId', i) as string;
responseData = await boxApiRequest.call(this, 'DELETE', `/files/${fileId}`);
responseData = { success: true };
returnData.push(responseData as IDataObject);
}
// https://developer.box.com/reference/get-files-id-content
if (operation === 'download') {
const fileId = this.getNodeParameter('fileId', i) as string;
const dataPropertyNameDownload = this.getNodeParameter('binaryPropertyName', i) as string;
responseData = await boxApiRequest.call(this, 'GET', `/files/${fileId}`);
const fileName = responseData.name;
let mimeType: string | undefined;
responseData = await boxApiRequest.call(this, 'GET', `/files/${fileId}/content`, {}, {}, undefined, { resolveWithFullResponse: true });
const newItem: INodeExecutionData = {
json: items[i].json,
binary: {},
};
if (mimeType === undefined && responseData.headers['content-type']) {
mimeType = responseData.headers['content-type'];
}
if (items[i].binary !== undefined) {
// Create a shallow copy of the binary data so that the old
// data references which do not get changed still stay behind
// but the incoming data does not get changed.
Object.assign(newItem.binary, items[i].binary);
}
items[i] = newItem;
const data = Buffer.from(responseData.body);
items[i].binary![dataPropertyNameDownload] = await this.helpers.prepareBinaryData(data as unknown as Buffer, fileName, mimeType);
}
// https://developer.box.com/reference/get-files-id
if (operation === 'get') {
const fileId = this.getNodeParameter('fileId', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (additionalFields.fields) {
qs.fields = additionalFields.fields as string;
}
responseData = await boxApiRequest.call(this, 'GET', `/files/${fileId}`, {}, qs);
returnData.push(responseData as IDataObject);
}
// https://developer.box.com/reference/get-search/
if (operation === 'search') {
const query = this.getNodeParameter('query', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const timezone = this.getTimezone();
qs.type = 'file';
qs.query = query;
Object.assign(qs, additionalFields);
if (qs.content_types) {
qs.content_types = (qs.content_types as string).split(',');
}
if (additionalFields.createdRangeUi) {
const createdRangeValues = (additionalFields.createdRangeUi as IDataObject).createdRangeValuesUi as IDataObject;
if (createdRangeValues) {
qs.created_at_range = `${moment.tz(createdRangeValues.from, timezone).format()},${moment.tz(createdRangeValues.to, timezone).format()}`;
}
delete qs.createdRangeUi;
}
if (additionalFields.updatedRangeUi) {
const updateRangeValues = (additionalFields.updatedRangeUi as IDataObject).updatedRangeValuesUi as IDataObject;
if (updateRangeValues) {
qs.updated_at_range = `${moment.tz(updateRangeValues.from, timezone).format()},${moment.tz(updateRangeValues.to, timezone).format()}`;
}
delete qs.updatedRangeUi;
}
if (returnAll) {
responseData = await boxApiRequestAllItems.call(this, 'entries', 'GET', `/search`, {}, qs);
} else {
qs.limit = this.getNodeParameter('limit', i) as number;
responseData = await boxApiRequest.call(this, 'GET', `/search`, {}, qs);
responseData = responseData.entries;
}
returnData.push.apply(returnData, responseData as IDataObject[]);
}
// https://developer.box.com/reference/post-collaborations/
if (operation === 'share') {
const fileId = this.getNodeParameter('fileId', i) as string;
const role = this.getNodeParameter('role', i) as string;
const accessibleBy = this.getNodeParameter('accessibleBy', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
// tslint:disable-next-line: no-any
const body: { accessible_by: IDataObject, [key: string]: any } = {
accessible_by: {},
item: {
id: fileId,
type: 'file',
},
role: (role === 'coOwner') ? 'co-owner' : noCase(role),
...options,
};
if (body.fields) {
qs.fields = body.fields;
delete body.fields;
}
if (body.expires_at) {
body.expires_at = moment.tz(body.expires_at, timezone).format();
}
if (body.notify) {
qs.notify = body.notify;
delete body.notify;
}
if (accessibleBy === 'user') {
const useEmail = this.getNodeParameter('useEmail', i) as boolean;
if (useEmail) {
body.accessible_by['login'] = this.getNodeParameter('email', i) as string;
} else {
body.accessible_by['id'] = this.getNodeParameter('userId', i) as string;
}
} else {
body.accessible_by['id'] = this.getNodeParameter('groupId', i) as string;
}
responseData = await boxApiRequest.call(this, 'POST', `/collaborations`, body, qs);
returnData.push(responseData as IDataObject);
}
// https://developer.box.com/reference/post-files-content
if (operation === 'upload') {
const parentId = this.getNodeParameter('parentId', i) as string;
const isBinaryData = this.getNodeParameter('binaryData', i) as boolean;
const fileName = this.getNodeParameter('fileName', i) as string;
const attributes: IDataObject = {};
if (parentId !== '') {
attributes['parent'] = { id: parentId };
} else {
// if not parent defined save it on the root directory
attributes['parent'] = { id: 0 };
}
if (isBinaryData) {
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', 0) as string;
if (items[i].binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
}
//@ts-ignore
if (items[i].binary[binaryPropertyName] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property "${binaryPropertyName}" does not exists on item!`);
}
const binaryData = (items[i].binary as IBinaryKeyData)[binaryPropertyName];
try {
if (resource === 'file') {
// https://developer.box.com/reference/post-files-id-copy
if (operation === 'copy') {
const fileId = this.getNodeParameter('fileId', i) as string;
const parentId = this.getNodeParameter('parentId', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IDataObject = {};
attributes['name'] = fileName || binaryData.fileName;
body['attributes'] = JSON.stringify(attributes);
body['file'] = {
value: Buffer.from(binaryData.data, BINARY_ENCODING),
options: {
filename: binaryData.fileName,
contentType: binaryData.mimeType,
},
};
responseData = await boxApiRequest.call(this, 'POST', '', {}, {}, 'https://upload.box.com/api/2.0/files/content', { formData: body });
returnData.push.apply(returnData, responseData.entries as IDataObject[]);
} else {
const content = this.getNodeParameter('fileContent', i) as string;
if (fileName === '') {
throw new NodeOperationError(this.getNode(), 'File name must be set!');
if (additionalFields.name) {
body.name = additionalFields.name as string;
}
attributes['name'] = fileName;
const body: IDataObject = {};
body['attributes'] = JSON.stringify(attributes);
body['file'] = {
value: Buffer.from(content),
options: {
filename: fileName,
contentType: 'text/plain',
},
};
responseData = await boxApiRequest.call(this, 'POST', '', {}, {}, 'https://upload.box.com/api/2.0/files/content', { formData: body });
returnData.push.apply(returnData, responseData.entries as IDataObject[]);
}
}
}
if (resource === 'folder') {
// https://developer.box.com/reference/post-folders
if (operation === 'create') {
const name = this.getNodeParameter('name', i) as string;
const parentId = this.getNodeParameter('parentId', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
const body: IDataObject = {
name,
};
if (parentId) {
body.parent = { id: parentId };
} else {
body.parent = { id: 0 };
}
if (options.access) {
body.folder_upload_email = {
access: options.access as string,
};
}
if (options.fields) {
qs.fields = options.fields as string;
}
responseData = await boxApiRequest.call(this, 'POST', '/folders', body, qs);
returnData.push(responseData);
}
// https://developer.box.com/reference/delete-folders-id
if (operation === 'delete') {
const folderId = this.getNodeParameter('folderId', i) as string;
const recursive = this.getNodeParameter('recursive', i) as boolean;
qs.recursive = recursive;
responseData = await boxApiRequest.call(this, 'DELETE', `/folders/${folderId}`, qs);
responseData = { success: true };
returnData.push(responseData as IDataObject);
}
// https://developer.box.com/reference/get-folders-id/
if (operation === 'get') {
const folderId = this.getNodeParameter('folderId', i) as string;
responseData = await boxApiRequest.call(this, 'GET', `/folders/${folderId}`, qs);
returnData.push(responseData as IDataObject);
}
// https://developer.box.com/reference/get-search/
if (operation === 'search') {
const query = this.getNodeParameter('query', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const timezone = this.getTimezone();
qs.type = 'folder';
qs.query = query;
Object.assign(qs, additionalFields);
if (qs.content_types) {
qs.content_types = (qs.content_types as string).split(',');
}
if (additionalFields.createdRangeUi) {
const createdRangeValues = (additionalFields.createdRangeUi as IDataObject).createdRangeValuesUi as IDataObject;
if (createdRangeValues) {
qs.created_at_range = `${moment.tz(createdRangeValues.from, timezone).format()},${moment.tz(createdRangeValues.to, timezone).format()}`;
}
delete qs.createdRangeUi;
}
if (additionalFields.updatedRangeUi) {
const updateRangeValues = (additionalFields.updatedRangeUi as IDataObject).updatedRangeValuesUi as IDataObject;
if (updateRangeValues) {
qs.updated_at_range = `${moment.tz(updateRangeValues.from, timezone).format()},${moment.tz(updateRangeValues.to, timezone).format()}`;
}
delete qs.updatedRangeUi;
}
if (returnAll) {
responseData = await boxApiRequestAllItems.call(this, 'entries', 'GET', `/search`, {}, qs);
} else {
qs.limit = this.getNodeParameter('limit', i) as number;
responseData = await boxApiRequest.call(this, 'GET', `/search`, {}, qs);
responseData = responseData.entries;
}
returnData.push.apply(returnData, responseData as IDataObject[]);
}
// https://developer.box.com/reference/post-collaborations/
if (operation === 'share') {
const folderId = this.getNodeParameter('folderId', i) as string;
const role = this.getNodeParameter('role', i) as string;
const accessibleBy = this.getNodeParameter('accessibleBy', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
// tslint:disable-next-line: no-any
const body: { accessible_by: IDataObject, [key: string]: any } = {
accessible_by: {},
item: {
id: folderId,
type: 'folder',
},
role: (role === 'coOwner') ? 'co-owner' : noCase(role),
...options,
};
if (body.fields) {
qs.fields = body.fields;
delete body.fields;
}
if (body.expires_at) {
body.expires_at = moment.tz(body.expires_at, timezone).format();
}
if (body.notify) {
qs.notify = body.notify;
delete body.notify;
}
if (accessibleBy === 'user') {
const useEmail = this.getNodeParameter('useEmail', i) as boolean;
if (useEmail) {
body.accessible_by['login'] = this.getNodeParameter('email', i) as string;
if (parentId) {
body.parent = { id: parentId };
} else {
body.accessible_by['id'] = this.getNodeParameter('userId', i) as string;
body.parent = { id: 0 };
}
} else {
body.accessible_by['id'] = this.getNodeParameter('groupId', i) as string;
if (additionalFields.fields) {
qs.fields = additionalFields.fields as string;
}
if (additionalFields.version) {
body.version = additionalFields.version as string;
}
responseData = await boxApiRequest.call(this, 'POST', `/files/${fileId}/copy`, body, qs);
returnData.push(responseData as IDataObject);
}
responseData = await boxApiRequest.call(this, 'POST', `/collaborations`, body, qs);
returnData.push(responseData as IDataObject);
}
//https://developer.box.com/guides/folders/single/move/
if (operation === 'update') {
const folderId = this.getNodeParameter('folderId', i) as string;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
if (updateFields.fields) {
qs.fields = updateFields.fields;
delete updateFields.fields;
// https://developer.box.com/reference/delete-files-id
if (operation === 'delete') {
const fileId = this.getNodeParameter('fileId', i) as string;
responseData = await boxApiRequest.call(this, 'DELETE', `/files/${fileId}`);
responseData = { success: true };
returnData.push(responseData as IDataObject);
}
// https://developer.box.com/reference/get-files-id-content
if (operation === 'download') {
const fileId = this.getNodeParameter('fileId', i) as string;
const dataPropertyNameDownload = this.getNodeParameter('binaryPropertyName', i) as string;
responseData = await boxApiRequest.call(this, 'GET', `/files/${fileId}`);
const body = {
...updateFields,
} as IDataObject;
const fileName = responseData.name;
if (body.parentId) {
body.parent = {
id: body.parentId,
let mimeType: string | undefined;
responseData = await boxApiRequest.call(this, 'GET', `/files/${fileId}/content`, {}, {}, undefined, { resolveWithFullResponse: true });
const newItem: INodeExecutionData = {
json: items[i].json,
binary: {},
};
delete body.parentId;
}
if (body.tags) {
body.tags = (body.tags as string).split(',');
}
if (mimeType === undefined && responseData.headers['content-type']) {
mimeType = responseData.headers['content-type'];
}
responseData = await boxApiRequest.call(this, 'PUT', `/folders/${folderId}`, body, qs);
returnData.push(responseData as IDataObject);
if (items[i].binary !== undefined) {
// Create a shallow copy of the binary data so that the old
// data references which do not get changed still stay behind
// but the incoming data does not get changed.
Object.assign(newItem.binary, items[i].binary);
}
items[i] = newItem;
const data = Buffer.from(responseData.body);
items[i].binary![dataPropertyNameDownload] = await this.helpers.prepareBinaryData(data as unknown as Buffer, fileName, mimeType);
}
// https://developer.box.com/reference/get-files-id
if (operation === 'get') {
const fileId = this.getNodeParameter('fileId', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (additionalFields.fields) {
qs.fields = additionalFields.fields as string;
}
responseData = await boxApiRequest.call(this, 'GET', `/files/${fileId}`, {}, qs);
returnData.push(responseData as IDataObject);
}
// https://developer.box.com/reference/get-search/
if (operation === 'search') {
const query = this.getNodeParameter('query', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const timezone = this.getTimezone();
qs.type = 'file';
qs.query = query;
Object.assign(qs, additionalFields);
if (qs.content_types) {
qs.content_types = (qs.content_types as string).split(',');
}
if (additionalFields.createdRangeUi) {
const createdRangeValues = (additionalFields.createdRangeUi as IDataObject).createdRangeValuesUi as IDataObject;
if (createdRangeValues) {
qs.created_at_range = `${moment.tz(createdRangeValues.from, timezone).format()},${moment.tz(createdRangeValues.to, timezone).format()}`;
}
delete qs.createdRangeUi;
}
if (additionalFields.updatedRangeUi) {
const updateRangeValues = (additionalFields.updatedRangeUi as IDataObject).updatedRangeValuesUi as IDataObject;
if (updateRangeValues) {
qs.updated_at_range = `${moment.tz(updateRangeValues.from, timezone).format()},${moment.tz(updateRangeValues.to, timezone).format()}`;
}
delete qs.updatedRangeUi;
}
if (returnAll) {
responseData = await boxApiRequestAllItems.call(this, 'entries', 'GET', `/search`, {}, qs);
} else {
qs.limit = this.getNodeParameter('limit', i) as number;
responseData = await boxApiRequest.call(this, 'GET', `/search`, {}, qs);
responseData = responseData.entries;
}
returnData.push.apply(returnData, responseData as IDataObject[]);
}
// https://developer.box.com/reference/post-collaborations/
if (operation === 'share') {
const fileId = this.getNodeParameter('fileId', i) as string;
const role = this.getNodeParameter('role', i) as string;
const accessibleBy = this.getNodeParameter('accessibleBy', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
// tslint:disable-next-line: no-any
const body: { accessible_by: IDataObject, [key: string]: any } = {
accessible_by: {},
item: {
id: fileId,
type: 'file',
},
role: (role === 'coOwner') ? 'co-owner' : noCase(role),
...options,
};
if (body.fields) {
qs.fields = body.fields;
delete body.fields;
}
if (body.expires_at) {
body.expires_at = moment.tz(body.expires_at, timezone).format();
}
if (body.notify) {
qs.notify = body.notify;
delete body.notify;
}
if (accessibleBy === 'user') {
const useEmail = this.getNodeParameter('useEmail', i) as boolean;
if (useEmail) {
body.accessible_by['login'] = this.getNodeParameter('email', i) as string;
} else {
body.accessible_by['id'] = this.getNodeParameter('userId', i) as string;
}
} else {
body.accessible_by['id'] = this.getNodeParameter('groupId', i) as string;
}
responseData = await boxApiRequest.call(this, 'POST', `/collaborations`, body, qs);
returnData.push(responseData as IDataObject);
}
// https://developer.box.com/reference/post-files-content
if (operation === 'upload') {
const parentId = this.getNodeParameter('parentId', i) as string;
const isBinaryData = this.getNodeParameter('binaryData', i) as boolean;
const fileName = this.getNodeParameter('fileName', i) as string;
const attributes: IDataObject = {};
if (parentId !== '') {
attributes['parent'] = { id: parentId };
} else {
// if not parent defined save it on the root directory
attributes['parent'] = { id: 0 };
}
if (isBinaryData) {
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', 0) as string;
if (items[i].binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
}
//@ts-ignore
if (items[i].binary[binaryPropertyName] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property "${binaryPropertyName}" does not exists on item!`);
}
const binaryData = (items[i].binary as IBinaryKeyData)[binaryPropertyName];
const body: IDataObject = {};
attributes['name'] = fileName || binaryData.fileName;
body['attributes'] = JSON.stringify(attributes);
body['file'] = {
value: Buffer.from(binaryData.data, BINARY_ENCODING),
options: {
filename: binaryData.fileName,
contentType: binaryData.mimeType,
},
};
responseData = await boxApiRequest.call(this, 'POST', '', {}, {}, 'https://upload.box.com/api/2.0/files/content', { formData: body });
returnData.push.apply(returnData, responseData.entries as IDataObject[]);
} else {
const content = this.getNodeParameter('fileContent', i) as string;
if (fileName === '') {
throw new NodeOperationError(this.getNode(), 'File name must be set!');
}
attributes['name'] = fileName;
const body: IDataObject = {};
body['attributes'] = JSON.stringify(attributes);
body['file'] = {
value: Buffer.from(content),
options: {
filename: fileName,
contentType: 'text/plain',
},
};
responseData = await boxApiRequest.call(this, 'POST', '', {}, {}, 'https://upload.box.com/api/2.0/files/content', { formData: body });
returnData.push.apply(returnData, responseData.entries as IDataObject[]);
}
}
}
if (resource === 'folder') {
// https://developer.box.com/reference/post-folders
if (operation === 'create') {
const name = this.getNodeParameter('name', i) as string;
const parentId = this.getNodeParameter('parentId', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
const body: IDataObject = {
name,
};
if (parentId) {
body.parent = { id: parentId };
} else {
body.parent = { id: 0 };
}
if (options.access) {
body.folder_upload_email = {
access: options.access as string,
};
}
if (options.fields) {
qs.fields = options.fields as string;
}
responseData = await boxApiRequest.call(this, 'POST', '/folders', body, qs);
returnData.push(responseData);
}
// https://developer.box.com/reference/delete-folders-id
if (operation === 'delete') {
const folderId = this.getNodeParameter('folderId', i) as string;
const recursive = this.getNodeParameter('recursive', i) as boolean;
qs.recursive = recursive;
responseData = await boxApiRequest.call(this, 'DELETE', `/folders/${folderId}`, qs);
responseData = { success: true };
returnData.push(responseData as IDataObject);
}
// https://developer.box.com/reference/get-folders-id/
if (operation === 'get') {
const folderId = this.getNodeParameter('folderId', i) as string;
responseData = await boxApiRequest.call(this, 'GET', `/folders/${folderId}`, qs);
returnData.push(responseData as IDataObject);
}
// https://developer.box.com/reference/get-search/
if (operation === 'search') {
const query = this.getNodeParameter('query', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const timezone = this.getTimezone();
qs.type = 'folder';
qs.query = query;
Object.assign(qs, additionalFields);
if (qs.content_types) {
qs.content_types = (qs.content_types as string).split(',');
}
if (additionalFields.createdRangeUi) {
const createdRangeValues = (additionalFields.createdRangeUi as IDataObject).createdRangeValuesUi as IDataObject;
if (createdRangeValues) {
qs.created_at_range = `${moment.tz(createdRangeValues.from, timezone).format()},${moment.tz(createdRangeValues.to, timezone).format()}`;
}
delete qs.createdRangeUi;
}
if (additionalFields.updatedRangeUi) {
const updateRangeValues = (additionalFields.updatedRangeUi as IDataObject).updatedRangeValuesUi as IDataObject;
if (updateRangeValues) {
qs.updated_at_range = `${moment.tz(updateRangeValues.from, timezone).format()},${moment.tz(updateRangeValues.to, timezone).format()}`;
}
delete qs.updatedRangeUi;
}
if (returnAll) {
responseData = await boxApiRequestAllItems.call(this, 'entries', 'GET', `/search`, {}, qs);
} else {
qs.limit = this.getNodeParameter('limit', i) as number;
responseData = await boxApiRequest.call(this, 'GET', `/search`, {}, qs);
responseData = responseData.entries;
}
returnData.push.apply(returnData, responseData as IDataObject[]);
}
// https://developer.box.com/reference/post-collaborations/
if (operation === 'share') {
const folderId = this.getNodeParameter('folderId', i) as string;
const role = this.getNodeParameter('role', i) as string;
const accessibleBy = this.getNodeParameter('accessibleBy', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
// tslint:disable-next-line: no-any
const body: { accessible_by: IDataObject, [key: string]: any } = {
accessible_by: {},
item: {
id: folderId,
type: 'folder',
},
role: (role === 'coOwner') ? 'co-owner' : noCase(role),
...options,
};
if (body.fields) {
qs.fields = body.fields;
delete body.fields;
}
if (body.expires_at) {
body.expires_at = moment.tz(body.expires_at, timezone).format();
}
if (body.notify) {
qs.notify = body.notify;
delete body.notify;
}
if (accessibleBy === 'user') {
const useEmail = this.getNodeParameter('useEmail', i) as boolean;
if (useEmail) {
body.accessible_by['login'] = this.getNodeParameter('email', i) as string;
} else {
body.accessible_by['id'] = this.getNodeParameter('userId', i) as string;
}
} else {
body.accessible_by['id'] = this.getNodeParameter('groupId', i) as string;
}
responseData = await boxApiRequest.call(this, 'POST', `/collaborations`, body, qs);
returnData.push(responseData as IDataObject);
}
//https://developer.box.com/guides/folders/single/move/
if (operation === 'update') {
const folderId = this.getNodeParameter('folderId', i) as string;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
if (updateFields.fields) {
qs.fields = updateFields.fields;
delete updateFields.fields;
}
const body = {
...updateFields,
} as IDataObject;
if (body.parentId) {
body.parent = {
id: body.parentId,
};
delete body.parentId;
}
if (body.tags) {
body.tags = (body.tags as string).split(',');
}
responseData = await boxApiRequest.call(this, 'PUT', `/folders/${folderId}`, body, qs);
returnData.push(responseData as IDataObject);
}
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
if (resource === 'file' && operation === 'download') {

View file

@ -167,97 +167,105 @@ export class Brandfetch implements INodeType {
const operation = this.getNodeParameter('operation', 0) as string;
const responseData = [];
for (let i = 0; i < length; i++) {
if (operation === 'logo') {
const domain = this.getNodeParameter('domain', i) as string;
const download = this.getNodeParameter('download', i) as boolean;
try {
if (operation === 'logo') {
const domain = this.getNodeParameter('domain', i) as string;
const download = this.getNodeParameter('download', i) as boolean;
const body: IDataObject = {
domain,
};
const response = await brandfetchApiRequest.call(this, 'POST', `/logo`, body);
if (download === true) {
const imageTypes = this.getNodeParameter('imageTypes', i) as string[];
const imageFormats = this.getNodeParameter('imageFormats', i) as string[];
const newItem: INodeExecutionData = {
json: {},
binary: {},
const body: IDataObject = {
domain,
};
if (items[i].binary !== undefined) {
// Create a shallow copy of the binary data so that the old
// data references which do not get changed still stay behind
// but the incoming data does not get changed.
Object.assign(newItem.binary, items[i].binary);
}
const response = await brandfetchApiRequest.call(this, 'POST', `/logo`, body);
newItem.json = response.response;
if (download === true) {
for (const imageType of imageTypes) {
for (const imageFormat of imageFormats) {
const imageTypes = this.getNodeParameter('imageTypes', i) as string[];
const url = response.response[imageType][(imageFormat === 'png') ? 'image' : imageFormat] as string;
const imageFormats = this.getNodeParameter('imageFormats', i) as string[];
if (url !== null) {
const data = await brandfetchApiRequest.call(this, 'GET', '', {}, {}, url, { json: false, encoding: null });
const newItem: INodeExecutionData = {
json: {},
binary: {},
};
newItem.binary![`${imageType}_${imageFormat}`] = await this.helpers.prepareBinaryData(data, `${imageType}_${domain}.${imageFormat}`);
if (items[i].binary !== undefined) {
// Create a shallow copy of the binary data so that the old
// data references which do not get changed still stay behind
// but the incoming data does not get changed.
Object.assign(newItem.binary, items[i].binary);
}
newItem.json = response.response;
for (const imageType of imageTypes) {
for (const imageFormat of imageFormats) {
const url = response.response[imageType][(imageFormat === 'png') ? 'image' : imageFormat] as string;
if (url !== null) {
const data = await brandfetchApiRequest.call(this, 'GET', '', {}, {}, url, { json: false, encoding: null });
newItem.binary![`${imageType}_${imageFormat}`] = await this.helpers.prepareBinaryData(data, `${imageType}_${domain}.${imageFormat}`);
items[i] = newItem;
}
items[i] = newItem;
}
items[i] = newItem;
}
if (Object.keys(items[i].binary!).length === 0) {
delete items[i].binary;
}
} else {
responseData.push(response.response);
}
if (Object.keys(items[i].binary!).length === 0) {
delete items[i].binary;
}
} else {
}
if (operation === 'color') {
const domain = this.getNodeParameter('domain', i) as string;
const body: IDataObject = {
domain,
};
const response = await brandfetchApiRequest.call(this, 'POST', `/color`, body);
responseData.push(response.response);
}
}
if (operation === 'color') {
const domain = this.getNodeParameter('domain', i) as string;
if (operation === 'font') {
const domain = this.getNodeParameter('domain', i) as string;
const body: IDataObject = {
domain,
};
const body: IDataObject = {
domain,
};
const response = await brandfetchApiRequest.call(this, 'POST', `/color`, body);
responseData.push(response.response);
}
if (operation === 'font') {
const domain = this.getNodeParameter('domain', i) as string;
const response = await brandfetchApiRequest.call(this, 'POST', `/font`, body);
responseData.push(response.response);
}
if (operation === 'company') {
const domain = this.getNodeParameter('domain', i) as string;
const body: IDataObject = {
domain,
};
const body: IDataObject = {
domain,
};
const response = await brandfetchApiRequest.call(this, 'POST', `/font`, body);
responseData.push(response.response);
}
if (operation === 'company') {
const domain = this.getNodeParameter('domain', i) as string;
const response = await brandfetchApiRequest.call(this, 'POST', `/company`, body);
responseData.push(response.response);
}
if (operation === 'industry') {
const domain = this.getNodeParameter('domain', i) as string;
const body: IDataObject = {
domain,
};
const body: IDataObject = {
domain,
};
const response = await brandfetchApiRequest.call(this, 'POST', `/company`, body);
responseData.push(response.response);
}
if (operation === 'industry') {
const domain = this.getNodeParameter('domain', i) as string;
const body: IDataObject = {
domain,
};
const response = await brandfetchApiRequest.call(this, 'POST', `/industry`, body);
responseData.push.apply(responseData, response.response);
const response = await brandfetchApiRequest.call(this, 'POST', `/industry`, body);
responseData.push.apply(responseData, response.response);
}
} catch (error) {
if (this.continueOnFail()) {
responseData.push({ error: error.message });
continue;
}
throw error;
}
}

View file

@ -502,139 +502,146 @@ export class Chargebee implements INodeType {
let qs: IDataObject;
for (let i = 0; i < items.length; i++) {
item = items[i];
const resource = this.getNodeParameter('resource', i) as string;
const operation = this.getNodeParameter('operation', i) as string;
let requestMethod = 'GET';
let endpoint = '';
body = {};
qs = {};
if (resource === 'customer') {
if (operation === 'create') {
// ----------------------------------
// create
// ----------------------------------
requestMethod = 'POST';
const properties = this.getNodeParameter('properties', i, {}) as IDataObject;
for (const key of Object.keys(properties)) {
if (key === 'customProperties' && (properties.customProperties as IDataObject).property !== undefined) {
for (const customProperty of (properties.customProperties as IDataObject)!.property! as CustomProperty[]) {
qs[customProperty.name] = customProperty.value;
}
} else {
qs[key] = properties[key];
}
}
endpoint = `customers`;
} else {
throw new NodeOperationError(this.getNode(), `The operation "${operation}" is not known!`);
}
} else if (resource === 'invoice') {
if (operation === 'list') {
// ----------------------------------
// list
// ----------------------------------
endpoint = 'invoices';
// TODO: Make also sorting configurable
qs['sort_by[desc]'] = 'date';
qs.limit = this.getNodeParameter('maxResults', i, {});
const setFilters: FilterValues = this.getNodeParameter('filters', i, {}) as unknown as FilterValues;
let filter: FilterValue;
let value: NodeParameterValue;
for (const filterProperty of Object.keys(setFilters)) {
for (filter of setFilters[filterProperty]) {
value = filter.value;
if (filterProperty === 'date') {
value = Math.floor(new Date(value as string).getTime() / 1000);
}
qs[`${filterProperty}[${filter.operation}]`] = value;
}
}
} else if (operation === 'pdfUrl') {
// ----------------------------------
// pdfUrl
// ----------------------------------
requestMethod = 'POST';
const invoiceId = this.getNodeParameter('invoiceId', i) as string;
endpoint = `invoices/${invoiceId.trim()}/pdf`;
} else {
throw new NodeOperationError(this.getNode(), `The operation "${operation}" is not known!`);
}
} else if (resource === 'subscription') {
if (operation === 'cancel') {
// ----------------------------------
// cancel
// ----------------------------------
requestMethod = 'POST';
const subscriptionId = this.getNodeParameter('subscriptionId', i, '') as string;
body.end_of_term = this.getNodeParameter('endOfTerm', i, false) as boolean;
endpoint = `subscriptions/${subscriptionId.trim()}/cancel`;
} else if (operation === 'delete') {
// ----------------------------------
// delete
// ----------------------------------
requestMethod = 'POST';
const subscriptionId = this.getNodeParameter('subscriptionId', i, '') as string;
endpoint = `subscriptions/${subscriptionId.trim()}/delete`;
} else {
throw new NodeOperationError(this.getNode(), `The operation "${operation}" is not known!`);
}
} else {
throw new NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`);
}
const options = {
method: requestMethod,
body,
qs,
uri: `${baseUrl}/${endpoint}`,
auth: {
user: credentials.apiKey as string,
pass: '',
},
json: true,
};
let responseData;
try {
responseData = await this.helpers.request!(options);
item = items[i];
const resource = this.getNodeParameter('resource', i) as string;
const operation = this.getNodeParameter('operation', i) as string;
let requestMethod = 'GET';
let endpoint = '';
body = {};
qs = {};
if (resource === 'customer') {
if (operation === 'create') {
// ----------------------------------
// create
// ----------------------------------
requestMethod = 'POST';
const properties = this.getNodeParameter('properties', i, {}) as IDataObject;
for (const key of Object.keys(properties)) {
if (key === 'customProperties' && (properties.customProperties as IDataObject).property !== undefined) {
for (const customProperty of (properties.customProperties as IDataObject)!.property! as CustomProperty[]) {
qs[customProperty.name] = customProperty.value;
}
} else {
qs[key] = properties[key];
}
}
endpoint = `customers`;
} else {
throw new NodeOperationError(this.getNode(), `The operation "${operation}" is not known!`);
}
} else if (resource === 'invoice') {
if (operation === 'list') {
// ----------------------------------
// list
// ----------------------------------
endpoint = 'invoices';
// TODO: Make also sorting configurable
qs['sort_by[desc]'] = 'date';
qs.limit = this.getNodeParameter('maxResults', i, {});
const setFilters: FilterValues = this.getNodeParameter('filters', i, {}) as unknown as FilterValues;
let filter: FilterValue;
let value: NodeParameterValue;
for (const filterProperty of Object.keys(setFilters)) {
for (filter of setFilters[filterProperty]) {
value = filter.value;
if (filterProperty === 'date') {
value = Math.floor(new Date(value as string).getTime() / 1000);
}
qs[`${filterProperty}[${filter.operation}]`] = value;
}
}
} else if (operation === 'pdfUrl') {
// ----------------------------------
// pdfUrl
// ----------------------------------
requestMethod = 'POST';
const invoiceId = this.getNodeParameter('invoiceId', i) as string;
endpoint = `invoices/${invoiceId.trim()}/pdf`;
} else {
throw new NodeOperationError(this.getNode(), `The operation "${operation}" is not known!`);
}
} else if (resource === 'subscription') {
if (operation === 'cancel') {
// ----------------------------------
// cancel
// ----------------------------------
requestMethod = 'POST';
const subscriptionId = this.getNodeParameter('subscriptionId', i, '') as string;
body.end_of_term = this.getNodeParameter('endOfTerm', i, false) as boolean;
endpoint = `subscriptions/${subscriptionId.trim()}/cancel`;
} else if (operation === 'delete') {
// ----------------------------------
// delete
// ----------------------------------
requestMethod = 'POST';
const subscriptionId = this.getNodeParameter('subscriptionId', i, '') as string;
endpoint = `subscriptions/${subscriptionId.trim()}/delete`;
} else {
throw new NodeOperationError(this.getNode(), `The operation "${operation}" is not known!`);
}
} else {
throw new NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`);
}
const options = {
method: requestMethod,
body,
qs,
uri: `${baseUrl}/${endpoint}`,
auth: {
user: credentials.apiKey as string,
pass: '',
},
json: true,
};
let responseData;
try {
responseData = await this.helpers.request!(options);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
if (resource === 'invoice' && operation === 'list') {
responseData.list.forEach((data: IDataObject) => {
returnData.push(data.invoice as IDataObject);
});
} else if (resource === 'invoice' && operation === 'pdfUrl') {
const data: IDataObject = {};
Object.assign(data, items[i].json);
data.pdfUrl = responseData.download.download_url;
returnData.push(data);
} else {
returnData.push(responseData);
}
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
if (resource === 'invoice' && operation === 'list') {
responseData.list.forEach((data: IDataObject) => {
returnData.push(data.invoice as IDataObject);
});
} else if (resource === 'invoice' && operation === 'pdfUrl') {
const data: IDataObject = {};
Object.assign(data, items[i].json);
data.pdfUrl = responseData.download.download_url;
returnData.push(data);
} else {
returnData.push(responseData);
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}

View file

@ -69,70 +69,78 @@ export class CircleCi implements INodeType {
const operation = this.getNodeParameter('operation', 0) as string;
for (let i = 0; i < length; i++) {
if (resource === 'pipeline') {
if (operation === 'get') {
const vcs = this.getNodeParameter('vcs', i) as string;
let slug = this.getNodeParameter('projectSlug', i) as string;
const pipelineNumber = this.getNodeParameter('pipelineNumber', i) as number;
try {
if (resource === 'pipeline') {
if (operation === 'get') {
const vcs = this.getNodeParameter('vcs', i) as string;
let slug = this.getNodeParameter('projectSlug', i) as string;
const pipelineNumber = this.getNodeParameter('pipelineNumber', i) as number;
slug = slug.replace(new RegExp(/\//g), '%2F');
slug = slug.replace(new RegExp(/\//g), '%2F');
const endpoint = `/project/${vcs}/${slug}/pipeline/${pipelineNumber}`;
const endpoint = `/project/${vcs}/${slug}/pipeline/${pipelineNumber}`;
responseData = await circleciApiRequest.call(this, 'GET', endpoint, {}, qs);
}
if (operation === 'getAll') {
const vcs = this.getNodeParameter('vcs', i) as string;
const filters = this.getNodeParameter('filters', i) as IDataObject;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
let slug = this.getNodeParameter('projectSlug', i) as string;
slug = slug.replace(new RegExp(/\//g), '%2F');
if (filters.branch) {
qs.branch = filters.branch;
}
const endpoint = `/project/${vcs}/${slug}/pipeline`;
if (returnAll === true) {
responseData = await circleciApiRequestAllItems.call(this, 'items', 'GET', endpoint, {}, qs);
} else {
qs.limit = this.getNodeParameter('limit', i) as number;
responseData = await circleciApiRequest.call(this, 'GET', endpoint, {}, qs);
responseData = responseData.items;
responseData = responseData.splice(0, qs.limit);
}
if (operation === 'getAll') {
const vcs = this.getNodeParameter('vcs', i) as string;
const filters = this.getNodeParameter('filters', i) as IDataObject;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
let slug = this.getNodeParameter('projectSlug', i) as string;
slug = slug.replace(new RegExp(/\//g), '%2F');
if (filters.branch) {
qs.branch = filters.branch;
}
const endpoint = `/project/${vcs}/${slug}/pipeline`;
if (returnAll === true) {
responseData = await circleciApiRequestAllItems.call(this, 'items', 'GET', endpoint, {}, qs);
} else {
qs.limit = this.getNodeParameter('limit', i) as number;
responseData = await circleciApiRequest.call(this, 'GET', endpoint, {}, qs);
responseData = responseData.items;
responseData = responseData.splice(0, qs.limit);
}
}
if (operation === 'trigger') {
const vcs = this.getNodeParameter('vcs', i) as string;
let slug = this.getNodeParameter('projectSlug', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
slug = slug.replace(new RegExp(/\//g), '%2F');
const endpoint = `/project/${vcs}/${slug}/pipeline`;
const body: IDataObject = {};
if (additionalFields.branch) {
body.branch = additionalFields.branch as string;
}
if (additionalFields.tag) {
body.tag = additionalFields.tag as string;
}
responseData = await circleciApiRequest.call(this, 'POST', endpoint, body, qs);
}
}
if (operation === 'trigger') {
const vcs = this.getNodeParameter('vcs', i) as string;
let slug = this.getNodeParameter('projectSlug', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
slug = slug.replace(new RegExp(/\//g), '%2F');
const endpoint = `/project/${vcs}/${slug}/pipeline`;
const body: IDataObject = {};
if (additionalFields.branch) {
body.branch = additionalFields.branch as string;
}
if (additionalFields.tag) {
body.tag = additionalFields.tag as string;
}
responseData = await circleciApiRequest.call(this, 'POST', endpoint, body, qs);
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];

View file

@ -81,70 +81,78 @@ export class Clearbit implements INodeType {
const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string;
for (let i = 0; i < length; i++) {
if (resource === 'person') {
if (operation === 'enrich') {
const email = this.getNodeParameter('email', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
qs.email = email;
if (additionalFields.givenName) {
qs.given_name = additionalFields.givenName as string;
try {
if (resource === 'person') {
if (operation === 'enrich') {
const email = this.getNodeParameter('email', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
qs.email = email;
if (additionalFields.givenName) {
qs.given_name = additionalFields.givenName as string;
}
if (additionalFields.familyName) {
qs.family_name = additionalFields.familyName as string;
}
if (additionalFields.ipAddress) {
qs.ip_address = additionalFields.ipAddress as string;
}
if (additionalFields.location) {
qs.location = additionalFields.location as string;
}
if (additionalFields.company) {
qs.company = additionalFields.company as string;
}
if (additionalFields.companyDomain) {
qs.company_domain = additionalFields.companyDomain as string;
}
if (additionalFields.linkedIn) {
qs.linkedin = additionalFields.linkedIn as string;
}
if (additionalFields.twitter) {
qs.twitter = additionalFields.twitter as string;
}
if (additionalFields.facebook) {
qs.facebook = additionalFields.facebook as string;
}
responseData = await clearbitApiRequest.call(this, 'GET', `${resource}-stream`, '/v2/people/find', {}, qs);
}
if (additionalFields.familyName) {
qs.family_name = additionalFields.familyName as string;
}
if (additionalFields.ipAddress) {
qs.ip_address = additionalFields.ipAddress as string;
}
if (additionalFields.location) {
qs.location = additionalFields.location as string;
}
if (additionalFields.company) {
qs.company = additionalFields.company as string;
}
if (additionalFields.companyDomain) {
qs.company_domain = additionalFields.companyDomain as string;
}
if (additionalFields.linkedIn) {
qs.linkedin = additionalFields.linkedIn as string;
}
if (additionalFields.twitter) {
qs.twitter = additionalFields.twitter as string;
}
if (additionalFields.facebook) {
qs.facebook = additionalFields.facebook as string;
}
responseData = await clearbitApiRequest.call(this, 'GET', `${resource}-stream`, '/v2/people/find', {}, qs);
}
}
if (resource === 'company') {
if (operation === 'enrich') {
const domain = this.getNodeParameter('domain', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
qs.domain = domain;
if (additionalFields.companyName) {
qs.company_name = additionalFields.companyName as string;
if (resource === 'company') {
if (operation === 'enrich') {
const domain = this.getNodeParameter('domain', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
qs.domain = domain;
if (additionalFields.companyName) {
qs.company_name = additionalFields.companyName as string;
}
if (additionalFields.linkedin) {
qs.linkedin = additionalFields.linkedin as string;
}
if (additionalFields.twitter) {
qs.twitter = additionalFields.twitter as string;
}
if (additionalFields.facebook) {
qs.facebook = additionalFields.facebook as string;
}
responseData = await clearbitApiRequest.call(this, 'GET', `${resource}-stream`, '/v2/companies/find', {}, qs);
}
if (additionalFields.linkedin) {
qs.linkedin = additionalFields.linkedin as string;
if (operation === 'autocomplete') {
const name = this.getNodeParameter('name', i) as string;
qs.query = name;
responseData = await clearbitApiRequest.call(this, 'GET', 'autocomplete', '/v1/companies/suggest', {}, qs);
}
if (additionalFields.twitter) {
qs.twitter = additionalFields.twitter as string;
}
if (additionalFields.facebook) {
qs.facebook = additionalFields.facebook as string;
}
responseData = await clearbitApiRequest.call(this, 'GET', `${resource}-stream`, '/v2/companies/find', {}, qs);
}
if (operation === 'autocomplete') {
const name = this.getNodeParameter('name', i) as string;
qs.query = name;
responseData = await clearbitApiRequest.call(this, 'GET', 'autocomplete', '/v1/companies/suggest', {}, qs);
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];

File diff suppressed because it is too large Load diff

View file

@ -233,354 +233,362 @@ export class Clockify implements INodeType {
for (let i = 0; i < length; i++) {
if (resource === 'project') {
try {
if (resource === 'project') {
if (operation === 'create') {
if (operation === 'create') {
const workspaceId = this.getNodeParameter('workspaceId', i) as string;
const workspaceId = this.getNodeParameter('workspaceId', i) as string;
const name = this.getNodeParameter('name', i) as string;
const name = this.getNodeParameter('name', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IDataObject = {
name,
};
const body: IDataObject = {
name,
};
Object.assign(body, additionalFields);
Object.assign(body, additionalFields);
if (body.estimateUi) {
if (body.estimateUi) {
body.estimate = (body.estimateUi as IDataObject).estimateValues;
body.estimate = (body.estimateUi as IDataObject).estimateValues;
delete body.estimateUi;
}
delete body.estimateUi;
}
responseData = await clockifyApiRequest.call(
this,
'POST',
`/workspaces/${workspaceId}/projects`,
body,
qs,
);
}
if (operation === 'delete') {
const workspaceId = this.getNodeParameter('workspaceId', i) as string;
const projectId = this.getNodeParameter('projectId', i) as string;
responseData = await clockifyApiRequest.call(
this,
'DELETE',
`/workspaces/${workspaceId}/projects/${projectId}`,
{},
qs,
);
responseData = { success: true };
}
if (operation === 'get') {
const workspaceId = this.getNodeParameter('workspaceId', i) as string;
const projectId = this.getNodeParameter('projectId', i) as string;
responseData = await clockifyApiRequest.call(
this,
'GET',
`/workspaces/${workspaceId}/projects/${projectId}`,
{},
qs,
);
}
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const workspaceId = this.getNodeParameter('workspaceId', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
Object.assign(qs, additionalFields);
if (returnAll) {
responseData = await clockifyApiRequestAllItems.call(
responseData = await clockifyApiRequest.call(
this,
'GET',
'POST',
`/workspaces/${workspaceId}/projects`,
body,
qs,
);
}
if (operation === 'delete') {
const workspaceId = this.getNodeParameter('workspaceId', i) as string;
const projectId = this.getNodeParameter('projectId', i) as string;
responseData = await clockifyApiRequest.call(
this,
'DELETE',
`/workspaces/${workspaceId}/projects/${projectId}`,
{},
qs,
);
} else {
responseData = { success: true };
}
qs.limit = this.getNodeParameter('limit', i) as number;
if (operation === 'get') {
responseData = await clockifyApiRequestAllItems.call(
const workspaceId = this.getNodeParameter('workspaceId', i) as string;
const projectId = this.getNodeParameter('projectId', i) as string;
responseData = await clockifyApiRequest.call(
this,
'GET',
`/workspaces/${workspaceId}/projects`,
`/workspaces/${workspaceId}/projects/${projectId}`,
{},
qs,
);
responseData = responseData.splice(0, qs.limit);
}
}
if (operation === 'update') {
const workspaceId = this.getNodeParameter('workspaceId', i) as string;
const projectId = this.getNodeParameter('projectId', i) as string;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const body: IDataObject = {};
Object.assign(body, updateFields);
if (body.estimateUi) {
body.estimate = (body.estimateUi as IDataObject).estimateValues;
delete body.estimateUi;
}
responseData = await clockifyApiRequest.call(
this,
'PUT',
`/workspaces/${workspaceId}/projects/${projectId}`,
body,
qs,
);
}
}
if (operation === 'getAll') {
if (resource === 'tag') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
if (operation === 'create') {
const workspaceId = this.getNodeParameter('workspaceId', i) as string;
const workspaceId = this.getNodeParameter('workspaceId', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const name = this.getNodeParameter('name', i) as string;
Object.assign(qs, additionalFields);
const body: IDataObject = {
name,
};
if (returnAll) {
responseData = await clockifyApiRequestAllItems.call(
this,
'GET',
`/workspaces/${workspaceId}/projects`,
{},
qs,
);
responseData = await clockifyApiRequest.call(
this,
'POST',
`/workspaces/${workspaceId}/tags`,
body,
qs,
);
}
} else {
if (operation === 'delete') {
qs.limit = this.getNodeParameter('limit', i) as number;
const workspaceId = this.getNodeParameter('workspaceId', i) as string;
responseData = await clockifyApiRequestAllItems.call(
this,
'GET',
`/workspaces/${workspaceId}/projects`,
{},
qs,
);
const tagId = this.getNodeParameter('tagId', i) as string;
responseData = responseData.splice(0, qs.limit);
}
}
responseData = await clockifyApiRequest.call(
this,
'DELETE',
`/workspaces/${workspaceId}/tags/${tagId}`,
{},
qs,
);
if (operation === 'update') {
responseData = { success: true };
}
const workspaceId = this.getNodeParameter('workspaceId', i) as string;
if (operation === 'getAll') {
const projectId = this.getNodeParameter('projectId', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const workspaceId = this.getNodeParameter('workspaceId', i) as string;
const body: IDataObject = {};
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
Object.assign(body, updateFields);
Object.assign(qs, additionalFields);
if (body.estimateUi) {
if (returnAll) {
responseData = await clockifyApiRequestAllItems.call(
body.estimate = (body.estimateUi as IDataObject).estimateValues;
delete body.estimateUi;
}
responseData = await clockifyApiRequest.call(
this,
'GET',
'PUT',
`/workspaces/${workspaceId}/projects/${projectId}`,
body,
qs,
);
}
}
if (resource === 'tag') {
if (operation === 'create') {
const workspaceId = this.getNodeParameter('workspaceId', i) as string;
const name = this.getNodeParameter('name', i) as string;
const body: IDataObject = {
name,
};
responseData = await clockifyApiRequest.call(
this,
'POST',
`/workspaces/${workspaceId}/tags`,
{},
body,
qs,
);
}
} else {
if (operation === 'delete') {
qs.limit = this.getNodeParameter('limit', i) as number;
const workspaceId = this.getNodeParameter('workspaceId', i) as string;
responseData = await clockifyApiRequestAllItems.call(
const tagId = this.getNodeParameter('tagId', i) as string;
responseData = await clockifyApiRequest.call(
this,
'GET',
`/workspaces/${workspaceId}/tags`,
'DELETE',
`/workspaces/${workspaceId}/tags/${tagId}`,
{},
qs,
);
responseData = responseData.splice(0, qs.limit);
responseData = { success: true };
}
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const workspaceId = this.getNodeParameter('workspaceId', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
Object.assign(qs, additionalFields);
if (returnAll) {
responseData = await clockifyApiRequestAllItems.call(
this,
'GET',
`/workspaces/${workspaceId}/tags`,
{},
qs,
);
} else {
qs.limit = this.getNodeParameter('limit', i) as number;
responseData = await clockifyApiRequestAllItems.call(
this,
'GET',
`/workspaces/${workspaceId}/tags`,
{},
qs,
);
responseData = responseData.splice(0, qs.limit);
}
}
if (operation === 'update') {
const workspaceId = this.getNodeParameter('workspaceId', i) as string;
const tagId = this.getNodeParameter('tagId', i) as string;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const body: IDataObject = {};
Object.assign(body, updateFields);
responseData = await clockifyApiRequest.call(
this,
'PUT',
`/workspaces/${workspaceId}/tags/${tagId}`,
body,
qs,
);
}
}
if (operation === 'update') {
if (resource === 'timeEntry') {
const workspaceId = this.getNodeParameter('workspaceId', i) as string;
if (operation === 'create') {
const tagId = this.getNodeParameter('tagId', i) as string;
const timezone = this.getTimezone();
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const workspaceId = this.getNodeParameter('workspaceId', i) as string;
const body: IDataObject = {};
const start = this.getNodeParameter('start', i) as string;
Object.assign(body, updateFields);
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
responseData = await clockifyApiRequest.call(
this,
'PUT',
`/workspaces/${workspaceId}/tags/${tagId}`,
body,
qs,
);
}
}
const body: IDataObject = {
start: moment.tz(start, timezone).utc().format(),
};
if (resource === 'timeEntry') {
Object.assign(body, additionalFields);
if (operation === 'create') {
if (body.end) {
body.end = moment.tz(body.end, timezone).utc().format();
}
const timezone = this.getTimezone();
if (body.customFieldsUi) {
const workspaceId = this.getNodeParameter('workspaceId', i) as string;
const customFields = (body.customFieldsUi as IDataObject).customFieldsValues as IDataObject[];
const start = this.getNodeParameter('start', i) as string;
body.customFields = customFields;
}
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IDataObject = {
start: moment.tz(start, timezone).utc().format(),
};
Object.assign(body, additionalFields);
if (body.end) {
body.end = moment.tz(body.end, timezone).utc().format();
responseData = await clockifyApiRequest.call(
this,
'POST',
`/workspaces/${workspaceId}/time-entries`,
body,
qs,
);
}
if (body.customFieldsUi) {
if (operation === 'delete') {
const customFields = (body.customFieldsUi as IDataObject).customFieldsValues as IDataObject[];
const workspaceId = this.getNodeParameter('workspaceId', i) as string;
body.customFields = customFields;
const timeEntryId = this.getNodeParameter('timeEntryId', i) as string;
responseData = await clockifyApiRequest.call(
this,
'DELETE',
`/workspaces/${workspaceId}/time-entries/${timeEntryId}`,
{},
qs,
);
responseData = { success: true };
}
responseData = await clockifyApiRequest.call(
this,
'POST',
`/workspaces/${workspaceId}/time-entries`,
body,
qs,
);
}
if (operation === 'get') {
if (operation === 'delete') {
const workspaceId = this.getNodeParameter('workspaceId', i) as string;
const workspaceId = this.getNodeParameter('workspaceId', i) as string;
const timeEntryId = this.getNodeParameter('timeEntryId', i) as string;
const timeEntryId = this.getNodeParameter('timeEntryId', i) as string;
responseData = await clockifyApiRequest.call(
this,
'DELETE',
`/workspaces/${workspaceId}/time-entries/${timeEntryId}`,
{},
qs,
);
responseData = { success: true };
}
if (operation === 'get') {
const workspaceId = this.getNodeParameter('workspaceId', i) as string;
const timeEntryId = this.getNodeParameter('timeEntryId', i) as string;
responseData = await clockifyApiRequest.call(
this,
'GET',
`/workspaces/${workspaceId}/time-entries/${timeEntryId}`,
{},
qs,
);
}
if (operation === 'update') {
const timezone = this.getTimezone();
const workspaceId = this.getNodeParameter('workspaceId', i) as string;
const timeEntryId = this.getNodeParameter('timeEntryId', i) as string;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const body: IDataObject = {};
Object.assign(body, updateFields);
if (body.end) {
body.end = moment.tz(body.end, timezone).utc().format();
}
if (body.start) {
body.start = moment.tz(body.start, timezone).utc().format();
} else {
// even if you do not want to update the start time, it always has to be set
// to make it more simple to the user, if he did not set a start time look for the current start time
// and set it
const { timeInterval: { start } } = await clockifyApiRequest.call(
responseData = await clockifyApiRequest.call(
this,
'GET',
`/workspaces/${workspaceId}/time-entries/${timeEntryId}`,
{},
qs,
);
body.start = start;
}
responseData = await clockifyApiRequest.call(
this,
'PUT',
`/workspaces/${workspaceId}/time-entries/${timeEntryId}`,
body,
qs,
);
if (operation === 'update') {
const timezone = this.getTimezone();
const workspaceId = this.getNodeParameter('workspaceId', i) as string;
const timeEntryId = this.getNodeParameter('timeEntryId', i) as string;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const body: IDataObject = {};
Object.assign(body, updateFields);
if (body.end) {
body.end = moment.tz(body.end, timezone).utc().format();
}
if (body.start) {
body.start = moment.tz(body.start, timezone).utc().format();
} else {
// even if you do not want to update the start time, it always has to be set
// to make it more simple to the user, if he did not set a start time look for the current start time
// and set it
const { timeInterval: { start } } = await clockifyApiRequest.call(
this,
'GET',
`/workspaces/${workspaceId}/time-entries/${timeEntryId}`,
{},
qs,
);
body.start = start;
}
responseData = await clockifyApiRequest.call(
this,
'PUT',
`/workspaces/${workspaceId}/time-entries/${timeEntryId}`,
body,
qs,
);
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else if (responseData !== undefined) {
returnData.push(responseData as IDataObject);
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else if (responseData !== undefined) {
returnData.push(responseData as IDataObject);
}
return [this.helpers.returnJsonArray(returnData)];
}
}

View file

@ -120,48 +120,56 @@ export class Cockpit implements INodeType {
let responseData;
for (let i = 0; i < length; i++) {
if (resource === 'collection') {
const collectionName = this.getNodeParameter('collection', i) as string;
try {
if (resource === 'collection') {
const collectionName = this.getNodeParameter('collection', i) as string;
if (operation === 'create') {
const data = createDataFromParameters.call(this, i);
if (operation === 'create') {
const data = createDataFromParameters.call(this, i);
responseData = await createCollectionEntry.call(this, collectionName, data);
} else if (operation === 'getAll') {
const options = this.getNodeParameter('options', i) as IDataObject;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
responseData = await createCollectionEntry.call(this, collectionName, data);
} else if (operation === 'getAll') {
const options = this.getNodeParameter('options', i) as IDataObject;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
if (!returnAll) {
options.limit = this.getNodeParameter('limit', i) as number;
if (!returnAll) {
options.limit = this.getNodeParameter('limit', i) as number;
}
responseData = await getAllCollectionEntries.call(this, collectionName, options);
} else if (operation === 'update') {
const id = this.getNodeParameter('id', i) as string;
const data = createDataFromParameters.call(this, i);
responseData = await createCollectionEntry.call(this, collectionName, data, id);
}
} else if (resource === 'form') {
const formName = this.getNodeParameter('form', i) as string;
responseData = await getAllCollectionEntries.call(this, collectionName, options);
} else if (operation === 'update') {
const id = this.getNodeParameter('id', i) as string;
const data = createDataFromParameters.call(this, i);
if (operation === 'submit') {
const form = createDataFromParameters.call(this, i);
responseData = await createCollectionEntry.call(this, collectionName, data, id);
responseData = await submitForm.call(this, formName, form);
}
} else if (resource === 'singleton') {
const singletonName = this.getNodeParameter('singleton', i) as string;
if (operation === 'get') {
responseData = await getSingleton.call(this, singletonName);
}
}
} else if (resource === 'form') {
const formName = this.getNodeParameter('form', i) as string;
if (operation === 'submit') {
const form = createDataFromParameters.call(this, i);
responseData = await submitForm.call(this, formName, form);
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
}
} else if (resource === 'singleton') {
const singletonName = this.getNodeParameter('singleton', i) as string;
if (operation === 'get') {
responseData = await getSingleton.call(this, singletonName);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
throw error;
}
}

View file

@ -231,78 +231,92 @@ export class Coda implements INodeType {
if (resource === 'table') {
// https://coda.io/developers/apis/v1beta1#operation/upsertRows
if (operation === 'createRow') {
const sendData = {} as IDataObject;
for (let i = 0; i < items.length; i++) {
qs = {};
const docId = this.getNodeParameter('docId', i) as string;
const tableId = this.getNodeParameter('tableId', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
const endpoint = `/docs/${docId}/tables/${tableId}/rows`;
try {
const sendData = {} as IDataObject;
for (let i = 0; i < items.length; i++) {
qs = {};
const docId = this.getNodeParameter('docId', i) as string;
const tableId = this.getNodeParameter('tableId', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
const endpoint = `/docs/${docId}/tables/${tableId}/rows`;
if (options.disableParsing) {
qs.disableParsing = options.disableParsing as boolean;
if (options.disableParsing) {
qs.disableParsing = options.disableParsing as boolean;
}
const cells = [];
cells.length = 0;
for (const key of Object.keys(items[i].json)) {
cells.push({
column: key,
value: items[i].json[key],
});
}
// Collect all the data for the different docs/tables
if (sendData[endpoint] === undefined) {
sendData[endpoint] = {
rows: [],
// TODO: This is not perfect as it ignores if qs changes between
// different items but should be OK for now
qs,
};
}
((sendData[endpoint]! as IDataObject).rows! as IDataObject[]).push({ cells });
if (options.keyColumns) {
// @ts-ignore
(sendData[endpoint]! as IDataObject).keyColumns! = options.keyColumns.split(',') as string[];
}
}
const cells = [];
cells.length = 0;
for (const key of Object.keys(items[i].json)) {
cells.push({
column: key,
value: items[i].json[key],
});
// Now that all data got collected make all the requests
for (const endpoint of Object.keys(sendData)) {
await codaApiRequest.call(this, 'POST', endpoint, sendData[endpoint], (sendData[endpoint]! as IDataObject).qs! as IDataObject);
}
// Collect all the data for the different docs/tables
if (sendData[endpoint] === undefined) {
sendData[endpoint] = {
rows: [],
// TODO: This is not perfect as it ignores if qs changes between
// different items but should be OK for now
qs,
};
}
((sendData[endpoint]! as IDataObject).rows! as IDataObject[]).push({ cells });
if (options.keyColumns) {
// @ts-ignore
(sendData[endpoint]! as IDataObject).keyColumns! = options.keyColumns.split(',') as string[];
} catch (error) {
if (this.continueOnFail()) {
return [this.helpers.returnJsonArray({ error: error.message })];
}
throw error;
}
// Now that all data got collected make all the requests
for (const endpoint of Object.keys(sendData)) {
await codaApiRequest.call(this, 'POST', endpoint, sendData[endpoint], (sendData[endpoint]! as IDataObject).qs! as IDataObject);
}
// Return the incoming data
return [items];
}
// https://coda.io/developers/apis/v1beta1#operation/getRow
if (operation === 'getRow') {
for (let i = 0; i < items.length; i++) {
const docId = this.getNodeParameter('docId', i) as string;
const tableId = this.getNodeParameter('tableId', i) as string;
const rowId = this.getNodeParameter('rowId', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
try {
const docId = this.getNodeParameter('docId', i) as string;
const tableId = this.getNodeParameter('tableId', i) as string;
const rowId = this.getNodeParameter('rowId', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
const endpoint = `/docs/${docId}/tables/${tableId}/rows/${rowId}`;
if (options.useColumnNames === false) {
qs.useColumnNames = options.useColumnNames as boolean;
} else {
qs.useColumnNames = true;
}
if (options.valueFormat) {
qs.valueFormat = options.valueFormat as string;
}
const endpoint = `/docs/${docId}/tables/${tableId}/rows/${rowId}`;
if (options.useColumnNames === false) {
qs.useColumnNames = options.useColumnNames as boolean;
} else {
qs.useColumnNames = true;
}
if (options.valueFormat) {
qs.valueFormat = options.valueFormat as string;
}
responseData = await codaApiRequest.call(this, 'GET', endpoint, {}, qs);
if (options.rawData === true) {
returnData.push(responseData);
} else {
returnData.push({
id: responseData.id,
...responseData.values,
});
responseData = await codaApiRequest.call(this, 'GET', endpoint, {}, qs);
if (options.rawData === true) {
returnData.push(responseData);
} else {
returnData.push({
id: responseData.id,
...responseData.values,
});
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
@ -341,6 +355,9 @@ export class Coda implements INodeType {
responseData = responseData.items;
}
} catch (error) {
if (this.continueOnFail()) {
return [this.helpers.returnJsonArray({ error: error.message })];
}
throw new NodeApiError(this.getNode(), error);
}
@ -358,69 +375,99 @@ export class Coda implements INodeType {
}
// https://coda.io/developers/apis/v1beta1#operation/deleteRows
if (operation === 'deleteRow') {
const sendData = {} as IDataObject;
for (let i = 0; i < items.length; i++) {
const docId = this.getNodeParameter('docId', i) as string;
const tableId = this.getNodeParameter('tableId', i) as string;
const rowId = this.getNodeParameter('rowId', i) as string;
const endpoint = `/docs/${docId}/tables/${tableId}/rows`;
try {
const sendData = {} as IDataObject;
for (let i = 0; i < items.length; i++) {
const docId = this.getNodeParameter('docId', i) as string;
const tableId = this.getNodeParameter('tableId', i) as string;
const rowId = this.getNodeParameter('rowId', i) as string;
const endpoint = `/docs/${docId}/tables/${tableId}/rows`;
// Collect all the data for the different docs/tables
if (sendData[endpoint] === undefined) {
sendData[endpoint] = [];
// Collect all the data for the different docs/tables
if (sendData[endpoint] === undefined) {
sendData[endpoint] = [];
}
(sendData[endpoint] as string[]).push(rowId);
}
(sendData[endpoint] as string[]).push(rowId);
// Now that all data got collected make all the requests
for (const endpoint of Object.keys(sendData)) {
await codaApiRequest.call(this, 'DELETE', endpoint, { rowIds: sendData[endpoint]}, qs);
}
} catch (error) {
if (this.continueOnFail()) {
return [this.helpers.returnJsonArray({ error: error.message })];
}
throw error;
}
// Now that all data got collected make all the requests
for (const endpoint of Object.keys(sendData)) {
await codaApiRequest.call(this, 'DELETE', endpoint, { rowIds: sendData[endpoint]}, qs);
}
// Return the incoming data
return [items];
}
// https://coda.io/developers/apis/v1beta1#operation/pushButton
if (operation === 'pushButton') {
for (let i = 0; i < items.length; i++) {
const docId = this.getNodeParameter('docId', i) as string;
const tableId = this.getNodeParameter('tableId', i) as string;
const rowId = this.getNodeParameter('rowId', i) as string;
const columnId = this.getNodeParameter('columnId', i) as string;
const endpoint = `/docs/${docId}/tables/${tableId}/rows/${rowId}/buttons/${columnId}`;
responseData = await codaApiRequest.call(this, 'POST', endpoint, {});
returnData.push(responseData);
try {
const docId = this.getNodeParameter('docId', i) as string;
const tableId = this.getNodeParameter('tableId', i) as string;
const rowId = this.getNodeParameter('rowId', i) as string;
const columnId = this.getNodeParameter('columnId', i) as string;
const endpoint = `/docs/${docId}/tables/${tableId}/rows/${rowId}/buttons/${columnId}`;
responseData = await codaApiRequest.call(this, 'POST', endpoint, {});
returnData.push(responseData);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];
}
//https://coda.io/developers/apis/v1beta1#operation/getColumn
if (operation === 'getColumn') {
for (let i = 0; i < items.length; i++) {
const docId = this.getNodeParameter('docId', i) as string;
const tableId = this.getNodeParameter('tableId', i) as string;
const columnId = this.getNodeParameter('columnId', i) as string;
const endpoint = `/docs/${docId}/tables/${tableId}/columns/${columnId}`;
responseData = await codaApiRequest.call(this, 'GET', endpoint, {});
returnData.push(responseData);
try {
const docId = this.getNodeParameter('docId', i) as string;
const tableId = this.getNodeParameter('tableId', i) as string;
const columnId = this.getNodeParameter('columnId', i) as string;
const endpoint = `/docs/${docId}/tables/${tableId}/columns/${columnId}`;
responseData = await codaApiRequest.call(this, 'GET', endpoint, {});
returnData.push(responseData);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];
}
//https://coda.io/developers/apis/v1beta1#operation/listColumns
if (operation === 'getAllColumns') {
for (let i = 0; i < items.length; i++) {
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const docId = this.getNodeParameter('docId', i) as string;
const tableId = this.getNodeParameter('tableId', i) as string;
const endpoint = `/docs/${docId}/tables/${tableId}/columns`;
if (returnAll) {
responseData = await codaApiRequestAllItems.call(this, 'items', 'GET', endpoint, {});
} else {
qs.limit = this.getNodeParameter('limit', 0) as number;
responseData = await codaApiRequest.call(this, 'GET', endpoint, {}, qs);
responseData = responseData.items;
try {
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const docId = this.getNodeParameter('docId', i) as string;
const tableId = this.getNodeParameter('tableId', i) as string;
const endpoint = `/docs/${docId}/tables/${tableId}/columns`;
if (returnAll) {
responseData = await codaApiRequestAllItems.call(this, 'items', 'GET', endpoint, {});
} else {
qs.limit = this.getNodeParameter('limit', 0) as number;
responseData = await codaApiRequest.call(this, 'GET', endpoint, {}, qs);
responseData = responseData.items;
}
returnData.push.apply(returnData,responseData);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
returnData.push.apply(returnData,responseData);
}
return [this.helpers.returnJsonArray(returnData)];
}
@ -429,28 +476,44 @@ export class Coda implements INodeType {
//https://coda.io/developers/apis/v1beta1#operation/getFormula
if (operation === 'get') {
for (let i = 0; i < items.length; i++) {
const docId = this.getNodeParameter('docId', i) as string;
const formulaId = this.getNodeParameter('formulaId', i) as string;
const endpoint = `/docs/${docId}/formulas/${formulaId}`;
responseData = await codaApiRequest.call(this, 'GET', endpoint, {});
returnData.push(responseData);
try {
const docId = this.getNodeParameter('docId', i) as string;
const formulaId = this.getNodeParameter('formulaId', i) as string;
const endpoint = `/docs/${docId}/formulas/${formulaId}`;
responseData = await codaApiRequest.call(this, 'GET', endpoint, {});
returnData.push(responseData);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];
}
//https://coda.io/developers/apis/v1beta1#operation/listFormulas
if (operation === 'getAll') {
for (let i = 0; i < items.length; i++) {
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const docId = this.getNodeParameter('docId', i) as string;
const endpoint = `/docs/${docId}/formulas`;
if (returnAll) {
responseData = await codaApiRequestAllItems.call(this, 'items', 'GET', endpoint, {});
} else {
qs.limit = this.getNodeParameter('limit', 0) as number;
responseData = await codaApiRequest.call(this, 'GET', endpoint, {}, qs);
responseData = responseData.items;
try {
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const docId = this.getNodeParameter('docId', i) as string;
const endpoint = `/docs/${docId}/formulas`;
if (returnAll) {
responseData = await codaApiRequestAllItems.call(this, 'items', 'GET', endpoint, {});
} else {
qs.limit = this.getNodeParameter('limit', 0) as number;
responseData = await codaApiRequest.call(this, 'GET', endpoint, {}, qs);
responseData = responseData.items;
}
returnData.push.apply(returnData,responseData);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
returnData.push.apply(returnData,responseData);
}
return [this.helpers.returnJsonArray(returnData)];
}
@ -459,28 +522,44 @@ export class Coda implements INodeType {
//https://coda.io/developers/apis/v1beta1#operation/getControl
if (operation === 'get') {
for (let i = 0; i < items.length; i++) {
const docId = this.getNodeParameter('docId', i) as string;
const controlId = this.getNodeParameter('controlId', i) as string;
const endpoint = `/docs/${docId}/controls/${controlId}`;
responseData = await codaApiRequest.call(this, 'GET', endpoint, {});
returnData.push(responseData);
try {
const docId = this.getNodeParameter('docId', i) as string;
const controlId = this.getNodeParameter('controlId', i) as string;
const endpoint = `/docs/${docId}/controls/${controlId}`;
responseData = await codaApiRequest.call(this, 'GET', endpoint, {});
returnData.push(responseData);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];
}
//https://coda.io/developers/apis/v1beta1#operation/listControls
if (operation === 'getAll') {
for (let i = 0; i < items.length; i++) {
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const docId = this.getNodeParameter('docId', i) as string;
const endpoint = `/docs/${docId}/controls`;
if (returnAll) {
responseData = await codaApiRequestAllItems.call(this, 'items', 'GET', endpoint, {});
} else {
qs.limit = this.getNodeParameter('limit', 0) as number;
responseData = await codaApiRequest.call(this, 'GET', endpoint, {}, qs);
responseData = responseData.items;
try {
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const docId = this.getNodeParameter('docId', i) as string;
const endpoint = `/docs/${docId}/controls`;
if (returnAll) {
responseData = await codaApiRequestAllItems.call(this, 'items', 'GET', endpoint, {});
} else {
qs.limit = this.getNodeParameter('limit', 0) as number;
responseData = await codaApiRequest.call(this, 'GET', endpoint, {}, qs);
responseData = responseData.items;
}
returnData.push.apply(returnData,responseData);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
returnData.push.apply(returnData,responseData);
}
return [this.helpers.returnJsonArray(returnData)];
}
@ -500,17 +579,25 @@ export class Coda implements INodeType {
//https://coda.io/developers/apis/v1beta1#operation/listViews
if (operation === 'getAll') {
for (let i = 0; i < items.length; i++) {
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const docId = this.getNodeParameter('docId', i) as string;
const endpoint = `/docs/${docId}/tables?tableTypes=view`;
if (returnAll) {
responseData = await codaApiRequestAllItems.call(this, 'items', 'GET', endpoint, {});
} else {
qs.limit = this.getNodeParameter('limit', 0) as number;
responseData = await codaApiRequest.call(this, 'GET', endpoint, {}, qs);
responseData = responseData.items;
try {
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const docId = this.getNodeParameter('docId', i) as string;
const endpoint = `/docs/${docId}/tables?tableTypes=view`;
if (returnAll) {
responseData = await codaApiRequestAllItems.call(this, 'items', 'GET', endpoint, {});
} else {
qs.limit = this.getNodeParameter('limit', 0) as number;
responseData = await codaApiRequest.call(this, 'GET', endpoint, {}, qs);
responseData = responseData.items;
}
returnData.push.apply(returnData,responseData);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
returnData.push.apply(returnData,responseData);
}
return [this.helpers.returnJsonArray(returnData)];
}
@ -543,6 +630,9 @@ export class Coda implements INodeType {
responseData = responseData.items;
}
} catch (error) {
if (this.continueOnFail()) {
return [this.helpers.returnJsonArray({ error: error.message })];
}
throw new NodeApiError(this.getNode(), error);
}
@ -561,74 +651,106 @@ export class Coda implements INodeType {
//https://coda.io/developers/apis/v1beta1#operation/deleteViewRow
if (operation === 'deleteViewRow') {
for (let i = 0; i < items.length; i++) {
const docId = this.getNodeParameter('docId', i) as string;
const viewId = this.getNodeParameter('viewId', i) as string;
const rowId = this.getNodeParameter('rowId', i) as string;
const endpoint = `/docs/${docId}/tables/${viewId}/rows/${rowId}`;
responseData = await codaApiRequest.call(this, 'DELETE', endpoint);
returnData.push.apply(returnData,responseData);
try {
const docId = this.getNodeParameter('docId', i) as string;
const viewId = this.getNodeParameter('viewId', i) as string;
const rowId = this.getNodeParameter('rowId', i) as string;
const endpoint = `/docs/${docId}/tables/${viewId}/rows/${rowId}`;
responseData = await codaApiRequest.call(this, 'DELETE', endpoint);
returnData.push.apply(returnData,responseData);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];
}
//https://coda.io/developers/apis/v1beta1#operation/pushViewButton
if (operation === 'pushViewButton') {
for (let i = 0; i < items.length; i++) {
const docId = this.getNodeParameter('docId', i) as string;
const viewId = this.getNodeParameter('viewId', i) as string;
const rowId = this.getNodeParameter('rowId', i) as string;
const columnId = this.getNodeParameter('columnId', i) as string;
const endpoint = `/docs/${docId}/tables/${viewId}/rows/${rowId}/buttons/${columnId}`;
responseData = await codaApiRequest.call(this, 'POST', endpoint);
returnData.push.apply(returnData,responseData);
try {
const docId = this.getNodeParameter('docId', i) as string;
const viewId = this.getNodeParameter('viewId', i) as string;
const rowId = this.getNodeParameter('rowId', i) as string;
const columnId = this.getNodeParameter('columnId', i) as string;
const endpoint = `/docs/${docId}/tables/${viewId}/rows/${rowId}/buttons/${columnId}`;
responseData = await codaApiRequest.call(this, 'POST', endpoint);
returnData.push.apply(returnData,responseData);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];
}
if (operation === 'getAllViewColumns') {
for (let i = 0; i < items.length; i++) {
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const docId = this.getNodeParameter('docId', i) as string;
const viewId = this.getNodeParameter('viewId', i) as string;
const endpoint = `/docs/${docId}/tables/${viewId}/columns`;
if (returnAll) {
responseData = await codaApiRequestAllItems.call(this, 'items', 'GET', endpoint, {});
} else {
qs.limit = this.getNodeParameter('limit', 0) as number;
responseData = await codaApiRequest.call(this, 'GET', endpoint, {}, qs);
responseData = responseData.items;
try {
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const docId = this.getNodeParameter('docId', i) as string;
const viewId = this.getNodeParameter('viewId', i) as string;
const endpoint = `/docs/${docId}/tables/${viewId}/columns`;
if (returnAll) {
responseData = await codaApiRequestAllItems.call(this, 'items', 'GET', endpoint, {});
} else {
qs.limit = this.getNodeParameter('limit', 0) as number;
responseData = await codaApiRequest.call(this, 'GET', endpoint, {}, qs);
responseData = responseData.items;
}
returnData.push.apply(returnData,responseData);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
returnData.push.apply(returnData,responseData);
}
return [this.helpers.returnJsonArray(returnData)];
}
//https://coda.io/developers/apis/v1beta1#operation/updateViewRow
if (operation === 'updateViewRow') {
for (let i = 0; i < items.length; i++) {
qs = {};
const docId = this.getNodeParameter('docId', i) as string;
const viewId = this.getNodeParameter('viewId', i) as string;
const rowId = this.getNodeParameter('rowId', i) as string;
const keyName = this.getNodeParameter('keyName', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
const body: IDataObject = {};
const endpoint = `/docs/${docId}/tables/${viewId}/rows/${rowId}`;
if (options.disableParsing) {
qs.disableParsing = options.disableParsing as boolean;
}
const cells = [];
cells.length = 0;
try {
qs = {};
const docId = this.getNodeParameter('docId', i) as string;
const viewId = this.getNodeParameter('viewId', i) as string;
const rowId = this.getNodeParameter('rowId', i) as string;
const keyName = this.getNodeParameter('keyName', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
const body: IDataObject = {};
const endpoint = `/docs/${docId}/tables/${viewId}/rows/${rowId}`;
if (options.disableParsing) {
qs.disableParsing = options.disableParsing as boolean;
}
const cells = [];
cells.length = 0;
//@ts-ignore
for (const key of Object.keys(items[i].json[keyName])) {
cells.push({
column: key,
//@ts-ignore
value: items[i].json[keyName][key],
});
//@ts-ignore
for (const key of Object.keys(items[i].json[keyName])) {
cells.push({
column: key,
//@ts-ignore
value: items[i].json[keyName][key],
});
}
body.row = {
cells,
};
await codaApiRequest.call(this, 'PUT', endpoint, body, qs);
} catch (error) {
if (this.continueOnFail()) {
items[i].json = { error: error.message };
continue;
}
throw error;
}
body.row = {
cells,
};
await codaApiRequest.call(this, 'PUT', endpoint, body, qs);
}
return [items];
}

View file

@ -169,126 +169,330 @@ export class CoinGecko implements INodeType {
const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string;
for (let i = 0; i < length; i++) {
try {
if (resource === 'coin') {
//https://www.coingecko.com/api/documentations/v3#/coins/get_coins__id_
//https://www.coingecko.com/api/documentations/v3#/contract/get_coins__id__contract__contract_address_
if (operation === 'get') {
if (resource === 'coin') {
//https://www.coingecko.com/api/documentations/v3#/coins/get_coins__id_
//https://www.coingecko.com/api/documentations/v3#/contract/get_coins__id__contract__contract_address_
if (operation === 'get') {
const options = this.getNodeParameter('options', i) as IDataObject;
const options = this.getNodeParameter('options', i) as IDataObject;
qs.community_data = false;
qs.developer_data = false;
qs.localization = false;
qs.market_data = false;
qs.sparkline = false;
qs.tickers = false;
qs.community_data = false;
qs.developer_data = false;
qs.localization = false;
qs.market_data = false;
qs.sparkline = false;
qs.tickers = false;
Object.assign(qs, options);
Object.assign(qs, options);
const searchBy = this.getNodeParameter('searchBy', i) as string;
const searchBy = this.getNodeParameter('searchBy', i) as string;
if (searchBy === 'coinId') {
const coinId = this.getNodeParameter('coinId', i) as string;
if (searchBy === 'coinId') {
responseData = await coinGeckoApiRequest.call(
this,
'GET',
`/coins/${coinId}`,
{},
qs,
);
}
if (searchBy === 'contractAddress') {
const platformId = this.getNodeParameter('platformId', i) as string;
const contractAddress = this.getNodeParameter('contractAddress', i) as string;
responseData = await coinGeckoApiRequest.call(
this,
'GET',
`/coins/${platformId}/contract/${contractAddress}`,
{},
qs,
);
}
}
//https://www.coingecko.com/api/documentations/v3#/coins/get_coins_list
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
let limit;
responseData = await coinGeckoApiRequest.call(
this,
'GET',
'/coins/list',
{},
qs,
);
if (returnAll === false) {
limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.splice(0, limit);
}
}
//https://www.coingecko.com/api/documentations/v3#/coins/get_coins_list
if (operation === 'market') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const baseCurrency = this.getNodeParameter('baseCurrency', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
qs.vs_currency = baseCurrency;
Object.assign(qs, options);
if (options.price_change_percentage) {
qs.price_change_percentage = (options.price_change_percentage as string[]).join(',');
}
if (returnAll) {
responseData = await coinGeckoRequestAllItems.call(
this,
'',
'GET',
`/coins/markets`,
{},
qs,
);
} else {
const limit = this.getNodeParameter('limit', i) as number;
qs.per_page = limit;
responseData = await coinGeckoApiRequest.call(
this,
'GET',
`/coins/markets`,
{},
qs,
);
}
}
//https://www.coingecko.com/api/documentations/v3#/simple/get_simple_price
//https://www.coingecko.com/api/documentations/v3#/simple/get_simple_token_price__id_
if (operation === 'price') {
const searchBy = this.getNodeParameter('searchBy', i) as string;
const quoteCurrencies = this.getNodeParameter('quoteCurrencies', i) as string[];
const options = this.getNodeParameter('options', i) as IDataObject;
qs.vs_currencies = quoteCurrencies.join(',');
Object.assign(qs, options);
if (searchBy === 'coinId') {
const baseCurrencies = this.getNodeParameter('baseCurrencies', i) as string[];
qs.ids = baseCurrencies.join(',');
responseData = await coinGeckoApiRequest.call(
this,
'GET',
'/simple/price',
{},
qs,
);
}
if (searchBy === 'contractAddress') {
const platformId = this.getNodeParameter('platformId', i) as string;
const contractAddresses = this.getNodeParameter('contractAddresses', i) as string;
qs.contract_addresses = contractAddresses;
responseData = await coinGeckoApiRequest.call(
this,
'GET',
`/simple/token_price/${platformId}`,
{},
qs,
);
}
}
//https://www.coingecko.com/api/documentations/v3#/coins/get_coins__id__tickers
if (operation === 'ticker') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const coinId = this.getNodeParameter('coinId', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
Object.assign(qs, options);
if (options.exchange_ids) {
qs.exchange_ids = (options.exchange_ids as string[]).join(',');
}
if (returnAll) {
responseData = await coinGeckoRequestAllItems.call(
this,
'tickers',
'GET',
`/coins/${coinId}/tickers`,
{},
qs,
);
} else {
const limit = this.getNodeParameter('limit', i) as number;
responseData = await coinGeckoApiRequest.call(
this,
'GET',
`/coins/${coinId}/tickers`,
{},
qs,
);
responseData = responseData.tickers;
responseData = responseData.splice(0, limit);
}
}
//https://www.coingecko.com/api/documentations/v3#/coins/get_coins__id__history
if (operation === 'history') {
const coinId = this.getNodeParameter('coinId', i) as string;
const date = this.getNodeParameter('date', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
Object.assign(qs, options);
qs.date = moment(date).format('DD-MM-YYYY');
responseData = await coinGeckoApiRequest.call(
this,
'GET',
`/coins/${coinId}`,
`/coins/${coinId}/history`,
{},
qs,
);
}
if (searchBy === 'contractAddress') {
const platformId = this.getNodeParameter('platformId', i) as string;
const contractAddress = this.getNodeParameter('contractAddress', i) as string;
//https://www.coingecko.com/api/documentations/v3#/coins/get_coins__id__market_chart
//https://www.coingecko.com/api/documentations/v3#/contract/get_coins__id__contract__contract_address__market_chart_
if (operation === 'marketChart') {
let respData;
const searchBy = this.getNodeParameter('searchBy', i) as string;
const quoteCurrency = this.getNodeParameter('quoteCurrency', i) as string;
const days = this.getNodeParameter('days', i) as string;
qs.vs_currency = quoteCurrency;
qs.days = days;
if (searchBy === 'coinId') {
const coinId = this.getNodeParameter('baseCurrency', i) as string;
respData = await coinGeckoApiRequest.call(
this,
'GET',
`/coins/${coinId}/market_chart`,
{},
qs,
);
}
if (searchBy === 'contractAddress') {
const platformId = this.getNodeParameter('platformId', i) as string;
const contractAddress = this.getNodeParameter('contractAddress', i) as string;
respData = await coinGeckoApiRequest.call(
this,
'GET',
`/coins/${platformId}/contract/${contractAddress}/market_chart`,
{},
qs,
);
}
responseData = [];
for (let idx = 0; idx < respData.prices.length; idx++) {
const [time, price] = respData.prices[idx];
const marketCaps = respData.market_caps[idx][1];
const totalVolume = respData.total_volumes[idx][1];
responseData.push({ time: moment(time).toISOString(), price, marketCaps, totalVolume } as IDataObject);
}
}
//https://www.coingecko.com/api/documentations/v3#/coins/get_coins__id__ohlc
if (operation === 'candlestick') {
const baseCurrency = this.getNodeParameter('baseCurrency', i) as string;
const quoteCurrency = this.getNodeParameter('quoteCurrency', i) as string;
const days = this.getNodeParameter('days', i) as string;
qs.vs_currency = quoteCurrency;
qs.days = days;
responseData = await coinGeckoApiRequest.call(
this,
'GET',
`/coins/${platformId}/contract/${contractAddress}`,
`/coins/${baseCurrency}/ohlc`,
{},
qs,
);
}
}
//https://www.coingecko.com/api/documentations/v3#/coins/get_coins_list
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
let limit;
responseData = await coinGeckoApiRequest.call(
this,
'GET',
'/coins/list',
{},
qs,
);
if (returnAll === false) {
limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.splice(0, limit);
for (let idx = 0; idx < responseData.length; idx++) {
const [time, open, high, low, close] = responseData[idx];
responseData[idx] = { time: moment(time).toISOString(), open, high, low, close } as IDataObject;
}
}
}
//https://www.coingecko.com/api/documentations/v3#/coins/get_coins_list
if (operation === 'market') {
if (resource === 'event') {
//https://www.coingecko.com/api/documentations/v3#/events/get_events
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const baseCurrency = this.getNodeParameter('baseCurrency', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const options = this.getNodeParameter('options', i) as IDataObject;
qs.vs_currency = baseCurrency;
Object.assign(qs, options);
Object.assign(qs, options);
if (returnAll) {
responseData = await coinGeckoRequestAllItems.call(
this,
'data',
'GET',
'/events',
{},
qs,
);
} else {
const limit = this.getNodeParameter('limit', i) as number;
if (options.price_change_percentage) {
qs.price_change_percentage = (options.price_change_percentage as string[]).join(',');
}
qs.per_page = limit;
if (returnAll) {
responseData = await coinGeckoRequestAllItems.call(
this,
'',
'GET',
`/coins/markets`,
{},
qs,
);
} else {
const limit = this.getNodeParameter('limit', i) as number;
qs.per_page = limit;
responseData = await coinGeckoApiRequest.call(
this,
'GET',
`/coins/markets`,
{},
qs,
);
responseData = await coinGeckoApiRequest.call(
this,
'GET',
'/events',
{},
qs,
);
responseData = responseData.data;
}
}
}
//https://www.coingecko.com/api/documentations/v3#/simple/get_simple_price
//https://www.coingecko.com/api/documentations/v3#/simple/get_simple_token_price__id_
if (operation === 'price') {
if (resource === 'simple') {
//https://www.coingecko.com/api/documentations/v3#/simple/get_simple_price
if (operation === 'price') {
const searchBy = this.getNodeParameter('searchBy', i) as string;
const quoteCurrencies = this.getNodeParameter('quoteCurrencies', i) as string[];
const options = this.getNodeParameter('options', i) as IDataObject;
const ids = this.getNodeParameter('ids', i) as string;
const currencies = this.getNodeParameter('currencies', i) as string[];
const options = this.getNodeParameter('options', i) as IDataObject;
qs.vs_currencies = quoteCurrencies.join(',');
qs.ids = ids,
qs.vs_currencies = currencies.join(',');
Object.assign(qs, options);
if (searchBy === 'coinId') {
const baseCurrencies = this.getNodeParameter('baseCurrencies', i) as string[];
qs.ids = baseCurrencies.join(',');
Object.assign(qs, options);
responseData = await coinGeckoApiRequest.call(
this,
@ -299,237 +503,40 @@ export class CoinGecko implements INodeType {
);
}
if (searchBy === 'contractAddress') {
const platformId = this.getNodeParameter('platformId', i) as string;
//https://www.coingecko.com/api/documentations/v3#/simple/get_simple_token_price__id_
if (operation === 'tokenPrice') {
const id = this.getNodeParameter('id', i) as string;
const contractAddresses = this.getNodeParameter('contractAddresses', i) as string;
const currencies = this.getNodeParameter('currencies', i) as string[];
const options = this.getNodeParameter('options', i) as IDataObject;
qs.contract_addresses = contractAddresses;
responseData = await coinGeckoApiRequest.call(
this,
'GET',
`/simple/token_price/${platformId}`,
{},
qs,
);
}
}
//https://www.coingecko.com/api/documentations/v3#/coins/get_coins__id__tickers
if (operation === 'ticker') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const coinId = this.getNodeParameter('coinId', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
Object.assign(qs, options);
if (options.exchange_ids) {
qs.exchange_ids = (options.exchange_ids as string[]).join(',');
}
if (returnAll) {
responseData = await coinGeckoRequestAllItems.call(
this,
'tickers',
'GET',
`/coins/${coinId}/tickers`,
{},
qs,
);
} else {
const limit = this.getNodeParameter('limit', i) as number;
responseData = await coinGeckoApiRequest.call(
this,
'GET',
`/coins/${coinId}/tickers`,
{},
qs,
);
responseData = responseData.tickers;
responseData = responseData.splice(0, limit);
}
}
//https://www.coingecko.com/api/documentations/v3#/coins/get_coins__id__history
if (operation === 'history') {
const coinId = this.getNodeParameter('coinId', i) as string;
const date = this.getNodeParameter('date', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
Object.assign(qs, options);
qs.date = moment(date).format('DD-MM-YYYY');
responseData = await coinGeckoApiRequest.call(
this,
'GET',
`/coins/${coinId}/history`,
{},
qs,
);
}
//https://www.coingecko.com/api/documentations/v3#/coins/get_coins__id__market_chart
//https://www.coingecko.com/api/documentations/v3#/contract/get_coins__id__contract__contract_address__market_chart_
if (operation === 'marketChart') {
let respData;
const searchBy = this.getNodeParameter('searchBy', i) as string;
const quoteCurrency = this.getNodeParameter('quoteCurrency', i) as string;
const days = this.getNodeParameter('days', i) as string;
qs.vs_currency = quoteCurrency;
qs.days = days;
if (searchBy === 'coinId') {
const coinId = this.getNodeParameter('baseCurrency', i) as string;
respData = await coinGeckoApiRequest.call(
this,
'GET',
`/coins/${coinId}/market_chart`,
{},
qs,
);
}
if (searchBy === 'contractAddress') {
const platformId = this.getNodeParameter('platformId', i) as string;
const contractAddress = this.getNodeParameter('contractAddress', i) as string;
respData = await coinGeckoApiRequest.call(
this,
'GET',
`/coins/${platformId}/contract/${contractAddress}/market_chart`,
{},
qs,
);
}
responseData = [];
for (let idx = 0; idx < respData.prices.length; idx++) {
const [time, price] = respData.prices[idx];
const marketCaps = respData.market_caps[idx][1];
const totalVolume = respData.total_volumes[idx][1];
responseData.push({ time: moment(time).toISOString(), price, marketCaps, totalVolume } as IDataObject);
}
}
//https://www.coingecko.com/api/documentations/v3#/coins/get_coins__id__ohlc
if (operation === 'candlestick') {
const baseCurrency = this.getNodeParameter('baseCurrency', i) as string;
const quoteCurrency = this.getNodeParameter('quoteCurrency', i) as string;
const days = this.getNodeParameter('days', i) as string;
qs.vs_currency = quoteCurrency;
qs.days = days;
responseData = await coinGeckoApiRequest.call(
this,
'GET',
`/coins/${baseCurrency}/ohlc`,
{},
qs,
);
for (let idx = 0; idx < responseData.length; idx++) {
const [time, open, high, low, close] = responseData[idx];
responseData[idx] = { time: moment(time).toISOString(), open, high, low, close } as IDataObject;
}
}
}
if (resource === 'event') {
//https://www.coingecko.com/api/documentations/v3#/events/get_events
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const options = this.getNodeParameter('options', i) as IDataObject;
Object.assign(qs, options);
if (returnAll) {
responseData = await coinGeckoRequestAllItems.call(
this,
'data',
'GET',
'/events',
{},
qs,
);
} else {
const limit = this.getNodeParameter('limit', i) as number;
qs.per_page = limit;
responseData = await coinGeckoApiRequest.call(
this,
'GET',
'/events',
{},
qs,
);
responseData = responseData.data;
}
}
}
if (resource === 'simple') {
//https://www.coingecko.com/api/documentations/v3#/simple/get_simple_price
if (operation === 'price') {
const ids = this.getNodeParameter('ids', i) as string;
const currencies = this.getNodeParameter('currencies', i) as string[];
const options = this.getNodeParameter('options', i) as IDataObject;
qs.ids = ids,
qs.vs_currencies = currencies.join(',');
Object.assign(qs, options);
Object.assign(qs, options);
responseData = await coinGeckoApiRequest.call(
this,
'GET',
'/simple/price',
{},
qs,
);
responseData = await coinGeckoApiRequest.call(
this,
'GET',
`/simple/token_price/${id}`,
{},
qs,
);
}
}
//https://www.coingecko.com/api/documentations/v3#/simple/get_simple_token_price__id_
if (operation === 'tokenPrice') {
const id = this.getNodeParameter('id', i) as string;
const contractAddresses = this.getNodeParameter('contractAddresses', i) as string;
const currencies = this.getNodeParameter('currencies', i) as string[];
const options = this.getNodeParameter('options', i) as IDataObject;
qs.contract_addresses = contractAddresses;
qs.vs_currencies = currencies.join(',');
Object.assign(qs, options);
responseData = await coinGeckoApiRequest.call(
this,
'GET',
`/simple/token_price/${id}`,
{},
qs,
);
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else if (responseData !== undefined) {
returnData.push(responseData as IDataObject);
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else if (responseData !== undefined) {
returnData.push(responseData as IDataObject);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}

View file

@ -205,122 +205,131 @@ export class Compression implements INodeType {
const operation = this.getNodeParameter('operation', 0) as string;
for (let i = 0; i < length; i++) {
try {
if (operation === 'decompress') {
const binaryPropertyNames = (this.getNodeParameter('binaryPropertyName', 0) as string).split(',').map(key => key.trim());
if (operation === 'decompress') {
const binaryPropertyNames = (this.getNodeParameter('binaryPropertyName', 0) as string).split(',').map(key => key.trim());
const outputPrefix = this.getNodeParameter('outputPrefix', 0) as string;
const outputPrefix = this.getNodeParameter('outputPrefix', 0) as string;
const binaryObject: IBinaryKeyData = {};
const binaryObject: IBinaryKeyData = {};
let zipIndex = 0;
let zipIndex = 0;
for (const [index, binaryPropertyName] of binaryPropertyNames.entries()) {
if (items[i].binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
}
//@ts-ignore
if (items[i].binary[binaryPropertyName] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property "${binaryPropertyName}" does not exists on item!`);
}
const binaryData = (items[i].binary as IBinaryKeyData)[binaryPropertyName];
if (binaryData.fileExtension === 'zip') {
const files = await unzip(Buffer.from(binaryData.data as string, BINARY_ENCODING));
for (const key of Object.keys(files)) {
// when files are compresed using MACOSX for some reason they are duplicated under __MACOSX
if (key.includes('__MACOSX')) {
continue;
}
const data = await this.helpers.prepareBinaryData(Buffer.from(files[key].buffer), key);
binaryObject[`${outputPrefix}${zipIndex++}`] = data;
for (const [index, binaryPropertyName] of binaryPropertyNames.entries()) {
if (items[i].binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
}
//@ts-ignore
if (items[i].binary[binaryPropertyName] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property "${binaryPropertyName}" does not exists on item!`);
}
} else if (binaryData.fileExtension === 'gz') {
const file = await gunzip(Buffer.from(binaryData.data as string, BINARY_ENCODING));
const fileName = binaryData.fileName?.split('.')[0];
const binaryData = (items[i].binary as IBinaryKeyData)[binaryPropertyName];
const propertyName = `${outputPrefix}${index}`;
if (binaryData.fileExtension === 'zip') {
const files = await unzip(Buffer.from(binaryData.data as string, BINARY_ENCODING));
binaryObject[propertyName] = await this.helpers.prepareBinaryData(Buffer.from(file.buffer), fileName);
const fileExtension = mime.extension(binaryObject[propertyName].mimeType) as string;
binaryObject[propertyName].fileName = `${fileName}.${fileExtension}`;
binaryObject[propertyName].fileExtension = fileExtension;
}
}
for (const key of Object.keys(files)) {
// when files are compresed using MACOSX for some reason they are duplicated under __MACOSX
if (key.includes('__MACOSX')) {
continue;
}
returnData.push({
json: items[i].json,
binary: binaryObject,
});
}
const data = await this.helpers.prepareBinaryData(Buffer.from(files[key].buffer), key);
if (operation === 'compress') {
const binaryPropertyNames = (this.getNodeParameter('binaryPropertyName', 0) as string).split(',').map(key => key.trim());
binaryObject[`${outputPrefix}${zipIndex++}`] = data;
}
} else if (binaryData.fileExtension === 'gz') {
const file = await gunzip(Buffer.from(binaryData.data as string, BINARY_ENCODING));
const outputFormat = this.getNodeParameter('outputFormat', 0) as string;
const fileName = binaryData.fileName?.split('.')[0];
const zipData: fflate.Zippable = {};
const propertyName = `${outputPrefix}${index}`;
const binaryObject: IBinaryKeyData = {};
for (const [index, binaryPropertyName] of binaryPropertyNames.entries()) {
if (items[i].binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
}
//@ts-ignore
if (items[i].binary[binaryPropertyName] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property "${binaryPropertyName}" does not exists on item!`);
binaryObject[propertyName] = await this.helpers.prepareBinaryData(Buffer.from(file.buffer), fileName);
const fileExtension = mime.extension(binaryObject[propertyName].mimeType) as string;
binaryObject[propertyName].fileName = `${fileName}.${fileExtension}`;
binaryObject[propertyName].fileExtension = fileExtension;
}
}
const binaryData = (items[i].binary as IBinaryKeyData)[binaryPropertyName];
if (outputFormat === 'zip') {
zipData[binaryData.fileName as string] = [
Buffer.from(binaryData.data, BINARY_ENCODING), {
level: ALREADY_COMPRESSED.includes(binaryData.fileExtension as string) ? 0 : 6,
},
];
} else if (outputFormat === 'gzip') {
const outputPrefix = this.getNodeParameter('outputPrefix', 0) as string;
const data = await gzip(Buffer.from(binaryData.data, BINARY_ENCODING)) as Uint8Array;
const fileName = binaryData.fileName?.split('.')[0];
binaryObject[`${outputPrefix}${index}`] = await this.helpers.prepareBinaryData(Buffer.from(data), `${fileName}.gzip`);
}
}
if (outputFormat === 'zip') {
const fileName = this.getNodeParameter('fileName', 0) as string;
const binaryPropertyOutput = this.getNodeParameter('binaryPropertyOutput', 0) as string;
const buffer = await zip(zipData);
const data = await this.helpers.prepareBinaryData(Buffer.from(buffer), fileName);
returnData.push({
json: items[i].json,
binary: {
[binaryPropertyOutput]: data,
},
});
}
if (outputFormat === 'gzip') {
returnData.push({
json: items[i].json,
binary: binaryObject,
});
}
if (operation === 'compress') {
const binaryPropertyNames = (this.getNodeParameter('binaryPropertyName', 0) as string).split(',').map(key => key.trim());
const outputFormat = this.getNodeParameter('outputFormat', 0) as string;
const zipData: fflate.Zippable = {};
const binaryObject: IBinaryKeyData = {};
for (const [index, binaryPropertyName] of binaryPropertyNames.entries()) {
if (items[i].binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
}
//@ts-ignore
if (items[i].binary[binaryPropertyName] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property "${binaryPropertyName}" does not exists on item!`);
}
const binaryData = (items[i].binary as IBinaryKeyData)[binaryPropertyName];
if (outputFormat === 'zip') {
zipData[binaryData.fileName as string] = [
Buffer.from(binaryData.data, BINARY_ENCODING), {
level: ALREADY_COMPRESSED.includes(binaryData.fileExtension as string) ? 0 : 6,
},
];
} else if (outputFormat === 'gzip') {
const outputPrefix = this.getNodeParameter('outputPrefix', 0) as string;
const data = await gzip(Buffer.from(binaryData.data, BINARY_ENCODING)) as Uint8Array;
const fileName = binaryData.fileName?.split('.')[0];
binaryObject[`${outputPrefix}${index}`] = await this.helpers.prepareBinaryData(Buffer.from(data), `${fileName}.gzip`);
}
}
if (outputFormat === 'zip') {
const fileName = this.getNodeParameter('fileName', 0) as string;
const binaryPropertyOutput = this.getNodeParameter('binaryPropertyOutput', 0) as string;
const buffer = await zip(zipData);
const data = await this.helpers.prepareBinaryData(Buffer.from(buffer), fileName);
returnData.push({
json: items[i].json,
binary: {
[binaryPropertyOutput]: data,
},
});
}
if (outputFormat === 'gzip') {
returnData.push({
json: items[i].json,
binary: binaryObject,
});
}
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({json:{ error: error.message }});
continue;
}
throw error;
}
}

View file

@ -101,224 +101,232 @@ export class Contentful implements INodeType {
const qs: Record<string, string | number> = {};
for (let i = 0; i < items.length; i++) {
if (resource === 'space') {
if (operation === 'get') {
try {
if (resource === 'space') {
if (operation === 'get') {
const credentials = this.getCredentials('contentfulApi');
const credentials = this.getCredentials('contentfulApi');
responseData = await contentfulApiRequest.call(this, 'GET', `/spaces/${credentials?.spaceId}`);
}
}
if (resource === 'contentType') {
if (operation === 'get') {
const credentials = this.getCredentials('contentfulApi');
const env = this.getNodeParameter('environmentId', 0) as string;
const id = this.getNodeParameter('contentTypeId', 0) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
responseData = await contentfulApiRequest.call(this, 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/content_types/${id}`);
if (!additionalFields.rawData) {
responseData = responseData.fields;
responseData = await contentfulApiRequest.call(this, 'GET', `/spaces/${credentials?.spaceId}`);
}
}
}
if (resource === 'entry') {
if (resource === 'contentType') {
if (operation === 'get') {
if (operation === 'get') {
const credentials = this.getCredentials('contentfulApi');
const credentials = this.getCredentials('contentfulApi');
const env = this.getNodeParameter('environmentId', 0) as string;
const env = this.getNodeParameter('environmentId', 0) as string;
const id = this.getNodeParameter('contentTypeId', 0) as string;
const id = this.getNodeParameter('entryId', 0) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
responseData = await contentfulApiRequest.call(this, 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/content_types/${id}`);
responseData = await contentfulApiRequest.call(this, 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/entries/${id}`, {}, qs);
if (!additionalFields.rawData) {
responseData = responseData.fields;
}
} else if (operation === 'getAll') {
const credentials = this.getCredentials('contentfulApi');
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const rawData = additionalFields.rawData;
additionalFields.rawData = undefined;
const env = this.getNodeParameter('environmentId', i) as string;
Object.assign(qs, additionalFields);
if (qs.equal) {
const [atribute, value] = (qs.equal as string).split('=');
qs[atribute] = value;
delete qs.equal;
}
if (qs.notEqual) {
const [atribute, value] = (qs.notEqual as string).split('=');
qs[atribute] = value;
delete qs.notEqual;
}
if (qs.include) {
const [atribute, value] = (qs.include as string).split('=');
qs[atribute] = value;
delete qs.include;
}
if (qs.exclude) {
const [atribute, value] = (qs.exclude as string).split('=');
qs[atribute] = value;
delete qs.exclude;
}
if (returnAll) {
responseData = await contenfulApiRequestAllItems.call(this, 'items', 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/entries`, {}, qs);
if (!rawData) {
const assets : IDataObject[] = [];
// tslint:disable-next-line: no-any
responseData.map((asset : any) => {
assets.push(asset.fields);
});
responseData = assets;
}
} else {
const limit = this.getNodeParameter('limit', 0) as number;
qs.limit = limit;
responseData = await contentfulApiRequest.call(this, 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/entries`, {}, qs);
responseData = responseData.items;
if (!rawData) {
const assets : IDataObject[] = [];
// tslint:disable-next-line: no-any
responseData.map((asset : any) => {
assets.push(asset.fields);
});
responseData = assets;
if (!additionalFields.rawData) {
responseData = responseData.fields;
}
}
}
}
if (resource === 'asset') {
if (operation === 'get') {
if (resource === 'entry') {
const credentials = this.getCredentials('contentfulApi');
if (operation === 'get') {
const env = this.getNodeParameter('environmentId', 0) as string;
const credentials = this.getCredentials('contentfulApi');
const id = this.getNodeParameter('assetId', 0) as string;
const env = this.getNodeParameter('environmentId', 0) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const id = this.getNodeParameter('entryId', 0) as string;
responseData = await contentfulApiRequest.call(this, 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/assets/${id}`, {}, qs);
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (!additionalFields.rawData) {
responseData = responseData.fields;
}
responseData = await contentfulApiRequest.call(this, 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/entries/${id}`, {}, qs);
} else if (operation === 'getAll') {
const credentials = this.getCredentials('contentfulApi');
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const rawData = additionalFields.rawData;
additionalFields.rawData = undefined;
const env = this.getNodeParameter('environmentId', i) as string;
Object.assign(qs, additionalFields);
if (qs.equal) {
const [atribute, value] = (qs.equal as string).split('=');
qs[atribute] = value;
delete qs.equal;
}
if (qs.notEqual) {
const [atribute, value] = (qs.notEqual as string).split('=');
qs[atribute] = value;
delete qs.notEqual;
}
if (qs.include) {
const [atribute, value] = (qs.include as string).split('=');
qs[atribute] = value;
delete qs.include;
}
if (qs.exclude) {
const [atribute, value] = (qs.exclude as string).split('=');
qs[atribute] = value;
delete qs.exclude;
}
if (returnAll) {
responseData = await contenfulApiRequestAllItems.call(this, 'items', 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/assets`, {}, qs);
if (!rawData) {
const assets : IDataObject[] = [];
// tslint:disable-next-line: no-any
responseData.map((asset : any) => {
assets.push(asset.fields);
});
responseData = assets;
if (!additionalFields.rawData) {
responseData = responseData.fields;
}
} else {
const limit = this.getNodeParameter('limit', i) as number;
qs.limit = limit;
responseData = await contentfulApiRequest.call(this, 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/assets`, {}, qs);
responseData = responseData.items;
if (!rawData) {
const assets : IDataObject[] = [];
// tslint:disable-next-line: no-any
responseData.map((asset : any) => {
assets.push(asset.fields);
});
responseData = assets;
} else if (operation === 'getAll') {
const credentials = this.getCredentials('contentfulApi');
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const rawData = additionalFields.rawData;
additionalFields.rawData = undefined;
const env = this.getNodeParameter('environmentId', i) as string;
Object.assign(qs, additionalFields);
if (qs.equal) {
const [atribute, value] = (qs.equal as string).split('=');
qs[atribute] = value;
delete qs.equal;
}
if (qs.notEqual) {
const [atribute, value] = (qs.notEqual as string).split('=');
qs[atribute] = value;
delete qs.notEqual;
}
if (qs.include) {
const [atribute, value] = (qs.include as string).split('=');
qs[atribute] = value;
delete qs.include;
}
if (qs.exclude) {
const [atribute, value] = (qs.exclude as string).split('=');
qs[atribute] = value;
delete qs.exclude;
}
if (returnAll) {
responseData = await contenfulApiRequestAllItems.call(this, 'items', 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/entries`, {}, qs);
if (!rawData) {
const assets : IDataObject[] = [];
// tslint:disable-next-line: no-any
responseData.map((asset : any) => {
assets.push(asset.fields);
});
responseData = assets;
}
} else {
const limit = this.getNodeParameter('limit', 0) as number;
qs.limit = limit;
responseData = await contentfulApiRequest.call(this, 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/entries`, {}, qs);
responseData = responseData.items;
if (!rawData) {
const assets : IDataObject[] = [];
// tslint:disable-next-line: no-any
responseData.map((asset : any) => {
assets.push(asset.fields);
});
responseData = assets;
}
}
}
}
}
if (resource === 'locale') {
if (resource === 'asset') {
if (operation === 'get') {
if (operation === 'getAll') {
const credentials = this.getCredentials('contentfulApi');
const credentials = this.getCredentials('contentfulApi');
const env = this.getNodeParameter('environmentId', 0) as string;
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const id = this.getNodeParameter('assetId', 0) as string;
const env = this.getNodeParameter('environmentId', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (returnAll) {
responseData = await contenfulApiRequestAllItems.call(this, 'items', 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/locales`, {}, qs);
responseData = await contentfulApiRequest.call(this, 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/assets/${id}`, {}, qs);
} else {
const limit = this.getNodeParameter('limit', 0) as number;
qs.limit = limit;
responseData = await contentfulApiRequest.call(this, 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/locales`, {}, qs);
responseData = responseData.items;
if (!additionalFields.rawData) {
responseData = responseData.fields;
}
} else if (operation === 'getAll') {
const credentials = this.getCredentials('contentfulApi');
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const rawData = additionalFields.rawData;
additionalFields.rawData = undefined;
const env = this.getNodeParameter('environmentId', i) as string;
Object.assign(qs, additionalFields);
if (qs.equal) {
const [atribute, value] = (qs.equal as string).split('=');
qs[atribute] = value;
delete qs.equal;
}
if (qs.notEqual) {
const [atribute, value] = (qs.notEqual as string).split('=');
qs[atribute] = value;
delete qs.notEqual;
}
if (qs.include) {
const [atribute, value] = (qs.include as string).split('=');
qs[atribute] = value;
delete qs.include;
}
if (qs.exclude) {
const [atribute, value] = (qs.exclude as string).split('=');
qs[atribute] = value;
delete qs.exclude;
}
if (returnAll) {
responseData = await contenfulApiRequestAllItems.call(this, 'items', 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/assets`, {}, qs);
if (!rawData) {
const assets : IDataObject[] = [];
// tslint:disable-next-line: no-any
responseData.map((asset : any) => {
assets.push(asset.fields);
});
responseData = assets;
}
} else {
const limit = this.getNodeParameter('limit', i) as number;
qs.limit = limit;
responseData = await contentfulApiRequest.call(this, 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/assets`, {}, qs);
responseData = responseData.items;
if (!rawData) {
const assets : IDataObject[] = [];
// tslint:disable-next-line: no-any
responseData.map((asset : any) => {
assets.push(asset.fields);
});
responseData = assets;
}
}
}
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
if (resource === 'locale') {
if (operation === 'getAll') {
const credentials = this.getCredentials('contentfulApi');
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const env = this.getNodeParameter('environmentId', i) as string;
if (returnAll) {
responseData = await contenfulApiRequestAllItems.call(this, 'items', 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/locales`, {}, qs);
} else {
const limit = this.getNodeParameter('limit', 0) as number;
qs.limit = limit;
responseData = await contentfulApiRequest.call(this, 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/locales`, {}, qs);
responseData = responseData.items;
}
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];

View file

@ -185,299 +185,309 @@ export class ConvertKit implements INodeType {
for (let i = 0; i < items.length; i++) {
if (resource === 'customField') {
if (operation === 'create') {
try {
const label = this.getNodeParameter('label', i) as string;
if (resource === 'customField') {
if (operation === 'create') {
responseData = await convertKitApiRequest.call(this, 'POST', '/custom_fields', { label }, qs);
}
if (operation === 'delete') {
const label = this.getNodeParameter('label', i) as string;
const id = this.getNodeParameter('id', i) as string;
responseData = await convertKitApiRequest.call(this, 'POST', '/custom_fields', { label }, qs);
}
if (operation === 'delete') {
responseData = await convertKitApiRequest.call(this, 'DELETE', `/custom_fields/${id}`);
}
if (operation === 'get') {
const id = this.getNodeParameter('id', i) as string;
const id = this.getNodeParameter('id', i) as string;
responseData = await convertKitApiRequest.call(this, 'DELETE', `/custom_fields/${id}`);
}
if (operation === 'get') {
responseData = await convertKitApiRequest.call(this, 'GET', `/custom_fields/${id}`);
}
if (operation === 'getAll') {
const id = this.getNodeParameter('id', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
responseData = await convertKitApiRequest.call(this, 'GET', `/custom_fields/${id}`);
}
if (operation === 'getAll') {
responseData = await convertKitApiRequest.call(this, 'GET', `/custom_fields`);
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
responseData = responseData.custom_fields;
responseData = await convertKitApiRequest.call(this, 'GET', `/custom_fields`);
if (!returnAll) {
responseData = responseData.custom_fields;
const limit = this.getNodeParameter('limit', i) as number;
if (!returnAll) {
responseData = responseData.slice(0, limit);
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.slice(0, limit);
}
}
if (operation === 'update') {
const id = this.getNodeParameter('id', i) as string;
const label = this.getNodeParameter('label', i) as string;
responseData = await convertKitApiRequest.call(this, 'PUT', `/custom_fields/${id}`, { label });
responseData = { success: true };
}
}
if (operation === 'update') {
const id = this.getNodeParameter('id', i) as string;
if (resource === 'form') {
if (operation === 'addSubscriber') {
const label = this.getNodeParameter('label', i) as string;
const email = this.getNodeParameter('email', i) as string;
responseData = await convertKitApiRequest.call(this, 'PUT', `/custom_fields/${id}`, { label });
const formId = this.getNodeParameter('id', i) as string;
responseData = { success: true };
}
}
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (resource === 'form') {
if (operation === 'addSubscriber') {
const body: IDataObject = {
email,
};
const email = this.getNodeParameter('email', i) as string;
if (additionalFields.firstName) {
body.first_name = additionalFields.firstName as string;
}
const formId = this.getNodeParameter('id', i) as string;
if (additionalFields.tags) {
body.tags = additionalFields.tags as string[];
}
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IDataObject = {
email,
};
if (additionalFields.firstName) {
body.first_name = additionalFields.firstName as string;
}
if (additionalFields.tags) {
body.tags = additionalFields.tags as string[];
}
if (additionalFields.fieldsUi) {
const fieldValues = (additionalFields.fieldsUi as IDataObject).fieldsValues as IDataObject[];
if (fieldValues) {
body.fields = {};
for (const fieldValue of fieldValues) {
//@ts-ignore
body.fields[fieldValue.key] = fieldValue.value;
if (additionalFields.fieldsUi) {
const fieldValues = (additionalFields.fieldsUi as IDataObject).fieldsValues as IDataObject[];
if (fieldValues) {
body.fields = {};
for (const fieldValue of fieldValues) {
//@ts-ignore
body.fields[fieldValue.key] = fieldValue.value;
}
}
}
const { subscription } = await convertKitApiRequest.call(this, 'POST', `/forms/${formId}/subscribe`, body);
responseData = subscription;
}
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
responseData = await convertKitApiRequest.call(this, 'GET', `/forms`);
responseData = responseData.forms;
if (!returnAll) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.slice(0, limit);
}
}
if (operation === 'getSubscriptions') {
const formId = this.getNodeParameter('id', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (additionalFields.subscriberState) {
qs.subscriber_state = additionalFields.subscriberState as string;
}
responseData = await convertKitApiRequest.call(this, 'GET', `/forms/${formId}/subscriptions`, {}, qs);
responseData = responseData.subscriptions;
if (!returnAll) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.slice(0, limit);
}
}
}
if (resource === 'sequence') {
if (operation === 'addSubscriber') {
const email = this.getNodeParameter('email', i) as string;
const sequenceId = this.getNodeParameter('id', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IDataObject = {
email,
};
if (additionalFields.firstName) {
body.first_name = additionalFields.firstName as string;
}
if (additionalFields.tags) {
body.tags = additionalFields.tags as string[];
}
if (additionalFields.fieldsUi) {
const fieldValues = (additionalFields.fieldsUi as IDataObject).fieldsValues as IDataObject[];
if (fieldValues) {
body.fields = {};
for (const fieldValue of fieldValues) {
//@ts-ignore
body.fields[fieldValue.key] = fieldValue.value;
}
}
}
const { subscription } = await convertKitApiRequest.call(this, 'POST', `/sequences/${sequenceId}/subscribe`, body);
responseData = subscription;
}
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
responseData = await convertKitApiRequest.call(this, 'GET', `/sequences`);
responseData = responseData.courses;
if (!returnAll) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.slice(0, limit);
}
}
if (operation === 'getSubscriptions') {
const sequenceId = this.getNodeParameter('id', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (additionalFields.subscriberState) {
qs.subscriber_state = additionalFields.subscriberState as string;
}
responseData = await convertKitApiRequest.call(this, 'GET', `/sequences/${sequenceId}/subscriptions`, {}, qs);
responseData = responseData.subscriptions;
if (!returnAll) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.slice(0, limit);
}
}
}
if (resource === 'tag') {
if (operation === 'create') {
const names = ((this.getNodeParameter('name', i) as string).split(',') as string[]).map((e) => ({ name: e }));
const body: IDataObject = {
tag: names,
};
responseData = await convertKitApiRequest.call(this, 'POST', '/tags', body);
}
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
responseData = await convertKitApiRequest.call(this, 'GET', `/tags`);
responseData = responseData.tags;
if (!returnAll) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.slice(0, limit);
}
}
}
if (resource === 'tagSubscriber') {
if (operation === 'add') {
const tagId = this.getNodeParameter('tagId', i) as string;
const email = this.getNodeParameter('email', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IDataObject = {
email,
};
if (additionalFields.firstName) {
body.first_name = additionalFields.firstName as string;
}
if (additionalFields.fieldsUi) {
const fieldValues = (additionalFields.fieldsUi as IDataObject).fieldsValues as IDataObject[];
if (fieldValues) {
body.fields = {};
for (const fieldValue of fieldValues) {
//@ts-ignore
body.fields[fieldValue.key] = fieldValue.value;
}
}
}
const { subscription } = await convertKitApiRequest.call(this, 'POST', `/tags/${tagId}/subscribe`, body);
responseData = subscription;
}
if (operation === 'getAll') {
const tagId = this.getNodeParameter('tagId', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
responseData = await convertKitApiRequest.call(this, 'GET', `/tags/${tagId}/subscriptions`);
responseData = responseData.subscriptions;
if (!returnAll) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.slice(0, limit);
}
}
const { subscription } = await convertKitApiRequest.call(this, 'POST', `/forms/${formId}/subscribe`, body);
if (operation === 'delete') {
responseData = subscription;
}
if (operation === 'getAll') {
const tagId = this.getNodeParameter('tagId', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const email = this.getNodeParameter('email', i) as string;
responseData = await convertKitApiRequest.call(this, 'GET', `/forms`);
responseData = responseData.forms;
if (!returnAll) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.slice(0, limit);
}
}
if (operation === 'getSubscriptions') {
const formId = this.getNodeParameter('id', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (additionalFields.subscriberState) {
qs.subscriber_state = additionalFields.subscriberState as string;
}
responseData = await convertKitApiRequest.call(this, 'GET', `/forms/${formId}/subscriptions`, {}, qs);
responseData = responseData.subscriptions;
if (!returnAll) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.slice(0, limit);
}
}
}
if (resource === 'sequence') {
if (operation === 'addSubscriber') {
const email = this.getNodeParameter('email', i) as string;
const sequenceId = this.getNodeParameter('id', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IDataObject = {
email,
};
if (additionalFields.firstName) {
body.first_name = additionalFields.firstName as string;
}
if (additionalFields.tags) {
body.tags = additionalFields.tags as string[];
}
if (additionalFields.fieldsUi) {
const fieldValues = (additionalFields.fieldsUi as IDataObject).fieldsValues as IDataObject[];
if (fieldValues) {
body.fields = {};
for (const fieldValue of fieldValues) {
//@ts-ignore
body.fields[fieldValue.key] = fieldValue.value;
}
}
}
const { subscription } = await convertKitApiRequest.call(this, 'POST', `/sequences/${sequenceId}/subscribe`, body);
responseData = subscription;
}
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
responseData = await convertKitApiRequest.call(this, 'GET', `/sequences`);
responseData = responseData.courses;
if (!returnAll) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.slice(0, limit);
}
}
if (operation === 'getSubscriptions') {
const sequenceId = this.getNodeParameter('id', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (additionalFields.subscriberState) {
qs.subscriber_state = additionalFields.subscriberState as string;
}
responseData = await convertKitApiRequest.call(this, 'GET', `/sequences/${sequenceId}/subscriptions`, {}, qs);
responseData = responseData.subscriptions;
if (!returnAll) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.slice(0, limit);
}
}
}
if (resource === 'tag') {
if (operation === 'create') {
const names = ((this.getNodeParameter('name', i) as string).split(',') as string[]).map((e) => ({ name: e }));
const body: IDataObject = {
tag: names,
};
responseData = await convertKitApiRequest.call(this, 'POST', '/tags', body);
}
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
responseData = await convertKitApiRequest.call(this, 'GET', `/tags`);
responseData = responseData.tags;
if (!returnAll) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.slice(0, limit);
}
}
}
if (resource === 'tagSubscriber') {
if (operation === 'add') {
const tagId = this.getNodeParameter('tagId', i) as string;
const email = this.getNodeParameter('email', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IDataObject = {
email,
};
if (additionalFields.firstName) {
body.first_name = additionalFields.firstName as string;
}
if (additionalFields.fieldsUi) {
const fieldValues = (additionalFields.fieldsUi as IDataObject).fieldsValues as IDataObject[];
if (fieldValues) {
body.fields = {};
for (const fieldValue of fieldValues) {
//@ts-ignore
body.fields[fieldValue.key] = fieldValue.value;
}
}
}
const { subscription } = await convertKitApiRequest.call(this, 'POST', `/tags/${tagId}/subscribe`, body);
responseData = subscription;
}
if (operation === 'getAll') {
const tagId = this.getNodeParameter('tagId', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
responseData = await convertKitApiRequest.call(this, 'GET', `/tags/${tagId}/subscriptions`);
responseData = responseData.subscriptions;
if (!returnAll) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.slice(0, limit);
responseData = await convertKitApiRequest.call(this, 'POST', `/tags/${tagId}>/unsubscribe`, { email });
}
}
if (operation === 'delete') {
const tagId = this.getNodeParameter('tagId', i) as string;
const email = this.getNodeParameter('email', i) as string;
responseData = await convertKitApiRequest.call(this, 'POST', `/tags/${tagId}>/unsubscribe`, { email });
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else if (responseData !== undefined) {
returnData.push(responseData as IDataObject);
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else if (responseData !== undefined) {
returnData.push(responseData as IDataObject);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}

View file

@ -204,264 +204,274 @@ export class Cortex implements INodeType {
const operation = this.getNodeParameter('operation', 0) as string;
for (let i = 0; i < length; i++) {
if (resource === 'analyzer') {
//https://github.com/TheHive-Project/CortexDocs/blob/master/api/api-guide.md#run
if (operation === 'execute') {
try {
let force = false;
if (resource === 'analyzer') {
//https://github.com/TheHive-Project/CortexDocs/blob/master/api/api-guide.md#run
if (operation === 'execute') {
const analyzer = this.getNodeParameter('analyzer', i) as string;
let force = false;
const observableType = this.getNodeParameter('observableType', i) as string;
const analyzer = this.getNodeParameter('analyzer', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const observableType = this.getNodeParameter('observableType', i) as string;
const tlp = this.getNodeParameter('tlp', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IDataObject = {
dataType: observableType,
tlp,
};
const tlp = this.getNodeParameter('tlp', i) as string;
if (additionalFields.force === true) {
force = true;
}
if (observableType === 'file') {
const item = items[i];
if (item.binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
}
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i) as string;
if (item.binary[binaryPropertyName] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property "${binaryPropertyName}" does not exists on item!`);
}
const fileBufferData = Buffer.from(item.binary[binaryPropertyName].data, BINARY_ENCODING);
const options = {
formData: {
data: {
value: fileBufferData,
options: {
contentType: item.binary[binaryPropertyName].mimeType,
filename: item.binary[binaryPropertyName].fileName,
},
},
_json: JSON.stringify({
dataType: observableType,
tlp,
}),
},
const body: IDataObject = {
dataType: observableType,
tlp,
};
responseData = await cortexApiRequest.call(
this,
'POST',
`/analyzer/${analyzer.split('::')[0]}/run`,
{},
{ force },
'',
options,
) as IJob;
if (additionalFields.force === true) {
force = true;
}
continue;
if (observableType === 'file') {
} else {
const observableValue = this.getNodeParameter('observableValue', i) as string;
const item = items[i];
body.data = observableValue;
if (item.binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
}
responseData = await cortexApiRequest.call(
this,
'POST',
`/analyzer/${analyzer.split('::')[0]}/run`,
body,
{ force },
) as IJob;
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i) as string;
if (item.binary[binaryPropertyName] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property "${binaryPropertyName}" does not exists on item!`);
}
const fileBufferData = Buffer.from(item.binary[binaryPropertyName].data, BINARY_ENCODING);
const options = {
formData: {
data: {
value: fileBufferData,
options: {
contentType: item.binary[binaryPropertyName].mimeType,
filename: item.binary[binaryPropertyName].fileName,
},
},
_json: JSON.stringify({
dataType: observableType,
tlp,
}),
},
};
responseData = await cortexApiRequest.call(
this,
'POST',
`/analyzer/${analyzer.split('::')[0]}/run`,
{},
{ force },
'',
options,
) as IJob;
continue;
} else {
const observableValue = this.getNodeParameter('observableValue', i) as string;
body.data = observableValue;
responseData = await cortexApiRequest.call(
this,
'POST',
`/analyzer/${analyzer.split('::')[0]}/run`,
body,
{ force },
) as IJob;
}
if (additionalFields.timeout) {
responseData = await cortexApiRequest.call(
this,
'GET',
`/job/${responseData.id}/waitreport`,
{},
{ atMost: `${additionalFields.timeout}second` },
);
}
}
}
if (resource === 'job') {
//https://github.com/TheHive-Project/CortexDocs/blob/master/api/api-guide.md#get-details-1
if (operation === 'get') {
const jobId = this.getNodeParameter('jobId', i) as string;
if (additionalFields.timeout) {
responseData = await cortexApiRequest.call(
this,
'GET',
`/job/${responseData.id}/waitreport`,
{},
{ atMost: `${additionalFields.timeout}second` },
`/job/${jobId}`,
);
}
//https://github.com/TheHive-Project/CortexDocs/blob/master/api/api-guide.md#get-details-and-report
if (operation === 'report') {
const jobId = this.getNodeParameter('jobId', i) as string;
responseData = await cortexApiRequest.call(
this,
'GET',
`/job/${jobId}/report`,
);
}
}
}
if (resource === 'job') {
//https://github.com/TheHive-Project/CortexDocs/blob/master/api/api-guide.md#get-details-1
if (operation === 'get') {
if (resource === 'responder') {
if (operation === 'execute') {
const responderId = (this.getNodeParameter('responder', i) as string).split('::')[0];
const jobId = this.getNodeParameter('jobId', i) as string;
const entityType = this.getNodeParameter('entityType', i) as string;
responseData = await cortexApiRequest.call(
this,
'GET',
`/job/${jobId}`,
);
}
//https://github.com/TheHive-Project/CortexDocs/blob/master/api/api-guide.md#get-details-and-report
if (operation === 'report') {
const jobId = this.getNodeParameter('jobId', i) as string;
responseData = await cortexApiRequest.call(
this,
'GET',
`/job/${jobId}/report`,
);
}
}
if (resource === 'responder') {
if (operation === 'execute') {
const responderId = (this.getNodeParameter('responder', i) as string).split('::')[0];
const entityType = this.getNodeParameter('entityType', i) as string;
const isJSON = this.getNodeParameter('jsonObject', i) as boolean;
let body: IDataObject;
const isJSON = this.getNodeParameter('jsonObject', i) as boolean;
let body: IDataObject;
if (isJSON) {
const entityJson = JSON.parse(this.getNodeParameter('objectData', i) as string);
if (isJSON) {
const entityJson = JSON.parse(this.getNodeParameter('objectData', i) as string);
body = {
responderId,
label: getEntityLabel(entityJson),
dataType: `thehive:${entityType}`,
data: entityJson,
tlp: entityJson.tlp || 2,
pap: entityJson.pap || 2,
message: entityJson.message || '',
parameters: [],
};
body = {
responderId,
label: getEntityLabel(entityJson),
dataType: `thehive:${entityType}`,
data: entityJson,
tlp: entityJson.tlp || 2,
pap: entityJson.pap || 2,
message: entityJson.message || '',
parameters: [],
};
} else {
} else {
const values = (this.getNodeParameter('parameters', i) as IDataObject).values as IDataObject;
const values = (this.getNodeParameter('parameters', i) as IDataObject).values as IDataObject;
body = {
responderId,
dataType: `thehive:${entityType}`,
data: {
_type: entityType,
...prepareParameters(values),
},
};
if (entityType === 'alert') {
// deal with alert artifacts
const artifacts = (body.data as IDataObject).artifacts as IDataObject;
body = {
responderId,
dataType: `thehive:${entityType}`,
data: {
_type: entityType,
...prepareParameters(values),
},
};
if (entityType === 'alert') {
// deal with alert artifacts
const artifacts = (body.data as IDataObject).artifacts as IDataObject;
if (artifacts) {
if (artifacts) {
const artifactValues = (artifacts as IDataObject).artifactValues as IDataObject[];
const artifactValues = (artifacts as IDataObject).artifactValues as IDataObject[];
if (artifactValues) {
if (artifactValues) {
const artifactData = [];
const artifactData = [];
for (const artifactvalue of artifactValues) {
for (const artifactvalue of artifactValues) {
const element: IDataObject = {};
const element: IDataObject = {};
element.message = artifactvalue.message as string;
element.message = artifactvalue.message as string;
element.tags = splitTags(artifactvalue.tags as string) as string[];
element.tags = splitTags(artifactvalue.tags as string) as string[];
element.dataType = artifactvalue.dataType as string;
element.dataType = artifactvalue.dataType as string;
element.data = artifactvalue.data as string;
element.data = artifactvalue.data as string;
if (artifactvalue.dataType === 'file') {
if (artifactvalue.dataType === 'file') {
const item = items[i];
const item = items[i];
if (item.binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
if (item.binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
}
const binaryPropertyName = artifactvalue.binaryProperty as string;
if (item.binary[binaryPropertyName] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property '${binaryPropertyName}' does not exists on item!`);
}
const binaryData = item.binary[binaryPropertyName] as IBinaryData;
element.data = `${binaryData.fileName};${binaryData.mimeType};${binaryData.data}`;
}
const binaryPropertyName = artifactvalue.binaryProperty as string;
if (item.binary[binaryPropertyName] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property '${binaryPropertyName}' does not exists on item!`);
}
const binaryData = item.binary[binaryPropertyName] as IBinaryData;
element.data = `${binaryData.fileName};${binaryData.mimeType};${binaryData.data}`;
artifactData.push(element);
}
artifactData.push(element);
(body.data as IDataObject).artifacts = artifactData;
}
}
}
if (entityType === 'case_artifact') {
// deal with file observable
if ((body.data as IDataObject).dataType === 'file') {
const item = items[i];
if (item.binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
}
(body.data as IDataObject).artifacts = artifactData;
const binaryPropertyName = (body.data as IDataObject).binaryPropertyName as string;
if (item.binary[binaryPropertyName] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property "${binaryPropertyName}" does not exists on item!`);
}
const fileBufferData = Buffer.from(item.binary[binaryPropertyName].data, BINARY_ENCODING);
const sha256 = createHash('sha256').update(fileBufferData).digest('hex');
(body.data as IDataObject).attachment = {
name: item.binary[binaryPropertyName].fileName,
hashes: [
sha256,
createHash('sha1').update(fileBufferData).digest('hex'),
createHash('md5').update(fileBufferData).digest('hex'),
],
size: fileBufferData.byteLength,
contentType: item.binary[binaryPropertyName].mimeType,
id: sha256,
};
delete (body.data as IDataObject).binaryPropertyName;
}
}
// add the job label after getting all entity attributes
body = {
label: getEntityLabel(body.data as IDataObject),
...body,
};
}
if (entityType === 'case_artifact') {
// deal with file observable
if ((body.data as IDataObject).dataType === 'file') {
const item = items[i];
if (item.binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
}
const binaryPropertyName = (body.data as IDataObject).binaryPropertyName as string;
if (item.binary[binaryPropertyName] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property "${binaryPropertyName}" does not exists on item!`);
}
const fileBufferData = Buffer.from(item.binary[binaryPropertyName].data, BINARY_ENCODING);
const sha256 = createHash('sha256').update(fileBufferData).digest('hex');
(body.data as IDataObject).attachment = {
name: item.binary[binaryPropertyName].fileName,
hashes: [
sha256,
createHash('sha1').update(fileBufferData).digest('hex'),
createHash('md5').update(fileBufferData).digest('hex'),
],
size: fileBufferData.byteLength,
contentType: item.binary[binaryPropertyName].mimeType,
id: sha256,
};
delete (body.data as IDataObject).binaryPropertyName;
}
}
// add the job label after getting all entity attributes
body = {
label: getEntityLabel(body.data as IDataObject),
...body,
};
responseData = await cortexApiRequest.call(
this,
'POST',
`/responder/${responderId}/run`,
body,
) as IJob;
}
responseData = await cortexApiRequest.call(
this,
'POST',
`/responder/${responderId}/run`,
body,
) as IJob;
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else if (responseData !== undefined) {
returnData.push(responseData as IDataObject);
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else if (responseData !== undefined) {
returnData.push(responseData as IDataObject);
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];

View file

@ -364,52 +364,63 @@ export class Crypto implements INodeType {
let item: INodeExecutionData;
for (let i = 0; i < length; i++) {
item = items[i];
const dataPropertyName = this.getNodeParameter('dataPropertyName', i) as string;
const value = this.getNodeParameter('value', i) as string;
let newValue;
if (action === 'hash') {
const type = this.getNodeParameter('type', i) as string;
const encoding = this.getNodeParameter('encoding', i) as BinaryToTextEncoding;
newValue = createHash(type).update(value).digest(encoding);
}
if (action === 'hmac') {
const type = this.getNodeParameter('type', i) as string;
const secret = this.getNodeParameter('secret', i) as string;
const encoding = this.getNodeParameter('encoding', i) as BinaryToTextEncoding;
newValue = createHmac(type, secret).update(value).digest(encoding);
}
if (action === 'sign') {
const algorithm = this.getNodeParameter('algorithm', i) as string;
const encoding = this.getNodeParameter('encoding', i) as BinaryToTextEncoding;
const privateKey = this.getNodeParameter('privateKey', i) as string;
const sign = createSign(algorithm);
sign.write(value as string);
sign.end();
newValue = sign.sign(privateKey, encoding);
}
try {
let newItem: INodeExecutionData;
if (dataPropertyName.includes('.')) {
// Uses dot notation so copy all data
newItem = {
json: JSON.parse(JSON.stringify(item.json)),
};
} else {
// Does not use dot notation so shallow copy is enough
newItem = {
json: { ...item.json },
};
item = items[i];
const dataPropertyName = this.getNodeParameter('dataPropertyName', i) as string;
const value = this.getNodeParameter('value', i) as string;
let newValue;
if (action === 'hash') {
const type = this.getNodeParameter('type', i) as string;
const encoding = this.getNodeParameter('encoding', i) as BinaryToTextEncoding;
newValue = createHash(type).update(value).digest(encoding);
}
if (action === 'hmac') {
const type = this.getNodeParameter('type', i) as string;
const secret = this.getNodeParameter('secret', i) as string;
const encoding = this.getNodeParameter('encoding', i) as BinaryToTextEncoding;
newValue = createHmac(type, secret).update(value).digest(encoding);
}
if (action === 'sign') {
const algorithm = this.getNodeParameter('algorithm', i) as string;
const encoding = this.getNodeParameter('encoding', i) as BinaryToTextEncoding;
const privateKey = this.getNodeParameter('privateKey', i) as string;
const sign = createSign(algorithm);
sign.write(value as string);
sign.end();
newValue = sign.sign(privateKey, encoding);
}
let newItem: INodeExecutionData;
if (dataPropertyName.includes('.')) {
// Uses dot notation so copy all data
newItem = {
json: JSON.parse(JSON.stringify(item.json)),
};
} else {
// Does not use dot notation so shallow copy is enough
newItem = {
json: { ...item.json },
};
}
if (item.binary !== undefined) {
newItem.binary = item.binary;
}
set(newItem, `json.${dataPropertyName}`, newValue);
returnData.push(newItem);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({json:{ error: error.message }});
continue;
}
throw error;
}
if (item.binary !== undefined) {
newItem.binary = item.binary;
}
set(newItem, `json.${dataPropertyName}`, newValue);
returnData.push(newItem);
}
return this.prepareOutputData(returnData);
}

View file

@ -102,239 +102,249 @@ export class CustomerIo implements INodeType {
let responseData;
for (let i = 0; i < items.length; i++) {
if (resource === 'campaign') {
if (operation === 'get') {
const campaignId = this.getNodeParameter('campaignId', i) as number;
const endpoint = `/campaigns/${campaignId}`;
try {
responseData = await customerIoApiRequest.call(this, 'GET', endpoint, body, 'beta');
responseData = responseData.campaign;
}
if (operation === 'getAll') {
const endpoint = `/campaigns`;
responseData = await customerIoApiRequest.call(this, 'GET', endpoint, body, 'beta');
responseData = responseData.campaigns;
}
if (operation === 'getMetrics') {
const campaignId = this.getNodeParameter('campaignId', i) as number;
const jsonParameters = this.getNodeParameter('jsonParameters', i) as boolean;
if (jsonParameters) {
const additionalFieldsJson = this.getNodeParameter('additionalFieldsJson', i) as string;
if (additionalFieldsJson !== '') {
if (validateJSON(additionalFieldsJson) !== undefined) {
Object.assign(body, JSON.parse(additionalFieldsJson));
} else {
throw new NodeOperationError(this.getNode(), 'Additional fields must be a valid JSON');
}
}
} else {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const period = this.getNodeParameter('period', i) as string;
let endpoint = `/campaigns/${campaignId}/metrics`;
if (period !== 'days') {
endpoint = `${endpoint}?period=${period}`;
}
if (additionalFields.steps) {
body.steps = additionalFields.steps as number;
}
if (additionalFields.type) {
if (additionalFields.type === 'urbanAirship') {
additionalFields.type = 'urban_airship';
} else {
body.type = additionalFields.type as string;
}
}
if (resource === 'campaign') {
if (operation === 'get') {
const campaignId = this.getNodeParameter('campaignId', i) as number;
const endpoint = `/campaigns/${campaignId}`;
responseData = await customerIoApiRequest.call(this, 'GET', endpoint, body, 'beta');
responseData = responseData.metric;
responseData = responseData.campaign;
}
if (operation === 'getAll') {
const endpoint = `/campaigns`;
responseData = await customerIoApiRequest.call(this, 'GET', endpoint, body, 'beta');
responseData = responseData.campaigns;
}
if (operation === 'getMetrics') {
const campaignId = this.getNodeParameter('campaignId', i) as number;
const jsonParameters = this.getNodeParameter('jsonParameters', i) as boolean;
if (jsonParameters) {
const additionalFieldsJson = this.getNodeParameter('additionalFieldsJson', i) as string;
if (additionalFieldsJson !== '') {
if (validateJSON(additionalFieldsJson) !== undefined) {
Object.assign(body, JSON.parse(additionalFieldsJson));
} else {
throw new NodeOperationError(this.getNode(), 'Additional fields must be a valid JSON');
}
}
} else {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const period = this.getNodeParameter('period', i) as string;
let endpoint = `/campaigns/${campaignId}/metrics`;
if (period !== 'days') {
endpoint = `${endpoint}?period=${period}`;
}
if (additionalFields.steps) {
body.steps = additionalFields.steps as number;
}
if (additionalFields.type) {
if (additionalFields.type === 'urbanAirship') {
additionalFields.type = 'urban_airship';
} else {
body.type = additionalFields.type as string;
}
}
responseData = await customerIoApiRequest.call(this, 'GET', endpoint, body, 'beta');
responseData = responseData.metric;
}
}
}
}
if (resource === 'customer') {
if (resource === 'customer') {
if (operation === 'upsert') {
const id = this.getNodeParameter('id', i) as number;
const jsonParameters = this.getNodeParameter('jsonParameters', i) as boolean;
if (operation === 'upsert') {
const id = this.getNodeParameter('id', i) as number;
const jsonParameters = this.getNodeParameter('jsonParameters', i) as boolean;
if (jsonParameters) {
const additionalFieldsJson = this.getNodeParameter('additionalFieldsJson', i) as string;
if (jsonParameters) {
const additionalFieldsJson = this.getNodeParameter('additionalFieldsJson', i) as string;
if (additionalFieldsJson !== '') {
if (additionalFieldsJson !== '') {
if (validateJSON(additionalFieldsJson) !== undefined) {
if (validateJSON(additionalFieldsJson) !== undefined) {
Object.assign(body, JSON.parse(additionalFieldsJson));
Object.assign(body, JSON.parse(additionalFieldsJson));
} else {
throw new NodeOperationError(this.getNode(), 'Additional fields must be a valid JSON');
} else {
throw new NodeOperationError(this.getNode(), 'Additional fields must be a valid JSON');
}
}
} else {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (additionalFields.customProperties) {
const data: any = {}; // tslint:disable-line:no-any
//@ts-ignore
additionalFields.customProperties.customProperty.map(property => {
data[property.key] = property.value;
});
body.data = data;
}
if (additionalFields.email) {
body.email = additionalFields.email as string;
}
if (additionalFields.createdAt) {
body.created_at = new Date(additionalFields.createdAt as string).getTime() / 1000;
}
}
} else {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (additionalFields.customProperties) {
const endpoint = `/customers/${id}`;
responseData = await customerIoApiRequest.call(this, 'PUT', endpoint, body, 'tracking');
responseData = Object.assign({ id }, body);
}
if (operation === 'delete') {
const id = this.getNodeParameter('id', i) as number;
body.id = id;
const endpoint = `/customers/${id}`;
await customerIoApiRequest.call(this, 'DELETE', endpoint, body, 'tracking');
responseData = {
success: true,
};
}
}
if (resource === 'event') {
if (operation === 'track') {
const customerId = this.getNodeParameter('customerId', i) as number;
const eventName = this.getNodeParameter('eventName', i) as string;
const jsonParameters = this.getNodeParameter('jsonParameters', i) as boolean;
body.name = eventName;
if (jsonParameters) {
const additionalFieldsJson = this.getNodeParameter('additionalFieldsJson', i) as string;
if (additionalFieldsJson !== '') {
if (validateJSON(additionalFieldsJson) !== undefined) {
Object.assign(body, JSON.parse(additionalFieldsJson));
} else {
throw new NodeOperationError(this.getNode(), 'Additional fields must be a valid JSON');
}
}
} else {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const data: any = {}; // tslint:disable-line:no-any
//@ts-ignore
additionalFields.customProperties.customProperty.map(property => {
data[property.key] = property.value;
});
if (additionalFields.customAttributes) {
//@ts-ignore
additionalFields.customAttributes.customAttribute.map(property => {
data[property.key] = property.value;
});
}
if (additionalFields.type) {
data.type = additionalFields.type as string;
}
body.data = data;
}
if (additionalFields.email) {
body.email = additionalFields.email as string;
}
const endpoint = `/customers/${customerId}/events`;
if (additionalFields.createdAt) {
body.created_at = new Date(additionalFields.createdAt as string).getTime() / 1000;
}
await customerIoApiRequest.call(this, 'POST', endpoint, body, 'tracking');
responseData = {
success: true,
};
}
const endpoint = `/customers/${id}`;
if (operation === 'trackAnonymous') {
const eventName = this.getNodeParameter('eventName', i) as string;
const jsonParameters = this.getNodeParameter('jsonParameters', i) as boolean;
responseData = await customerIoApiRequest.call(this, 'PUT', endpoint, body, 'tracking');
body.name = eventName;
responseData = Object.assign({ id }, body);
}
if (jsonParameters) {
const additionalFieldsJson = this.getNodeParameter('additionalFieldsJson', i) as string;
if (operation === 'delete') {
const id = this.getNodeParameter('id', i) as number;
if (additionalFieldsJson !== '') {
body.id = id;
if (validateJSON(additionalFieldsJson) !== undefined) {
const endpoint = `/customers/${id}`;
Object.assign(body, JSON.parse(additionalFieldsJson));
await customerIoApiRequest.call(this, 'DELETE', endpoint, body, 'tracking');
responseData = {
success: true,
};
}
}
if (resource === 'event') {
if (operation === 'track') {
const customerId = this.getNodeParameter('customerId', i) as number;
const eventName = this.getNodeParameter('eventName', i) as string;
const jsonParameters = this.getNodeParameter('jsonParameters', i) as boolean;
body.name = eventName;
if (jsonParameters) {
const additionalFieldsJson = this.getNodeParameter('additionalFieldsJson', i) as string;
if (additionalFieldsJson !== '') {
if (validateJSON(additionalFieldsJson) !== undefined) {
Object.assign(body, JSON.parse(additionalFieldsJson));
} else {
throw new NodeOperationError(this.getNode(), 'Additional fields must be a valid JSON');
} else {
throw new NodeOperationError(this.getNode(), 'Additional fields must be a valid JSON');
}
}
}
} else {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const data: any = {}; // tslint:disable-line:no-any
} else {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const data: any = {}; // tslint:disable-line:no-any
if (additionalFields.customAttributes) {
//@ts-ignore
additionalFields.customAttributes.customAttribute.map(property => {
data[property.key] = property.value;
});
}
if (additionalFields.type) {
data.type = additionalFields.type as string;
}
body.data = data;
}
const endpoint = `/customers/${customerId}/events`;
await customerIoApiRequest.call(this, 'POST', endpoint, body, 'tracking');
responseData = {
success: true,
};
}
if (operation === 'trackAnonymous') {
const eventName = this.getNodeParameter('eventName', i) as string;
const jsonParameters = this.getNodeParameter('jsonParameters', i) as boolean;
body.name = eventName;
if (jsonParameters) {
const additionalFieldsJson = this.getNodeParameter('additionalFieldsJson', i) as string;
if (additionalFieldsJson !== '') {
if (validateJSON(additionalFieldsJson) !== undefined) {
Object.assign(body, JSON.parse(additionalFieldsJson));
} else {
throw new NodeOperationError(this.getNode(), 'Additional fields must be a valid JSON');
if (additionalFields.customAttributes) {
//@ts-ignore
additionalFields.customAttributes.customAttribute.map(property => {
data[property.key] = property.value;
});
}
body.data = data;
}
} else {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const data: any = {}; // tslint:disable-line:no-any
if (additionalFields.customAttributes) {
//@ts-ignore
additionalFields.customAttributes.customAttribute.map(property => {
data[property.key] = property.value;
});
}
body.data = data;
const endpoint = `/events`;
await customerIoApiRequest.call(this, 'POST', endpoint, body, 'tracking');
responseData = {
success: true,
};
}
}
if (resource === 'segment') {
const segmentId = this.getNodeParameter('segmentId', i) as number;
const customerIds = this.getNodeParameter('customerIds', i) as string;
body.id = segmentId;
body.ids = customerIds.split(',');
let endpoint = '';
if (operation === 'add') {
endpoint = `/segments/${segmentId}/add_customers`;
} else {
endpoint = `/segments/${segmentId}/remove_customers`;
}
const endpoint = `/events`;
await customerIoApiRequest.call(this, 'POST', endpoint, body, 'tracking');
responseData = await customerIoApiRequest.call(this, 'POST', endpoint, body, 'tracking');
responseData = {
success: true,
};
}
}
if (resource === 'segment') {
const segmentId = this.getNodeParameter('segmentId', i) as number;
const customerIds = this.getNodeParameter('customerIds', i) as string;
body.id = segmentId;
body.ids = customerIds.split(',');
let endpoint = '';
if (operation === 'add') {
endpoint = `/segments/${segmentId}/add_customers`;
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
endpoint = `/segments/${segmentId}/remove_customers`;
returnData.push(responseData as unknown as IDataObject);
}
responseData = await customerIoApiRequest.call(this, 'POST', endpoint, body, 'tracking');
responseData = {
success: true,
};
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as unknown as IDataObject);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}

View file

@ -393,110 +393,120 @@ export class DateTime implements INodeType {
let item: INodeExecutionData;
for (let i = 0; i < length; i++) {
const action = this.getNodeParameter('action', 0) as string;
item = items[i];
try {
if (action === 'format') {
const currentDate = this.getNodeParameter('value', i) as string;
const dataPropertyName = this.getNodeParameter('dataPropertyName', i) as string;
const toFormat = this.getNodeParameter('toFormat', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
let newDate;
const action = this.getNodeParameter('action', 0) as string;
item = items[i];
if (currentDate === undefined) {
continue;
}
if (options.fromFormat === undefined && !moment(currentDate as string | number).isValid()) {
throw new NodeOperationError(this.getNode(), 'The date input format could not be recognized. Please set the "From Format" field');
}
if (action === 'format') {
const currentDate = this.getNodeParameter('value', i) as string;
const dataPropertyName = this.getNodeParameter('dataPropertyName', i) as string;
const toFormat = this.getNodeParameter('toFormat', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
let newDate;
if (Number.isInteger(currentDate as unknown as number)) {
newDate = moment.unix(currentDate as unknown as number);
} else {
if (options.fromTimezone || options.toTimezone) {
const fromTimezone = options.fromTimezone || workflowTimezone;
if (options.fromFormat) {
newDate = moment.tz(currentDate as string, options.fromFormat as string, fromTimezone as string);
} else {
newDate = moment.tz(currentDate as string, fromTimezone as string);
}
if (currentDate === undefined) {
continue;
}
if (options.fromFormat === undefined && !moment(currentDate as string | number).isValid()) {
throw new NodeOperationError(this.getNode(), 'The date input format could not be recognized. Please set the "From Format" field');
}
if (Number.isInteger(currentDate as unknown as number)) {
newDate = moment.unix(currentDate as unknown as number);
} else {
if (options.fromFormat) {
newDate = moment(currentDate as string, options.fromFormat as string);
if (options.fromTimezone || options.toTimezone) {
const fromTimezone = options.fromTimezone || workflowTimezone;
if (options.fromFormat) {
newDate = moment.tz(currentDate as string, options.fromFormat as string, fromTimezone as string);
} else {
newDate = moment.tz(currentDate as string, fromTimezone as string);
}
} else {
newDate = moment(currentDate as string);
if (options.fromFormat) {
newDate = moment(currentDate as string, options.fromFormat as string);
} else {
newDate = moment(currentDate as string);
}
}
}
if (options.toTimezone || options.fromTimezone) {
// If either a source or a target timezone got defined the
// timezone of the date has to be changed. If a target-timezone
// is set use it else fall back to workflow timezone.
newDate = newDate.tz(options.toTimezone as string || workflowTimezone);
}
newDate = newDate.format(toFormat);
let newItem: INodeExecutionData;
if (dataPropertyName.includes('.')) {
// Uses dot notation so copy all data
newItem = {
json: JSON.parse(JSON.stringify(item.json)),
};
} else {
// Does not use dot notation so shallow copy is enough
newItem = {
json: { ...item.json },
};
}
if (item.binary !== undefined) {
newItem.binary = item.binary;
}
set(newItem, `json.${dataPropertyName}`, newDate);
returnData.push(newItem);
}
if (options.toTimezone || options.fromTimezone) {
// If either a source or a target timezone got defined the
// timezone of the date has to be changed. If a target-timezone
// is set use it else fall back to workflow timezone.
newDate = newDate.tz(options.toTimezone as string || workflowTimezone);
if (action === 'calculate') {
const dateValue = this.getNodeParameter('value', i) as string;
const operation = this.getNodeParameter('operation', i) as 'add' | 'subtract';
const duration = this.getNodeParameter('duration', i) as number;
const timeUnit = this.getNodeParameter('timeUnit', i) as moment.DurationInputArg2;
const { fromFormat } = this.getNodeParameter('options', i) as { fromFormat?: string };
const dataPropertyName = this.getNodeParameter('dataPropertyName', i) as string;
const newDate = fromFormat
? parseDateByFormat(dateValue, fromFormat)
: parseDateByDefault(dateValue);
operation === 'add'
? newDate.add(duration, timeUnit).utc().format()
: newDate.subtract(duration, timeUnit).utc().format();
let newItem: INodeExecutionData;
if (dataPropertyName.includes('.')) {
// Uses dot notation so copy all data
newItem = {
json: JSON.parse(JSON.stringify(item.json)),
};
} else {
// Does not use dot notation so shallow copy is enough
newItem = {
json: { ...item.json },
};
}
if (item.binary !== undefined) {
newItem.binary = item.binary;
}
set(newItem, `json.${dataPropertyName}`, newDate);
returnData.push(newItem);
}
newDate = newDate.format(toFormat);
let newItem: INodeExecutionData;
if (dataPropertyName.includes('.')) {
// Uses dot notation so copy all data
newItem = {
json: JSON.parse(JSON.stringify(item.json)),
};
} else {
// Does not use dot notation so shallow copy is enough
newItem = {
json: { ...item.json },
};
} catch (error) {
if (this.continueOnFail()) {
returnData.push({json:{ error: error.message }});
continue;
}
if (item.binary !== undefined) {
newItem.binary = item.binary;
}
set(newItem, `json.${dataPropertyName}`, newDate);
returnData.push(newItem);
}
if (action === 'calculate') {
const dateValue = this.getNodeParameter('value', i) as string;
const operation = this.getNodeParameter('operation', i) as 'add' | 'subtract';
const duration = this.getNodeParameter('duration', i) as number;
const timeUnit = this.getNodeParameter('timeUnit', i) as moment.DurationInputArg2;
const { fromFormat } = this.getNodeParameter('options', i) as { fromFormat?: string };
const dataPropertyName = this.getNodeParameter('dataPropertyName', i) as string;
const newDate = fromFormat
? parseDateByFormat(dateValue, fromFormat)
: parseDateByDefault(dateValue);
operation === 'add'
? newDate.add(duration, timeUnit).utc().format()
: newDate.subtract(duration, timeUnit).utc().format();
let newItem: INodeExecutionData;
if (dataPropertyName.includes('.')) {
// Uses dot notation so copy all data
newItem = {
json: JSON.parse(JSON.stringify(item.json)),
};
} else {
// Does not use dot notation so shallow copy is enough
newItem = {
json: { ...item.json },
};
}
if (item.binary !== undefined) {
newItem.binary = item.binary;
}
set(newItem, `json.${dataPropertyName}`, newDate);
returnData.push(newItem);
throw error;
}
}

View file

@ -108,28 +108,35 @@ export class DeepL implements INodeType {
const responseData = [];
for (let i = 0; i < length; i++) {
try {
const resource = this.getNodeParameter('resource', i) as string;
const operation = this.getNodeParameter('operation', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const resource = this.getNodeParameter('resource', i) as string;
const operation = this.getNodeParameter('operation', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (resource === 'language') {
if (resource === 'language') {
if (operation === 'translate') {
if (operation === 'translate') {
const text = this.getNodeParameter('text', i) as string;
const translateTo = this.getNodeParameter('translateTo', i) as string;
const qs = { target_lang: translateTo, text } as IDataObject;
const text = this.getNodeParameter('text', i) as string;
const translateTo = this.getNodeParameter('translateTo', i) as string;
const qs = { target_lang: translateTo, text } as IDataObject;
if (additionalFields.sourceLang !== undefined) {
qs.source_lang = ['EN-GB', 'EN-US'].includes(additionalFields.sourceLang as string)
? 'EN'
: additionalFields.sourceLang;
}
if (additionalFields.sourceLang !== undefined) {
qs.source_lang = ['EN-GB', 'EN-US'].includes(additionalFields.sourceLang as string)
? 'EN'
: additionalFields.sourceLang;
const response = await deepLApiRequest.call(this, 'GET', '/translate', {}, qs);
responseData.push(response.translations[0]);
}
const response = await deepLApiRequest.call(this, 'GET', '/translate', {}, qs);
responseData.push(response.translations[0]);
}
} catch (error) {
if (this.continueOnFail()) {
responseData.push({ error: error.message });
continue;
}
throw error;
}
}

View file

@ -139,71 +139,79 @@ export class Demio implements INodeType {
const operation = this.getNodeParameter('operation', 0) as string;
for (let i = 0; i < length; i++) {
if (resource === 'event') {
if (operation === 'get') {
const id = this.getNodeParameter('eventId', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
try {
if (resource === 'event') {
if (operation === 'get') {
const id = this.getNodeParameter('eventId', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (additionalFields.date_id !== undefined) {
responseData = await demioApiRequest.call(this, 'GET', `/event/${id}/date/${additionalFields.date_id}`);
} else {
Object.assign(qs, additionalFields);
responseData = await demioApiRequest.call(this, 'GET', `/event/${id}`, {}, qs);
if (additionalFields.date_id !== undefined) {
responseData = await demioApiRequest.call(this, 'GET', `/event/${id}/date/${additionalFields.date_id}`);
} else {
Object.assign(qs, additionalFields);
responseData = await demioApiRequest.call(this, 'GET', `/event/${id}`, {}, qs);
}
}
if (operation === 'getAll') {
const filters = this.getNodeParameter('filters', i) as IDataObject;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
Object.assign(qs, filters);
responseData = await demioApiRequest.call(this, 'GET', `/events`, {}, qs);
if (returnAll === false) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.splice(0, limit);
}
}
if (operation === 'register') {
const eventId = this.getNodeParameter('eventId', i) as string;
const firstName = this.getNodeParameter('firstName', i) as string;
const email = this.getNodeParameter('email', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IDataObject = {
name: firstName,
email,
id: eventId,
};
Object.assign(body, additionalFields);
if (additionalFields.customFieldsUi) {
const customFields = (additionalFields.customFieldsUi as IDataObject || {}).customFieldsValues as IDataObject[] || [];
const data = customFields.reduce((obj, value) => Object.assign(obj, { [`${value.fieldId}`]: value.value }), {});
Object.assign(body, data);
delete additionalFields.customFields;
}
responseData = await demioApiRequest.call(this, 'PUT', `/event/register`, body);
}
}
if (operation === 'getAll') {
const filters = this.getNodeParameter('filters', i) as IDataObject;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
if (resource === 'report') {
if (operation === 'get') {
const sessionId = this.getNodeParameter('dateId', i) as string;
const filters = this.getNodeParameter('filters', i) as IDataObject;
Object.assign(qs, filters);
Object.assign(qs, filters);
responseData = await demioApiRequest.call(this, 'GET', `/events`, {}, qs);
if (returnAll === false) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.splice(0, limit);
responseData = await demioApiRequest.call(this, 'GET', `/report/${sessionId}/participants`, {}, qs);
responseData = responseData.participants;
}
}
if (operation === 'register') {
const eventId = this.getNodeParameter('eventId', i) as string;
const firstName = this.getNodeParameter('firstName', i) as string;
const email = this.getNodeParameter('email', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IDataObject = {
name: firstName,
email,
id: eventId,
};
Object.assign(body, additionalFields);
if (additionalFields.customFieldsUi) {
const customFields = (additionalFields.customFieldsUi as IDataObject || {}).customFieldsValues as IDataObject[] || [];
const data = customFields.reduce((obj, value) => Object.assign(obj, { [`${value.fieldId}`]: value.value }), {});
Object.assign(body, data);
delete additionalFields.customFields;
}
responseData = await demioApiRequest.call(this, 'PUT', `/event/register`, body);
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
}
}
if (resource === 'report') {
if (operation === 'get') {
const sessionId = this.getNodeParameter('dateId', i) as string;
const filters = this.getNodeParameter('filters', i) as IDataObject;
Object.assign(qs, filters);
responseData = await demioApiRequest.call(this, 'GET', `/report/${sessionId}/participants`, {}, qs);
responseData = responseData.participants;
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];

View file

@ -150,351 +150,359 @@ export class Discourse implements INodeType {
const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string;
for (let i = 0; i < length; i++) {
if (resource === 'category') {
//https://docs.discourse.org/#tag/Categories/paths/~1categories.json/post
if (operation === 'create') {
const name = this.getNodeParameter('name', i) as string;
const color = this.getNodeParameter('color', i) as string;
const textColor = this.getNodeParameter('textColor', i) as string;
try {
if (resource === 'category') {
//https://docs.discourse.org/#tag/Categories/paths/~1categories.json/post
if (operation === 'create') {
const name = this.getNodeParameter('name', i) as string;
const color = this.getNodeParameter('color', i) as string;
const textColor = this.getNodeParameter('textColor', i) as string;
const body: IDataObject = {
name,
color,
text_color: textColor,
};
const body: IDataObject = {
name,
color,
text_color: textColor,
};
responseData = await discourseApiRequest.call(
this,
'POST',
`/categories.json`,
body,
);
responseData = await discourseApiRequest.call(
this,
'POST',
`/categories.json`,
body,
);
responseData = responseData.category;
}
//https://docs.discourse.org/#tag/Categories/paths/~1categories.json/get
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
responseData = responseData.category;
}
//https://docs.discourse.org/#tag/Categories/paths/~1categories.json/get
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
responseData = await discourseApiRequest.call(
this,
'GET',
`/categories.json`,
{},
qs,
);
responseData = await discourseApiRequest.call(
this,
'GET',
`/categories.json`,
{},
qs,
);
responseData = responseData.category_list.categories;
responseData = responseData.category_list.categories;
if (returnAll === false) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.splice(0, limit);
if (returnAll === false) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.splice(0, limit);
}
}
//https://docs.discourse.org/#tag/Categories/paths/~1categories~1{id}/put
if (operation === 'update') {
const categoryId = this.getNodeParameter('categoryId', i) as string;
const name = this.getNodeParameter('name', i) as string;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const body: IDataObject = {
name,
};
Object.assign(body, updateFields);
responseData = await discourseApiRequest.call(
this,
'PUT',
`/categories/${categoryId}.json`,
body,
);
responseData = responseData.category;
}
}
//https://docs.discourse.org/#tag/Categories/paths/~1categories~1{id}/put
if (operation === 'update') {
const categoryId = this.getNodeParameter('categoryId', i) as string;
if (resource === 'group') {
//https://docs.discourse.org/#tag/Posts/paths/~1posts.json/post
if (operation === 'create') {
const name = this.getNodeParameter('name', i) as string;
const name = this.getNodeParameter('name', i) as string;
const body: IDataObject = {
name,
};
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
responseData = await discourseApiRequest.call(
this,
'POST',
`/admin/groups.json`,
{ group: body },
);
const body: IDataObject = {
name,
};
responseData = responseData.basic_group;
}
//https://docs.discourse.org/#tag/Groups/paths/~1groups~1{name}.json/get
if (operation === 'get') {
const name = this.getNodeParameter('name', i) as string;
Object.assign(body, updateFields);
responseData = await discourseApiRequest.call(
this,
'GET',
`/groups/${name}`,
{},
qs,
);
responseData = await discourseApiRequest.call(
this,
'PUT',
`/categories/${categoryId}.json`,
body,
);
responseData = responseData.group;
responseData = responseData.category;
}
}
if (resource === 'group') {
//https://docs.discourse.org/#tag/Posts/paths/~1posts.json/post
if (operation === 'create') {
const name = this.getNodeParameter('name', i) as string;
}
//https://docs.discourse.org/#tag/Groups/paths/~1groups.json/get
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const body: IDataObject = {
name,
};
responseData = await discourseApiRequest.call(
this,
'GET',
`/groups.json`,
{},
qs,
);
responseData = await discourseApiRequest.call(
this,
'POST',
`/admin/groups.json`,
{ group: body },
);
responseData = responseData.groups;
responseData = responseData.basic_group;
}
//https://docs.discourse.org/#tag/Groups/paths/~1groups~1{name}.json/get
if (operation === 'get') {
const name = this.getNodeParameter('name', i) as string;
if (returnAll === false) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.splice(0, limit);
}
}
//https://docs.discourse.org/#tag/Posts/paths/~1posts~1{id}.json/put
if (operation === 'update') {
const groupId = this.getNodeParameter('groupId', i) as string;
responseData = await discourseApiRequest.call(
this,
'GET',
`/groups/${name}`,
{},
qs,
);
const name = this.getNodeParameter('name', i) as string;
responseData = responseData.group;
const body: IDataObject = {
name,
};
}
//https://docs.discourse.org/#tag/Groups/paths/~1groups.json/get
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
responseData = await discourseApiRequest.call(
this,
'GET',
`/groups.json`,
{},
qs,
);
responseData = responseData.groups;
if (returnAll === false) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.splice(0, limit);
responseData = await discourseApiRequest.call(
this,
'PUT',
`/groups/${groupId}.json`,
{ group: body },
);
}
}
//https://docs.discourse.org/#tag/Posts/paths/~1posts~1{id}.json/put
if (operation === 'update') {
const groupId = this.getNodeParameter('groupId', i) as string;
if (resource === 'post') {
//https://docs.discourse.org/#tag/Posts/paths/~1posts.json/post
if (operation === 'create') {
const content = this.getNodeParameter('content', i) as string;
const title = this.getNodeParameter('title', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const name = this.getNodeParameter('name', i) as string;
const body: IDataObject = {
title,
raw: content,
};
const body: IDataObject = {
name,
};
Object.assign(body, additionalFields);
responseData = await discourseApiRequest.call(
this,
'PUT',
`/groups/${groupId}.json`,
{ group: body },
);
}
}
if (resource === 'post') {
//https://docs.discourse.org/#tag/Posts/paths/~1posts.json/post
if (operation === 'create') {
const content = this.getNodeParameter('content', i) as string;
const title = this.getNodeParameter('title', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
responseData = await discourseApiRequest.call(
this,
'POST',
`/posts.json`,
body,
);
}
//https://docs.discourse.org/#tag/Posts/paths/~1posts~1{id}.json/get
if (operation === 'get') {
const postId = this.getNodeParameter('postId', i) as string;
const body: IDataObject = {
title,
raw: content,
};
responseData = await discourseApiRequest.call(
this,
'GET',
`/posts/${postId}`,
{},
qs,
);
}
//https://docs.discourse.org/#tag/Posts/paths/~1posts.json/get
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
Object.assign(body, additionalFields);
responseData = await discourseApiRequest.call(
this,
'GET',
`/posts.json`,
{},
qs,
);
responseData = await discourseApiRequest.call(
this,
'POST',
`/posts.json`,
body,
);
}
//https://docs.discourse.org/#tag/Posts/paths/~1posts~1{id}.json/get
if (operation === 'get') {
const postId = this.getNodeParameter('postId', i) as string;
responseData = responseData.latest_posts;
responseData = await discourseApiRequest.call(
this,
'GET',
`/posts/${postId}`,
{},
qs,
);
}
//https://docs.discourse.org/#tag/Posts/paths/~1posts.json/get
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
if (returnAll === false) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.splice(0, limit);
}
}
//https://docs.discourse.org/#tag/Posts/paths/~1posts~1{id}.json/put
if (operation === 'update') {
const postId = this.getNodeParameter('postId', i) as string;
responseData = await discourseApiRequest.call(
this,
'GET',
`/posts.json`,
{},
qs,
);
const content = this.getNodeParameter('content', i) as string;
responseData = responseData.latest_posts;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
if (returnAll === false) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.splice(0, limit);
const body: IDataObject = {
raw: content,
};
Object.assign(body, updateFields);
responseData = await discourseApiRequest.call(
this,
'PUT',
`/posts/${postId}.json`,
body,
);
responseData = responseData.post;
}
}
//https://docs.discourse.org/#tag/Posts/paths/~1posts~1{id}.json/put
if (operation === 'update') {
const postId = this.getNodeParameter('postId', i) as string;
// TODO figure how to paginate the results
// if (resource === 'search') {
// //https://docs.discourse.org/#tag/Search/paths/~1search~1query/get
// if (operation === 'query') {
// qs.term = this.getNodeParameter('term', i) as string;
const content = this.getNodeParameter('content', i) as string;
// const simple = this.getNodeParameter('simple', i) as boolean;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
// const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const body: IDataObject = {
raw: content,
};
// Object.assign(qs, updateFields);
Object.assign(body, updateFields);
// qs.page = 1;
responseData = await discourseApiRequest.call(
this,
'PUT',
`/posts/${postId}.json`,
body,
);
// responseData = await discourseApiRequest.call(
// this,
// 'GET',
// `/search/query`,
// {},
// qs,
// );
responseData = responseData.post;
}
}
// TODO figure how to paginate the results
// if (resource === 'search') {
// //https://docs.discourse.org/#tag/Search/paths/~1search~1query/get
// if (operation === 'query') {
// qs.term = this.getNodeParameter('term', i) as string;
// const simple = this.getNodeParameter('simple', i) as boolean;
// const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
// Object.assign(qs, updateFields);
// qs.page = 1;
// responseData = await discourseApiRequest.call(
// this,
// 'GET',
// `/search/query`,
// {},
// qs,
// );
// if (simple === true) {
// const response = [];
// for (const key of Object.keys(responseData)) {
// console.log(key)
// for (const data of responseData[key]) {
// response.push(Object.assign(data, { __type: key }));
// }
// }
// responseData = response;
// }
// }
// }
if (resource === 'user') {
//https://docs.discourse.org/#tag/Users/paths/~1users/post
if (operation === 'create') {
const name = this.getNodeParameter('name', i) as string;
const email = this.getNodeParameter('email', i) as string;
const password = this.getNodeParameter('password', i) as string;
const username = this.getNodeParameter('username', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IDataObject = {
name,
password,
email,
username,
};
Object.assign(body, additionalFields);
responseData = await discourseApiRequest.call(
this,
'POST',
`/users.json`,
body,
);
}
//https://docs.discourse.org/#tag/Users/paths/~1users~1{username}.json/get
if (operation === 'get') {
const by = this.getNodeParameter('by', i) as string;
let endpoint = '';
if (by === 'username') {
// if (simple === true) {
// const response = [];
// for (const key of Object.keys(responseData)) {
// console.log(key)
// for (const data of responseData[key]) {
// response.push(Object.assign(data, { __type: key }));
// }
// }
// responseData = response;
// }
// }
// }
if (resource === 'user') {
//https://docs.discourse.org/#tag/Users/paths/~1users/post
if (operation === 'create') {
const name = this.getNodeParameter('name', i) as string;
const email = this.getNodeParameter('email', i) as string;
const password = this.getNodeParameter('password', i) as string;
const username = this.getNodeParameter('username', i) as string;
endpoint = `/users/${username}`;
} else if (by === 'externalId') {
const externalId = this.getNodeParameter('externalId', i) as string;
endpoint = `/u/by-external/${externalId}.json`;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IDataObject = {
name,
password,
email,
username,
};
Object.assign(body, additionalFields);
responseData = await discourseApiRequest.call(
this,
'POST',
`/users.json`,
body,
);
}
//https://docs.discourse.org/#tag/Users/paths/~1users~1{username}.json/get
if (operation === 'get') {
const by = this.getNodeParameter('by', i) as string;
let endpoint = '';
if (by === 'username') {
const username = this.getNodeParameter('username', i) as string;
endpoint = `/users/${username}`;
} else if (by === 'externalId') {
const externalId = this.getNodeParameter('externalId', i) as string;
endpoint = `/u/by-external/${externalId}.json`;
}
responseData = await discourseApiRequest.call(
this,
'GET',
endpoint,
);
}
//https://docs.discourse.org/#tag/Users/paths/~1admin~1users~1{id}.json/delete
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const flag = this.getNodeParameter('flag', i) as boolean;
responseData = await discourseApiRequest.call(
this,
'GET',
endpoint,
);
}
//https://docs.discourse.org/#tag/Users/paths/~1admin~1users~1{id}.json/delete
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const flag = this.getNodeParameter('flag', i) as boolean;
responseData = await discourseApiRequest.call(
this,
'GET',
`/admin/users/list/${flag}.json`,
{},
qs,
);
responseData = await discourseApiRequest.call(
this,
'GET',
`/admin/users/list/${flag}.json`,
{},
qs,
);
if (returnAll === false) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.splice(0, limit);
if (returnAll === false) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.splice(0, limit);
}
}
}
}
if (resource === 'userGroup') {
//https://docs.discourse.org/#tag/Groups/paths/~1groups~1{group_id}~1members.json/put
if (operation === 'add') {
const usernames = this.getNodeParameter('usernames', i) as string;
const groupId = this.getNodeParameter('groupId', i) as string;
const body: IDataObject = {
usernames,
};
if (resource === 'userGroup') {
//https://docs.discourse.org/#tag/Groups/paths/~1groups~1{group_id}~1members.json/put
if (operation === 'add') {
const usernames = this.getNodeParameter('usernames', i) as string;
const groupId = this.getNodeParameter('groupId', i) as string;
const body: IDataObject = {
usernames,
};
responseData = await discourseApiRequest.call(
this,
'PUT',
`/groups/${groupId}/members.json`,
body,
);
}
//https://docs.discourse.org/#tag/Groups/paths/~1groups~1{group_id}~1members.json/delete
if (operation === 'remove') {
const usernames = this.getNodeParameter('usernames', i) as string;
const groupId = this.getNodeParameter('groupId', i) as string;
const body: IDataObject = {
usernames,
};
responseData = await discourseApiRequest.call(
this,
'PUT',
`/groups/${groupId}/members.json`,
body,
);
}
//https://docs.discourse.org/#tag/Groups/paths/~1groups~1{group_id}~1members.json/delete
if (operation === 'remove') {
const usernames = this.getNodeParameter('usernames', i) as string;
const groupId = this.getNodeParameter('groupId', i) as string;
const body: IDataObject = {
usernames,
};
responseData = await discourseApiRequest.call(
this,
'DELETE',
`/groups/${groupId}/members.json`,
body,
);
responseData = await discourseApiRequest.call(
this,
'DELETE',
`/groups/${groupId}/members.json`,
body,
);
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else if (responseData !== undefined) {
returnData.push(responseData as IDataObject);
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else if (responseData !== undefined) {
returnData.push(responseData as IDataObject);
}
return [this.helpers.returnJsonArray(returnData)];
}
}

View file

@ -647,136 +647,144 @@ export class Disqus implements INodeType {
for (let i = 0; i < items.length; i++) {
body = {};
qs = {};
try {
body = {};
qs = {};
if (resource === 'forum') {
if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
if (resource === 'forum') {
if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
requestMethod = 'GET';
requestMethod = 'GET';
endpoint = 'forums/details.json';
endpoint = 'forums/details.json';
const id = this.getNodeParameter('id', i) as string;
qs.forum = id;
const id = this.getNodeParameter('id', i) as string;
qs.forum = id;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
Object.assign(qs, additionalFields);
Object.assign(qs, additionalFields);
try {
const responseData = await disqusApiRequest.call(this, requestMethod, qs, endpoint);
returnData.push(responseData.response);
} catch (error) {
throw error;
}
} else if (operation === 'getPosts') {
// ----------------------------------
// getPosts
// ----------------------------------
requestMethod = 'GET';
endpoint = 'forums/listPosts.json';
const id = this.getNodeParameter('id', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
Object.assign(qs, additionalFields);
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
qs.forum = id;
qs.limit = 100;
try {
let responseData: IDataObject = {};
if(returnAll) {
responseData.response = await disqusApiRequestAllItems.call(this, requestMethod, qs, endpoint);
} else {
const limit = this.getNodeParameter('limit', i) as string;
qs.limit = limit;
responseData = await disqusApiRequest.call(this, requestMethod, qs, endpoint);
try {
const responseData = await disqusApiRequest.call(this, requestMethod, qs, endpoint);
returnData.push(responseData.response);
} catch (error) {
throw error;
}
returnData.push.apply(returnData, responseData.response as IDataObject[]);
} catch (error) {
throw error;
}
} else if (operation === 'getCategories') {
// ----------------------------------
// getCategories
// ----------------------------------
} else if (operation === 'getPosts') {
// ----------------------------------
// getPosts
// ----------------------------------
requestMethod = 'GET';
requestMethod = 'GET';
endpoint = 'forums/listCategories.json';
endpoint = 'forums/listPosts.json';
const id = this.getNodeParameter('id', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
Object.assign(qs, additionalFields);
const id = this.getNodeParameter('id', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
Object.assign(qs, additionalFields);
qs.forum = id;
qs.limit = 100;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
try {
let responseData: IDataObject = {};
qs.forum = id;
qs.limit = 100;
if(returnAll) {
responseData.response = await disqusApiRequestAllItems.call(this, requestMethod, qs, endpoint);
} else {
const limit = this.getNodeParameter('limit', i) as string;
qs.limit = limit;
responseData = await disqusApiRequest.call(this, requestMethod, qs, endpoint) as IDataObject;
try {
let responseData: IDataObject = {};
if(returnAll) {
responseData.response = await disqusApiRequestAllItems.call(this, requestMethod, qs, endpoint);
} else {
const limit = this.getNodeParameter('limit', i) as string;
qs.limit = limit;
responseData = await disqusApiRequest.call(this, requestMethod, qs, endpoint);
}
returnData.push.apply(returnData, responseData.response as IDataObject[]);
} catch (error) {
throw error;
}
returnData.push.apply(returnData, responseData.response as IDataObject[]) ;
} catch (error) {
throw error;
}
} else if (operation === 'getThreads') {
// ----------------------------------
// getThreads
// ----------------------------------
} else if (operation === 'getCategories') {
// ----------------------------------
// getCategories
// ----------------------------------
requestMethod = 'GET';
requestMethod = 'GET';
endpoint = 'forums/listThreads.json';
endpoint = 'forums/listCategories.json';
const id = this.getNodeParameter('id', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const id = this.getNodeParameter('id', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
Object.assign(qs, additionalFields);
qs.forum = id;
qs.limit = 100;
qs.forum = id;
qs.limit = 100;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
try {
let responseData: IDataObject = {};
Object.assign(qs, additionalFields);
try {
let responseData: IDataObject = {};
if(returnAll) {
responseData.response = await disqusApiRequestAllItems.call(this, requestMethod, qs, endpoint);
} else {
const limit = this.getNodeParameter('limit', i) as string;
qs.limit = limit;
responseData = await disqusApiRequest.call(this, requestMethod, qs, endpoint);
if(returnAll) {
responseData.response = await disqusApiRequestAllItems.call(this, requestMethod, qs, endpoint);
} else {
const limit = this.getNodeParameter('limit', i) as string;
qs.limit = limit;
responseData = await disqusApiRequest.call(this, requestMethod, qs, endpoint) as IDataObject;
}
returnData.push.apply(returnData, responseData.response as IDataObject[]) ;
} catch (error) {
throw error;
}
returnData.push.apply(returnData, responseData.response as IDataObject[]);
} catch (error) {
throw error;
} else if (operation === 'getThreads') {
// ----------------------------------
// getThreads
// ----------------------------------
requestMethod = 'GET';
endpoint = 'forums/listThreads.json';
const id = this.getNodeParameter('id', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
qs.forum = id;
qs.limit = 100;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
Object.assign(qs, additionalFields);
try {
let responseData: IDataObject = {};
if(returnAll) {
responseData.response = await disqusApiRequestAllItems.call(this, requestMethod, qs, endpoint);
} else {
const limit = this.getNodeParameter('limit', i) as string;
qs.limit = limit;
responseData = await disqusApiRequest.call(this, requestMethod, qs, endpoint);
}
returnData.push.apply(returnData, responseData.response as IDataObject[]);
} catch (error) {
throw error;
}
} else {
throw new NodeOperationError(this.getNode(), `The operation "${operation}" is not known!`);
}
} else {
throw new NodeOperationError(this.getNode(), `The operation "${operation}" is not known!`);
throw new NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`);
}
} else {
throw new NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}

View file

@ -102,62 +102,70 @@ export class Drift implements INodeType {
const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string;
for (let i = 0; i < length; i++) {
if (resource === 'contact') {
//https://devdocs.drift.com/docs/creating-a-contact
if (operation === 'create') {
const email = this.getNodeParameter('email', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IContact = {
email,
};
if (additionalFields.name) {
body.name = additionalFields.name as string;
try {
if (resource === 'contact') {
//https://devdocs.drift.com/docs/creating-a-contact
if (operation === 'create') {
const email = this.getNodeParameter('email', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IContact = {
email,
};
if (additionalFields.name) {
body.name = additionalFields.name as string;
}
if (additionalFields.phone) {
body.phone = additionalFields.phone as string;
}
responseData = await driftApiRequest.call(this, 'POST', '/contacts', { attributes: body });
responseData = responseData.data;
}
if (additionalFields.phone) {
body.phone = additionalFields.phone as string;
//https://devdocs.drift.com/docs/updating-a-contact
if (operation === 'update') {
const contactId = this.getNodeParameter('contactId', i) as string;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const body: IContact = {};
if (updateFields.name) {
body.name = updateFields.name as string;
}
if (updateFields.phone) {
body.phone = updateFields.phone as string;
}
if (updateFields.email) {
body.email = updateFields.email as string;
}
responseData = await driftApiRequest.call(this, 'PATCH', `/contacts/${contactId}`, { attributes: body });
responseData = responseData.data;
}
responseData = await driftApiRequest.call(this, 'POST', '/contacts', { attributes: body });
responseData = responseData.data;
}
//https://devdocs.drift.com/docs/updating-a-contact
if (operation === 'update') {
const contactId = this.getNodeParameter('contactId', i) as string;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const body: IContact = {};
if (updateFields.name) {
body.name = updateFields.name as string;
//https://devdocs.drift.com/docs/retrieving-contact
if (operation === 'get') {
const contactId = this.getNodeParameter('contactId', i) as string;
responseData = await driftApiRequest.call(this, 'GET', `/contacts/${contactId}`);
responseData = responseData.data;
}
if (updateFields.phone) {
body.phone = updateFields.phone as string;
//https://devdocs.drift.com/docs/listing-custom-attributes
if (operation === 'getCustomAttributes') {
responseData = await driftApiRequest.call(this, 'GET', '/contacts/attributes');
responseData = responseData.data.properties;
}
if (updateFields.email) {
body.email = updateFields.email as string;
//https://devdocs.drift.com/docs/removing-a-contact
if (operation === 'delete') {
const contactId = this.getNodeParameter('contactId', i) as string;
responseData = await driftApiRequest.call(this, 'DELETE', `/contacts/${contactId}`);
responseData = { success: true };
}
responseData = await driftApiRequest.call(this, 'PATCH', `/contacts/${contactId}`, { attributes: body });
responseData = responseData.data;
}
//https://devdocs.drift.com/docs/retrieving-contact
if (operation === 'get') {
const contactId = this.getNodeParameter('contactId', i) as string;
responseData = await driftApiRequest.call(this, 'GET', `/contacts/${contactId}`);
responseData = responseData.data;
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
}
//https://devdocs.drift.com/docs/listing-custom-attributes
if (operation === 'getCustomAttributes') {
responseData = await driftApiRequest.call(this, 'GET', '/contacts/attributes');
responseData = responseData.data.properties;
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
//https://devdocs.drift.com/docs/removing-a-contact
if (operation === 'delete') {
const contactId = this.getNodeParameter('contactId', i) as string;
responseData = await driftApiRequest.call(this, 'DELETE', `/contacts/${contactId}`);
responseData = { success: true };
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];

View file

@ -811,258 +811,270 @@ export class Dropbox implements INodeType {
}
for (let i = 0; i < items.length; i++) {
body = {};
try {
body = {};
if (resource === 'file') {
if (operation === 'download') {
// ----------------------------------
// download
// ----------------------------------
if (resource === 'file') {
if (operation === 'download') {
// ----------------------------------
// download
// ----------------------------------
requestMethod = 'POST';
requestMethod = 'POST';
query.arg = JSON.stringify({
path: this.getNodeParameter('path', i) as string,
});
query.arg = JSON.stringify({
path: this.getNodeParameter('path', i) as string,
});
endpoint = 'https://content.dropboxapi.com/2/files/download';
endpoint = 'https://content.dropboxapi.com/2/files/download';
} else if (operation === 'upload') {
// ----------------------------------
// upload
// ----------------------------------
} else if (operation === 'upload') {
// ----------------------------------
// upload
// ----------------------------------
requestMethod = 'POST';
headers['Content-Type'] = 'application/octet-stream';
requestMethod = 'POST';
headers['Content-Type'] = 'application/octet-stream';
query.arg = JSON.stringify({
mode: 'overwrite',
path: this.getNodeParameter('path', i) as string,
});
query.arg = JSON.stringify({
mode: 'overwrite',
path: this.getNodeParameter('path', i) as string,
});
endpoint = 'https://content.dropboxapi.com/2/files/upload';
endpoint = 'https://content.dropboxapi.com/2/files/upload';
options = { json: false };
options = { json: false };
if (this.getNodeParameter('binaryData', i) === true) {
if (this.getNodeParameter('binaryData', i) === true) {
// Is binary file to upload
const item = items[i];
// Is binary file to upload
const item = items[i];
if (item.binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
}
if (item.binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
}
const propertyNameUpload = this.getNodeParameter('binaryPropertyName', i) as string;
const propertyNameUpload = this.getNodeParameter('binaryPropertyName', i) as string;
if (item.binary[propertyNameUpload] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property "${propertyNameUpload}" does not exists on item!`);
}
if (item.binary[propertyNameUpload] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property "${propertyNameUpload}" does not exists on item!`);
}
body = Buffer.from(item.binary[propertyNameUpload].data, BINARY_ENCODING);
} else {
// Is text file
body = Buffer.from(this.getNodeParameter('fileContent', i) as string, 'utf8');
}
}
} else if (resource === 'folder') {
if (operation === 'create') {
// ----------------------------------
// create
// ----------------------------------
requestMethod = 'POST';
body = {
path: this.getNodeParameter('path', i) as string,
};
endpoint = 'https://api.dropboxapi.com/2/files/create_folder_v2';
} else if (operation === 'list') {
// ----------------------------------
// list
// ----------------------------------
returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const filters = this.getNodeParameter('filters', i) as IDataObject;
property = 'entries';
requestMethod = 'POST';
body = {
path: this.getNodeParameter('path', i) as string,
limit: 1000,
};
if (returnAll === false) {
const limit = this.getNodeParameter('limit', 0) as number;
body.limit = limit;
}
Object.assign(body, filters);
endpoint = 'https://api.dropboxapi.com/2/files/list_folder';
}
} else if (resource === 'search') {
if (operation === 'query') {
// ----------------------------------
// query
// ----------------------------------
returnAll = this.getNodeParameter('returnAll', 0) as boolean;
simple = this.getNodeParameter('simple', 0) as boolean;
const filters = this.getNodeParameter('filters', i) as IDataObject;
property = 'matches';
requestMethod = 'POST';
body = {
query: this.getNodeParameter('query', i) as string,
options: {
filename_only: true,
},
};
if (filters.file_extensions) {
filters.file_extensions = (filters.file_extensions as string).split(',');
}
Object.assign(body.options, filters);
if (returnAll === false) {
const limit = this.getNodeParameter('limit', i) as number;
Object.assign(body.options, { max_results: limit });
}
endpoint = 'https://api.dropboxapi.com/2/files/search_v2';
}
}
if (['file', 'folder', 'search'].includes(resource)) {
if (operation === 'copy') {
// ----------------------------------
// copy
// ----------------------------------
requestMethod = 'POST';
body = {
from_path: this.getNodeParameter('path', i) as string,
to_path: this.getNodeParameter('toPath', i) as string,
};
endpoint = 'https://api.dropboxapi.com/2/files/copy_v2';
} else if (operation === 'delete') {
// ----------------------------------
// delete
// ----------------------------------
requestMethod = 'POST';
body = {
path: this.getNodeParameter('path', i) as string,
};
endpoint = 'https://api.dropboxapi.com/2/files/delete_v2';
} else if (operation === 'move') {
// ----------------------------------
// move
// ----------------------------------
requestMethod = 'POST';
body = {
from_path: this.getNodeParameter('path', i) as string,
to_path: this.getNodeParameter('toPath', i) as string,
};
endpoint = 'https://api.dropboxapi.com/2/files/move_v2';
}
} else {
throw new NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`);
}
if (resource === 'file' && operation === 'download') {
// Return the data as a buffer
options = { encoding: null };
}
let responseData;
if (returnAll === true) {
responseData = await dropboxpiRequestAllItems.call(this, property, requestMethod, endpoint, body, query, headers);
} else {
responseData = await dropboxApiRequest.call(this, requestMethod, endpoint, body, query, headers, options);
}
if (resource === 'file' && operation === 'upload') {
responseData = JSON.parse(responseData);
}
if (resource === 'file' && operation === 'download') {
const newItem: INodeExecutionData = {
json: items[i].json,
binary: {},
};
if (items[i].binary !== undefined) {
// Create a shallow copy of the binary data so that the old
// data references which do not get changed still stay behind
// but the incoming data does not get changed.
Object.assign(newItem.binary, items[i].binary);
}
items[i] = newItem;
const dataPropertyNameDownload = this.getNodeParameter('binaryPropertyName', i) as string;
const filePathDownload = this.getNodeParameter('path', i) as string;
items[i].binary![dataPropertyNameDownload] = await this.helpers.prepareBinaryData(Buffer.from(responseData), filePathDownload);
} else if (resource === 'folder' && operation === 'list') {
const propNames: { [key: string]: string } = {
'id': 'id',
'name': 'name',
'client_modified': 'lastModifiedClient',
'server_modified': 'lastModifiedServer',
'rev': 'rev',
'size': 'contentSize',
'.tag': 'type',
'content_hash': 'contentHash',
'path_lower': 'pathLower',
'path_display': 'pathDisplay',
'has_explicit_shared_members': 'hasExplicitSharedMembers',
'is_downloadable': 'isDownloadable',
};
if (returnAll === false) {
responseData = responseData.entries;
}
for (const item of responseData) {
const newItem: IDataObject = {};
// Get the props and save them under a proper name
for (const propName of Object.keys(propNames)) {
if (item[propName] !== undefined) {
newItem[propNames[propName]] = item[propName];
body = Buffer.from(item.binary[propertyNameUpload].data, BINARY_ENCODING);
} else {
// Is text file
body = Buffer.from(this.getNodeParameter('fileContent', i) as string, 'utf8');
}
}
} else if (resource === 'folder') {
if (operation === 'create') {
// ----------------------------------
// create
// ----------------------------------
returnData.push(newItem as IDataObject);
requestMethod = 'POST';
body = {
path: this.getNodeParameter('path', i) as string,
};
endpoint = 'https://api.dropboxapi.com/2/files/create_folder_v2';
} else if (operation === 'list') {
// ----------------------------------
// list
// ----------------------------------
returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const filters = this.getNodeParameter('filters', i) as IDataObject;
property = 'entries';
requestMethod = 'POST';
body = {
path: this.getNodeParameter('path', i) as string,
limit: 1000,
};
if (returnAll === false) {
const limit = this.getNodeParameter('limit', 0) as number;
body.limit = limit;
}
Object.assign(body, filters);
endpoint = 'https://api.dropboxapi.com/2/files/list_folder';
}
} else if (resource === 'search') {
if (operation === 'query') {
// ----------------------------------
// query
// ----------------------------------
returnAll = this.getNodeParameter('returnAll', 0) as boolean;
simple = this.getNodeParameter('simple', 0) as boolean;
const filters = this.getNodeParameter('filters', i) as IDataObject;
property = 'matches';
requestMethod = 'POST';
body = {
query: this.getNodeParameter('query', i) as string,
options: {
filename_only: true,
},
};
if (filters.file_extensions) {
filters.file_extensions = (filters.file_extensions as string).split(',');
}
Object.assign(body.options, filters);
if (returnAll === false) {
const limit = this.getNodeParameter('limit', i) as number;
Object.assign(body.options, { max_results: limit });
}
endpoint = 'https://api.dropboxapi.com/2/files/search_v2';
}
}
} else if (resource === 'search' && operation === 'query') {
if (returnAll === true) {
returnData.push.apply(returnData, (simple === true) ? simplify(responseData) : responseData);
if (['file', 'folder', 'search'].includes(resource)) {
if (operation === 'copy') {
// ----------------------------------
// copy
// ----------------------------------
requestMethod = 'POST';
body = {
from_path: this.getNodeParameter('path', i) as string,
to_path: this.getNodeParameter('toPath', i) as string,
};
endpoint = 'https://api.dropboxapi.com/2/files/copy_v2';
} else if (operation === 'delete') {
// ----------------------------------
// delete
// ----------------------------------
requestMethod = 'POST';
body = {
path: this.getNodeParameter('path', i) as string,
};
endpoint = 'https://api.dropboxapi.com/2/files/delete_v2';
} else if (operation === 'move') {
// ----------------------------------
// move
// ----------------------------------
requestMethod = 'POST';
body = {
from_path: this.getNodeParameter('path', i) as string,
to_path: this.getNodeParameter('toPath', i) as string,
};
endpoint = 'https://api.dropboxapi.com/2/files/move_v2';
}
} else {
returnData.push.apply(returnData, (simple === true) ? simplify(responseData[property]) : responseData[property]);
throw new NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`);
}
} else {
returnData.push(responseData);
if (resource === 'file' && operation === 'download') {
// Return the data as a buffer
options = { encoding: null };
}
let responseData;
if (returnAll === true) {
responseData = await dropboxpiRequestAllItems.call(this, property, requestMethod, endpoint, body, query, headers);
} else {
responseData = await dropboxApiRequest.call(this, requestMethod, endpoint, body, query, headers, options);
}
if (resource === 'file' && operation === 'upload') {
responseData = JSON.parse(responseData);
}
if (resource === 'file' && operation === 'download') {
const newItem: INodeExecutionData = {
json: items[i].json,
binary: {},
};
if (items[i].binary !== undefined) {
// Create a shallow copy of the binary data so that the old
// data references which do not get changed still stay behind
// but the incoming data does not get changed.
Object.assign(newItem.binary, items[i].binary);
}
items[i] = newItem;
const dataPropertyNameDownload = this.getNodeParameter('binaryPropertyName', i) as string;
const filePathDownload = this.getNodeParameter('path', i) as string;
items[i].binary![dataPropertyNameDownload] = await this.helpers.prepareBinaryData(Buffer.from(responseData), filePathDownload);
} else if (resource === 'folder' && operation === 'list') {
const propNames: { [key: string]: string } = {
'id': 'id',
'name': 'name',
'client_modified': 'lastModifiedClient',
'server_modified': 'lastModifiedServer',
'rev': 'rev',
'size': 'contentSize',
'.tag': 'type',
'content_hash': 'contentHash',
'path_lower': 'pathLower',
'path_display': 'pathDisplay',
'has_explicit_shared_members': 'hasExplicitSharedMembers',
'is_downloadable': 'isDownloadable',
};
if (returnAll === false) {
responseData = responseData.entries;
}
for (const item of responseData) {
const newItem: IDataObject = {};
// Get the props and save them under a proper name
for (const propName of Object.keys(propNames)) {
if (item[propName] !== undefined) {
newItem[propNames[propName]] = item[propName];
}
}
returnData.push(newItem as IDataObject);
}
} else if (resource === 'search' && operation === 'query') {
if (returnAll === true) {
returnData.push.apply(returnData, (simple === true) ? simplify(responseData) : responseData);
} else {
returnData.push.apply(returnData, (simple === true) ? simplify(responseData[property]) : responseData[property]);
}
} else {
returnData.push(responseData);
}
} catch (error) {
if (this.continueOnFail()) {
if (resource === 'file' && operation === 'download'){
items[i].json = { error: error.message };
}else{
returnData.push({ error: error.message });
}
continue;
}
throw error;
}
}

View file

@ -957,292 +957,302 @@ export class EditImage implements INodeType {
let item: INodeExecutionData;
for (let itemIndex = 0; itemIndex < length; itemIndex++) {
item = items[itemIndex];
try {
item = items[itemIndex];
const operation = this.getNodeParameter('operation', itemIndex) as string;
const dataPropertyName = this.getNodeParameter('dataPropertyName', itemIndex) as string;
const operation = this.getNodeParameter('operation', itemIndex) as string;
const dataPropertyName = this.getNodeParameter('dataPropertyName', itemIndex) as string;
const options = this.getNodeParameter('options', itemIndex,{}) as IDataObject;
const options = this.getNodeParameter('options', itemIndex,{}) as IDataObject;
const cleanupFunctions: Array<() => void> = [];
const cleanupFunctions: Array<() => void> = [];
let gmInstance: gm.State;
let gmInstance: gm.State;
const requiredOperationParameters: {
[key: string]: string[],
} = {
blur: [
'blur',
'sigma',
],
border: [
'borderColor',
'borderWidth',
'borderHeight',
],
create: [
'backgroundColor',
'height',
'width',
],
crop: [
'height',
'positionX',
'positionY',
'width',
],
composite: [
'dataPropertyNameComposite',
'positionX',
'positionY',
],
draw: [
'color',
'cornerRadius',
'endPositionX',
'endPositionY',
'primitive',
'startPositionX',
'startPositionY',
],
information: [],
resize: [
'height',
'resizeOption',
'width',
],
rotate: [
'backgroundColor',
'rotate',
],
shear: [
'degreesX',
'degreesY',
],
text: [
'font',
'fontColor',
'fontSize',
'lineLength',
'positionX',
'positionY',
'text',
],
};
const requiredOperationParameters: {
[key: string]: string[],
} = {
blur: [
'blur',
'sigma',
],
border: [
'borderColor',
'borderWidth',
'borderHeight',
],
create: [
'backgroundColor',
'height',
'width',
],
crop: [
'height',
'positionX',
'positionY',
'width',
],
composite: [
'dataPropertyNameComposite',
'positionX',
'positionY',
],
draw: [
'color',
'cornerRadius',
'endPositionX',
'endPositionY',
'primitive',
'startPositionX',
'startPositionY',
],
information: [],
resize: [
'height',
'resizeOption',
'width',
],
rotate: [
'backgroundColor',
'rotate',
],
shear: [
'degreesX',
'degreesY',
],
text: [
'font',
'fontColor',
'fontSize',
'lineLength',
'positionX',
'positionY',
'text',
],
};
let operations: IDataObject[] = [];
if (operation === 'multiStep') {
// Operation parameters are already in the correct format
const operationsData = this.getNodeParameter('operations', itemIndex ,{ operations: [] }) as IDataObject;
operations = operationsData.operations as IDataObject[];
} else {
// Operation parameters have to first get collected
const operationParameters: IDataObject = {};
requiredOperationParameters[operation].forEach(parameterName => {
try {
operationParameters[parameterName] = this.getNodeParameter(parameterName, itemIndex);
} catch (error) {}
});
operations = [
{
operation,
...operationParameters,
},
];
}
if (operations[0].operation !== 'create') {
// "create" generates a new image so does not require any incoming data.
if (item.binary === undefined) {
throw new NodeOperationError(this.getNode(), 'Item does not contain any binary data.');
}
if (item.binary[dataPropertyName as string] === undefined) {
throw new NodeOperationError(this.getNode(), `Item does not contain any binary data with the name "${dataPropertyName}".`);
}
gmInstance = gm(Buffer.from(item.binary![dataPropertyName as string].data, BINARY_ENCODING));
gmInstance = gmInstance.background('transparent');
}
if (operation === 'information') {
// Just return the information
const imageData = await new Promise<IDataObject>((resolve, reject) => {
gmInstance = gmInstance.identify((error, imageData) => {
if (error) {
reject(error);
return;
}
resolve(imageData as unknown as IDataObject);
let operations: IDataObject[] = [];
if (operation === 'multiStep') {
// Operation parameters are already in the correct format
const operationsData = this.getNodeParameter('operations', itemIndex ,{ operations: [] }) as IDataObject;
operations = operationsData.operations as IDataObject[];
} else {
// Operation parameters have to first get collected
const operationParameters: IDataObject = {};
requiredOperationParameters[operation].forEach(parameterName => {
try {
operationParameters[parameterName] = this.getNodeParameter(parameterName, itemIndex);
} catch (error) {}
});
});
item.json = imageData;
returnData.push(item);
}
operations = [
{
operation,
...operationParameters,
},
];
}
for (let i = 0; i < operations.length; i++) {
const operationData = operations[i];
if (operationData.operation === 'blur') {
gmInstance = gmInstance!.blur(operationData.blur as number, operationData.sigma as number);
} else if (operationData.operation === 'border') {
gmInstance = gmInstance!.borderColor(operationData.borderColor as string).border(operationData.borderWidth as number, operationData.borderHeight as number);
} else if (operationData.operation === 'composite') {
const positionX = operationData.positionX as number;
const positionY = operationData.positionY as number;
const geometryString = (positionX >= 0 ? '+' : '') + positionX + (positionY >= 0 ? '+' : '') + positionY;
if (item.binary![operationData.dataPropertyNameComposite as string] === undefined) {
throw new NodeOperationError(this.getNode(), `Item does not contain any binary data with the name "${operationData.dataPropertyNameComposite}".`);
if (operations[0].operation !== 'create') {
// "create" generates a new image so does not require any incoming data.
if (item.binary === undefined) {
throw new NodeOperationError(this.getNode(), 'Item does not contain any binary data.');
}
const { fd, path, cleanup } = await file();
cleanupFunctions.push(cleanup);
await fsWriteFileAsync(fd, Buffer.from(item.binary![operationData.dataPropertyNameComposite as string].data, BINARY_ENCODING));
if (operations[0].operation === 'create') {
// It seems like if the image gets created newly we have to create a new gm instance
// else it fails for some reason
gmInstance = gm(gmInstance!.stream('png')).geometry(geometryString).composite(path);
} else {
gmInstance = gmInstance!.geometry(geometryString).composite(path);
if (item.binary[dataPropertyName as string] === undefined) {
throw new NodeOperationError(this.getNode(), `Item does not contain any binary data with the name "${dataPropertyName}".`);
}
if (operations.length !== i + 1) {
// If there are other operations after the current one create a new gm instance
// because else things do get messed up
gmInstance = gm(gmInstance.stream());
}
} else if (operationData.operation === 'create') {
gmInstance = gm(operationData.width as number, operationData.height as number, operationData.backgroundColor as string);
if (!options.format) {
options.format = 'png';
}
} else if (operationData.operation === 'crop') {
gmInstance = gmInstance!.crop(operationData.width as number, operationData.height as number, operationData.positionX as number, operationData.positionY as number);
} else if (operationData.operation === 'draw') {
gmInstance = gmInstance!.fill(operationData.color as string);
gmInstance = gm(Buffer.from(item.binary![dataPropertyName as string].data, BINARY_ENCODING));
gmInstance = gmInstance.background('transparent');
}
if (operationData.primitive === 'line') {
gmInstance = gmInstance.drawLine(operationData.startPositionX as number, operationData.startPositionY as number, operationData.endPositionX as number, operationData.endPositionY as number);
} else if (operationData.primitive === 'rectangle') {
gmInstance = gmInstance.drawRectangle(operationData.startPositionX as number, operationData.startPositionY as number, operationData.endPositionX as number, operationData.endPositionY as number, operationData.cornerRadius as number || undefined);
}
} else if (operationData.operation === 'resize') {
const resizeOption = operationData.resizeOption as string;
// By default use "maximumArea"
let option: gm.ResizeOption = '@';
if (resizeOption === 'ignoreAspectRatio') {
option = '!';
} else if (resizeOption === 'minimumArea') {
option = '^';
} else if (resizeOption === 'onlyIfSmaller') {
option = '<';
} else if (resizeOption === 'onlyIfLarger') {
option = '>';
} else if (resizeOption === 'percent') {
option = '%';
}
gmInstance = gmInstance!.resize(operationData.width as number, operationData.height as number, option);
} else if (operationData.operation === 'rotate') {
gmInstance = gmInstance!.rotate(operationData.backgroundColor as string, operationData.rotate as number);
} else if (operationData.operation === 'shear') {
gmInstance = gmInstance!.shear(operationData.degreesX as number, operationData.degreesY as number);
} else if (operationData.operation === 'text') {
// Split the text in multiple lines
const lines: string[] = [];
let currentLine = '';
(operationData.text as string).split('\n').forEach((textLine: string) => {
textLine.split(' ').forEach((textPart: string) => {
if ((currentLine.length + textPart.length + 1) > (operationData.lineLength as number)) {
lines.push(currentLine.trim());
currentLine = `${textPart} `;
if (operation === 'information') {
// Just return the information
const imageData = await new Promise<IDataObject>((resolve, reject) => {
gmInstance = gmInstance.identify((error, imageData) => {
if (error) {
reject(error);
return;
}
currentLine += `${textPart} `;
resolve(imageData as unknown as IDataObject);
});
lines.push(currentLine.trim());
currentLine = '';
});
// Combine the lines to a single string
const renderText = lines.join('\n');
const font = options.font || operationData.font;
if (font && font !== 'default') {
gmInstance = gmInstance!.font(font as string);
}
gmInstance = gmInstance!
.fill(operationData.fontColor as string)
.fontSize(operationData.fontSize as number)
.drawText(operationData.positionX as number, operationData.positionY as number, renderText);
item.json = imageData;
returnData.push(item);
}
}
const newItem: INodeExecutionData = {
json: item.json,
binary: {},
};
for (let i = 0; i < operations.length; i++) {
const operationData = operations[i];
if (operationData.operation === 'blur') {
gmInstance = gmInstance!.blur(operationData.blur as number, operationData.sigma as number);
} else if (operationData.operation === 'border') {
gmInstance = gmInstance!.borderColor(operationData.borderColor as string).border(operationData.borderWidth as number, operationData.borderHeight as number);
} else if (operationData.operation === 'composite') {
const positionX = operationData.positionX as number;
const positionY = operationData.positionY as number;
if (item.binary !== undefined) {
// Create a shallow copy of the binary data so that the old
// data references which do not get changed still stay behind
// but the incoming data does not get changed.
Object.assign(newItem.binary, item.binary);
// Make a deep copy of the binary data we change
if (newItem.binary![dataPropertyName as string]) {
newItem.binary![dataPropertyName as string] = JSON.parse(JSON.stringify(newItem.binary![dataPropertyName as string]));
}
}
const geometryString = (positionX >= 0 ? '+' : '') + positionX + (positionY >= 0 ? '+' : '') + positionY;
if (newItem.binary![dataPropertyName as string] === undefined) {
newItem.binary![dataPropertyName as string] = {
data: '',
mimeType: '',
};
}
if (options.quality !== undefined) {
gmInstance = gmInstance!.quality(options.quality as number);
}
if (options.format !== undefined) {
gmInstance = gmInstance!.setFormat(options.format as string);
newItem.binary![dataPropertyName as string].fileExtension = options.format as string;
newItem.binary![dataPropertyName as string].mimeType = `image/${options.format}`;
const fileName = newItem.binary![dataPropertyName as string].fileName;
if (fileName && fileName.includes('.')) {
newItem.binary![dataPropertyName as string].fileName = fileName.split('.').slice(0, -1).join('.') + '.' + options.format;
}
}
if (options.fileName !== undefined) {
newItem.binary![dataPropertyName as string].fileName = options.fileName as string;
}
returnData.push(await (new Promise<INodeExecutionData>((resolve, reject) => {
gmInstance
.toBuffer((error: Error | null, buffer: Buffer) => {
cleanupFunctions.forEach(async cleanup => await cleanup());
if (error) {
return reject(error);
if (item.binary![operationData.dataPropertyNameComposite as string] === undefined) {
throw new NodeOperationError(this.getNode(), `Item does not contain any binary data with the name "${operationData.dataPropertyNameComposite}".`);
}
newItem.binary![dataPropertyName as string].data = buffer.toString(BINARY_ENCODING);
const { fd, path, cleanup } = await file();
cleanupFunctions.push(cleanup);
await fsWriteFileAsync(fd, Buffer.from(item.binary![operationData.dataPropertyNameComposite as string].data, BINARY_ENCODING));
return resolve(newItem);
});
})));
if (operations[0].operation === 'create') {
// It seems like if the image gets created newly we have to create a new gm instance
// else it fails for some reason
gmInstance = gm(gmInstance!.stream('png')).geometry(geometryString).composite(path);
} else {
gmInstance = gmInstance!.geometry(geometryString).composite(path);
}
if (operations.length !== i + 1) {
// If there are other operations after the current one create a new gm instance
// because else things do get messed up
gmInstance = gm(gmInstance.stream());
}
} else if (operationData.operation === 'create') {
gmInstance = gm(operationData.width as number, operationData.height as number, operationData.backgroundColor as string);
if (!options.format) {
options.format = 'png';
}
} else if (operationData.operation === 'crop') {
gmInstance = gmInstance!.crop(operationData.width as number, operationData.height as number, operationData.positionX as number, operationData.positionY as number);
} else if (operationData.operation === 'draw') {
gmInstance = gmInstance!.fill(operationData.color as string);
if (operationData.primitive === 'line') {
gmInstance = gmInstance.drawLine(operationData.startPositionX as number, operationData.startPositionY as number, operationData.endPositionX as number, operationData.endPositionY as number);
} else if (operationData.primitive === 'rectangle') {
gmInstance = gmInstance.drawRectangle(operationData.startPositionX as number, operationData.startPositionY as number, operationData.endPositionX as number, operationData.endPositionY as number, operationData.cornerRadius as number || undefined);
}
} else if (operationData.operation === 'resize') {
const resizeOption = operationData.resizeOption as string;
// By default use "maximumArea"
let option: gm.ResizeOption = '@';
if (resizeOption === 'ignoreAspectRatio') {
option = '!';
} else if (resizeOption === 'minimumArea') {
option = '^';
} else if (resizeOption === 'onlyIfSmaller') {
option = '<';
} else if (resizeOption === 'onlyIfLarger') {
option = '>';
} else if (resizeOption === 'percent') {
option = '%';
}
gmInstance = gmInstance!.resize(operationData.width as number, operationData.height as number, option);
} else if (operationData.operation === 'rotate') {
gmInstance = gmInstance!.rotate(operationData.backgroundColor as string, operationData.rotate as number);
} else if (operationData.operation === 'shear') {
gmInstance = gmInstance!.shear(operationData.degreesX as number, operationData.degreesY as number);
} else if (operationData.operation === 'text') {
// Split the text in multiple lines
const lines: string[] = [];
let currentLine = '';
(operationData.text as string).split('\n').forEach((textLine: string) => {
textLine.split(' ').forEach((textPart: string) => {
if ((currentLine.length + textPart.length + 1) > (operationData.lineLength as number)) {
lines.push(currentLine.trim());
currentLine = `${textPart} `;
return;
}
currentLine += `${textPart} `;
});
lines.push(currentLine.trim());
currentLine = '';
});
// Combine the lines to a single string
const renderText = lines.join('\n');
const font = options.font || operationData.font;
if (font && font !== 'default') {
gmInstance = gmInstance!.font(font as string);
}
gmInstance = gmInstance!
.fill(operationData.fontColor as string)
.fontSize(operationData.fontSize as number)
.drawText(operationData.positionX as number, operationData.positionY as number, renderText);
}
}
const newItem: INodeExecutionData = {
json: item.json,
binary: {},
};
if (item.binary !== undefined) {
// Create a shallow copy of the binary data so that the old
// data references which do not get changed still stay behind
// but the incoming data does not get changed.
Object.assign(newItem.binary, item.binary);
// Make a deep copy of the binary data we change
if (newItem.binary![dataPropertyName as string]) {
newItem.binary![dataPropertyName as string] = JSON.parse(JSON.stringify(newItem.binary![dataPropertyName as string]));
}
}
if (newItem.binary![dataPropertyName as string] === undefined) {
newItem.binary![dataPropertyName as string] = {
data: '',
mimeType: '',
};
}
if (options.quality !== undefined) {
gmInstance = gmInstance!.quality(options.quality as number);
}
if (options.format !== undefined) {
gmInstance = gmInstance!.setFormat(options.format as string);
newItem.binary![dataPropertyName as string].fileExtension = options.format as string;
newItem.binary![dataPropertyName as string].mimeType = `image/${options.format}`;
const fileName = newItem.binary![dataPropertyName as string].fileName;
if (fileName && fileName.includes('.')) {
newItem.binary![dataPropertyName as string].fileName = fileName.split('.').slice(0, -1).join('.') + '.' + options.format;
}
}
if (options.fileName !== undefined) {
newItem.binary![dataPropertyName as string].fileName = options.fileName as string;
}
returnData.push(await (new Promise<INodeExecutionData>((resolve, reject) => {
gmInstance
.toBuffer((error: Error | null, buffer: Buffer) => {
cleanupFunctions.forEach(async cleanup => await cleanup());
if (error) {
return reject(error);
}
newItem.binary![dataPropertyName as string].data = buffer.toString(BINARY_ENCODING);
return resolve(newItem);
});
})));
} catch (error) {
if (this.continueOnFail()) {
returnData.push({json:{ error: error.message }});
continue;
}
throw error;
}
}
return this.prepareOutputData(returnData);
}

View file

@ -0,0 +1,364 @@
import {
IExecuteFunctions,
} from 'n8n-core';
import {
IDataObject,
INodeExecutionData,
INodeType,
INodeTypeDescription,
} from 'n8n-workflow';
import {
elasticsearchApiRequest,
} from './GenericFunctions';
import {
documentFields,
documentOperations,
indexFields,
indexOperations,
} from './descriptions';
import {
DocumentGetAllOptions,
FieldsUiValues,
} from './types';
import {
omit,
} from 'lodash';
export class Elasticsearch implements INodeType {
description: INodeTypeDescription = {
displayName: 'Elasticsearch',
name: 'elasticsearch',
icon: 'file:elasticsearch.svg',
group: ['transform'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Consume the Elasticsearch API',
defaults: {
name: 'Elasticsearch',
color: '#f3d337',
},
inputs: ['main'],
outputs: ['main'],
credentials: [
{
name: 'elasticsearchApi',
required: true,
},
],
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
options: [
{
name: 'Document',
value: 'document',
},
{
name: 'Index',
value: 'index',
},
],
default: 'document',
description: 'Resource to consume',
},
...documentOperations,
...documentFields,
...indexOperations,
...indexFields,
],
};
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const items = this.getInputData();
const returnData: IDataObject[] = [];
const resource = this.getNodeParameter('resource', 0) as 'document' | 'index';
const operation = this.getNodeParameter('operation', 0) as string;
let responseData;
for (let i = 0; i < items.length; i++) {
if (resource === 'document') {
// **********************************************************************
// document
// **********************************************************************
// https://www.elastic.co/guide/en/elasticsearch/reference/current/docs.html
if (operation === 'delete') {
// ----------------------------------------
// document: delete
// ----------------------------------------
// https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-delete.html
const indexId = this.getNodeParameter('indexId', i);
const documentId = this.getNodeParameter('documentId', i);
const endpoint = `/${indexId}/_doc/${documentId}`;
responseData = await elasticsearchApiRequest.call(this, 'DELETE', endpoint);
} else if (operation === 'get') {
// ----------------------------------------
// document: get
// ----------------------------------------
// https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-get.html
const indexId = this.getNodeParameter('indexId', i);
const documentId = this.getNodeParameter('documentId', i);
const qs = {} as IDataObject;
const options = this.getNodeParameter('options', i) as IDataObject;
if (Object.keys(options).length) {
Object.assign(qs, options);
qs._source = true;
}
const endpoint = `/${indexId}/_doc/${documentId}`;
responseData = await elasticsearchApiRequest.call(this, 'GET', endpoint, {}, qs);
const simple = this.getNodeParameter('simple', i) as IDataObject;
if (simple) {
responseData = {
_id: responseData._id,
...responseData._source,
};
}
} else if (operation === 'getAll') {
// ----------------------------------------
// document: getAll
// ----------------------------------------
// https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html
const indexId = this.getNodeParameter('indexId', i);
const body = {} as IDataObject;
const qs = {} as IDataObject;
const options = this.getNodeParameter('options', i) as DocumentGetAllOptions;
if (Object.keys(options).length) {
const { query, ...rest } = options;
if (query) Object.assign(body, JSON.parse(query));
Object.assign(qs, rest);
qs._source = true;
}
const returnAll = this.getNodeParameter('returnAll', 0);
if (!returnAll) {
qs.size = this.getNodeParameter('limit', 0);
}
responseData = await elasticsearchApiRequest.call(this, 'GET', `/${indexId}/_search`, body, qs);
responseData = responseData.hits.hits;
const simple = this.getNodeParameter('simple', 0) as IDataObject;
if (simple) {
responseData = responseData.map((item: IDataObject) => {
return {
_id: item._id,
...(item._source as {}),
};
});
}
} else if (operation === 'create') {
// ----------------------------------------
// document: create
// ----------------------------------------
// https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-index_.html
const body: IDataObject = {};
const dataToSend = this.getNodeParameter('dataToSend', 0) as 'defineBelow' | 'autoMapInputData';
if (dataToSend === 'defineBelow') {
const fields = this.getNodeParameter('fieldsUi.fieldValues', i, []) as FieldsUiValues;
fields.forEach(({ fieldId, fieldValue }) => body[fieldId] = fieldValue);
} else {
const inputData = items[i].json;
const rawInputsToIgnore = this.getNodeParameter('inputsToIgnore', i) as string;
const inputsToIgnore = rawInputsToIgnore.split(',').map(c => c.trim());
for (const key of Object.keys(inputData)) {
if (inputsToIgnore.includes(key)) continue;
body[key] = inputData[key];
}
}
const qs = {} as IDataObject;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (Object.keys(additionalFields).length) {
Object.assign(qs, omit(additionalFields, ['documentId']));
}
const indexId = this.getNodeParameter('indexId', i);
const { documentId } = additionalFields;
if (documentId) {
const endpoint = `/${indexId}/_doc/${documentId}`;
responseData = await elasticsearchApiRequest.call(this, 'PUT', endpoint, body);
} else {
const endpoint = `/${indexId}/_doc`;
responseData = await elasticsearchApiRequest.call(this, 'POST', endpoint, body);
}
} else if (operation === 'update') {
// ----------------------------------------
// document: update
// ----------------------------------------
// https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update.html
const body = { doc: {} } as { doc: { [key: string]: string } };
const dataToSend = this.getNodeParameter('dataToSend', 0) as 'defineBelow' | 'autoMapInputData';
if (dataToSend === 'defineBelow') {
const fields = this.getNodeParameter('fieldsUi.fieldValues', i, []) as FieldsUiValues;
fields.forEach(({ fieldId, fieldValue }) => body.doc[fieldId] = fieldValue);
} else {
const inputData = items[i].json;
const rawInputsToIgnore = this.getNodeParameter('inputsToIgnore', i) as string;
const inputsToIgnore = rawInputsToIgnore.split(',').map(c => c.trim());
for (const key of Object.keys(inputData)) {
if (inputsToIgnore.includes(key)) continue;
body.doc[key] = inputData[key] as string;
}
}
const indexId = this.getNodeParameter('indexId', i);
const documentId = this.getNodeParameter('documentId', i);
const endpoint = `/${indexId}/_update/${documentId}`;
responseData = await elasticsearchApiRequest.call(this, 'POST', endpoint, body);
}
} else if (resource === 'index') {
// **********************************************************************
// index
// **********************************************************************
// https://www.elastic.co/guide/en/elasticsearch/reference/current/indices.html
if (operation === 'create') {
// ----------------------------------------
// index: create
// ----------------------------------------
// https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html
const indexId = this.getNodeParameter('indexId', i);
const body = {} as IDataObject;
const qs = {} as IDataObject;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (Object.keys(additionalFields).length) {
const { aliases, mappings, settings, ...rest } = additionalFields;
Object.assign(body, aliases, mappings, settings);
Object.assign(qs, rest);
}
responseData = await elasticsearchApiRequest.call(this, 'PUT', `/${indexId}`);
responseData = { id: indexId, ...responseData };
delete responseData.index;
} else if (operation === 'delete') {
// ----------------------------------------
// index: delete
// ----------------------------------------
// https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-delete-index.html
const indexId = this.getNodeParameter('indexId', i);
responseData = await elasticsearchApiRequest.call(this, 'DELETE', `/${indexId}`);
responseData = { success: true };
} else if (operation === 'get') {
// ----------------------------------------
// index: get
// ----------------------------------------
// https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-index.html
const indexId = this.getNodeParameter('indexId', i) as string;
const qs = {} as IDataObject;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (Object.keys(additionalFields).length) {
Object.assign(qs, additionalFields);
}
responseData = await elasticsearchApiRequest.call(this, 'GET', `/${indexId}`, {}, qs);
responseData = { id: indexId, ...responseData[indexId] };
} else if (operation === 'getAll') {
// ----------------------------------------
// index: getAll
// ----------------------------------------
// https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html
responseData = await elasticsearchApiRequest.call(this, 'GET', '/_aliases');
responseData = Object.keys(responseData).map(i => ({ indexId: i }));
const returnAll = this.getNodeParameter('returnAll', i);
if (!returnAll) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.slice(0, limit);
}
}
}
Array.isArray(responseData)
? returnData.push(...responseData)
: returnData.push(responseData);
}
return [this.helpers.returnJsonArray(returnData)];
}
}

View file

@ -0,0 +1,58 @@
import {
OptionsWithUri,
} from 'request';
import {
IExecuteFunctions,
} from 'n8n-core';
import {
IDataObject,
NodeApiError,
} from 'n8n-workflow';
import {
ElasticsearchApiCredentials,
} from './types';
export async function elasticsearchApiRequest(
this: IExecuteFunctions,
method: 'GET' | 'PUT' | 'POST' | 'DELETE',
endpoint: string,
body: IDataObject = {},
qs: IDataObject = {},
) {
const {
username,
password,
baseUrl,
} = this.getCredentials('elasticsearchApi') as ElasticsearchApiCredentials;
const token = Buffer.from(`${username}:${password}`).toString('base64');
const options: OptionsWithUri = {
headers: {
Authorization: `Basic ${token}`,
'Content-Type': 'application/json',
},
method,
body,
qs,
uri: `${baseUrl}${endpoint}`,
json: true,
};
if (!Object.keys(body).length) {
delete options.body;
}
if (!Object.keys(qs).length) {
delete options.qs;
}
try {
return await this.helpers.request(options);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
}

View file

@ -0,0 +1,788 @@
import {
INodeProperties,
} from 'n8n-workflow';
import * as placeholders from './placeholders';
export const documentOperations = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
displayOptions: {
show: {
resource: [
'document',
],
},
},
options: [
{
name: 'Create',
value: 'create',
description: 'Create a document',
},
{
name: 'Delete',
value: 'delete',
description: 'Delete a document',
},
{
name: 'Get',
value: 'get',
description: 'Get a document',
},
{
name: 'Get All',
value: 'getAll',
description: 'Get all documents',
},
{
name: 'Update',
value: 'update',
description: 'Update a document',
},
],
default: 'get',
description: 'Operation to perform',
},
] as INodeProperties[];
export const documentFields = [
// ----------------------------------------
// document: delete
// ----------------------------------------
{
displayName: 'Index ID',
name: 'indexId',
description: 'ID of the index containing the document to delete',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: [
'document',
],
operation: [
'delete',
],
},
},
},
{
displayName: 'Document ID',
name: 'documentId',
description: 'ID of the document to delete',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: [
'document',
],
operation: [
'delete',
],
},
},
},
// ----------------------------------------
// document: get
// ----------------------------------------
{
displayName: 'Index ID',
name: 'indexId',
description: 'ID of the index containing the document to retrieve',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: [
'document',
],
operation: [
'get',
],
},
},
},
{
displayName: 'Document ID',
name: 'documentId',
description: 'ID of the document to retrieve',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: [
'document',
],
operation: [
'get',
],
},
},
},
{
displayName: 'Simple',
name: 'simple',
type: 'boolean',
default: true,
description: 'Whether to return a simplified version of the response instead of the raw data',
displayOptions: {
show: {
resource: [
'document',
],
operation: [
'get',
],
},
},
},
{
displayName: 'Options',
name: 'options',
type: 'collection',
placeholder: 'Add Option',
default: {},
displayOptions: {
show: {
resource: [
'document',
],
operation: [
'get',
],
},
},
options: [
{
displayName: 'Source Excludes',
name: '_source_excludes',
description: 'Comma-separated list of source fields to exclude from the response',
type: 'string',
default: '',
},
{
displayName: 'Source Includes',
name: '_source_includes',
description: 'Comma-separated list of source fields to include in the response',
type: 'string',
default: '',
},
{
displayName: 'Stored Fields',
name: 'stored_fields',
description: 'If true, retrieve the document fields stored in the index rather than the document <code>_source</code>. Defaults to false',
type: 'boolean',
default: false,
},
],
},
// ----------------------------------------
// document: getAll
// ----------------------------------------
{
displayName: 'Index ID',
name: 'indexId',
description: 'ID of the index containing the documents to retrieve',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: [
'document',
],
operation: [
'getAll',
],
},
},
},
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
default: false,
description: 'Whether to return all results or only up to a given limit',
displayOptions: {
show: {
resource: [
'document',
],
operation: [
'getAll',
],
},
},
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
default: 50,
description: 'How many results to return',
typeOptions: {
minValue: 1,
},
displayOptions: {
show: {
resource: [
'document',
],
operation: [
'getAll',
],
returnAll: [
false,
],
},
},
},
{
displayName: 'Simple',
name: 'simple',
type: 'boolean',
default: true,
description: 'Whether to return a simplified version of the response instead of the raw data',
displayOptions: {
show: {
resource: [
'document',
],
operation: [
'getAll',
],
},
},
},
{
displayName: 'Options',
name: 'options',
type: 'collection',
placeholder: 'Add Option',
default: {},
displayOptions: {
show: {
resource: [
'document',
],
operation: [
'getAll',
],
},
},
options: [
{
displayName: 'Allow No Indices',
name: 'allow_no_indices',
description: 'If false, return an error if any of the following targets only missing/closed indices: wildcard expression, index alias, or <code>_all</code> value. Defaults to true',
type: 'boolean',
default: true,
},
{
displayName: 'Allow Partial Search Results',
name: 'allow_partial_search_results',
description: 'If true, return partial results if there are shard request timeouts or shard failures.<br>If false, returns an error with no partial results. Defaults to true',
type: 'boolean',
default: true,
},
{
displayName: 'Batched Reduce Size',
name: 'batched_reduce_size',
description: 'Number of shard results that should be reduced at once on the coordinating node. Defaults to 512',
type: 'number',
typeOptions: {
minValue: 2,
},
default: 512,
},
{
displayName: 'CCS Minimize Roundtrips',
name: 'ccs_minimize_roundtrips',
description: 'If true, network round-trips between the coordinating node and the remote clusters are minimized when executing cross-cluster search (CCS) requests. Defaults to true',
type: 'boolean',
default: true,
},
{
displayName: 'Doc Value Fields',
name: 'docvalue_fields',
description: 'Comma-separated list of fields to return as the docvalue representation of a field for each hit',
type: 'string',
default: '',
},
{
displayName: 'Expand Wildcards',
name: 'expand_wildcards',
description: 'Type of index that wildcard expressions can match. Defaults to <code>open</code>',
type: 'options',
options: [
{
name: 'All',
value: 'all',
},
{
name: 'Closed',
value: 'closed',
},
{
name: 'Hidden',
value: 'hidden',
},
{
name: 'None',
value: 'none',
},
{
name: 'Open',
value: 'open',
},
],
default: 'open',
},
{
displayName: 'Explain',
name: 'explain',
description: 'If true, return detailed information about score computation as part of a hit. Defaults to false',
type: 'boolean',
default: false,
},
{
displayName: 'Ignore Throttled',
name: 'ignore_throttled',
description: 'If true, concrete, expanded or aliased indices are ignored when frozen. Defaults to true',
type: 'boolean',
default: true,
},
{
displayName: 'Ignore Unavailable',
name: 'ignore_unavailable',
description: 'If true, missing or closed indices are not included in the response. Defaults to false',
type: 'boolean',
default: false,
},
{
displayName: 'Max Concurrent Shard Requests',
name: 'max_concurrent_shard_requests',
description: 'Define the number of shard requests per node this search executes concurrently. Defaults to 5',
type: 'number',
default: 5,
},
{
displayName: 'Pre-Filter Shard Size',
name: 'pre_filter_shard_size',
description: 'Define a threshold that enforces a pre-filter roundtrip to prefilter search shards based on query rewriting.<br>Only used if the number of shards the search request expands to exceeds the threshold',
type: 'number',
typeOptions: {
minValue: 1,
},
default: 1,
},
{
displayName: 'Query',
name: 'query',
description: 'Query in the <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html" target="_blank">Elasticsearch Query DSL</a>',
type: 'json',
typeOptions: {
alwaysOpenEditWindow: true,
},
default: '',
placeholder: placeholders.query,
},
{
displayName: 'Request Cache',
name: 'request_cache',
description: 'If true, the caching of search results is enabled for requests where size is 0. See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/shard-request-cache.html" target="_blank">Elasticsearch shard request cache settings</a>',
type: 'boolean',
default: false,
},
{
displayName: 'Routing',
name: 'routing',
description: 'Target this primary shard',
type: 'string',
default: '',
},
{
displayName: 'Search Type',
name: 'search_type',
description: 'How distributed term frequencies are calculated for relevance scoring. Defaults to Query then Fetch',
type: 'options',
options: [
{
name: 'DFS Query Then Fetch',
value: 'dfs_query_then_fetch',
},
{
name: 'Query Then Fetch',
value: 'query_then_fetch',
},
],
default: 'query_then_fetch',
},
{
displayName: 'Sequence Number and Primary Term',
name: 'seq_no_primary_term',
description: 'If true, return the sequence number and primary term of the last modification of each hit. See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/optimistic-concurrency-control.html" target="_blank">Optimistic concurrency control</a>',
type: 'boolean',
default: false,
},
{
displayName: 'Sort',
name: 'sort',
description: 'Comma-separated list of <code>field:direction</code> pairs',
type: 'string',
default: '',
},
{
displayName: 'Stats',
name: 'stats',
description: 'Tag of the request for logging and statistical purposes',
type: 'string',
default: '',
},
{
displayName: 'Stored Fields',
name: 'stored_fields',
description: 'If true, retrieve the document fields stored in the index rather than the document <code>_source</code>. Defaults to false',
type: 'boolean',
default: false,
},
{
displayName: 'Terminate After',
name: 'terminate_after',
description: 'Max number of documents to collect for each shard',
type: 'number',
default: 0,
},
{
displayName: 'Timeout',
name: 'timeout',
description: 'Period to wait for active shards. Defaults to <code>1m</code> (one minute). See the <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/common-options.html#time-units" target="_blank">Elasticsearch time units reference</a>',
type: 'string',
default: '1m',
},
{
displayName: 'Track Scores',
name: 'track_scores',
description: 'If true, calculate and return document scores, even if the scores are not used for sorting. Defaults to false',
type: 'boolean',
default: false,
},
{
displayName: 'Track Total Hits',
name: 'track_total_hits',
description: 'Number of hits matching the query to count accurately. Defaults to 10000',
type: 'number',
default: 10000,
},
{
displayName: 'Version',
name: 'version',
description: 'If true, return document version as part of a hit. Defaults to false',
type: 'boolean',
default: false,
},
],
},
// ----------------------------------------
// document: create
// ----------------------------------------
{
displayName: 'Index ID',
name: 'indexId',
description: 'ID of the index to add the document to',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: [
'document',
],
operation: [
'create',
],
},
},
},
{
displayName: 'Data to Send',
name: 'dataToSend',
type: 'options',
options: [
{
name: 'Define Below for Each Column',
value: 'defineBelow',
description: 'Set the value for each destination column',
},
{
name: 'Auto-map Input Data to Columns',
value: 'autoMapInputData',
description: 'Use when node input properties match destination column names',
},
],
displayOptions: {
show: {
resource: [
'document',
],
operation: [
'create',
],
},
},
default: 'defineBelow',
description: 'Whether to insert the input data this node receives in the new row',
},
{
displayName: 'Inputs to Ignore',
name: 'inputsToIgnore',
type: 'string',
displayOptions: {
show: {
resource: [
'document',
],
operation: [
'create',
],
dataToSend: [
'autoMapInputData',
],
},
},
default: '',
required: false,
description: 'List of input properties to avoid sending, separated by commas. Leave empty to send all properties',
placeholder: 'Enter properties...',
},
{
displayName: 'Fields to Send',
name: 'fieldsUi',
placeholder: 'Add Field',
type: 'fixedCollection',
typeOptions: {
multipleValueButtonText: 'Add Field to Send',
multipleValues: true,
},
displayOptions: {
show: {
resource: [
'document',
],
operation: [
'create',
],
dataToSend: [
'defineBelow',
],
},
},
default: {},
options: [
{
displayName: 'Field',
name: 'fieldValues',
values: [
{
displayName: 'Field Name',
name: 'fieldId',
type: 'string',
default: '',
},
{
displayName: 'Field Value',
name: 'fieldValue',
type: 'string',
default: '',
},
],
},
],
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: [
'document',
],
operation: [
'create',
],
},
},
options: [
{
displayName: 'Document ID',
name: 'documentId',
description: 'ID of the document to create and add to the index',
type: 'string',
default: '',
},
{
displayName: 'Routing',
name: 'routing',
description: 'Target this primary shard',
type: 'string',
default: '',
},
{
displayName: 'Timeout',
name: 'timeout',
description: 'Period to wait for active shards. Defaults to <code>1m</code> (one minute). See the <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/common-options.html#time-units" target="_blank">Elasticsearch time units reference</a>',
type: 'string',
default: '1m',
},
],
},
// ----------------------------------------
// document: update
// ----------------------------------------
{
displayName: 'Index ID',
name: 'indexId',
description: 'ID of the document to update',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: [
'document',
],
operation: [
'update',
],
},
},
},
{
displayName: 'Document ID',
name: 'documentId',
description: 'ID of the document to update',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: [
'document',
],
operation: [
'update',
],
},
},
},
{
displayName: 'Data to Send',
name: 'dataToSend',
type: 'options',
options: [
{
name: 'Define Below for Each Column',
value: 'defineBelow',
description: 'Set the value for each destination column',
},
{
name: 'Auto-map Input Data to Columns',
value: 'autoMapInputData',
description: 'Use when node input properties match destination column names',
},
],
displayOptions: {
show: {
resource: [
'document',
],
operation: [
'update',
],
},
},
default: 'defineBelow',
description: 'Whether to insert the input data this node receives in the new row',
},
{
displayName: 'Inputs to Ignore',
name: 'inputsToIgnore',
type: 'string',
displayOptions: {
show: {
resource: [
'document',
],
operation: [
'update',
],
dataToSend: [
'autoMapInputData',
],
},
},
default: '',
required: false,
description: 'List of input properties to avoid sending, separated by commas. Leave empty to send all properties',
placeholder: 'Enter properties...',
},
{
displayName: 'Fields to Send',
name: 'fieldsUi',
placeholder: 'Add Field',
type: 'fixedCollection',
typeOptions: {
multipleValueButtonText: 'Add Field to Send',
multipleValues: true,
},
displayOptions: {
show: {
resource: [
'document',
],
operation: [
'update',
],
dataToSend: [
'defineBelow',
],
},
},
default: {},
options: [
{
displayName: 'Field',
name: 'fieldValues',
values: [
{
displayName: 'Field Name',
name: 'fieldId',
type: 'string',
default: '',
},
{
displayName: 'Field Value',
name: 'fieldValue',
type: 'string',
default: '',
},
],
},
],
},
] as INodeProperties[];

View file

@ -0,0 +1,322 @@
import {
INodeProperties,
} from 'n8n-workflow';
import * as placeholders from './placeholders';
export const indexOperations = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
displayOptions: {
show: {
resource: [
'index',
],
},
},
options: [
{
name: 'Create',
value: 'create',
},
{
name: 'Delete',
value: 'delete',
},
{
name: 'Get',
value: 'get',
},
{
name: 'Get All',
value: 'getAll',
},
],
default: 'create',
description: 'Operation to perform',
},
] as INodeProperties[];
export const indexFields = [
// ----------------------------------------
// index: create
// ----------------------------------------
{
displayName: 'Index ID',
name: 'indexId',
description: 'ID of the index to create',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: [
'index',
],
operation: [
'create',
],
},
},
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: [
'index',
],
operation: [
'create',
],
},
},
options: [
{
displayName: 'Aliases',
name: 'aliases',
description: 'Index aliases which include the index, as an <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html" target="_blank">alias object</a>',
type: 'json',
typeOptions: {
alwaysOpenEditWindow: true,
},
default: '',
placeholder: placeholders.aliases,
},
{
displayName: 'Include Type Name',
name: 'include_type_name',
description: 'If true, a mapping type is expected in the body of mappings. Defaults to false',
type: 'boolean',
default: false,
},
{
displayName: 'Mappings',
name: 'mappings',
description: 'Mapping for fields in the index, as <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html" target="_blank">mapping object</a>',
type: 'json',
typeOptions: {
alwaysOpenEditWindow: true,
},
default: '',
placeholder: placeholders.mappings,
},
{
displayName: 'Master Timeout',
name: 'master_timeout',
description: 'Period to wait for a connection to the master node. If no response is received before the timeout expires,<br>the request fails and returns an error. Defaults to <code>1m</code>. See the <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/common-options.html#time-units" target="_blank">Elasticsearch time units reference</a>',
type: 'string',
default: '1m',
},
{
displayName: 'Settings',
name: 'settings',
description: 'Configuration options for the index, as an <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules.html#index-modules-settings" target="_blank">index settings object</a>',
type: 'json',
typeOptions: {
alwaysOpenEditWindow: true,
},
default: '',
placeholder: placeholders.indexSettings,
},
{
displayName: 'Timeout',
name: 'timeout',
description: 'Period to wait for a response. If no response is received before the timeout expires, the request<br>fails and returns an error. Defaults to <code>30s</code>. See the <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/common-options.html#time-units" target="_blank">Elasticsearch time units reference</a>',
type: 'string',
default: '30s',
},
{
displayName: 'Wait for Active Shards',
name: 'wait_for_active_shards',
description: 'The number of shard copies that must be active before proceeding with the operation. Set to <code>all</code><br>or any positive integer up to the total number of shards in the index. Default: 1, the primary shard',
type: 'string',
default: '1',
},
],
},
// ----------------------------------------
// index: delete
// ----------------------------------------
{
displayName: 'Index ID',
name: 'indexId',
description: 'ID of the index to delete',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: [
'index',
],
operation: [
'delete',
],
},
},
},
// ----------------------------------------
// index: get
// ----------------------------------------
{
displayName: 'Index ID',
name: 'indexId',
description: 'ID of the index to retrieve',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: [
'index',
],
operation: [
'get',
],
},
},
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: [
'index',
],
operation: [
'get',
],
},
},
options: [
{
displayName: 'Allow No Indices',
name: 'allow_no_indices',
description: 'If false, return an error if any of the following targets only missing/closed indices: wildcard expression, index alias, or <code>_all</code> value. Defaults to true',
type: 'boolean',
default: true,
},
{
displayName: 'Expand Wildcards',
name: 'expand_wildcards',
description: 'Type of index that wildcard expressions can match. Defaults to <code>open</code>',
type: 'options',
options: [
{
name: 'All',
value: 'all',
},
{
name: 'Closed',
value: 'closed',
},
{
name: 'Hidden',
value: 'hidden',
},
{
name: 'None',
value: 'none',
},
{
name: 'Open',
value: 'open',
},
],
default: 'all',
},
{
displayName: 'Flat Settings',
name: 'flat_settings',
description: 'If true, return settings in flat format. Defaults to false',
type: 'boolean',
default: false,
},
{
displayName: 'Ignore Unavailable',
name: 'ignore_unavailable',
description: 'If false, requests that target a missing index return an error. Defaults to false',
type: 'boolean',
default: false,
},
{
displayName: 'Include Defaults',
name: 'include_defaults',
description: 'If true, return all default settings in the response. Defaults to false',
type: 'boolean',
default: false,
},
{
displayName: 'Local',
name: 'local',
description: 'If true, retrieve information from the local node only. Defaults to false',
type: 'boolean',
default: false,
},
{
displayName: 'Master Timeout',
name: 'master_timeout',
description: 'Period to wait for a connection to the master node. If no response is received before the timeout expires,<br>the request fails and returns an error. Defaults to <code>1m</code>. See the <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/common-options.html#time-units" target="_blank">Elasticsearch time units reference</a>',
type: 'string',
default: '1m',
},
],
},
// ----------------------------------------
// index: getAll
// ----------------------------------------
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
default: false,
description: 'Whether to return all results or only up to a given limit',
displayOptions: {
show: {
resource: [
'index',
],
operation: [
'getAll',
],
},
},
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
default: 50,
description: 'How many results to return',
typeOptions: {
minValue: 1,
},
displayOptions: {
show: {
resource: [
'index',
],
operation: [
'getAll',
],
returnAll: [
false,
],
},
},
},
] as INodeProperties[];

View file

@ -0,0 +1,2 @@
export * from './DocumentDescription';
export * from './IndexDescription';

View file

@ -0,0 +1,43 @@
export const indexSettings = `{
"settings": {
"index": {
"number_of_shards": 3,
"number_of_replicas": 2
}
}
}`;
export const mappings = `{
"mappings": {
"properties": {
"field1": { "type": "text" }
}
}
}`;
export const aliases = `{
"aliases": {
"alias_1": {},
"alias_2": {
"filter": {
"term": { "user.id": "kimchy" }
},
"routing": "shard-1"
}
}
}`;
export const query = `{
"query": {
"term": {
"user.id": "john"
}
}
}`;
export const document = `{
"timestamp": "2099-05-06T16:21:15.000Z",
"event": {
"original": "192.0.2.42 - - [06/May/2099:16:21:15 +0000] \"GET /images/bg.jpg HTTP/1.0\" 200 24736"
}
}`;

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="64px" height="64px" viewBox="6 5 54 54" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 63.1 (92452) - https://sketch.com -->
<title>elastic-search-logo-color-64px</title>
<desc>Created with Sketch.</desc>
<g id="elastic-search-logo-color-64px" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<rect id="bounding-box" x="0" y="0" width="64" height="64"></rect>
<g id="group" transform="translate(8.000000, 4.999500)">
<path d="M47.7246,9.708 L47.7276,9.702 C42.7746,3.774 35.3286,0 26.9996,0 C16.4006,0 7.2326,6.112 2.8136,15 L38.0056,15 C40.5306,15 42.9886,14.13 44.9206,12.504 C45.9246,11.659 46.8636,10.739 47.7246,9.708" id="Fill-1" fill="#FEC514"></path>
<path d="M0,27.0005 C0,29.4225 0.324,31.7675 0.922,34.0005 L34,34.0005 C37.866,34.0005 41,30.8665 41,27.0005 C41,23.1345 37.866,20.0005 34,20.0005 L0.922,20.0005 C0.324,22.2335 0,24.5785 0,27.0005" id="Fill-4" fill="#343741"></path>
<path d="M47.7246,44.293 L47.7276,44.299 C42.7746,50.227 35.3286,54.001 26.9996,54.001 C16.4006,54.001 7.2326,47.889 2.8136,39.001 L38.0056,39.001 C40.5306,39.001 42.9886,39.871 44.9206,41.497 C45.9246,42.342 46.8636,43.262 47.7246,44.293" id="Fill-6" fill="#00BFB3"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -0,0 +1,40 @@
export type ElasticsearchApiCredentials = {
username: string;
password: string;
baseUrl: string;
};
export type DocumentGetAllOptions = Partial<{
allow_no_indices: boolean;
allow_partial_search_results: boolean;
batched_reduce_size: number;
ccs_minimize_roundtrips: boolean;
docvalue_fields: string;
expand_wildcards: 'All' | 'Closed' | 'Hidden' | 'None' | 'Open';
explain: boolean;
ignore_throttled: boolean;
ignore_unavailable: boolean;
max_concurrent_shard_requests: number;
pre_filter_shard_size: number;
query: string;
request_cache: boolean;
routing: string;
search_type: 'query_then_fetch' | 'dfs_query_then_fetch';
seq_no_primary_term: boolean;
sort: string;
_source: boolean;
_source_excludes: string;
_source_includes: string;
stats: string;
stored_fields: boolean;
terminate_after: boolean;
timeout: number;
track_scores: boolean;
track_total_hits: string;
version: boolean;
}>;
export type FieldsUiValues = Array<{
fieldId: string;
fieldValue: string;
}>;

View file

@ -133,84 +133,93 @@ export class EmailSend implements INodeType {
let item: INodeExecutionData;
for (let itemIndex = 0; itemIndex < length; itemIndex++) {
try {
item = items[itemIndex];
item = items[itemIndex];
const fromEmail = this.getNodeParameter('fromEmail', itemIndex) as string;
const toEmail = this.getNodeParameter('toEmail', itemIndex) as string;
const ccEmail = this.getNodeParameter('ccEmail', itemIndex) as string;
const bccEmail = this.getNodeParameter('bccEmail', itemIndex) as string;
const subject = this.getNodeParameter('subject', itemIndex) as string;
const text = this.getNodeParameter('text', itemIndex) as string;
const html = this.getNodeParameter('html', itemIndex) as string;
const attachmentPropertyString = this.getNodeParameter('attachments', itemIndex) as string;
const options = this.getNodeParameter('options', itemIndex, {}) as IDataObject;
const fromEmail = this.getNodeParameter('fromEmail', itemIndex) as string;
const toEmail = this.getNodeParameter('toEmail', itemIndex) as string;
const ccEmail = this.getNodeParameter('ccEmail', itemIndex) as string;
const bccEmail = this.getNodeParameter('bccEmail', itemIndex) as string;
const subject = this.getNodeParameter('subject', itemIndex) as string;
const text = this.getNodeParameter('text', itemIndex) as string;
const html = this.getNodeParameter('html', itemIndex) as string;
const attachmentPropertyString = this.getNodeParameter('attachments', itemIndex) as string;
const options = this.getNodeParameter('options', itemIndex, {}) as IDataObject;
const credentials = this.getCredentials('smtp');
const credentials = this.getCredentials('smtp');
if (credentials === undefined) {
throw new NodeOperationError(this.getNode(), 'No credentials got returned!');
}
const connectionOptions: SMTPTransport.Options = {
host: credentials.host as string,
port: credentials.port as number,
secure: credentials.secure as boolean,
};
if (credentials.user || credentials.password) {
// @ts-ignore
connectionOptions.auth = {
user: credentials.user as string,
pass: credentials.password as string,
};
}
if (options.allowUnauthorizedCerts === true) {
connectionOptions.tls = {
rejectUnauthorized: false,
};
}
const transporter = createTransport(connectionOptions);
// setup email data with unicode symbols
const mailOptions = {
from: fromEmail,
to: toEmail,
cc: ccEmail,
bcc: bccEmail,
subject,
text,
html,
};
if (attachmentPropertyString && item.binary) {
const attachments = [];
const attachmentProperties: string[] = attachmentPropertyString.split(',').map((propertyName) => {
return propertyName.trim();
});
for (const propertyName of attachmentProperties) {
if (!item.binary.hasOwnProperty(propertyName)) {
continue;
}
attachments.push({
filename: item.binary[propertyName].fileName || 'unknown',
content: Buffer.from(item.binary[propertyName].data, BINARY_ENCODING),
});
if (credentials === undefined) {
throw new NodeOperationError(this.getNode(), 'No credentials got returned!');
}
if (attachments.length) {
const connectionOptions: SMTPTransport.Options = {
host: credentials.host as string,
port: credentials.port as number,
secure: credentials.secure as boolean,
};
if (credentials.user || credentials.password) {
// @ts-ignore
mailOptions.attachments = attachments;
connectionOptions.auth = {
user: credentials.user as string,
pass: credentials.password as string,
};
}
if (options.allowUnauthorizedCerts === true) {
connectionOptions.tls = {
rejectUnauthorized: false,
};
}
const transporter = createTransport(connectionOptions);
// setup email data with unicode symbols
const mailOptions = {
from: fromEmail,
to: toEmail,
cc: ccEmail,
bcc: bccEmail,
subject,
text,
html,
};
if (attachmentPropertyString && item.binary) {
const attachments = [];
const attachmentProperties: string[] = attachmentPropertyString.split(',').map((propertyName) => {
return propertyName.trim();
});
for (const propertyName of attachmentProperties) {
if (!item.binary.hasOwnProperty(propertyName)) {
continue;
}
attachments.push({
filename: item.binary[propertyName].fileName || 'unknown',
content: Buffer.from(item.binary[propertyName].data, BINARY_ENCODING),
});
}
if (attachments.length) {
// @ts-ignore
mailOptions.attachments = attachments;
}
}
// Send the email
const info = await transporter.sendMail(mailOptions);
returnData.push({ json: info as unknown as IDataObject });
}catch (error) {
if (this.continueOnFail()) {
returnData.push({json:{ error: error.message }});
continue;
}
throw error;
}
// Send the email
const info = await transporter.sendMail(mailOptions);
returnData.push({ json: info as unknown as IDataObject });
}
return this.prepareOutputData(returnData);

View file

@ -3,6 +3,7 @@ import {
INodeExecutionData,
INodeType,
INodeTypeDescription,
NodeOperationError
} from 'n8n-workflow';
import { exec } from 'child_process';
@ -24,6 +25,7 @@ export interface IExecReturnData {
*/
function execPromise(command: string): Promise<IExecReturnData> {
const returnData: IExecReturnData = {
error: undefined,
exitCode: 0,
stderr: '',
stdout: '',
@ -94,24 +96,39 @@ export class ExecuteCommand implements INodeType {
const returnItems: INodeExecutionData[] = [];
for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
command = this.getNodeParameter('command', itemIndex) as string;
const {
// error, TODO: Later make it possible to select if it should fail on error or not
exitCode,
stdout,
stderr,
} = await execPromise(command);
try{
returnItems.push(
{
json: {
exitCode,
stderr,
stdout,
command = this.getNodeParameter('command', itemIndex) as string;
const {
error,
exitCode,
stdout,
stderr,
} = await execPromise(command);
if (error !== undefined) {
throw new NodeOperationError(this.getNode(), error.message);
}
returnItems.push(
{
json: {
exitCode,
stderr,
stdout,
},
},
},
);
);
} catch (error) {
if (this.continueOnFail()) {
returnItems.push({json:{ error: error.message }});
continue;
}
throw error;
}
}
return this.prepareOutputData(returnItems);

View file

@ -149,53 +149,64 @@ export class ExecuteWorkflow implements INodeType {
const source = this.getNodeParameter('source', 0) as string;
const workflowInfo: IExecuteWorkflowInfo = {};
if (source === 'database') {
// Read workflow from database
workflowInfo.id = this.getNodeParameter('workflowId', 0) as string;
} else if (source === 'localFile') {
// Read workflow from filesystem
const workflowPath = this.getNodeParameter('workflowPath', 0) as string;
try {
let workflowJson;
try {
workflowJson = await fsReadFile(workflowPath, { encoding: 'utf8' }) as string;
} catch (error) {
if (error.code === 'ENOENT') {
throw new NodeOperationError(this.getNode(), `The file "${workflowPath}" could not be found.`);
if (source === 'database') {
// Read workflow from database
workflowInfo.id = this.getNodeParameter('workflowId', 0) as string;
} else if (source === 'localFile') {
// Read workflow from filesystem
const workflowPath = this.getNodeParameter('workflowPath', 0) as string;
let workflowJson;
try {
workflowJson = await fsReadFile(workflowPath, { encoding: 'utf8' }) as string;
} catch (error) {
if (error.code === 'ENOENT') {
throw new NodeOperationError(this.getNode(), `The file "${workflowPath}" could not be found.`);
}
throw error;
}
throw error;
workflowInfo.code = JSON.parse(workflowJson) as IWorkflowBase;
} else if (source === 'parameter') {
// Read workflow from parameter
const workflowJson = this.getNodeParameter('workflowJson', 0) as string;
workflowInfo.code = JSON.parse(workflowJson) as IWorkflowBase;
} else if (source === 'url') {
// Read workflow from url
const workflowUrl = this.getNodeParameter('workflowUrl', 0) as string;
const requestOptions = {
headers: {
'accept': 'application/json,text/*;q=0.99',
},
method: 'GET',
uri: workflowUrl,
json: true,
gzip: true,
};
const response = await this.helpers.request(requestOptions);
workflowInfo.code = response;
}
workflowInfo.code = JSON.parse(workflowJson) as IWorkflowBase;
} else if (source === 'parameter') {
// Read workflow from parameter
const workflowJson = this.getNodeParameter('workflowJson', 0) as string;
workflowInfo.code = JSON.parse(workflowJson) as IWorkflowBase;
const receivedData = await this.executeWorkflow(workflowInfo, items);
} else if (source === 'url') {
// Read workflow from url
const workflowUrl = this.getNodeParameter('workflowUrl', 0) as string;
return receivedData;
} catch (error) {
if (this.continueOnFail()) {
return this.prepareOutputData([{json:{ error: error.message }}]);
}
const requestOptions = {
headers: {
'accept': 'application/json,text/*;q=0.99',
},
method: 'GET',
uri: workflowUrl,
json: true,
gzip: true,
};
const response = await this.helpers.request(requestOptions);
workflowInfo.code = response;
throw error;
}
const receivedData = await this.executeWorkflow(workflowInfo, items);
return receivedData;
}
}

View file

@ -1148,283 +1148,291 @@ export class Freshdesk implements INodeType {
const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string;
for (let i = 0; i < items.length; i++) {
if (resource === 'ticket') {
//https://developers.freshdesk.com/api/#create_ticket
if (operation === 'create') {
const requester = this.getNodeParameter('requester', i) as string;
const value = this.getNodeParameter('requesterIdentificationValue', i) as string;
const status = this.getNodeParameter('status', i) as string;
const priority = this.getNodeParameter('priority', i) as string;
const source = this.getNodeParameter('source', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
//const jsonActive = this.getNodeParameter('jsonParameters') as boolean;
const body: ICreateTicketBody = {
// @ts-ignore
status: Status[capitalize(status)],
// @ts-ignore
priority: Priority[capitalize(priority)],
// @ts-ignore
source: Source[capitalize(source)],
};
if (requester === 'requesterId') {
// @ts-ignore
if (isNaN(value)) {
throw new NodeOperationError(this.getNode(), 'Requester Id must be a number');
}
body.requester_id = parseInt(value, 10);
} else if (requester === 'email') {
body.email = value;
} else if (requester === 'facebookId') {
body.facebook_id = value;
} else if (requester === 'phone') {
body.phone = value;
} else if (requester === 'twitterId') {
body.twitter_id = value;
} else if (requester === 'uniqueExternalId') {
body.unique_external_id = value;
}
// if (!jsonActive) {
// const customFieldsUi = this.getNodeParameter('customFieldsUi') as IDataObject;
// if (Object.keys(customFieldsUi).length > 0) {
// const aux: IDataObject = {};
// // @ts-ignore
// customFieldsUi.customFieldsValues.forEach( o => {
// aux[`${o.key}`] = o.value;
// return aux;
// });
// body.custom_fields = aux;
// } else {
// body.custom_fields = validateJSON(this.getNodeParameter('customFielsJson') as string);
// }
if (options.name) {
body.name = options.name as string;
}
if (options.subject) {
body.subject = options.subject as string;
} else {
body.subject = 'null';
}
if (options.type) {
body.type = options.type as string;
}
if (options.description) {
body.description = options.description as string;
} else {
body.description = 'null';
}
if (options.agent) {
body.responder_id = options.agent as number;
}
if (options.company) {
body.company_id = options.company as number;
}
if (options.product) {
body.product_id = options.product as number;
}
if (options.group) {
body.group_id = options.group as number;
}
if (options.frDueBy) {
body.fr_due_by = options.frDueBy as string;
}
if (options.emailConfigId) {
body.email_config_id = options.emailConfigId as number;
}
if (options.dueBy) {
body.due_by = options.dueBy as string;
}
if (options.tags) {
body.tags = (options.tags as string).split(',') as [string];
}
if (options.ccEmails) {
body.cc_emails = (options.ccEmails as string).split(',') as [string];
}
responseData = await freshdeskApiRequest.call(this, 'POST', '/tickets', body);
}
//https://developers.freshdesk.com/api/#update_ticket
if (operation === 'update') {
const ticketId = this.getNodeParameter('ticketId', i) as string;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const body: ICreateTicketBody = {};
if (updateFields.requester) {
const value = updateFields.requesterIdentificationValue as string;
if (updateFields.requester === 'requesterId') {
try {
if (resource === 'ticket') {
//https://developers.freshdesk.com/api/#create_ticket
if (operation === 'create') {
const requester = this.getNodeParameter('requester', i) as string;
const value = this.getNodeParameter('requesterIdentificationValue', i) as string;
const status = this.getNodeParameter('status', i) as string;
const priority = this.getNodeParameter('priority', i) as string;
const source = this.getNodeParameter('source', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
//const jsonActive = this.getNodeParameter('jsonParameters') as boolean;
const body: ICreateTicketBody = {
// @ts-ignore
if (isNaN(parseInt(value, 10))) {
status: Status[capitalize(status)],
// @ts-ignore
priority: Priority[capitalize(priority)],
// @ts-ignore
source: Source[capitalize(source)],
};
if (requester === 'requesterId') {
// @ts-ignore
if (isNaN(value)) {
throw new NodeOperationError(this.getNode(), 'Requester Id must be a number');
}
body.requester_id = parseInt(value as string, 10);
} else if (updateFields.requester === 'email') {
body.email = value as string;
} else if (updateFields.requester === 'facebookId') {
body.facebook_id = value as string;
} else if (updateFields.requester === 'phone') {
body.phone = value as string;
} else if (updateFields.requester === 'twitterId') {
body.twitter_id = value as string;
} else if (updateFields.requester === 'uniqueExternalId') {
body.unique_external_id = value as string;
body.requester_id = parseInt(value, 10);
} else if (requester === 'email') {
body.email = value;
} else if (requester === 'facebookId') {
body.facebook_id = value;
} else if (requester === 'phone') {
body.phone = value;
} else if (requester === 'twitterId') {
body.twitter_id = value;
} else if (requester === 'uniqueExternalId') {
body.unique_external_id = value;
}
}
if (updateFields.status) {
//@ts-ignore
body.status = Status[capitalize(updateFields.status)];
}
if (updateFields.priority) {
//@ts-ignore
body.priority = Priority[capitalize(updateFields.priority)];
}
if (updateFields.source) {
//@ts-ignore
body.source = Source[capitalize(updateFields.source)];
}
if (updateFields.name) {
body.name = updateFields.name as string;
}
if (updateFields.type) {
body.type = updateFields.type as string;
}
if (updateFields.agent) {
body.responder_id = updateFields.agent as number;
}
if (updateFields.company) {
body.company_id = updateFields.company as number;
}
if (updateFields.product) {
body.product_id = updateFields.product as number;
}
if (updateFields.group) {
body.group_id = updateFields.group as number;
}
if (updateFields.frDueBy) {
body.fr_due_by = updateFields.frDueBy as string;
}
if (updateFields.emailConfigId) {
body.email_config_id = updateFields.emailConfigId as number;
}
if (updateFields.dueBy) {
body.due_by = updateFields.dueBy as string;
}
if (updateFields.tags) {
body.tags = (updateFields.tags as string).split(',') as [string];
}
if (updateFields.ccEmails) {
body.cc_emails = (updateFields.ccEmails as string).split(',') as [string];
}
responseData = await freshdeskApiRequest.call(this, 'PUT', `/tickets/${ticketId}`, body);
}
//https://developers.freshdesk.com/api/#view_a_ticket
if (operation === 'get') {
const ticketId = this.getNodeParameter('ticketId', i) as string;
responseData = await freshdeskApiRequest.call(this, 'GET', `/tickets/${ticketId}`);
}
//https://developers.freshdesk.com/api/#list_all_tickets
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const options = this.getNodeParameter('options', i) as IDataObject;
if (options.requesterId) {
qs.requester_id = options.requesterId as string;
}
if (options.requesterEmail) {
qs.email = options.requesterEmail as string;
}
if (options.companyId) {
qs.company_id = options.companyId as string;
}
if (options.updatedSince) {
qs.updated_since = options.updatedSince as string;
}
if (options.orderBy) {
qs.order_by = options.orderBy as string;
}
if (options.order) {
qs.order_type = options.order as string;
}
if (options.include) {
if ((options.include as string[]).length !== 0) {
qs.include = (options.include as string[]).join(',');
}
}
if (returnAll === true) {
responseData = await freshdeskApiRequestAllItems.call(this, 'GET', '/tickets', {}, qs);
} else {
qs.per_page = this.getNodeParameter('limit', i) as number;
responseData = await freshdeskApiRequest.call(this, 'GET', '/tickets', {}, qs);
}
}
//https://developers.freshdesk.com/api/#delete_a_ticket
if (operation === 'delete') {
const ticketId = this.getNodeParameter('ticketId', i) as string;
responseData = await freshdeskApiRequest.call(this, 'DELETE', `/tickets/${ticketId}`);
}
} else if (resource === 'contact') {
//https://developers.freshdesk.com/api/#create_contact
if (operation === 'create') {
const name = this.getNodeParameter('name', i) as string;
const email = this.getNodeParameter('email', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i, {}) as IDataObject;
if (additionalFields.customFields) {
const metadata = (additionalFields.customFields as IDataObject).customField as IDataObject[];
additionalFields.custom_fields = {};
for (const data of metadata) {
// if (!jsonActive) {
// const customFieldsUi = this.getNodeParameter('customFieldsUi') as IDataObject;
// if (Object.keys(customFieldsUi).length > 0) {
// const aux: IDataObject = {};
// // @ts-ignore
// customFieldsUi.customFieldsValues.forEach( o => {
// aux[`${o.key}`] = o.value;
// return aux;
// });
// body.custom_fields = aux;
// } else {
// body.custom_fields = validateJSON(this.getNodeParameter('customFielsJson') as string);
// }
if (options.name) {
body.name = options.name as string;
}
if (options.subject) {
body.subject = options.subject as string;
} else {
body.subject = 'null';
}
if (options.type) {
body.type = options.type as string;
}
if (options.description) {
body.description = options.description as string;
} else {
body.description = 'null';
}
if (options.agent) {
body.responder_id = options.agent as number;
}
if (options.company) {
body.company_id = options.company as number;
}
if (options.product) {
body.product_id = options.product as number;
}
if (options.group) {
body.group_id = options.group as number;
}
if (options.frDueBy) {
body.fr_due_by = options.frDueBy as string;
}
if (options.emailConfigId) {
body.email_config_id = options.emailConfigId as number;
}
if (options.dueBy) {
body.due_by = options.dueBy as string;
}
if (options.tags) {
body.tags = (options.tags as string).split(',') as [string];
}
if (options.ccEmails) {
body.cc_emails = (options.ccEmails as string).split(',') as [string];
}
responseData = await freshdeskApiRequest.call(this, 'POST', '/tickets', body);
}
//https://developers.freshdesk.com/api/#update_ticket
if (operation === 'update') {
const ticketId = this.getNodeParameter('ticketId', i) as string;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const body: ICreateTicketBody = {};
if (updateFields.requester) {
const value = updateFields.requesterIdentificationValue as string;
if (updateFields.requester === 'requesterId') {
// @ts-ignore
if (isNaN(parseInt(value, 10))) {
throw new NodeOperationError(this.getNode(), 'Requester Id must be a number');
}
body.requester_id = parseInt(value as string, 10);
} else if (updateFields.requester === 'email') {
body.email = value as string;
} else if (updateFields.requester === 'facebookId') {
body.facebook_id = value as string;
} else if (updateFields.requester === 'phone') {
body.phone = value as string;
} else if (updateFields.requester === 'twitterId') {
body.twitter_id = value as string;
} else if (updateFields.requester === 'uniqueExternalId') {
body.unique_external_id = value as string;
}
}
if (updateFields.status) {
//@ts-ignore
additionalFields.custom_fields[data.name as string] = data.value;
body.status = Status[capitalize(updateFields.status)];
}
delete additionalFields.customFields;
}
const body: ICreateContactBody = additionalFields;
body.name = name;
if (email) {
body.email = email;
}
responseData = await freshdeskApiRequest.call(this, 'POST', '/contacts', body);
//https://developers.freshdesk.com/api/#delete_contact
} else if (operation === 'delete') {
const contactId = this.getNodeParameter('contactId', i) as string;
responseData = await freshdeskApiRequest.call(this, 'DELETE', `/contacts/${contactId}`, {});
} else if (operation === 'get') {
const contactId = this.getNodeParameter('contactId', i) as string;
responseData = await freshdeskApiRequest.call(this, 'GET', `/contacts/${contactId}`, {});
//https://developers.freshdesk.com/api/#list_all_contacts
} else if (operation === 'getAll') {
const qs = this.getNodeParameter('filters', i, {}) as IDataObject;
responseData = await freshdeskApiRequest.call(this, 'GET', '/contacts', {}, qs);
//https://developers.freshdesk.com/api/#update_contact
} else if (operation === 'update') {
const contactId = this.getNodeParameter('contactId', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i, {}) as IDataObject;
if (additionalFields.customFields) {
const metadata = (additionalFields.customFields as IDataObject).customField as IDataObject[];
additionalFields.custom_fields = {};
for (const data of metadata) {
if (updateFields.priority) {
//@ts-ignore
additionalFields.custom_fields[data.name as string] = data.value;
body.priority = Priority[capitalize(updateFields.priority)];
}
delete additionalFields.customFields;
if (updateFields.source) {
//@ts-ignore
body.source = Source[capitalize(updateFields.source)];
}
if (updateFields.name) {
body.name = updateFields.name as string;
}
if (updateFields.type) {
body.type = updateFields.type as string;
}
if (updateFields.agent) {
body.responder_id = updateFields.agent as number;
}
if (updateFields.company) {
body.company_id = updateFields.company as number;
}
if (updateFields.product) {
body.product_id = updateFields.product as number;
}
if (updateFields.group) {
body.group_id = updateFields.group as number;
}
if (updateFields.frDueBy) {
body.fr_due_by = updateFields.frDueBy as string;
}
if (updateFields.emailConfigId) {
body.email_config_id = updateFields.emailConfigId as number;
}
if (updateFields.dueBy) {
body.due_by = updateFields.dueBy as string;
}
if (updateFields.tags) {
body.tags = (updateFields.tags as string).split(',') as [string];
}
if (updateFields.ccEmails) {
body.cc_emails = (updateFields.ccEmails as string).split(',') as [string];
}
responseData = await freshdeskApiRequest.call(this, 'PUT', `/tickets/${ticketId}`, body);
}
//https://developers.freshdesk.com/api/#view_a_ticket
if (operation === 'get') {
const ticketId = this.getNodeParameter('ticketId', i) as string;
responseData = await freshdeskApiRequest.call(this, 'GET', `/tickets/${ticketId}`);
}
//https://developers.freshdesk.com/api/#list_all_tickets
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const options = this.getNodeParameter('options', i) as IDataObject;
if (options.requesterId) {
qs.requester_id = options.requesterId as string;
}
if (options.requesterEmail) {
qs.email = options.requesterEmail as string;
}
if (options.companyId) {
qs.company_id = options.companyId as string;
}
if (options.updatedSince) {
qs.updated_since = options.updatedSince as string;
}
if (options.orderBy) {
qs.order_by = options.orderBy as string;
}
if (options.order) {
qs.order_type = options.order as string;
}
if (options.include) {
if ((options.include as string[]).length !== 0) {
qs.include = (options.include as string[]).join(',');
}
}
if (returnAll === true) {
responseData = await freshdeskApiRequestAllItems.call(this, 'GET', '/tickets', {}, qs);
} else {
qs.per_page = this.getNodeParameter('limit', i) as number;
responseData = await freshdeskApiRequest.call(this, 'GET', '/tickets', {}, qs);
}
}
//https://developers.freshdesk.com/api/#delete_a_ticket
if (operation === 'delete') {
const ticketId = this.getNodeParameter('ticketId', i) as string;
responseData = await freshdeskApiRequest.call(this, 'DELETE', `/tickets/${ticketId}`);
}
} else if (resource === 'contact') {
//https://developers.freshdesk.com/api/#create_contact
if (operation === 'create') {
const name = this.getNodeParameter('name', i) as string;
const email = this.getNodeParameter('email', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i, {}) as IDataObject;
if (additionalFields.customFields) {
const metadata = (additionalFields.customFields as IDataObject).customField as IDataObject[];
additionalFields.custom_fields = {};
for (const data of metadata) {
//@ts-ignore
additionalFields.custom_fields[data.name as string] = data.value;
}
delete additionalFields.customFields;
}
const body: ICreateContactBody = additionalFields;
body.name = name;
if (email) {
body.email = email;
}
responseData = await freshdeskApiRequest.call(this, 'POST', '/contacts', body);
//https://developers.freshdesk.com/api/#delete_contact
} else if (operation === 'delete') {
const contactId = this.getNodeParameter('contactId', i) as string;
responseData = await freshdeskApiRequest.call(this, 'DELETE', `/contacts/${contactId}`, {});
} else if (operation === 'get') {
const contactId = this.getNodeParameter('contactId', i) as string;
responseData = await freshdeskApiRequest.call(this, 'GET', `/contacts/${contactId}`, {});
//https://developers.freshdesk.com/api/#list_all_contacts
} else if (operation === 'getAll') {
const qs = this.getNodeParameter('filters', i, {}) as IDataObject;
responseData = await freshdeskApiRequest.call(this, 'GET', '/contacts', {}, qs);
//https://developers.freshdesk.com/api/#update_contact
} else if (operation === 'update') {
const contactId = this.getNodeParameter('contactId', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i, {}) as IDataObject;
if (additionalFields.customFields) {
const metadata = (additionalFields.customFields as IDataObject).customField as IDataObject[];
additionalFields.custom_fields = {};
for (const data of metadata) {
//@ts-ignore
additionalFields.custom_fields[data.name as string] = data.value;
}
delete additionalFields.customFields;
}
const body: ICreateContactBody = additionalFields;
responseData = await freshdeskApiRequest.call(this, 'PUT', `/contacts/${contactId}`, body);
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
if (responseData === undefined) {
responseData = {
success: true,
};
}
const body: ICreateContactBody = additionalFields;
responseData = await freshdeskApiRequest.call(this, 'PUT', `/contacts/${contactId}`, body);
returnData.push(responseData as IDataObject);
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
if (responseData === undefined) {
responseData = {
success: true,
};
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
returnData.push(responseData as IDataObject);
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];

View file

@ -378,263 +378,271 @@ export class Ftp implements INodeType {
} else {
credentials = this.getCredentials('ftp');
}
try {
if (credentials === undefined) {
throw new NodeOperationError(this.getNode(), 'Failed to get credentials!');
}
let ftp : ftpClient;
let sftp : sftpClient;
if (protocol === 'sftp') {
sftp = new sftpClient();
await sftp.connect({
host: credentials.host as string,
port: credentials.port as number,
username: credentials.username as string,
password: credentials.password as string,
privateKey: credentials.privateKey as string | undefined,
passphrase: credentials.passphrase as string | undefined,
});
} else {
ftp = new ftpClient();
await ftp.connect({
host: credentials.host as string,
port: credentials.port as number,
user: credentials.username as string,
password: credentials.password as string,
});
}
for (let i = 0; i < items.length; i++) {
const newItem: INodeExecutionData = {
json: items[i].json,
binary: {},
};
if (items[i].binary !== undefined) {
// Create a shallow copy of the binary data so that the old
// data references which do not get changed still stay behind
// but the incoming data does not get changed.
Object.assign(newItem.binary, items[i].binary);
if (credentials === undefined) {
throw new NodeOperationError(this.getNode(), 'Failed to get credentials!');
}
items[i] = newItem;
let ftp : ftpClient;
let sftp : sftpClient;
if (protocol === 'sftp') {
sftp = new sftpClient();
await sftp.connect({
host: credentials.host as string,
port: credentials.port as number,
username: credentials.username as string,
password: credentials.password as string,
privateKey: credentials.privateKey as string | undefined,
passphrase: credentials.passphrase as string | undefined,
});
if (operation === 'list') {
const path = this.getNodeParameter('path', i) as string;
} else {
ftp = new ftpClient();
await ftp.connect({
host: credentials.host as string,
port: credentials.port as number,
user: credentials.username as string,
password: credentials.password as string,
});
}
const recursive = this.getNodeParameter('recursive', i) as boolean;
for (let i = 0; i < items.length; i++) {
const newItem: INodeExecutionData = {
json: items[i].json,
binary: {},
};
if (recursive) {
responseData = await callRecursiveList(path, sftp!, normalizeSFtpItem);
returnItems.push.apply(returnItems, this.helpers.returnJsonArray(responseData as unknown as IDataObject[]));
} else {
responseData = await sftp!.list(path);
responseData.forEach(item => normalizeSFtpItem(item as sftpClient.FileInfo, path));
returnItems.push.apply(returnItems, this.helpers.returnJsonArray(responseData as unknown as IDataObject[]));
}
if (items[i].binary !== undefined) {
// Create a shallow copy of the binary data so that the old
// data references which do not get changed still stay behind
// but the incoming data does not get changed.
Object.assign(newItem.binary, items[i].binary);
}
if (operation === 'delete') {
const path = this.getNodeParameter('path', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
items[i] = newItem;
if (options.folder === true) {
responseData = await sftp!.rmdir(path, !!options.recursive);
} else {
responseData = await sftp!.delete(path);
if (protocol === 'sftp') {
if (operation === 'list') {
const path = this.getNodeParameter('path', i) as string;
const recursive = this.getNodeParameter('recursive', i) as boolean;
if (recursive) {
responseData = await callRecursiveList(path, sftp!, normalizeSFtpItem);
returnItems.push.apply(returnItems, this.helpers.returnJsonArray(responseData as unknown as IDataObject[]));
} else {
responseData = await sftp!.list(path);
responseData.forEach(item => normalizeSFtpItem(item as sftpClient.FileInfo, path));
returnItems.push.apply(returnItems, this.helpers.returnJsonArray(responseData as unknown as IDataObject[]));
}
}
returnItems.push({ json: { success: true } });
}
if (operation === 'delete') {
const path = this.getNodeParameter('path', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
if (operation === 'rename') {
const oldPath = this.getNodeParameter('oldPath', i) as string;
const newPath = this.getNodeParameter('newPath', i) as string;
responseData = await sftp!.rename(oldPath, newPath);
returnItems.push({ json: { success: true } });
}
if (operation === 'download') {
const path = this.getNodeParameter('path', i) as string;
responseData = await sftp!.get(path);
const dataPropertyNameDownload = this.getNodeParameter('binaryPropertyName', i) as string;
const filePathDownload = this.getNodeParameter('path', i) as string;
items[i].binary![dataPropertyNameDownload] = await this.helpers.prepareBinaryData(responseData as Buffer, filePathDownload);
returnItems.push(items[i]);
}
if (operation === 'upload') {
const remotePath = this.getNodeParameter('path', i) as string;
// Check if dir path exists
const dirPath = dirname(remotePath);
const dirExists = await sftp!.exists(dirPath);
// If dir does not exist, create all recursively in path
if (!dirExists) {
// Create directory
await sftp!.mkdir(dirPath, true);
}
if (this.getNodeParameter('binaryData', i) === true) {
// Is binary file to upload
const item = items[i];
if (item.binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
if (options.folder === true) {
responseData = await sftp!.rmdir(path, !!options.recursive);
} else {
responseData = await sftp!.delete(path);
}
const propertyNameUpload = this.getNodeParameter('binaryPropertyName', i) as string;
if (item.binary[propertyNameUpload] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property "${propertyNameUpload}" does not exists on item!`);
}
const buffer = Buffer.from(item.binary[propertyNameUpload].data, BINARY_ENCODING) as Buffer;
await sftp!.put(buffer, remotePath);
} else {
// Is text file
const buffer = Buffer.from(this.getNodeParameter('fileContent', i) as string, 'utf8') as Buffer;
await sftp!.put(buffer, remotePath);
returnItems.push({ json: { success: true } });
}
returnItems.push(items[i]);
if (operation === 'rename') {
const oldPath = this.getNodeParameter('oldPath', i) as string;
const newPath = this.getNodeParameter('newPath', i) as string;
responseData = await sftp!.rename(oldPath, newPath);
returnItems.push({ json: { success: true } });
}
if (operation === 'download') {
const path = this.getNodeParameter('path', i) as string;
responseData = await sftp!.get(path);
const dataPropertyNameDownload = this.getNodeParameter('binaryPropertyName', i) as string;
const filePathDownload = this.getNodeParameter('path', i) as string;
items[i].binary![dataPropertyNameDownload] = await this.helpers.prepareBinaryData(responseData as Buffer, filePathDownload);
returnItems.push(items[i]);
}
if (operation === 'upload') {
const remotePath = this.getNodeParameter('path', i) as string;
// Check if dir path exists
const dirPath = dirname(remotePath);
const dirExists = await sftp!.exists(dirPath);
// If dir does not exist, create all recursively in path
if (!dirExists) {
// Create directory
await sftp!.mkdir(dirPath, true);
}
if (this.getNodeParameter('binaryData', i) === true) {
// Is binary file to upload
const item = items[i];
if (item.binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
}
const propertyNameUpload = this.getNodeParameter('binaryPropertyName', i) as string;
if (item.binary[propertyNameUpload] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property "${propertyNameUpload}" does not exists on item!`);
}
const buffer = Buffer.from(item.binary[propertyNameUpload].data, BINARY_ENCODING) as Buffer;
await sftp!.put(buffer, remotePath);
} else {
// Is text file
const buffer = Buffer.from(this.getNodeParameter('fileContent', i) as string, 'utf8') as Buffer;
await sftp!.put(buffer, remotePath);
}
returnItems.push(items[i]);
}
}
if (protocol === 'ftp') {
if (operation === 'list') {
const path = this.getNodeParameter('path', i) as string;
const recursive = this.getNodeParameter('recursive', i) as boolean;
if (recursive) {
responseData = await callRecursiveList(path, ftp!, normalizeFtpItem);
returnItems.push.apply(returnItems, this.helpers.returnJsonArray(responseData as unknown as IDataObject[]));
} else {
responseData = await ftp!.list(path);
responseData.forEach(item => normalizeFtpItem(item as ftpClient.ListingElement, path));
returnItems.push.apply(returnItems, this.helpers.returnJsonArray(responseData as unknown as IDataObject[]));
}
}
if (operation === 'delete') {
const path = this.getNodeParameter('path', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
if (options.folder === true) {
responseData = await ftp!.rmdir(path, !!options.recursive);
} else {
responseData = await ftp!.delete(path);
}
returnItems.push({ json: { success: true } });
}
if (operation === 'download') {
const path = this.getNodeParameter('path', i) as string;
responseData = await ftp!.get(path);
// Convert readable stream to buffer so that can be displayed properly
const chunks = [];
for await (const chunk of responseData) {
chunks.push(chunk);
}
// @ts-ignore
responseData = Buffer.concat(chunks);
const dataPropertyNameDownload = this.getNodeParameter('binaryPropertyName', i) as string;
const filePathDownload = this.getNodeParameter('path', i) as string;
items[i].binary![dataPropertyNameDownload] = await this.helpers.prepareBinaryData(responseData, filePathDownload);
returnItems.push(items[i]);
}
if (operation === 'rename') {
const oldPath = this.getNodeParameter('oldPath', i) as string;
const newPath = this.getNodeParameter('newPath', i) as string;
responseData = await ftp!.rename(oldPath, newPath);
returnItems.push({ json: { success: true } });
}
if (operation === 'upload') {
const remotePath = this.getNodeParameter('path', i) as string;
const fileName = basename(remotePath);
const dirPath = remotePath.replace(fileName, '');
if (this.getNodeParameter('binaryData', i) === true) {
// Is binary file to upload
const item = items[i];
if (item.binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
}
const propertyNameUpload = this.getNodeParameter('binaryPropertyName', i) as string;
if (item.binary[propertyNameUpload] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property "${propertyNameUpload}" does not exists on item!`);
}
const buffer = Buffer.from(item.binary[propertyNameUpload].data, BINARY_ENCODING) as Buffer;
try {
await ftp!.put(buffer, remotePath);
} catch (error) {
if (error.code === 553) {
// Create directory
await ftp!.mkdir(dirPath, true);
await ftp!.put(buffer, remotePath);
} else {
throw new NodeApiError(this.getNode(), error);
}
}
} else {
// Is text file
const buffer = Buffer.from(this.getNodeParameter('fileContent', i) as string, 'utf8') as Buffer;
try {
await ftp!.put(buffer, remotePath);
} catch (error) {
if (error.code === 553) {
// Create directory
await ftp!.mkdir(dirPath, true);
await ftp!.put(buffer, remotePath);
} else {
throw new NodeApiError(this.getNode(), error);
}
}
}
returnItems.push(items[i]);
}
}
}
if (protocol === 'ftp') {
if (operation === 'list') {
const path = this.getNodeParameter('path', i) as string;
const recursive = this.getNodeParameter('recursive', i) as boolean;
if (recursive) {
responseData = await callRecursiveList(path, ftp!, normalizeFtpItem);
returnItems.push.apply(returnItems, this.helpers.returnJsonArray(responseData as unknown as IDataObject[]));
} else {
responseData = await ftp!.list(path);
responseData.forEach(item => normalizeFtpItem(item as ftpClient.ListingElement, path));
returnItems.push.apply(returnItems, this.helpers.returnJsonArray(responseData as unknown as IDataObject[]));
}
}
if (operation === 'delete') {
const path = this.getNodeParameter('path', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
if (options.folder === true) {
responseData = await ftp!.rmdir(path, !!options.recursive);
} else {
responseData = await ftp!.delete(path);
}
returnItems.push({ json: { success: true } });
}
if (operation === 'download') {
const path = this.getNodeParameter('path', i) as string;
responseData = await ftp!.get(path);
// Convert readable stream to buffer so that can be displayed properly
const chunks = [];
for await (const chunk of responseData) {
chunks.push(chunk);
}
// @ts-ignore
responseData = Buffer.concat(chunks);
const dataPropertyNameDownload = this.getNodeParameter('binaryPropertyName', i) as string;
const filePathDownload = this.getNodeParameter('path', i) as string;
items[i].binary![dataPropertyNameDownload] = await this.helpers.prepareBinaryData(responseData, filePathDownload);
returnItems.push(items[i]);
}
if (operation === 'rename') {
const oldPath = this.getNodeParameter('oldPath', i) as string;
const newPath = this.getNodeParameter('newPath', i) as string;
responseData = await ftp!.rename(oldPath, newPath);
returnItems.push({ json: { success: true } });
}
if (operation === 'upload') {
const remotePath = this.getNodeParameter('path', i) as string;
const fileName = basename(remotePath);
const dirPath = remotePath.replace(fileName, '');
if (this.getNodeParameter('binaryData', i) === true) {
// Is binary file to upload
const item = items[i];
if (item.binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
}
const propertyNameUpload = this.getNodeParameter('binaryPropertyName', i) as string;
if (item.binary[propertyNameUpload] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property "${propertyNameUpload}" does not exists on item!`);
}
const buffer = Buffer.from(item.binary[propertyNameUpload].data, BINARY_ENCODING) as Buffer;
try {
await ftp!.put(buffer, remotePath);
} catch (error) {
if (error.code === 553) {
// Create directory
await ftp!.mkdir(dirPath, true);
await ftp!.put(buffer, remotePath);
} else {
throw new NodeApiError(this.getNode(), error);
}
}
} else {
// Is text file
const buffer = Buffer.from(this.getNodeParameter('fileContent', i) as string, 'utf8') as Buffer;
try {
await ftp!.put(buffer, remotePath);
} catch (error) {
if (error.code === 553) {
// Create directory
await ftp!.mkdir(dirPath, true);
await ftp!.put(buffer, remotePath);
} else {
throw new NodeApiError(this.getNode(), error);
}
}
}
returnItems.push(items[i]);
}
if (protocol === 'sftp') {
await sftp!.end();
} else {
await ftp!.end();
}
}
if (protocol === 'sftp') {
await sftp!.end();
} else {
await ftp!.end();
}
} catch (error) {
if (this.continueOnFail()) {
return this.prepareOutputData([{json:{ error: error.message }}]);
}
throw error;
}
return [returnItems];
}
}

View file

@ -102,32 +102,37 @@ return items;`,
try {
// Execute the function code
items = (await vm.run(`module.exports = async function() {${functionCode}}()`, __dirname));
} catch (error) {
return Promise.reject(error);
}
// Do very basic validation of the data
if (items === undefined) {
throw new NodeOperationError(this.getNode(), 'No data got returned. Always return an Array of items!');
}
if (!Array.isArray(items)) {
throw new NodeOperationError(this.getNode(), 'Always an Array of items has to be returned!');
}
for (const item of items) {
if (item.json === undefined) {
throw new NodeOperationError(this.getNode(), 'All returned items have to contain a property named "json"!');
// Do very basic validation of the data
if (items === undefined) {
throw new NodeOperationError(this.getNode(), 'No data got returned. Always return an Array of items!');
}
if (typeof item.json !== 'object') {
throw new NodeOperationError(this.getNode(), 'The json-property has to be an object!');
if (!Array.isArray(items)) {
throw new NodeOperationError(this.getNode(), 'Always an Array of items has to be returned!');
}
if (item.binary !== undefined) {
if (Array.isArray(item.binary) || typeof item.binary !== 'object') {
throw new NodeOperationError(this.getNode(), 'The binary-property has to be an object!');
for (const item of items) {
if (item.json === undefined) {
throw new NodeOperationError(this.getNode(), 'All returned items have to contain a property named "json"!');
}
if (typeof item.json !== 'object') {
throw new NodeOperationError(this.getNode(), 'The json-property has to be an object!');
}
if (item.binary !== undefined) {
if (Array.isArray(item.binary) || typeof item.binary !== 'object') {
throw new NodeOperationError(this.getNode(), 'The binary-property has to be an object!');
}
}
}
} catch (error) {
if (this.continueOnFail()) {
items=[{json:{ error: error.message }}];
} else {
return Promise.reject(error);
}
}
return this.prepareOutputData(items);
}
}

View file

@ -58,80 +58,92 @@ return item;`,
let item: INodeExecutionData;
for (let itemIndex = 0; itemIndex < length; itemIndex++) {
item = items[itemIndex];
// Copy the items as they may get changed in the functions
item = JSON.parse(JSON.stringify(item));
// Define the global objects for the custom function
const sandbox = {
getBinaryData: (): IBinaryKeyData | undefined => {
return item.binary;
},
getNodeParameter: this.getNodeParameter,
getWorkflowStaticData: this.getWorkflowStaticData,
helpers: this.helpers,
item: item.json,
setBinaryData: (data: IBinaryKeyData) => {
item.binary = data;
},
};
// Make it possible to access data via $node, $parameter, ...
const dataProxy = this.getWorkflowDataProxy(itemIndex);
Object.assign(sandbox, dataProxy);
const mode = this.getMode();
const options = {
console: (mode === 'manual') ? 'redirect' : 'inherit',
sandbox,
require: {
external: false as boolean | { modules: string[] },
builtin: [] as string[],
},
};
if (process.env.NODE_FUNCTION_ALLOW_BUILTIN) {
options.require.builtin = process.env.NODE_FUNCTION_ALLOW_BUILTIN.split(',');
}
if (process.env.NODE_FUNCTION_ALLOW_EXTERNAL) {
options.require.external = { modules: process.env.NODE_FUNCTION_ALLOW_EXTERNAL.split(',') };
}
const vm = new NodeVM(options);
if (mode === 'manual') {
vm.on('console.log', this.sendMessageToUI);
}
// Get the code to execute
const functionCode = this.getNodeParameter('functionCode', itemIndex) as string;
let jsonData: IDataObject;
try {
// Execute the function code
jsonData = await vm.run(`module.exports = async function() {${functionCode}}()`, __dirname);
item = items[itemIndex];
// Copy the items as they may get changed in the functions
item = JSON.parse(JSON.stringify(item));
// Define the global objects for the custom function
const sandbox = {
getBinaryData: (): IBinaryKeyData | undefined => {
return item.binary;
},
getNodeParameter: this.getNodeParameter,
getWorkflowStaticData: this.getWorkflowStaticData,
helpers: this.helpers,
item: item.json,
setBinaryData: (data: IBinaryKeyData) => {
item.binary = data;
},
};
// Make it possible to access data via $node, $parameter, ...
const dataProxy = this.getWorkflowDataProxy(itemIndex);
Object.assign(sandbox, dataProxy);
const mode = this.getMode();
const options = {
console: (mode === 'manual') ? 'redirect' : 'inherit',
sandbox,
require: {
external: false as boolean | { modules: string[] },
builtin: [] as string[],
},
};
if (process.env.NODE_FUNCTION_ALLOW_BUILTIN) {
options.require.builtin = process.env.NODE_FUNCTION_ALLOW_BUILTIN.split(',');
}
if (process.env.NODE_FUNCTION_ALLOW_EXTERNAL) {
options.require.external = { modules: process.env.NODE_FUNCTION_ALLOW_EXTERNAL.split(',') };
}
const vm = new NodeVM(options);
if (mode === 'manual') {
vm.on('console.log', this.sendMessageToUI);
}
// Get the code to execute
const functionCode = this.getNodeParameter('functionCode', itemIndex) as string;
let jsonData: IDataObject;
try {
// Execute the function code
jsonData = await vm.run(`module.exports = async function() {${functionCode}}()`, __dirname);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({json:{ error: error.message }});
continue;
} else {
return Promise.reject(error);
}
}
// Do very basic validation of the data
if (jsonData === undefined) {
throw new NodeOperationError(this.getNode(), 'No data got returned. Always an object has to be returned!');
}
const returnItem: INodeExecutionData = {
json: jsonData,
};
if (item.binary) {
returnItem.binary = item.binary;
}
returnData.push(returnItem);
} catch (error) {
return Promise.reject(error);
if (this.continueOnFail()) {
returnData.push({json:{ error: error.message }});
continue;
}
throw error;
}
// Do very basic validation of the data
if (jsonData === undefined) {
throw new NodeOperationError(this.getNode(), 'No data got returned. Always an object has to be returned!');
}
const returnItem: INodeExecutionData = {
json: jsonData,
};
if (item.binary) {
returnItem.binary = item.binary;
}
returnData.push(returnItem);
}
return this.prepareOutputData(returnData);
}

View file

@ -169,150 +169,157 @@ export class GetResponse implements INodeType {
const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string;
for (let i = 0; i < length; i++) {
try {
if (resource === 'contact') {
//https://apireference.getresponse.com/#operation/createContact
if (operation === 'create') {
const email = this.getNodeParameter('email', i) as string;
if (resource === 'contact') {
//https://apireference.getresponse.com/#operation/createContact
if (operation === 'create') {
const email = this.getNodeParameter('email', i) as string;
const campaignId = this.getNodeParameter('campaignId', i) as string;
const campaignId = this.getNodeParameter('campaignId', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IDataObject = {
email,
campaign: {
campaignId,
},
};
const body: IDataObject = {
email,
campaign: {
campaignId,
},
};
Object.assign(body, additionalFields);
Object.assign(body, additionalFields);
if (additionalFields.customFieldsUi) {
const customFieldValues = (additionalFields.customFieldsUi as IDataObject).customFieldValues as IDataObject[];
if (customFieldValues) {
body.customFieldValues = customFieldValues;
for (let i = 0; i < customFieldValues.length; i++) {
if (!Array.isArray(customFieldValues[i].value)) {
customFieldValues[i].value = [customFieldValues[i].value];
if (additionalFields.customFieldsUi) {
const customFieldValues = (additionalFields.customFieldsUi as IDataObject).customFieldValues as IDataObject[];
if (customFieldValues) {
body.customFieldValues = customFieldValues;
for (let i = 0; i < customFieldValues.length; i++) {
if (!Array.isArray(customFieldValues[i].value)) {
customFieldValues[i].value = [customFieldValues[i].value];
}
}
delete body.customFieldsUi;
}
delete body.customFieldsUi;
}
responseData = await getresponseApiRequest.call(this, 'POST', '/contacts', body);
responseData = { success: true };
}
//https://apireference.getresponse.com/?_ga=2.160836350.2102802044.1604719933-1897033509.1604598019#operation/deleteContact
if (operation === 'delete') {
const contactId = this.getNodeParameter('contactId', i) as string;
responseData = await getresponseApiRequest.call(this, 'POST', '/contacts', body);
const options = this.getNodeParameter('options', i) as IDataObject;
responseData = { success: true };
}
//https://apireference.getresponse.com/?_ga=2.160836350.2102802044.1604719933-1897033509.1604598019#operation/deleteContact
if (operation === 'delete') {
const contactId = this.getNodeParameter('contactId', i) as string;
Object.assign(qs, options);
const options = this.getNodeParameter('options', i) as IDataObject;
responseData = await getresponseApiRequest.call(this, 'DELETE', `/contacts/${contactId}`, {}, qs);
Object.assign(qs, options);
responseData = { success: true };
}
//https://apireference.getresponse.com/?_ga=2.160836350.2102802044.1604719933-1897033509.1604598019#operation/getContactById
if (operation === 'get') {
const contactId = this.getNodeParameter('contactId', i) as string;
responseData = await getresponseApiRequest.call(this, 'DELETE', `/contacts/${contactId}`, {}, qs);
const options = this.getNodeParameter('options', i) as IDataObject;
responseData = { success: true };
}
//https://apireference.getresponse.com/?_ga=2.160836350.2102802044.1604719933-1897033509.1604598019#operation/getContactById
if (operation === 'get') {
const contactId = this.getNodeParameter('contactId', i) as string;
Object.assign(qs, options);
const options = this.getNodeParameter('options', i) as IDataObject;
responseData = await getresponseApiRequest.call(this, 'GET', `/contacts/${contactId}`, {}, qs);
}
//https://apireference.getresponse.com/?_ga=2.160836350.2102802044.1604719933-1897033509.1604598019#operation/getContactList
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
Object.assign(qs, options);
const options = this.getNodeParameter('options', i) as IDataObject;
responseData = await getresponseApiRequest.call(this, 'GET', `/contacts/${contactId}`, {}, qs);
}
//https://apireference.getresponse.com/?_ga=2.160836350.2102802044.1604719933-1897033509.1604598019#operation/getContactList
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const timezone = this.getTimezone();
const options = this.getNodeParameter('options', i) as IDataObject;
Object.assign(qs, options);
const timezone = this.getTimezone();
const isNotQuery = [
'sortBy',
'sortOrder',
'additionalFlags',
'fields',
'exactMatch',
];
Object.assign(qs, options);
const isDate = [
'createdOnFrom',
'createdOnTo',
'changeOnFrom',
'changeOnTo',
];
const isNotQuery = [
'sortBy',
'sortOrder',
'additionalFlags',
'fields',
'exactMatch',
];
const dateMapToKey: { [key: string]: string; } = {
'createdOnFrom': '[createdOn][from]',
'createdOnTo': '[createdOn][to]',
'changeOnFrom': '[changeOn][from]',
'changeOnTo': '[changeOn][to]',
};
const isDate = [
'createdOnFrom',
'createdOnTo',
'changeOnFrom',
'changeOnTo',
];
const dateMapToKey: { [key: string]: string; } = {
'createdOnFrom': '[createdOn][from]',
'createdOnTo': '[createdOn][to]',
'changeOnFrom': '[changeOn][from]',
'changeOnTo': '[changeOn][to]',
};
for (const key of Object.keys(qs)) {
if (!isNotQuery.includes(key)) {
if (isDate.includes(key)) {
qs[`query${dateMapToKey[key]}`] = moment.tz(qs[key], timezone).format('YYYY-MM-DDTHH:mm:ssZZ');
} else {
qs[`query[${key}]`] = qs[key];
for (const key of Object.keys(qs)) {
if (!isNotQuery.includes(key)) {
if (isDate.includes(key)) {
qs[`query${dateMapToKey[key]}`] = moment.tz(qs[key], timezone).format('YYYY-MM-DDTHH:mm:ssZZ');
} else {
qs[`query[${key}]`] = qs[key];
}
delete qs[key];
}
delete qs[key];
}
if (qs.sortBy) {
qs[`sort[${qs.sortBy}]`] = qs.sortOrder || 'ASC';
}
if (qs.exactMatch === true) {
qs['additionalFlags'] = 'exactMatch';
delete qs.exactMatch;
}
if (returnAll) {
responseData = await getResponseApiRequestAllItems.call(this, 'GET', `/contacts`, {}, qs);
} else {
qs.perPage = this.getNodeParameter('limit', i) as number;
responseData = await getresponseApiRequest.call(this, 'GET', `/contacts`, {}, qs);
}
}
//https://apireference.getresponse.com/?_ga=2.160836350.2102802044.1604719933-1897033509.1604598019#operation/updateContact
if (operation === 'update') {
if (qs.sortBy) {
qs[`sort[${qs.sortBy}]`] = qs.sortOrder || 'ASC';
}
const contactId = this.getNodeParameter('contactId', i) as string;
if (qs.exactMatch === true) {
qs['additionalFlags'] = 'exactMatch';
delete qs.exactMatch;
}
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
if (returnAll) {
responseData = await getResponseApiRequestAllItems.call(this, 'GET', `/contacts`, {}, qs);
} else {
qs.perPage = this.getNodeParameter('limit', i) as number;
responseData = await getresponseApiRequest.call(this, 'GET', `/contacts`, {}, qs);
}
}
//https://apireference.getresponse.com/?_ga=2.160836350.2102802044.1604719933-1897033509.1604598019#operation/updateContact
if (operation === 'update') {
const body: IDataObject = {};
const contactId = this.getNodeParameter('contactId', i) as string;
Object.assign(body, updateFields);
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const body: IDataObject = {};
Object.assign(body, updateFields);
if (updateFields.customFieldsUi) {
const customFieldValues = (updateFields.customFieldsUi as IDataObject).customFieldValues as IDataObject[];
if (customFieldValues) {
body.customFieldValues = customFieldValues;
delete body.customFieldsUi;
if (updateFields.customFieldsUi) {
const customFieldValues = (updateFields.customFieldsUi as IDataObject).customFieldValues as IDataObject[];
if (customFieldValues) {
body.customFieldValues = customFieldValues;
delete body.customFieldsUi;
}
}
responseData = await getresponseApiRequest.call(this, 'POST', `/contacts/${contactId}`, body);
}
responseData = await getresponseApiRequest.call(this, 'POST', `/contacts/${contactId}`, body);
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else if (responseData !== undefined) {
returnData.push(responseData as IDataObject);
} else if (responseData !== undefined) {
returnData.push(responseData as IDataObject);
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];

View file

@ -156,196 +156,204 @@ export class Ghost implements INodeType {
const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string;
const source = this.getNodeParameter('source', 0) as string;
for (let i = 0; i < length; i++) {
try {
if (source === 'contentApi') {
if (resource === 'post') {
if (operation === 'get') {
if (source === 'contentApi') {
if (resource === 'post') {
if (operation === 'get') {
for (let i = 0; i < items.length; i++) {
const by = this.getNodeParameter('by', i) as string;
const by = this.getNodeParameter('by', i) as string;
const identifier = this.getNodeParameter('identifier', i) as string;
const identifier = this.getNodeParameter('identifier', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
const options = this.getNodeParameter('options', i) as IDataObject;
Object.assign(qs, options);
Object.assign(qs, options);
let endpoint;
let endpoint;
if (by === 'slug') {
endpoint = `/content/posts/slug/${identifier}`;
} else {
endpoint = `/content/posts/${identifier}`;
}
responseData = await ghostApiRequest.call(this, 'GET', endpoint, {}, qs);
returnData.push.apply(returnData, responseData.posts);
}
}
if (operation === 'getAll') {
for (let i = 0; i < items.length; i++) {
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const options = this.getNodeParameter('options', i) as IDataObject;
Object.assign(qs, options);
if (returnAll) {
responseData = await ghostApiRequestAllItems.call(this, 'posts', 'GET', '/content/posts', {} ,qs);
} else {
qs.limit = this.getNodeParameter('limit', 0);
responseData = await ghostApiRequest.call(this, 'GET', '/content/posts', {}, qs);
responseData = responseData.posts;
}
returnData.push.apply(returnData, responseData);
}
}
}
}
if (source === 'adminApi') {
if (resource === 'post') {
if (operation === 'create') {
for (let i = 0; i < length; i++) {
const title = this.getNodeParameter('title', i) as string;
const contentFormat = this.getNodeParameter('contentFormat', i) as string;
const content = this.getNodeParameter('content', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const post: IDataObject = {
title,
};
if (contentFormat === 'html') {
post.html = content;
qs.source = 'html';
} else {
const mobileDoc = validateJSON(content);
if (mobileDoc === undefined) {
throw new NodeOperationError(this.getNode(), 'Content must be a valid JSON');
if (by === 'slug') {
endpoint = `/content/posts/slug/${identifier}`;
} else {
endpoint = `/content/posts/${identifier}`;
}
post.mobiledoc = content;
responseData = await ghostApiRequest.call(this, 'GET', endpoint, {}, qs);
returnData.push.apply(returnData, responseData.posts);
}
delete post.content;
if (operation === 'getAll') {
Object.assign(post, additionalFields);
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
if (post.published_at) {
post.published_at = moment.tz(post.published_at, timezone).utc().format();
}
const options = this.getNodeParameter('options', i) as IDataObject;
if (post.status === 'scheduled' && post.published_at === undefined) {
throw new NodeOperationError(this.getNode(), 'Published at must be define when status is scheduled');
}
Object.assign(qs, options);
responseData = await ghostApiRequest.call(this, 'POST', '/admin/posts', { posts: [post] }, qs);
returnData.push.apply(returnData, responseData.posts);
}
}
if (operation === 'delete') {
for (let i = 0; i < length; i++) {
const postId = this.getNodeParameter('postId', i) as string;
responseData = await ghostApiRequest.call(this, 'DELETE', `/admin/posts/${postId}`);
returnData.push({ success: true });
}
}
if (operation === 'get') {
for (let i = 0; i < length; i++) {
const by = this.getNodeParameter('by', i) as string;
const identifier = this.getNodeParameter('identifier', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
Object.assign(qs, options);
let endpoint;
if (by === 'slug') {
endpoint = `/admin/posts/slug/${identifier}`;
} else {
endpoint = `/admin/posts/${identifier}`;
}
responseData = await ghostApiRequest.call(this, 'GET', endpoint, {}, qs);
returnData.push.apply(returnData, responseData.posts);
}
}
if (operation === 'getAll') {
for (let i = 0; i < length; i++) {
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const options = this.getNodeParameter('options', i) as IDataObject;
Object.assign(qs, options);
if (returnAll) {
responseData = await ghostApiRequestAllItems.call(this, 'posts', 'GET', '/admin/posts', {} ,qs);
} else {
qs.limit = this.getNodeParameter('limit', 0);
responseData = await ghostApiRequest.call(this, 'GET', '/admin/posts', {}, qs);
responseData = responseData.posts;
}
returnData.push.apply(returnData, responseData);
}
}
if (operation === 'update') {
for (let i = 0; i < length; i++) {
const postId = this.getNodeParameter('postId', i) as string;
const contentFormat = this.getNodeParameter('contentFormat', i) as string;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const post: IDataObject = {};
if (contentFormat === 'html') {
post.html = updateFields.content || '';
qs.source = 'html';
delete updateFields.content;
} else {
const mobileDoc = validateJSON(updateFields.contentJson as string || undefined);
if (mobileDoc === undefined) {
throw new NodeOperationError(this.getNode(), 'Content must be a valid JSON');
if (returnAll) {
responseData = await ghostApiRequestAllItems.call(this, 'posts', 'GET', '/content/posts', {} ,qs);
} else {
qs.limit = this.getNodeParameter('limit', 0);
responseData = await ghostApiRequest.call(this, 'GET', '/content/posts', {}, qs);
responseData = responseData.posts;
}
post.mobiledoc = updateFields.contentJson;
delete updateFields.contentJson;
returnData.push.apply(returnData, responseData);
}
Object.assign(post, updateFields);
const { posts } = await ghostApiRequest.call(this, 'GET', `/admin/posts/${postId}`, {}, { fields: 'id, updated_at' });
if (post.published_at) {
post.published_at = moment.tz(post.published_at, timezone).utc().format();
}
if (post.status === 'scheduled' && post.published_at === undefined) {
throw new NodeOperationError(this.getNode(), 'Published at must be define when status is scheduled');
}
post.updated_at = posts[0].updated_at;
responseData = await ghostApiRequest.call(this, 'PUT', `/admin/posts/${postId}`, { posts: [post] }, qs);
returnData.push.apply(returnData, responseData.posts);
}
}
if (source === 'adminApi') {
if (resource === 'post') {
if (operation === 'create') {
const title = this.getNodeParameter('title', i) as string;
const contentFormat = this.getNodeParameter('contentFormat', i) as string;
const content = this.getNodeParameter('content', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const post: IDataObject = {
title,
};
if (contentFormat === 'html') {
post.html = content;
qs.source = 'html';
} else {
const mobileDoc = validateJSON(content);
if (mobileDoc === undefined) {
throw new NodeOperationError(this.getNode(), 'Content must be a valid JSON');
}
post.mobiledoc = content;
}
delete post.content;
Object.assign(post, additionalFields);
if (post.published_at) {
post.published_at = moment.tz(post.published_at, timezone).utc().format();
}
if (post.status === 'scheduled' && post.published_at === undefined) {
throw new NodeOperationError(this.getNode(), 'Published at must be define when status is scheduled');
}
responseData = await ghostApiRequest.call(this, 'POST', '/admin/posts', { posts: [post] }, qs);
returnData.push.apply(returnData, responseData.posts);
}
if (operation === 'delete') {
const postId = this.getNodeParameter('postId', i) as string;
responseData = await ghostApiRequest.call(this, 'DELETE', `/admin/posts/${postId}`);
returnData.push({ success: true });
}
if (operation === 'get') {
const by = this.getNodeParameter('by', i) as string;
const identifier = this.getNodeParameter('identifier', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
Object.assign(qs, options);
let endpoint;
if (by === 'slug') {
endpoint = `/admin/posts/slug/${identifier}`;
} else {
endpoint = `/admin/posts/${identifier}`;
}
responseData = await ghostApiRequest.call(this, 'GET', endpoint, {}, qs);
returnData.push.apply(returnData, responseData.posts);
}
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const options = this.getNodeParameter('options', i) as IDataObject;
Object.assign(qs, options);
if (returnAll) {
responseData = await ghostApiRequestAllItems.call(this, 'posts', 'GET', '/admin/posts', {} ,qs);
} else {
qs.limit = this.getNodeParameter('limit', 0);
responseData = await ghostApiRequest.call(this, 'GET', '/admin/posts', {}, qs);
responseData = responseData.posts;
}
returnData.push.apply(returnData, responseData);
}
if (operation === 'update') {
const postId = this.getNodeParameter('postId', i) as string;
const contentFormat = this.getNodeParameter('contentFormat', i) as string;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const post: IDataObject = {};
if (contentFormat === 'html') {
post.html = updateFields.content || '';
qs.source = 'html';
delete updateFields.content;
} else {
const mobileDoc = validateJSON(updateFields.contentJson as string || undefined);
if (mobileDoc === undefined) {
throw new NodeOperationError(this.getNode(), 'Content must be a valid JSON');
}
post.mobiledoc = updateFields.contentJson;
delete updateFields.contentJson;
}
Object.assign(post, updateFields);
const { posts } = await ghostApiRequest.call(this, 'GET', `/admin/posts/${postId}`, {}, { fields: 'id, updated_at' });
if (post.published_at) {
post.published_at = moment.tz(post.published_at, timezone).utc().format();
}
if (post.status === 'scheduled' && post.published_at === undefined) {
throw new NodeOperationError(this.getNode(), 'Published at must be define when status is scheduled');
}
post.updated_at = posts[0].updated_at;
responseData = await ghostApiRequest.call(this, 'PUT', `/admin/posts/${postId}`, { posts: [post] }, qs);
returnData.push.apply(returnData, responseData.posts);
}
}
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];

View file

@ -1754,421 +1754,434 @@ export class Github implements INodeType {
const fullOperation = `${resource}:${operation}`;
for (let i = 0; i < items.length; i++) {
// Reset all values
requestMethod = 'GET';
endpoint = '';
body = {};
qs = {};
try {
// Reset all values
requestMethod = 'GET';
endpoint = '';
body = {};
qs = {};
let owner = '';
if (fullOperation !== 'user:invite') {
// Request the parameters which almost all operations need
owner = this.getNodeParameter('owner', i) as string;
}
let owner = '';
if (fullOperation !== 'user:invite') {
// Request the parameters which almost all operations need
owner = this.getNodeParameter('owner', i) as string;
}
let repository = '';
if (fullOperation !== 'user:getRepositories' && fullOperation !== 'user:invite') {
repository = this.getNodeParameter('repository', i) as string;
}
let repository = '';
if (fullOperation !== 'user:getRepositories' && fullOperation !== 'user:invite') {
repository = this.getNodeParameter('repository', i) as string;
}
if (resource === 'file') {
if (['create', 'edit'].includes(operation)) {
// ----------------------------------
// create/edit
// ----------------------------------
if (resource === 'file') {
if (['create', 'edit'].includes(operation)) {
// ----------------------------------
// create/edit
// ----------------------------------
requestMethod = 'PUT';
requestMethod = 'PUT';
const filePath = this.getNodeParameter('filePath', i) as string;
const filePath = this.getNodeParameter('filePath', i) as string;
const additionalParameters = this.getNodeParameter('additionalParameters', i, {}) as IDataObject;
if (additionalParameters.author) {
body.author = additionalParameters.author;
}
if (additionalParameters.committer) {
body.committer = additionalParameters.committer;
}
if (additionalParameters.branch && (additionalParameters.branch as IDataObject).branch) {
body.branch = (additionalParameters.branch as IDataObject).branch;
}
if (operation === 'edit') {
// If the file should be updated the request has to contain the SHA
// of the file which gets replaced.
body.sha = await getFileSha.call(this, owner, repository, filePath, body.branch as string | undefined);
}
body.message = this.getNodeParameter('commitMessage', i) as string;
if (this.getNodeParameter('binaryData', i) === true) {
// Is binary file to upload
const item = items[i];
if (item.binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
const additionalParameters = this.getNodeParameter('additionalParameters', i, {}) as IDataObject;
if (additionalParameters.author) {
body.author = additionalParameters.author;
}
if (additionalParameters.committer) {
body.committer = additionalParameters.committer;
}
if (additionalParameters.branch && (additionalParameters.branch as IDataObject).branch) {
body.branch = (additionalParameters.branch as IDataObject).branch;
}
if (operation === 'edit') {
// If the file should be updated the request has to contain the SHA
// of the file which gets replaced.
body.sha = await getFileSha.call(this, owner, repository, filePath, body.branch as string | undefined);
}
body.message = this.getNodeParameter('commitMessage', i) as string;
if (this.getNodeParameter('binaryData', i) === true) {
// Is binary file to upload
const item = items[i];
if (item.binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
}
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i) as string;
if (item.binary[binaryPropertyName] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property "${binaryPropertyName}" does not exists on item!`);
}
// Currently internally n8n uses base64 and also Github expects it base64 encoded.
// If that ever changes the data has to get converted here.
body.content = item.binary[binaryPropertyName].data;
} else {
// Is text file
// body.content = Buffer.from(this.getNodeParameter('fileContent', i) as string, 'base64');
body.content = Buffer.from(this.getNodeParameter('fileContent', i) as string).toString('base64');
}
endpoint = `/repos/${owner}/${repository}/contents/${encodeURI(filePath)}`;
} else if (operation === 'delete') {
// ----------------------------------
// delete
// ----------------------------------
requestMethod = 'DELETE';
const additionalParameters = this.getNodeParameter('additionalParameters', i, {}) as IDataObject;
if (additionalParameters.author) {
body.author = additionalParameters.author;
}
if (additionalParameters.committer) {
body.committer = additionalParameters.committer;
}
if (additionalParameters.branch && (additionalParameters.branch as IDataObject).branch) {
body.branch = (additionalParameters.branch as IDataObject).branch;
}
const filePath = this.getNodeParameter('filePath', i) as string;
body.message = this.getNodeParameter('commitMessage', i) as string;
body.sha = await getFileSha.call(this, owner, repository, filePath, body.branch as string | undefined);
endpoint = `/repos/${owner}/${repository}/contents/${encodeURI(filePath)}`;
} else if (operation === 'get') {
requestMethod = 'GET';
const filePath = this.getNodeParameter('filePath', i) as string;
endpoint = `/repos/${owner}/${repository}/contents/${encodeURI(filePath)}`;
}
} else if (resource === 'issue') {
if (operation === 'create') {
// ----------------------------------
// create
// ----------------------------------
requestMethod = 'POST';
body.title = this.getNodeParameter('title', i) as string;
body.body = this.getNodeParameter('body', i) as string;
const labels = this.getNodeParameter('labels', i) as IDataObject[];
const assignees = this.getNodeParameter('assignees', i) as IDataObject[];
body.labels = labels.map((data) => data['label']);
body.assignees = assignees.map((data) => data['assignee']);
endpoint = `/repos/${owner}/${repository}/issues`;
} else if (operation === 'createComment') {
// ----------------------------------
// createComment
// ----------------------------------
requestMethod = 'POST';
const issueNumber = this.getNodeParameter('issueNumber', i) as string;
body.body = this.getNodeParameter('body', i) as string;
endpoint = `/repos/${owner}/${repository}/issues/${issueNumber}/comments`;
} else if (operation === 'edit') {
// ----------------------------------
// edit
// ----------------------------------
requestMethod = 'PATCH';
const issueNumber = this.getNodeParameter('issueNumber', i) as string;
body = this.getNodeParameter('editFields', i, {}) as IDataObject;
if (body.labels !== undefined) {
body.labels = (body.labels as IDataObject[]).map((data) => data['label']);
}
if (body.assignees !== undefined) {
body.assignees = (body.assignees as IDataObject[]).map((data) => data['assignee']);
}
endpoint = `/repos/${owner}/${repository}/issues/${issueNumber}`;
} else if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
requestMethod = 'GET';
const issueNumber = this.getNodeParameter('issueNumber', i) as string;
endpoint = `/repos/${owner}/${repository}/issues/${issueNumber}`;
} else if (operation === 'lock') {
// ----------------------------------
// lock
// ----------------------------------
requestMethod = 'PUT';
const issueNumber = this.getNodeParameter('issueNumber', i) as string;
qs.lock_reason = this.getNodeParameter('lockReason', i) as string;
endpoint = `/repos/${owner}/${repository}/issues/${issueNumber}/lock`;
}
} else if (resource === 'release') {
if (operation === 'create') {
// ----------------------------------
// create
// ----------------------------------
requestMethod = 'POST';
body = this.getNodeParameter('additionalFields', i, {}) as IDataObject;
body.tag_name = this.getNodeParameter('releaseTag', i) as string;
endpoint = `/repos/${owner}/${repository}/releases`;
}
if (operation === 'delete') {
// ----------------------------------
// delete
// ----------------------------------
requestMethod = 'DELETE';
const releaseId = this.getNodeParameter('release_id', i) as string;
endpoint = `/repos/${owner}/${repository}/releases/${releaseId}`;
}
if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
requestMethod = 'GET';
const releaseId = this.getNodeParameter('release_id', i) as string;
endpoint = `/repos/${owner}/${repository}/releases/${releaseId}`;
}
if (operation === 'getAll') {
// ----------------------------------
// getAll
// ----------------------------------
requestMethod = 'GET';
endpoint = `/repos/${owner}/${repository}/releases`;
returnAll = this.getNodeParameter('returnAll', 0) as boolean;
if (returnAll === false) {
qs.per_page = this.getNodeParameter('limit', 0) as number;
}
}
if (operation === 'update') {
// ----------------------------------
// update
// ----------------------------------
requestMethod = 'PATCH';
const releaseId = this.getNodeParameter('release_id', i) as string;
body = this.getNodeParameter('additionalFields', i, {}) as IDataObject;
endpoint = `/repos/${owner}/${repository}/releases/${releaseId}`;
}
} else if (resource === 'repository') {
if (operation === 'listPopularPaths') {
// ----------------------------------
// listPopularPaths
// ----------------------------------
requestMethod = 'GET';
endpoint = `/repos/${owner}/${repository}/traffic/popular/paths`;
} else if (operation === 'listReferrers') {
// ----------------------------------
// listReferrers
// ----------------------------------
requestMethod = 'GET';
endpoint = `/repos/${owner}/${repository}/traffic/popular/referrers`;
} else if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
requestMethod = 'GET';
endpoint = `/repos/${owner}/${repository}`;
} else if (operation === 'getLicense') {
// ----------------------------------
// getLicense
// ----------------------------------
requestMethod = 'GET';
endpoint = `/repos/${owner}/${repository}/license`;
} else if (operation === 'getIssues') {
// ----------------------------------
// getIssues
// ----------------------------------
requestMethod = 'GET';
qs = this.getNodeParameter('getRepositoryIssuesFilters', i) as IDataObject;
endpoint = `/repos/${owner}/${repository}/issues`;
returnAll = this.getNodeParameter('returnAll', 0) as boolean;
if (returnAll === false) {
qs.per_page = this.getNodeParameter('limit', 0) as number;
}
}
} else if (resource === 'review') {
if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
requestMethod = 'GET';
const reviewId = this.getNodeParameter('reviewId', i) as string;
const pullRequestNumber = this.getNodeParameter('pullRequestNumber', i) as string;
endpoint = `/repos/${owner}/${repository}/pulls/${pullRequestNumber}/reviews/${reviewId}`;
} else if (operation === 'getAll') {
// ----------------------------------
// getAll
// ----------------------------------
requestMethod = 'GET';
returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const pullRequestNumber = this.getNodeParameter('pullRequestNumber', i) as string;
if (returnAll === false) {
qs.per_page = this.getNodeParameter('limit', 0) as number;
}
endpoint = `/repos/${owner}/${repository}/pulls/${pullRequestNumber}/reviews`;
} else if (operation === 'create') {
// ----------------------------------
// create
// ----------------------------------
requestMethod = 'POST';
const pullRequestNumber = this.getNodeParameter('pullRequestNumber', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
Object.assign(body, additionalFields);
body.event = snakeCase(this.getNodeParameter('event', i) as string).toUpperCase();
if (body.event === 'REQUEST_CHANGES' || body.event === 'COMMENT') {
body.body = this.getNodeParameter('body', i) as string;
}
endpoint = `/repos/${owner}/${repository}/pulls/${pullRequestNumber}/reviews`;
} else if (operation === 'update') {
// ----------------------------------
// update
// ----------------------------------
requestMethod = 'PUT';
const pullRequestNumber = this.getNodeParameter('pullRequestNumber', i) as string;
const reviewId = this.getNodeParameter('reviewId', i) as string;
body.body = this.getNodeParameter('body', i) as string;
endpoint = `/repos/${owner}/${repository}/pulls/${pullRequestNumber}/reviews/${reviewId}`;
}
} else if (resource === 'user') {
if (operation === 'getRepositories') {
// ----------------------------------
// getRepositories
// ----------------------------------
requestMethod = 'GET';
endpoint = `/users/${owner}/repos`;
returnAll = this.getNodeParameter('returnAll', 0) as boolean;
if (returnAll === false) {
qs.per_page = this.getNodeParameter('limit', 0) as number;
}
} else if (operation === 'invite') {
// ----------------------------------
// invite
// ----------------------------------
requestMethod = 'POST';
const org = this.getNodeParameter('organization', i) as string;
endpoint = `/orgs/${org}/invitations`;
body.email = this.getNodeParameter('email', i) as string;
}
} else {
throw new NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`);
}
if (returnAll === true) {
responseData = await githubApiRequestAllItems.call(this, requestMethod, endpoint, body, qs);
} else {
responseData = await githubApiRequest.call(this, requestMethod, endpoint, body, qs);
}
if (fullOperation === 'file:get') {
const asBinaryProperty = this.getNodeParameter('asBinaryProperty', i);
if (asBinaryProperty === true) {
// Add the returned data to the item as binary property
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i) as string;
if (item.binary[binaryPropertyName] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property "${binaryPropertyName}" does not exists on item!`);
const newItem: INodeExecutionData = {
json: items[i].json,
binary: {},
};
if (items[i].binary !== undefined) {
// Create a shallow copy of the binary data so that the old
// data references which do not get changed still stay behind
// but the incoming data does not get changed.
Object.assign(newItem.binary, items[i].binary);
}
// Currently internally n8n uses base64 and also Github expects it base64 encoded.
// If that ever changes the data has to get converted here.
body.content = item.binary[binaryPropertyName].data;
newItem.binary![binaryPropertyName] = await this.helpers.prepareBinaryData(Buffer.from(responseData.content, 'base64'), responseData.path);
items[i] = newItem;
return this.prepareOutputData(items);
}
}
if (fullOperation === 'release:delete') {
responseData = { success: true };
}
if (overwriteDataOperations.includes(fullOperation)) {
returnData.push(responseData);
} else if (overwriteDataOperationsArray.includes(fullOperation)) {
returnData.push.apply(returnData, responseData);
}
} catch (error) {
if (this.continueOnFail()) {
if (overwriteDataOperations.includes(fullOperation) || overwriteDataOperationsArray.includes(fullOperation)) {
returnData.push({ error: error.message });
} else {
// Is text file
// body.content = Buffer.from(this.getNodeParameter('fileContent', i) as string, 'base64');
body.content = Buffer.from(this.getNodeParameter('fileContent', i) as string).toString('base64');
items[i].json = { error: error.message };
}
endpoint = `/repos/${owner}/${repository}/contents/${encodeURI(filePath)}`;
} else if (operation === 'delete') {
// ----------------------------------
// delete
// ----------------------------------
requestMethod = 'DELETE';
const additionalParameters = this.getNodeParameter('additionalParameters', i, {}) as IDataObject;
if (additionalParameters.author) {
body.author = additionalParameters.author;
}
if (additionalParameters.committer) {
body.committer = additionalParameters.committer;
}
if (additionalParameters.branch && (additionalParameters.branch as IDataObject).branch) {
body.branch = (additionalParameters.branch as IDataObject).branch;
}
const filePath = this.getNodeParameter('filePath', i) as string;
body.message = this.getNodeParameter('commitMessage', i) as string;
body.sha = await getFileSha.call(this, owner, repository, filePath, body.branch as string | undefined);
endpoint = `/repos/${owner}/${repository}/contents/${encodeURI(filePath)}`;
} else if (operation === 'get') {
requestMethod = 'GET';
const filePath = this.getNodeParameter('filePath', i) as string;
endpoint = `/repos/${owner}/${repository}/contents/${encodeURI(filePath)}`;
continue;
}
} else if (resource === 'issue') {
if (operation === 'create') {
// ----------------------------------
// create
// ----------------------------------
requestMethod = 'POST';
body.title = this.getNodeParameter('title', i) as string;
body.body = this.getNodeParameter('body', i) as string;
const labels = this.getNodeParameter('labels', i) as IDataObject[];
const assignees = this.getNodeParameter('assignees', i) as IDataObject[];
body.labels = labels.map((data) => data['label']);
body.assignees = assignees.map((data) => data['assignee']);
endpoint = `/repos/${owner}/${repository}/issues`;
} else if (operation === 'createComment') {
// ----------------------------------
// createComment
// ----------------------------------
requestMethod = 'POST';
const issueNumber = this.getNodeParameter('issueNumber', i) as string;
body.body = this.getNodeParameter('body', i) as string;
endpoint = `/repos/${owner}/${repository}/issues/${issueNumber}/comments`;
} else if (operation === 'edit') {
// ----------------------------------
// edit
// ----------------------------------
requestMethod = 'PATCH';
const issueNumber = this.getNodeParameter('issueNumber', i) as string;
body = this.getNodeParameter('editFields', i, {}) as IDataObject;
if (body.labels !== undefined) {
body.labels = (body.labels as IDataObject[]).map((data) => data['label']);
}
if (body.assignees !== undefined) {
body.assignees = (body.assignees as IDataObject[]).map((data) => data['assignee']);
}
endpoint = `/repos/${owner}/${repository}/issues/${issueNumber}`;
} else if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
requestMethod = 'GET';
const issueNumber = this.getNodeParameter('issueNumber', i) as string;
endpoint = `/repos/${owner}/${repository}/issues/${issueNumber}`;
} else if (operation === 'lock') {
// ----------------------------------
// lock
// ----------------------------------
requestMethod = 'PUT';
const issueNumber = this.getNodeParameter('issueNumber', i) as string;
qs.lock_reason = this.getNodeParameter('lockReason', i) as string;
endpoint = `/repos/${owner}/${repository}/issues/${issueNumber}/lock`;
}
} else if (resource === 'release') {
if (operation === 'create') {
// ----------------------------------
// create
// ----------------------------------
requestMethod = 'POST';
body = this.getNodeParameter('additionalFields', i, {}) as IDataObject;
body.tag_name = this.getNodeParameter('releaseTag', i) as string;
endpoint = `/repos/${owner}/${repository}/releases`;
}
if (operation === 'delete') {
// ----------------------------------
// delete
// ----------------------------------
requestMethod = 'DELETE';
const releaseId = this.getNodeParameter('release_id', i) as string;
endpoint = `/repos/${owner}/${repository}/releases/${releaseId}`;
}
if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
requestMethod = 'GET';
const releaseId = this.getNodeParameter('release_id', i) as string;
endpoint = `/repos/${owner}/${repository}/releases/${releaseId}`;
}
if (operation === 'getAll') {
// ----------------------------------
// getAll
// ----------------------------------
requestMethod = 'GET';
endpoint = `/repos/${owner}/${repository}/releases`;
returnAll = this.getNodeParameter('returnAll', 0) as boolean;
if (returnAll === false) {
qs.per_page = this.getNodeParameter('limit', 0) as number;
}
}
if (operation === 'update') {
// ----------------------------------
// update
// ----------------------------------
requestMethod = 'PATCH';
const releaseId = this.getNodeParameter('release_id', i) as string;
body = this.getNodeParameter('additionalFields', i, {}) as IDataObject;
endpoint = `/repos/${owner}/${repository}/releases/${releaseId}`;
}
} else if (resource === 'repository') {
if (operation === 'listPopularPaths') {
// ----------------------------------
// listPopularPaths
// ----------------------------------
requestMethod = 'GET';
endpoint = `/repos/${owner}/${repository}/traffic/popular/paths`;
} else if (operation === 'listReferrers') {
// ----------------------------------
// listReferrers
// ----------------------------------
requestMethod = 'GET';
endpoint = `/repos/${owner}/${repository}/traffic/popular/referrers`;
} else if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
requestMethod = 'GET';
endpoint = `/repos/${owner}/${repository}`;
} else if (operation === 'getLicense') {
// ----------------------------------
// getLicense
// ----------------------------------
requestMethod = 'GET';
endpoint = `/repos/${owner}/${repository}/license`;
} else if (operation === 'getIssues') {
// ----------------------------------
// getIssues
// ----------------------------------
requestMethod = 'GET';
qs = this.getNodeParameter('getRepositoryIssuesFilters', i) as IDataObject;
endpoint = `/repos/${owner}/${repository}/issues`;
returnAll = this.getNodeParameter('returnAll', 0) as boolean;
if (returnAll === false) {
qs.per_page = this.getNodeParameter('limit', 0) as number;
}
}
} else if (resource === 'review') {
if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
requestMethod = 'GET';
const reviewId = this.getNodeParameter('reviewId', i) as string;
const pullRequestNumber = this.getNodeParameter('pullRequestNumber', i) as string;
endpoint = `/repos/${owner}/${repository}/pulls/${pullRequestNumber}/reviews/${reviewId}`;
} else if (operation === 'getAll') {
// ----------------------------------
// getAll
// ----------------------------------
requestMethod = 'GET';
returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const pullRequestNumber = this.getNodeParameter('pullRequestNumber', i) as string;
if (returnAll === false) {
qs.per_page = this.getNodeParameter('limit', 0) as number;
}
endpoint = `/repos/${owner}/${repository}/pulls/${pullRequestNumber}/reviews`;
} else if (operation === 'create') {
// ----------------------------------
// create
// ----------------------------------
requestMethod = 'POST';
const pullRequestNumber = this.getNodeParameter('pullRequestNumber', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
Object.assign(body, additionalFields);
body.event = snakeCase(this.getNodeParameter('event', i) as string).toUpperCase();
if (body.event === 'REQUEST_CHANGES' || body.event === 'COMMENT') {
body.body = this.getNodeParameter('body', i) as string;
}
endpoint = `/repos/${owner}/${repository}/pulls/${pullRequestNumber}/reviews`;
} else if (operation === 'update') {
// ----------------------------------
// update
// ----------------------------------
requestMethod = 'PUT';
const pullRequestNumber = this.getNodeParameter('pullRequestNumber', i) as string;
const reviewId = this.getNodeParameter('reviewId', i) as string;
body.body = this.getNodeParameter('body', i) as string;
endpoint = `/repos/${owner}/${repository}/pulls/${pullRequestNumber}/reviews/${reviewId}`;
}
} else if (resource === 'user') {
if (operation === 'getRepositories') {
// ----------------------------------
// getRepositories
// ----------------------------------
requestMethod = 'GET';
endpoint = `/users/${owner}/repos`;
returnAll = this.getNodeParameter('returnAll', 0) as boolean;
if (returnAll === false) {
qs.per_page = this.getNodeParameter('limit', 0) as number;
}
} else if (operation === 'invite') {
// ----------------------------------
// invite
// ----------------------------------
requestMethod = 'POST';
const org = this.getNodeParameter('organization', i) as string;
endpoint = `/orgs/${org}/invitations`;
body.email = this.getNodeParameter('email', i) as string;
}
} else {
throw new NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`);
}
if (returnAll === true) {
responseData = await githubApiRequestAllItems.call(this, requestMethod, endpoint, body, qs);
} else {
responseData = await githubApiRequest.call(this, requestMethod, endpoint, body, qs);
}
if (fullOperation === 'file:get') {
const asBinaryProperty = this.getNodeParameter('asBinaryProperty', i);
if (asBinaryProperty === true) {
// Add the returned data to the item as binary property
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i) as string;
const newItem: INodeExecutionData = {
json: items[i].json,
binary: {},
};
if (items[i].binary !== undefined) {
// Create a shallow copy of the binary data so that the old
// data references which do not get changed still stay behind
// but the incoming data does not get changed.
Object.assign(newItem.binary, items[i].binary);
}
newItem.binary![binaryPropertyName] = await this.helpers.prepareBinaryData(Buffer.from(responseData.content, 'base64'), responseData.path);
items[i] = newItem;
return this.prepareOutputData(items);
}
}
if (fullOperation === 'release:delete') {
responseData = { success: true };
}
if (overwriteDataOperations.includes(fullOperation)) {
returnData.push(responseData);
} else if (overwriteDataOperationsArray.includes(fullOperation)) {
returnData.push.apply(returnData, responseData);
throw error;
}
}

View file

@ -1114,6 +1114,9 @@ export class Gitlab implements INodeType {
}
}
} catch (error) {
if (this.continueOnFail()) {
return [this.helpers.returnJsonArray([{ error: error.message }])];
}
throw new NodeOperationError(this.getNode(), error);
}
@ -1152,218 +1155,230 @@ export class Gitlab implements INodeType {
const fullOperation = `${resource}:${operation}`;
for (let i = 0; i < items.length; i++) {
// Reset all values
requestMethod = 'GET';
endpoint = '';
body = {};
qs = {};
try {
// Reset all values
requestMethod = 'GET';
endpoint = '';
body = {};
qs = {};
// Request the parameters which almost all operations need
let owner = this.getNodeParameter('owner', i) as string;
// Request the parameters which almost all operations need
let owner = this.getNodeParameter('owner', i) as string;
// Replace all slashes to work with subgroups
owner = owner.replace(new RegExp(/\//g), '%2F');
// Replace all slashes to work with subgroups
owner = owner.replace(new RegExp(/\//g), '%2F');
let repository = '';
if (fullOperation !== 'user:getRepositories') {
repository = this.getNodeParameter('repository', i) as string;
}
let repository = '';
if (fullOperation !== 'user:getRepositories') {
repository = this.getNodeParameter('repository', i) as string;
}
const baseEndpoint = `/projects/${owner}%2F${repository}`;
const baseEndpoint = `/projects/${owner}%2F${repository}`;
if (resource === 'issue') {
if (operation === 'create') {
// ----------------------------------
// create
// ----------------------------------
if (resource === 'issue') {
if (operation === 'create') {
// ----------------------------------
// create
// ----------------------------------
requestMethod = 'POST';
requestMethod = 'POST';
body.title = this.getNodeParameter('title', i) as string;
body.description = this.getNodeParameter('body', i) as string;
body.due_date = this.getNodeParameter('due_date', i) as string;
const labels = this.getNodeParameter('labels', i) as IDataObject[];
body.title = this.getNodeParameter('title', i) as string;
body.description = this.getNodeParameter('body', i) as string;
body.due_date = this.getNodeParameter('due_date', i) as string;
const labels = this.getNodeParameter('labels', i) as IDataObject[];
const assigneeIds = this.getNodeParameter('assignee_ids', i) as IDataObject[];
const assigneeIds = this.getNodeParameter('assignee_ids', i) as IDataObject[];
body.labels = labels.map((data) => data['label']).join(',');
body.assignee_ids = assigneeIds.map((data) => data['assignee']);
body.labels = labels.map((data) => data['label']).join(',');
body.assignee_ids = assigneeIds.map((data) => data['assignee']);
endpoint = `${baseEndpoint}/issues`;
} else if (operation === 'createComment') {
// ----------------------------------
// createComment
// ----------------------------------
requestMethod = 'POST';
endpoint = `${baseEndpoint}/issues`;
} else if (operation === 'createComment') {
// ----------------------------------
// createComment
// ----------------------------------
requestMethod = 'POST';
const issueNumber = this.getNodeParameter('issueNumber', i) as string;
const issueNumber = this.getNodeParameter('issueNumber', i) as string;
body.body = this.getNodeParameter('body', i) as string;
body.body = this.getNodeParameter('body', i) as string;
endpoint = `${baseEndpoint}/issues/${issueNumber}/notes`;
} else if (operation === 'edit') {
// ----------------------------------
// edit
// ----------------------------------
endpoint = `${baseEndpoint}/issues/${issueNumber}/notes`;
} else if (operation === 'edit') {
// ----------------------------------
// edit
// ----------------------------------
requestMethod = 'PUT';
requestMethod = 'PUT';
const issueNumber = this.getNodeParameter('issueNumber', i) as string;
const issueNumber = this.getNodeParameter('issueNumber', i) as string;
body = this.getNodeParameter('editFields', i, {}) as IDataObject;
body = this.getNodeParameter('editFields', i, {}) as IDataObject;
if (body.labels !== undefined) {
body.labels = (body.labels as IDataObject[]).map((data) => data['label']).join(',');
if (body.labels !== undefined) {
body.labels = (body.labels as IDataObject[]).map((data) => data['label']).join(',');
}
if (body.assignee_ids !== undefined) {
body.assignee_ids = (body.assignee_ids as IDataObject[]).map((data) => data['assignee']);
}
endpoint = `${baseEndpoint}/issues/${issueNumber}`;
} else if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
requestMethod = 'GET';
const issueNumber = this.getNodeParameter('issueNumber', i) as string;
endpoint = `${baseEndpoint}/issues/${issueNumber}`;
} else if (operation === 'lock') {
// ----------------------------------
// lock
// ----------------------------------
requestMethod = 'PUT';
const issueNumber = this.getNodeParameter('issueNumber', i) as string;
body.discussion_locked = true;
endpoint = `${baseEndpoint}/issues/${issueNumber}`;
}
if (body.assignee_ids !== undefined) {
body.assignee_ids = (body.assignee_ids as IDataObject[]).map((data) => data['assignee']);
} else if (resource === 'release') {
if (operation === 'create') {
// ----------------------------------
// create
// ----------------------------------
requestMethod = 'POST';
body = this.getNodeParameter('additionalFields', i, {}) as IDataObject;
body.tag_name = this.getNodeParameter('releaseTag', i) as string;
endpoint = `${baseEndpoint}/releases`;
}
if (operation === 'delete') {
// ----------------------------------
// delete
// ----------------------------------
endpoint = `${baseEndpoint}/issues/${issueNumber}`;
} else if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
requestMethod = 'DELETE';
requestMethod = 'GET';
const id = this.getNodeParameter('projectId', i) as string;
const issueNumber = this.getNodeParameter('issueNumber', i) as string;
const tagName = this.getNodeParameter('tag_name', i) as string;
endpoint = `${baseEndpoint}/issues/${issueNumber}`;
} else if (operation === 'lock') {
// ----------------------------------
// lock
// ----------------------------------
requestMethod = 'PUT';
const issueNumber = this.getNodeParameter('issueNumber', i) as string;
body.discussion_locked = true;
endpoint = `${baseEndpoint}/issues/${issueNumber}`;
}
} else if (resource === 'release') {
if (operation === 'create') {
// ----------------------------------
// create
// ----------------------------------
requestMethod = 'POST';
body = this.getNodeParameter('additionalFields', i, {}) as IDataObject;
body.tag_name = this.getNodeParameter('releaseTag', i) as string;
endpoint = `${baseEndpoint}/releases`;
}
if (operation === 'delete') {
// ----------------------------------
// delete
// ----------------------------------
requestMethod = 'DELETE';
const id = this.getNodeParameter('projectId', i) as string;
const tagName = this.getNodeParameter('tag_name', i) as string;
endpoint = `/projects/${id}/releases/${tagName}`;
}
if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
requestMethod = 'GET';
const id = this.getNodeParameter('projectId', i) as string;
const tagName = this.getNodeParameter('tag_name', i) as string;
endpoint = `/projects/${id}/releases/${tagName}`;
}
if (operation === 'getAll') {
// ----------------------------------
// getAll
// ----------------------------------
requestMethod = 'GET';
const id = this.getNodeParameter('projectId', i) as string;
qs = this.getNodeParameter('additionalFields', i, {}) as IDataObject;
returnAll = this.getNodeParameter('returnAll', 0) as boolean;
if (returnAll === false) {
qs.per_page = this.getNodeParameter('limit', 0) as number;
endpoint = `/projects/${id}/releases/${tagName}`;
}
if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
endpoint = `/projects/${id}/releases`;
}
if (operation === 'update') {
// ----------------------------------
// update
// ----------------------------------
requestMethod = 'GET';
requestMethod = 'PUT';
const id = this.getNodeParameter('projectId', i) as string;
const id = this.getNodeParameter('projectId', i) as string;
const tagName = this.getNodeParameter('tag_name', i) as string;
const tagName = this.getNodeParameter('tag_name', i) as string;
body = this.getNodeParameter('additionalFields', i, {}) as IDataObject;
if(body.milestones){
body.milestones = (body.milestones as string).split(',');
endpoint = `/projects/${id}/releases/${tagName}`;
}
if (operation === 'getAll') {
// ----------------------------------
// getAll
// ----------------------------------
endpoint = `/projects/${id}/releases/${tagName}`;
requestMethod = 'GET';
const id = this.getNodeParameter('projectId', i) as string;
qs = this.getNodeParameter('additionalFields', i, {}) as IDataObject;
returnAll = this.getNodeParameter('returnAll', 0) as boolean;
if (returnAll === false) {
qs.per_page = this.getNodeParameter('limit', 0) as number;
}
endpoint = `/projects/${id}/releases`;
}
if (operation === 'update') {
// ----------------------------------
// update
// ----------------------------------
requestMethod = 'PUT';
const id = this.getNodeParameter('projectId', i) as string;
const tagName = this.getNodeParameter('tag_name', i) as string;
body = this.getNodeParameter('additionalFields', i, {}) as IDataObject;
if(body.milestones){
body.milestones = (body.milestones as string).split(',');
}
endpoint = `/projects/${id}/releases/${tagName}`;
}
} else if (resource === 'repository') {
if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
requestMethod = 'GET';
endpoint = `${baseEndpoint}`;
} else if (operation === 'getIssues') {
// ----------------------------------
// getIssues
// ----------------------------------
requestMethod = 'GET';
qs = this.getNodeParameter('getRepositoryIssuesFilters', i) as IDataObject;
endpoint = `${baseEndpoint}/issues`;
}
} else if (resource === 'user') {
if (operation === 'getRepositories') {
// ----------------------------------
// getRepositories
// ----------------------------------
requestMethod = 'GET';
endpoint = `/users/${owner}/projects`;
}
} else {
throw new NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`);
}
} else if (resource === 'repository') {
if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
requestMethod = 'GET';
endpoint = `${baseEndpoint}`;
} else if (operation === 'getIssues') {
// ----------------------------------
// getIssues
// ----------------------------------
requestMethod = 'GET';
qs = this.getNodeParameter('getRepositoryIssuesFilters', i) as IDataObject;
endpoint = `${baseEndpoint}/issues`;
if (returnAll === true) {
responseData = await gitlabApiRequestAllItems.call(this, requestMethod, endpoint, body, qs);
} else {
responseData = await gitlabApiRequest.call(this, requestMethod, endpoint, body, qs);
}
} else if (resource === 'user') {
if (operation === 'getRepositories') {
// ----------------------------------
// getRepositories
// ----------------------------------
requestMethod = 'GET';
endpoint = `/users/${owner}/projects`;
if (overwriteDataOperations.includes(fullOperation)) {
returnData.push(responseData);
} else if (overwriteDataOperationsArray.includes(fullOperation)) {
returnData.push.apply(returnData, responseData);
}
} else {
throw new NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`);
}
if (returnAll === true) {
responseData = await gitlabApiRequestAllItems.call(this, requestMethod, endpoint, body, qs);
} else {
responseData = await gitlabApiRequest.call(this, requestMethod, endpoint, body, qs);
}
if (overwriteDataOperations.includes(fullOperation)) {
returnData.push(responseData);
} else if (overwriteDataOperationsArray.includes(fullOperation)) {
returnData.push.apply(returnData, responseData);
} catch (error) {
if (this.continueOnFail()) {
if (overwriteDataOperations.includes(fullOperation) || overwriteDataOperationsArray.includes(fullOperation)) {
returnData.push({ error: error.message });
} else {
items[i].json = { error: error.message };
}
continue;
}
throw error;
}
}

View file

@ -162,123 +162,131 @@ export class GoogleAnalytics implements INodeType {
let endpoint = '';
let responseData;
for (let i = 0; i < items.length; i++) {
if (resource === 'report') {
if (operation === 'get') {
//https://developers.google.com/analytics/devguides/reporting/core/v4/rest/v4/reports/batchGet
method = 'POST';
endpoint = '/v4/reports:batchGet';
const viewId = this.getNodeParameter('viewId', i) as string;
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const additionalFields = this.getNodeParameter(
'additionalFields',
i,
) as IDataObject;
const simple = this.getNodeParameter('simple', i) as boolean;
try {
if(resource === 'report') {
if(operation === 'get') {
//https://developers.google.com/analytics/devguides/reporting/core/v4/rest/v4/reports/batchGet
method = 'POST';
endpoint = '/v4/reports:batchGet';
const viewId = this.getNodeParameter('viewId', i) as string;
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const additionalFields = this.getNodeParameter(
'additionalFields',
i,
) as IDataObject;
const simple = this.getNodeParameter('simple', i) as boolean;
const body: IData = {
viewId,
};
const body: IData = {
viewId,
};
if (additionalFields.useResourceQuotas) {
qs.useResourceQuotas = additionalFields.useResourceQuotas;
}
if (additionalFields.dateRangesUi) {
const dateValues = (additionalFields.dateRangesUi as IDataObject).dateRanges as IDataObject;
if (dateValues) {
const start = dateValues.startDate as string;
const end = dateValues.endDate as string;
Object.assign(
body,
{
dateRanges:
[
{
startDate: moment(start).utc().format('YYYY-MM-DD'),
endDate: moment(end).utc().format('YYYY-MM-DD'),
},
],
},
);
if (additionalFields.useResourceQuotas) {
qs.useResourceQuotas = additionalFields.useResourceQuotas;
}
}
if (additionalFields.metricsUi) {
const metrics = (additionalFields.metricsUi as IDataObject).metricValues as IDataObject[];
body.metrics = metrics;
}
if (additionalFields.dimensionUi) {
const dimensions = (additionalFields.dimensionUi as IDataObject).dimensionValues as IDataObject[];
if (dimensions) {
body.dimensions = dimensions;
if (additionalFields.dateRangesUi) {
const dateValues = (additionalFields.dateRangesUi as IDataObject).dateRanges as IDataObject;
if (dateValues) {
const start = dateValues.startDate as string;
const end = dateValues.endDate as string;
Object.assign(
body,
{
dateRanges:
[
{
startDate: moment(start).utc().format('YYYY-MM-DD'),
endDate: moment(end).utc().format('YYYY-MM-DD'),
},
],
},
);
}
}
}
if (additionalFields.dimensionFiltersUi) {
const dimensionFilters = (additionalFields.dimensionFiltersUi as IDataObject).filterValues as IDataObject[];
if (dimensionFilters) {
dimensionFilters.forEach(filter => filter.expressions = [filter.expressions]);
body.dimensionFilterClauses = { filters: dimensionFilters };
if (additionalFields.metricsUi) {
const metrics = (additionalFields.metricsUi as IDataObject).metricValues as IDataObject[];
body.metrics = metrics;
}
if (additionalFields.dimensionUi) {
const dimensions = (additionalFields.dimensionUi as IDataObject).dimensionValues as IDataObject[];
if (dimensions) {
body.dimensions = dimensions;
}
}
if (additionalFields.dimensionFiltersUi) {
const dimensionFilters = (additionalFields.dimensionFiltersUi as IDataObject).filterValues as IDataObject[];
if (dimensionFilters) {
dimensionFilters.forEach(filter => filter.expressions = [filter.expressions]);
body.dimensionFilterClauses = { filters: dimensionFilters };
}
}
}
if (additionalFields.includeEmptyRows) {
Object.assign(body, { includeEmptyRows: additionalFields.includeEmptyRows });
}
if (additionalFields.hideTotals) {
Object.assign(body, { hideTotals: additionalFields.hideTotals });
}
if (additionalFields.hideValueRanges) {
Object.assign(body, { hideTotals: additionalFields.hideTotals });
}
if (additionalFields.includeEmptyRows) {
Object.assign(body, { includeEmptyRows: additionalFields.includeEmptyRows });
}
if (additionalFields.hideTotals) {
Object.assign(body, { hideTotals: additionalFields.hideTotals });
}
if (additionalFields.hideValueRanges) {
Object.assign(body, { hideTotals: additionalFields.hideTotals });
}
if (returnAll === true) {
responseData = await googleApiRequestAllItems.call(this, 'reports', method, endpoint, { reportRequests: [body] }, qs);
} else {
responseData = await googleApiRequest.call(this, method, endpoint, { reportRequests: [body] }, qs);
responseData = responseData.reports;
}
if (returnAll === true) {
responseData = await googleApiRequestAllItems.call(this, 'reports', method, endpoint, { reportRequests: [body] }, qs);
} else {
responseData = await googleApiRequest.call(this, method, endpoint, { reportRequests: [body] }, qs);
responseData = responseData.reports;
}
if (simple === true) {
responseData = simplify(responseData);
} else if (returnAll === true && responseData.length > 1) {
responseData = merge(responseData);
if (simple === true) {
responseData = simplify(responseData);
} else if (returnAll === true && responseData.length > 1) {
responseData = merge(responseData);
}
}
}
}
if (resource === 'userActivity') {
if (operation === 'search') {
//https://developers.google.com/analytics/devguides/reporting/core/v4/rest/v4/userActivity/search
method = 'POST';
endpoint = '/v4/userActivity:search';
const viewId = this.getNodeParameter('viewId', i);
const userId = this.getNodeParameter('userId', i);
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const additionalFields = this.getNodeParameter(
'additionalFields',
i,
) as IDataObject;
const body: IDataObject = {
viewId,
user: {
userId,
},
};
if (additionalFields.activityTypes) {
Object.assign(body, { activityTypes: additionalFields.activityTypes });
}
if (resource === 'userActivity') {
if (operation === 'search') {
//https://developers.google.com/analytics/devguides/reporting/core/v4/rest/v4/userActivity/search
method = 'POST';
endpoint = '/v4/userActivity:search';
const viewId = this.getNodeParameter('viewId', i);
const userId = this.getNodeParameter('userId', i);
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const additionalFields = this.getNodeParameter(
'additionalFields',
i,
) as IDataObject;
const body: IDataObject = {
viewId,
user: {
userId,
},
};
if (additionalFields.activityTypes) {
Object.assign(body, { activityTypes: additionalFields.activityTypes });
}
if (returnAll) {
responseData = await googleApiRequestAllItems.call(this, 'sessions', method, endpoint, body);
} else {
body.pageSize = this.getNodeParameter('limit', 0) as number;
responseData = await googleApiRequest.call(this, method, endpoint, body);
responseData = responseData.sessions;
if (returnAll) {
responseData = await googleApiRequestAllItems.call(this, 'sessions', method, endpoint, body);
} else {
body.pageSize = this.getNodeParameter('limit', 0) as number;
responseData = await googleApiRequest.call(this, method, endpoint, body);
responseData = responseData.sessions;
}
}
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else if (responseData !== undefined) {
returnData.push(responseData as IDataObject);
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else if (responseData !== undefined) {
returnData.push(responseData as IDataObject);
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];

View file

@ -385,115 +385,125 @@ export class GoogleBooks implements INodeType {
let responseData;
for (let i = 0; i < length; i++) {
if (resource === 'volume') {
if (operation === 'get') {
const volumeId = this.getNodeParameter('volumeId', i) as string;
responseData = await googleApiRequest.call(this, 'GET', `v1/volumes/${volumeId}`, {});
} else if (operation === 'getAll') {
const searchQuery = this.getNodeParameter('searchQuery', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
if (returnAll) {
responseData = await googleApiRequestAllItems.call(this, 'items', 'GET', `v1/volumes?q=${searchQuery}`, {});
} else {
qs.maxResults = this.getNodeParameter('limit', i) as number;
responseData = await googleApiRequest.call(this, 'GET', `v1/volumes?q=${searchQuery}`, {}, qs);
responseData = responseData.items || [];
}
}
}
try {
if (resource === 'bookshelf') {
if (operation === 'get') {
const shelfId = this.getNodeParameter('shelfId', i) as string;
const myLibrary = this.getNodeParameter('myLibrary', i) as boolean;
let endpoint;
if (myLibrary === false) {
const userId = this.getNodeParameter('userId', i) as string;
endpoint = `v1/users/${userId}/bookshelves/${shelfId}`;
} else {
endpoint = `v1/mylibrary/bookshelves/${shelfId}`;
}
responseData = await googleApiRequest.call(this, 'GET', endpoint, {});
} else if (operation === 'getAll') {
const myLibrary = this.getNodeParameter('myLibrary', i) as boolean;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
let endpoint;
if (myLibrary === false) {
const userId = this.getNodeParameter('userId', i) as string;
endpoint = `v1/users/${userId}/bookshelves`;
} else {
endpoint = `v1/mylibrary/bookshelves`;
}
if (returnAll) {
responseData = await googleApiRequestAllItems.call(this, 'items', 'GET', endpoint, {});
} else {
qs.maxResults = this.getNodeParameter('limit', i) as number;
responseData = await googleApiRequest.call(this, 'GET', endpoint, {}, qs);
responseData = responseData.items || [];
}
}
}
if (resource === 'bookshelfVolume') {
if (operation === 'add') {
const shelfId = this.getNodeParameter('shelfId', i) as string;
const volumeId = this.getNodeParameter('volumeId', i) as string;
const body: IDataObject = {
volumeId,
};
responseData = await googleApiRequest.call(this, 'POST', `v1/mylibrary/bookshelves/${shelfId}/addVolume`, body);
}
if (operation === 'clear') {
const shelfId = this.getNodeParameter('shelfId', i) as string;
responseData = await googleApiRequest.call(this, 'POST', `v1/mylibrary/bookshelves/${shelfId}/clearVolumes`);
}
if (operation === 'getAll') {
const shelfId = this.getNodeParameter('shelfId', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const myLibrary = this.getNodeParameter('myLibrary', i) as boolean;
let endpoint;
if (myLibrary === false) {
const userId = this.getNodeParameter('userId', i) as string;
endpoint = `v1/users/${userId}/bookshelves/${shelfId}/volumes`;
} else {
endpoint = `v1/mylibrary/bookshelves/${shelfId}/volumes`;
}
if (returnAll) {
responseData = await googleApiRequestAllItems.call(this, 'items', 'GET', endpoint, {});
} else {
qs.maxResults = this.getNodeParameter('limit', i) as number;
responseData = await googleApiRequest.call(this, 'GET', endpoint, {}, qs);
responseData = responseData.items || [];
if (resource === 'volume') {
if (operation === 'get') {
const volumeId = this.getNodeParameter('volumeId', i) as string;
responseData = await googleApiRequest.call(this, 'GET', `v1/volumes/${volumeId}`, {});
} else if (operation === 'getAll') {
const searchQuery = this.getNodeParameter('searchQuery', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
if (returnAll) {
responseData = await googleApiRequestAllItems.call(this, 'items', 'GET', `v1/volumes?q=${searchQuery}`, {});
} else {
qs.maxResults = this.getNodeParameter('limit', i) as number;
responseData = await googleApiRequest.call(this, 'GET', `v1/volumes?q=${searchQuery}`, {}, qs);
responseData = responseData.items || [];
}
}
}
if (operation === 'move') {
const shelfId = this.getNodeParameter('shelfId', i) as string;
const volumeId = this.getNodeParameter('volumeId', i) as string;
const volumePosition = this.getNodeParameter('volumePosition', i) as number;
const body: IDataObject = {
volumeId,
volumePosition,
};
responseData = await googleApiRequest.call(this, 'POST', `v1/mylibrary/bookshelves/${shelfId}/moveVolume`, body);
if (resource === 'bookshelf') {
if (operation === 'get') {
const shelfId = this.getNodeParameter('shelfId', i) as string;
const myLibrary = this.getNodeParameter('myLibrary', i) as boolean;
let endpoint;
if (myLibrary === false) {
const userId = this.getNodeParameter('userId', i) as string;
endpoint = `v1/users/${userId}/bookshelves/${shelfId}`;
} else {
endpoint = `v1/mylibrary/bookshelves/${shelfId}`;
}
responseData = await googleApiRequest.call(this, 'GET', endpoint, {});
} else if (operation === 'getAll') {
const myLibrary = this.getNodeParameter('myLibrary', i) as boolean;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
let endpoint;
if (myLibrary === false) {
const userId = this.getNodeParameter('userId', i) as string;
endpoint = `v1/users/${userId}/bookshelves`;
} else {
endpoint = `v1/mylibrary/bookshelves`;
}
if (returnAll) {
responseData = await googleApiRequestAllItems.call(this, 'items', 'GET', endpoint, {});
} else {
qs.maxResults = this.getNodeParameter('limit', i) as number;
responseData = await googleApiRequest.call(this, 'GET', endpoint, {}, qs);
responseData = responseData.items || [];
}
}
}
if (operation === 'remove') {
const shelfId = this.getNodeParameter('shelfId', i) as string;
const volumeId = this.getNodeParameter('volumeId', i) as string;
const body: IDataObject = {
volumeId,
};
responseData = await googleApiRequest.call(this, 'POST', `v1/mylibrary/bookshelves/${shelfId}/removeVolume`, body);
if (resource === 'bookshelfVolume') {
if (operation === 'add') {
const shelfId = this.getNodeParameter('shelfId', i) as string;
const volumeId = this.getNodeParameter('volumeId', i) as string;
const body: IDataObject = {
volumeId,
};
responseData = await googleApiRequest.call(this, 'POST', `v1/mylibrary/bookshelves/${shelfId}/addVolume`, body);
}
if (operation === 'clear') {
const shelfId = this.getNodeParameter('shelfId', i) as string;
responseData = await googleApiRequest.call(this, 'POST', `v1/mylibrary/bookshelves/${shelfId}/clearVolumes`);
}
if (operation === 'getAll') {
const shelfId = this.getNodeParameter('shelfId', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const myLibrary = this.getNodeParameter('myLibrary', i) as boolean;
let endpoint;
if (myLibrary === false) {
const userId = this.getNodeParameter('userId', i) as string;
endpoint = `v1/users/${userId}/bookshelves/${shelfId}/volumes`;
} else {
endpoint = `v1/mylibrary/bookshelves/${shelfId}/volumes`;
}
if (returnAll) {
responseData = await googleApiRequestAllItems.call(this, 'items', 'GET', endpoint, {});
} else {
qs.maxResults = this.getNodeParameter('limit', i) as number;
responseData = await googleApiRequest.call(this, 'GET', endpoint, {}, qs);
responseData = responseData.items || [];
}
}
if (operation === 'move') {
const shelfId = this.getNodeParameter('shelfId', i) as string;
const volumeId = this.getNodeParameter('volumeId', i) as string;
const volumePosition = this.getNodeParameter('volumePosition', i) as number;
const body: IDataObject = {
volumeId,
volumePosition,
};
responseData = await googleApiRequest.call(this, 'POST', `v1/mylibrary/bookshelves/${shelfId}/moveVolume`, body);
}
if (operation === 'remove') {
const shelfId = this.getNodeParameter('shelfId', i) as string;
const volumeId = this.getNodeParameter('volumeId', i) as string;
const body: IDataObject = {
volumeId,
};
responseData = await googleApiRequest.call(this, 'POST', `v1/mylibrary/bookshelves/${shelfId}/removeVolume`, body);
}
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(responseData)];

View file

@ -30,7 +30,6 @@ export async function googleApiRequest(this: IExecuteFunctions | IExecuteSingleF
if (Object.keys(body).length === 0) {
delete options.body;
}
console.log(options);
//@ts-ignore
return await this.helpers.requestOAuth2.call(this, 'googleCalendarOAuth2Api', options);
} catch (error) {

View file

@ -606,6 +606,12 @@ export class GoogleCalendar implements INodeType {
);
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else if (responseData !== undefined) {
returnData.push(responseData as IDataObject);
}
} catch (error) {
if (this.continueOnFail() !== true) {
throw error;
@ -619,12 +625,6 @@ export class GoogleCalendar implements INodeType {
continue;
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else if (responseData !== undefined) {
returnData.push(responseData as IDataObject);
}
}
return [this.helpers.returnJsonArray(returnData)];
}

View file

@ -101,396 +101,404 @@ export class GoogleContacts implements INodeType {
const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string;
for (let i = 0; i < length; i++) {
if (resource === 'contact') {
//https://developers.google.com/calendar/v3/reference/events/insert
if (operation === 'create') {
const familyName = this.getNodeParameter('familyName', i) as string;
const givenName = this.getNodeParameter('givenName', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
try {
if (resource === 'contact') {
//https://developers.google.com/calendar/v3/reference/events/insert
if (operation === 'create') {
const familyName = this.getNodeParameter('familyName', i) as string;
const givenName = this.getNodeParameter('givenName', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IDataObject = {
names: [
{
familyName,
givenName,
middleName: '',
},
],
};
if (additionalFields.middleName) {
//@ts-ignore
body.names[0].middleName = additionalFields.middleName as string;
}
if (additionalFields.honorificPrefix) {
//@ts-ignore
body.names[0].honorificPrefix = additionalFields.honorificPrefix as string;
}
if (additionalFields.honorificSuffix) {
//@ts-ignore
body.names[0].honorificSuffix = additionalFields.honorificSuffix as string;
}
if (additionalFields.companyUi) {
const companyValues = (additionalFields.companyUi as IDataObject).companyValues as IDataObject[];
body.organizations = companyValues;
}
if (additionalFields.phoneUi) {
const phoneValues = (additionalFields.phoneUi as IDataObject).phoneValues as IDataObject[];
body.phoneNumbers = phoneValues;
}
if (additionalFields.addressesUi) {
const addressesValues = (additionalFields.addressesUi as IDataObject).addressesValues as IDataObject[];
body.addresses = addressesValues;
}
if (additionalFields.relationsUi) {
const relationsValues = (additionalFields.relationsUi as IDataObject).relationsValues as IDataObject[];
body.relations = relationsValues;
}
if (additionalFields.eventsUi) {
const eventsValues = (additionalFields.eventsUi as IDataObject).eventsValues as IDataObject[];
for (let i = 0; i < eventsValues.length; i++) {
const [month, day, year] = moment(eventsValues[i].date as string).format('MM/DD/YYYY').split('/');
eventsValues[i] = {
date: {
day,
month,
year,
const body: IDataObject = {
names: [
{
familyName,
givenName,
middleName: '',
},
type: eventsValues[i].type,
};
],
};
if (additionalFields.middleName) {
//@ts-ignore
body.names[0].middleName = additionalFields.middleName as string;
}
body.events = eventsValues;
}
if (additionalFields.birthday) {
const [month, day, year] = moment(additionalFields.birthday as string).format('MM/DD/YYYY').split('/');
if (additionalFields.honorificPrefix) {
//@ts-ignore
body.names[0].honorificPrefix = additionalFields.honorificPrefix as string;
}
body.birthdays = [
{
date: {
day,
month,
year,
if (additionalFields.honorificSuffix) {
//@ts-ignore
body.names[0].honorificSuffix = additionalFields.honorificSuffix as string;
}
if (additionalFields.companyUi) {
const companyValues = (additionalFields.companyUi as IDataObject).companyValues as IDataObject[];
body.organizations = companyValues;
}
if (additionalFields.phoneUi) {
const phoneValues = (additionalFields.phoneUi as IDataObject).phoneValues as IDataObject[];
body.phoneNumbers = phoneValues;
}
if (additionalFields.addressesUi) {
const addressesValues = (additionalFields.addressesUi as IDataObject).addressesValues as IDataObject[];
body.addresses = addressesValues;
}
if (additionalFields.relationsUi) {
const relationsValues = (additionalFields.relationsUi as IDataObject).relationsValues as IDataObject[];
body.relations = relationsValues;
}
if (additionalFields.eventsUi) {
const eventsValues = (additionalFields.eventsUi as IDataObject).eventsValues as IDataObject[];
for (let i = 0; i < eventsValues.length; i++) {
const [month, day, year] = moment(eventsValues[i].date as string).format('MM/DD/YYYY').split('/');
eventsValues[i] = {
date: {
day,
month,
year,
},
type: eventsValues[i].type,
};
}
body.events = eventsValues;
}
if (additionalFields.birthday) {
const [month, day, year] = moment(additionalFields.birthday as string).format('MM/DD/YYYY').split('/');
body.birthdays = [
{
date: {
day,
month,
year,
},
},
},
];
}
];
}
if (additionalFields.emailsUi) {
const emailsValues = (additionalFields.emailsUi as IDataObject).emailsValues as IDataObject[];
body.emailAddresses = emailsValues;
}
if (additionalFields.emailsUi) {
const emailsValues = (additionalFields.emailsUi as IDataObject).emailsValues as IDataObject[];
body.emailAddresses = emailsValues;
}
if (additionalFields.biographies) {
body.biographies = [
{
value: additionalFields.biographies,
contentType: 'TEXT_PLAIN',
},
];
}
if (additionalFields.customFieldsUi) {
const customFieldsValues = (additionalFields.customFieldsUi as IDataObject).customFieldsValues as IDataObject[];
body.userDefined = customFieldsValues;
}
if (additionalFields.group) {
const memberships = (additionalFields.group as string[]).map((groupId: string) => {
return {
contactGroupMembership: {
contactGroupResourceName: groupId,
if (additionalFields.biographies) {
body.biographies = [
{
value: additionalFields.biographies,
contentType: 'TEXT_PLAIN',
},
};
});
];
}
body.memberships = memberships;
}
if (additionalFields.customFieldsUi) {
const customFieldsValues = (additionalFields.customFieldsUi as IDataObject).customFieldsValues as IDataObject[];
body.userDefined = customFieldsValues;
}
responseData = await googleApiRequest.call(
this,
'POST',
`/people:createContact`,
body,
qs,
);
if (additionalFields.group) {
const memberships = (additionalFields.group as string[]).map((groupId: string) => {
return {
contactGroupMembership: {
contactGroupResourceName: groupId,
},
};
});
responseData.contactId = responseData.resourceName.split('/')[1];
body.memberships = memberships;
}
}
//https://developers.google.com/people/api/rest/v1/people/deleteContact
if (operation === 'delete') {
const contactId = this.getNodeParameter('contactId', i) as string;
responseData = await googleApiRequest.call(
this,
'DELETE',
`/people/${contactId}:deleteContact`,
{},
);
responseData = { success: true };
}
//https://developers.google.com/people/api/rest/v1/people/get
if (operation === 'get') {
const contactId = this.getNodeParameter('contactId', i) as string;
const fields = this.getNodeParameter('fields', i) as string[];
const rawData = this.getNodeParameter('rawData', i) as boolean;
if (fields.includes('*')) {
qs.personFields = allFields.join(',');
} else {
qs.personFields = (fields as string[]).join(',');
}
responseData = await googleApiRequest.call(
this,
'GET',
`/people/${contactId}`,
{},
qs,
);
if (!rawData) {
responseData = cleanData(responseData)[0];
}
responseData.contactId = responseData.resourceName.split('/')[1];
}
//https://developers.google.com/people/api/rest/v1/people.connections/list
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const fields = this.getNodeParameter('fields', i) as string[];
const options = this.getNodeParameter('options', i) as IDataObject;
const rawData = this.getNodeParameter('rawData', i) as boolean;
if (options.sortOrder) {
qs.sortOrder = options.sortOrder as number;
}
if (fields.includes('*')) {
qs.personFields = allFields.join(',');
} else {
qs.personFields = (fields as string[]).join(',');
}
if (returnAll) {
responseData = await googleApiRequestAllItems.call(
this,
'connections',
'GET',
`/people/me/connections`,
{},
qs,
);
} else {
qs.pageSize = this.getNodeParameter('limit', i) as number;
responseData = await googleApiRequest.call(
this,
'GET',
`/people/me/connections`,
{},
'POST',
`/people:createContact`,
body,
qs,
);
responseData = responseData.connections;
responseData.contactId = responseData.resourceName.split('/')[1];
}
if (!rawData) {
responseData = cleanData(responseData);
//https://developers.google.com/people/api/rest/v1/people/deleteContact
if (operation === 'delete') {
const contactId = this.getNodeParameter('contactId', i) as string;
responseData = await googleApiRequest.call(
this,
'DELETE',
`/people/${contactId}:deleteContact`,
{},
);
responseData = { success: true };
}
//https://developers.google.com/people/api/rest/v1/people/get
if (operation === 'get') {
const contactId = this.getNodeParameter('contactId', i) as string;
const fields = this.getNodeParameter('fields', i) as string[];
const rawData = this.getNodeParameter('rawData', i) as boolean;
for (let i = 0; i < responseData.length; i++) {
responseData[i].contactId = responseData[i].resourceName.split('/')[1];
}
}
//https://developers.google.com/people/api/rest/v1/people/updateContact
if (operation === 'update') {
const updatePersonFields = [];
if (fields.includes('*')) {
qs.personFields = allFields.join(',');
} else {
qs.personFields = (fields as string[]).join(',');
}
const contactId = this.getNodeParameter('contactId', i) as string;
const fields = this.getNodeParameter('fields', i) as string[];
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
let etag;
if (updateFields.etag) {
etag = updateFields.etag as string;
} else {
const data = await googleApiRequest.call(
responseData = await googleApiRequest.call(
this,
'GET',
`/people/${contactId}`,
{},
{ personFields: 'Names' },
qs,
);
etag = data.etag;
}
if (fields.includes('*')) {
qs.personFields = allFields.join(',');
} else {
qs.personFields = (fields as string[]).join(',');
}
const body: IDataObject = {
etag,
names: [
{},
],
};
if (updateFields.givenName) {
//@ts-ignore
body.names[0].givenName = updateFields.givenName as string;
}
if (updateFields.familyName) {
//@ts-ignore
body.names[0].familyName = updateFields.familyName as string;
}
if (updateFields.middleName) {
//@ts-ignore
body.names[0].middleName = updateFields.middleName as string;
}
if (updateFields.honorificPrefix) {
//@ts-ignore
body.names[0].honorificPrefix = updateFields.honorificPrefix as string;
}
if (updateFields.honorificSuffix) {
//@ts-ignore
body.names[0].honorificSuffix = updateFields.honorificSuffix as string;
}
if (updateFields.companyUi) {
const companyValues = (updateFields.companyUi as IDataObject).companyValues as IDataObject[];
body.organizations = companyValues;
updatePersonFields.push('organizations');
}
if (updateFields.phoneUi) {
const phoneValues = (updateFields.phoneUi as IDataObject).phoneValues as IDataObject[];
body.phoneNumbers = phoneValues;
updatePersonFields.push('phoneNumbers');
}
if (updateFields.addressesUi) {
const addressesValues = (updateFields.addressesUi as IDataObject).addressesValues as IDataObject[];
body.addresses = addressesValues;
updatePersonFields.push('addresses');
}
if (updateFields.relationsUi) {
const relationsValues = (updateFields.relationsUi as IDataObject).relationsValues as IDataObject[];
body.relations = relationsValues;
updatePersonFields.push('relations');
}
if (updateFields.eventsUi) {
const eventsValues = (updateFields.eventsUi as IDataObject).eventsValues as IDataObject[];
for (let i = 0; i < eventsValues.length; i++) {
const [month, day, year] = moment(eventsValues[i].date as string).format('MM/DD/YYYY').split('/');
eventsValues[i] = {
date: {
day,
month,
year,
},
type: eventsValues[i].type,
};
if (!rawData) {
responseData = cleanData(responseData)[0];
}
body.events = eventsValues;
updatePersonFields.push('events');
responseData.contactId = responseData.resourceName.split('/')[1];
}
//https://developers.google.com/people/api/rest/v1/people.connections/list
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const fields = this.getNodeParameter('fields', i) as string[];
const options = this.getNodeParameter('options', i) as IDataObject;
const rawData = this.getNodeParameter('rawData', i) as boolean;
if (updateFields.birthday) {
const [month, day, year] = moment(updateFields.birthday as string).format('MM/DD/YYYY').split('/');
if (options.sortOrder) {
qs.sortOrder = options.sortOrder as number;
}
body.birthdays = [
{
date: {
day,
month,
year,
if (fields.includes('*')) {
qs.personFields = allFields.join(',');
} else {
qs.personFields = (fields as string[]).join(',');
}
if (returnAll) {
responseData = await googleApiRequestAllItems.call(
this,
'connections',
'GET',
`/people/me/connections`,
{},
qs,
);
} else {
qs.pageSize = this.getNodeParameter('limit', i) as number;
responseData = await googleApiRequest.call(
this,
'GET',
`/people/me/connections`,
{},
qs,
);
responseData = responseData.connections;
}
if (!rawData) {
responseData = cleanData(responseData);
}
for (let i = 0; i < responseData.length; i++) {
responseData[i].contactId = responseData[i].resourceName.split('/')[1];
}
}
//https://developers.google.com/people/api/rest/v1/people/updateContact
if (operation === 'update') {
const updatePersonFields = [];
const contactId = this.getNodeParameter('contactId', i) as string;
const fields = this.getNodeParameter('fields', i) as string[];
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
let etag;
if (updateFields.etag) {
etag = updateFields.etag as string;
} else {
const data = await googleApiRequest.call(
this,
'GET',
`/people/${contactId}`,
{},
{ personFields: 'Names' },
);
etag = data.etag;
}
if (fields.includes('*')) {
qs.personFields = allFields.join(',');
} else {
qs.personFields = (fields as string[]).join(',');
}
const body: IDataObject = {
etag,
names: [
{},
],
};
if (updateFields.givenName) {
//@ts-ignore
body.names[0].givenName = updateFields.givenName as string;
}
if (updateFields.familyName) {
//@ts-ignore
body.names[0].familyName = updateFields.familyName as string;
}
if (updateFields.middleName) {
//@ts-ignore
body.names[0].middleName = updateFields.middleName as string;
}
if (updateFields.honorificPrefix) {
//@ts-ignore
body.names[0].honorificPrefix = updateFields.honorificPrefix as string;
}
if (updateFields.honorificSuffix) {
//@ts-ignore
body.names[0].honorificSuffix = updateFields.honorificSuffix as string;
}
if (updateFields.companyUi) {
const companyValues = (updateFields.companyUi as IDataObject).companyValues as IDataObject[];
body.organizations = companyValues;
updatePersonFields.push('organizations');
}
if (updateFields.phoneUi) {
const phoneValues = (updateFields.phoneUi as IDataObject).phoneValues as IDataObject[];
body.phoneNumbers = phoneValues;
updatePersonFields.push('phoneNumbers');
}
if (updateFields.addressesUi) {
const addressesValues = (updateFields.addressesUi as IDataObject).addressesValues as IDataObject[];
body.addresses = addressesValues;
updatePersonFields.push('addresses');
}
if (updateFields.relationsUi) {
const relationsValues = (updateFields.relationsUi as IDataObject).relationsValues as IDataObject[];
body.relations = relationsValues;
updatePersonFields.push('relations');
}
if (updateFields.eventsUi) {
const eventsValues = (updateFields.eventsUi as IDataObject).eventsValues as IDataObject[];
for (let i = 0; i < eventsValues.length; i++) {
const [month, day, year] = moment(eventsValues[i].date as string).format('MM/DD/YYYY').split('/');
eventsValues[i] = {
date: {
day,
month,
year,
},
type: eventsValues[i].type,
};
}
body.events = eventsValues;
updatePersonFields.push('events');
}
if (updateFields.birthday) {
const [month, day, year] = moment(updateFields.birthday as string).format('MM/DD/YYYY').split('/');
body.birthdays = [
{
date: {
day,
month,
year,
},
},
},
];
];
updatePersonFields.push('birthdays');
}
updatePersonFields.push('birthdays');
}
if (updateFields.emailsUi) {
const emailsValues = (updateFields.emailsUi as IDataObject).emailsValues as IDataObject[];
body.emailAddresses = emailsValues;
updatePersonFields.push('emailAddresses');
}
if (updateFields.emailsUi) {
const emailsValues = (updateFields.emailsUi as IDataObject).emailsValues as IDataObject[];
body.emailAddresses = emailsValues;
updatePersonFields.push('emailAddresses');
}
if (updateFields.biographies) {
body.biographies = [
{
value: updateFields.biographies,
contentType: 'TEXT_PLAIN',
},
];
updatePersonFields.push('biographies');
}
if (updateFields.customFieldsUi) {
const customFieldsValues = (updateFields.customFieldsUi as IDataObject).customFieldsValues as IDataObject[];
body.userDefined = customFieldsValues;
updatePersonFields.push('userDefined');
}
if (updateFields.group) {
const memberships = (updateFields.group as string[]).map((groupId: string) => {
return {
contactGroupMembership: {
contactGroupResourceName: groupId,
if (updateFields.biographies) {
body.biographies = [
{
value: updateFields.biographies,
contentType: 'TEXT_PLAIN',
},
};
});
];
updatePersonFields.push('biographies');
}
body.memberships = memberships;
updatePersonFields.push('memberships');
if (updateFields.customFieldsUi) {
const customFieldsValues = (updateFields.customFieldsUi as IDataObject).customFieldsValues as IDataObject[];
body.userDefined = customFieldsValues;
updatePersonFields.push('userDefined');
}
if (updateFields.group) {
const memberships = (updateFields.group as string[]).map((groupId: string) => {
return {
contactGroupMembership: {
contactGroupResourceName: groupId,
},
};
});
body.memberships = memberships;
updatePersonFields.push('memberships');
}
if ((body.names as IDataObject[]).length > 0) {
updatePersonFields.push('names');
}
qs.updatePersonFields = updatePersonFields.join(',');
responseData = await googleApiRequest.call(
this,
'PATCH',
`/people/${contactId}:updateContact`,
body,
qs,
);
responseData.contactId = responseData.resourceName.split('/')[1];
}
if ((body.names as IDataObject[]).length > 0) {
updatePersonFields.push('names');
}
qs.updatePersonFields = updatePersonFields.join(',');
responseData = await googleApiRequest.call(
this,
'PATCH',
`/people/${contactId}:updateContact`,
body,
qs,
);
responseData.contactId = responseData.resourceName.split('/')[1];
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else if (responseData !== undefined) {
returnData.push(responseData as IDataObject);
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else if (responseData !== undefined) {
returnData.push(responseData as IDataObject);
}
return [this.helpers.returnJsonArray(returnData)];
}
}

View file

@ -1996,436 +1996,448 @@ export class GoogleDrive implements INodeType {
const operation = this.getNodeParameter('operation', 0) as string;
for (let i = 0; i < items.length; i++) {
const options = this.getNodeParameter('options', i, {}) as IDataObject;
try {
const options = this.getNodeParameter('options', i, {}) as IDataObject;
let queryFields = 'id, name';
if (options && options.fields) {
const fields = options.fields as string[];
if (fields.includes('*')) {
queryFields = '*';
} else {
queryFields = fields.join(', ');
}
}
if (resource === 'drive') {
if (operation === 'create') {
// ----------------------------------
// create
// ----------------------------------
const name = this.getNodeParameter('name', i) as string;
const body: IDataObject = {
name,
};
Object.assign(body, options);
const response = await googleApiRequest.call(this, 'POST', `/drive/v3/drives`, body, { requestId: uuid() });
returnData.push(response as IDataObject);
}
if (operation === 'delete') {
// ----------------------------------
// delete
// ----------------------------------
const driveId = this.getNodeParameter('driveId', i) as string;
await googleApiRequest.call(this, 'DELETE', `/drive/v3/drives/${driveId}`);
returnData.push({ success: true });
}
if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
const driveId = this.getNodeParameter('driveId', i) as string;
const qs: IDataObject = {};
Object.assign(qs, options);
const response = await googleApiRequest.call(this, 'GET', `/drive/v3/drives/${driveId}`, {}, qs);
returnData.push(response as IDataObject);
}
if (operation === 'list') {
// ----------------------------------
// list
// ----------------------------------
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const qs: IDataObject = {};
let response: IDataObject[] = [];
Object.assign(qs, options);
if (returnAll === true) {
response = await googleApiRequestAllItems.call(this, 'drives', 'GET', `/drive/v3/drives`, {}, qs);
let queryFields = 'id, name';
if (options && options.fields) {
const fields = options.fields as string[];
if (fields.includes('*')) {
queryFields = '*';
} else {
qs.pageSize = this.getNodeParameter('limit', i) as number;
const data = await googleApiRequest.call(this, 'GET', `/drive/v3/drives`, {}, qs);
response = data.drives as IDataObject[];
queryFields = fields.join(', ');
}
returnData.push.apply(returnData, response);
}
if (operation === 'update') {
// ----------------------------------
// update
// ----------------------------------
const driveId = this.getNodeParameter('driveId', i) as string;
const body: IDataObject = {};
Object.assign(body, options);
const response = await googleApiRequest.call(this, 'PATCH', `/drive/v3/drives/${driveId}`, body);
returnData.push(response as IDataObject);
}
}
if (resource === 'file') {
if (operation === 'copy') {
// ----------------------------------
// copy
// ----------------------------------
if (resource === 'drive') {
if (operation === 'create') {
// ----------------------------------
// create
// ----------------------------------
const fileId = this.getNodeParameter('fileId', i) as string;
const name = this.getNodeParameter('name', i) as string;
const body: IDataObject = {
fields: queryFields,
};
const body: IDataObject = {
name,
};
const optionProperties = ['name', 'parents'];
for (const propertyName of optionProperties) {
if (options[propertyName] !== undefined) {
body[propertyName] = options[propertyName];
}
Object.assign(body, options);
const response = await googleApiRequest.call(this, 'POST', `/drive/v3/drives`, body, { requestId: uuid() });
returnData.push(response as IDataObject);
}
if (operation === 'delete') {
// ----------------------------------
// delete
// ----------------------------------
const qs = {
supportsAllDrives: true,
};
const driveId = this.getNodeParameter('driveId', i) as string;
const response = await googleApiRequest.call(this, 'POST', `/drive/v3/files/${fileId}/copy`, body, qs);
await googleApiRequest.call(this, 'DELETE', `/drive/v3/drives/${driveId}`);
returnData.push(response as IDataObject);
} else if (operation === 'download') {
// ----------------------------------
// download
// ----------------------------------
const fileId = this.getNodeParameter('fileId', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
const requestOptions = {
resolveWithFullResponse: true,
encoding: null,
json: false,
};
const response = await googleApiRequest.call(this, 'GET', `/drive/v3/files/${fileId}`, {}, { alt: 'media' }, undefined, requestOptions);
let mimeType: string | undefined;
let fileName: string | undefined = undefined;
if (response.headers['content-type']) {
mimeType = response.headers['content-type'];
returnData.push({ success: true });
}
if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
if (options.fileName) {
fileName = options.fileName as string;
const driveId = this.getNodeParameter('driveId', i) as string;
const qs: IDataObject = {};
Object.assign(qs, options);
const response = await googleApiRequest.call(this, 'GET', `/drive/v3/drives/${driveId}`, {}, qs);
returnData.push(response as IDataObject);
}
if (operation === 'list') {
// ----------------------------------
// list
// ----------------------------------
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const newItem: INodeExecutionData = {
json: items[i].json,
binary: {},
};
const qs: IDataObject = {};
if (items[i].binary !== undefined) {
// Create a shallow copy of the binary data so that the old
// data references which do not get changed still stay behind
// but the incoming data does not get changed.
Object.assign(newItem.binary, items[i].binary);
}
let response: IDataObject[] = [];
items[i] = newItem;
Object.assign(qs, options);
const dataPropertyNameDownload = this.getNodeParameter('binaryPropertyName', i) as string;
const data = Buffer.from(response.body as string);
items[i].binary![dataPropertyNameDownload] = await this.helpers.prepareBinaryData(data as unknown as Buffer, fileName, mimeType);
} else if (operation === 'list') {
// ----------------------------------
// list
// ----------------------------------
let querySpaces = '';
if (options.spaces) {
const spaces = options.spaces as string[];
if (spaces.includes('*')) {
querySpaces = 'appDataFolder, drive, photos';
if (returnAll === true) {
response = await googleApiRequestAllItems.call(this, 'drives', 'GET', `/drive/v3/drives`, {}, qs);
} else {
querySpaces = spaces.join(', ');
}
}
let queryCorpora = '';
if (options.corpora) {
queryCorpora = options.corpora as string;
}
let driveId: string | undefined;
driveId = options.driveId as string;
if (driveId === '') {
driveId = undefined;
}
let queryString = '';
const useQueryString = this.getNodeParameter('useQueryString', i) as boolean;
if (useQueryString === true) {
// Use the user defined query string
queryString = this.getNodeParameter('queryString', i) as string;
} else {
// Build query string out of parameters set by user
const queryFilters = this.getNodeParameter('queryFilters', i) as IDataObject;
const queryFilterFields: string[] = [];
if (queryFilters.name) {
(queryFilters.name as IDataObject[]).forEach(nameFilter => {
let operation = nameFilter.operation;
if (operation === 'is') {
operation = '=';
} else if (operation === 'isNot') {
operation = '!=';
}
queryFilterFields.push(`name ${operation} '${nameFilter.value}'`);
});
queryString += queryFilterFields.join(' or ');
qs.pageSize = this.getNodeParameter('limit', i) as number;
const data = await googleApiRequest.call(this, 'GET', `/drive/v3/drives`, {}, qs);
response = data.drives as IDataObject[];
}
queryFilterFields.length = 0;
if (queryFilters.mimeType) {
(queryFilters.mimeType as IDataObject[]).forEach(mimeTypeFilter => {
let mimeType = mimeTypeFilter.mimeType;
if (mimeTypeFilter.mimeType === 'custom') {
mimeType = mimeTypeFilter.customMimeType;
}
queryFilterFields.push(`mimeType = '${mimeType}'`);
});
returnData.push.apply(returnData, response);
}
if (operation === 'update') {
// ----------------------------------
// update
// ----------------------------------
if (queryFilterFields.length) {
if (queryString !== '') {
queryString += ' and ';
}
const driveId = this.getNodeParameter('driveId', i) as string;
const body: IDataObject = {};
Object.assign(body, options);
const response = await googleApiRequest.call(this, 'PATCH', `/drive/v3/drives/${driveId}`, body);
returnData.push(response as IDataObject);
}
}
if (resource === 'file') {
if (operation === 'copy') {
// ----------------------------------
// copy
// ----------------------------------
const fileId = this.getNodeParameter('fileId', i) as string;
const body: IDataObject = {
fields: queryFields,
};
const optionProperties = ['name', 'parents'];
for (const propertyName of optionProperties) {
if (options[propertyName] !== undefined) {
body[propertyName] = options[propertyName];
}
}
const qs = {
supportsAllDrives: true,
};
const response = await googleApiRequest.call(this, 'POST', `/drive/v3/files/${fileId}/copy`, body, qs);
returnData.push(response as IDataObject);
} else if (operation === 'download') {
// ----------------------------------
// download
// ----------------------------------
const fileId = this.getNodeParameter('fileId', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
const requestOptions = {
resolveWithFullResponse: true,
encoding: null,
json: false,
};
const response = await googleApiRequest.call(this, 'GET', `/drive/v3/files/${fileId}`, {}, { alt: 'media' }, undefined, requestOptions);
let mimeType: string | undefined;
let fileName: string | undefined = undefined;
if (response.headers['content-type']) {
mimeType = response.headers['content-type'];
}
if (options.fileName) {
fileName = options.fileName as string;
}
const newItem: INodeExecutionData = {
json: items[i].json,
binary: {},
};
if (items[i].binary !== undefined) {
// Create a shallow copy of the binary data so that the old
// data references which do not get changed still stay behind
// but the incoming data does not get changed.
Object.assign(newItem.binary, items[i].binary);
}
items[i] = newItem;
const dataPropertyNameDownload = this.getNodeParameter('binaryPropertyName', i) as string;
const data = Buffer.from(response.body as string);
items[i].binary![dataPropertyNameDownload] = await this.helpers.prepareBinaryData(data as unknown as Buffer, fileName, mimeType);
} else if (operation === 'list') {
// ----------------------------------
// list
// ----------------------------------
let querySpaces = '';
if (options.spaces) {
const spaces = options.spaces as string[];
if (spaces.includes('*')) {
querySpaces = 'appDataFolder, drive, photos';
} else {
querySpaces = spaces.join(', ');
}
}
let queryCorpora = '';
if (options.corpora) {
queryCorpora = options.corpora as string;
}
let driveId: string | undefined;
driveId = options.driveId as string;
if (driveId === '') {
driveId = undefined;
}
let queryString = '';
const useQueryString = this.getNodeParameter('useQueryString', i) as boolean;
if (useQueryString === true) {
// Use the user defined query string
queryString = this.getNodeParameter('queryString', i) as string;
} else {
// Build query string out of parameters set by user
const queryFilters = this.getNodeParameter('queryFilters', i) as IDataObject;
const queryFilterFields: string[] = [];
if (queryFilters.name) {
(queryFilters.name as IDataObject[]).forEach(nameFilter => {
let operation = nameFilter.operation;
if (operation === 'is') {
operation = '=';
} else if (operation === 'isNot') {
operation = '!=';
}
queryFilterFields.push(`name ${operation} '${nameFilter.value}'`);
});
queryString += queryFilterFields.join(' or ');
}
queryFilterFields.length = 0;
if (queryFilters.mimeType) {
(queryFilters.mimeType as IDataObject[]).forEach(mimeTypeFilter => {
let mimeType = mimeTypeFilter.mimeType;
if (mimeTypeFilter.mimeType === 'custom') {
mimeType = mimeTypeFilter.customMimeType;
}
queryFilterFields.push(`mimeType = '${mimeType}'`);
});
if (queryFilterFields.length) {
if (queryString !== '') {
queryString += ' and ';
}
queryString += queryFilterFields.join(' or ');
}
}
}
const pageSize = this.getNodeParameter('limit', i) as number;
const qs = {
pageSize,
orderBy: 'modifiedTime',
fields: `nextPageToken, files(${queryFields})`,
spaces: querySpaces,
q: queryString,
includeItemsFromAllDrives: (queryCorpora !== '' || driveId !== ''),
supportsAllDrives: (queryCorpora !== '' || driveId !== ''),
};
const response = await googleApiRequest.call(this, 'GET', `/drive/v3/files`, {}, qs);
const files = response!.files;
return [this.helpers.returnJsonArray(files as IDataObject[])];
} else if (operation === 'upload') {
// ----------------------------------
// upload
// ----------------------------------
const resolveData = this.getNodeParameter('resolveData', 0) as boolean;
let mimeType = 'text/plain';
let body;
let originalFilename: string | undefined;
if (this.getNodeParameter('binaryData', i) === true) {
// Is binary file to upload
const item = items[i];
if (item.binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
}
const propertyNameUpload = this.getNodeParameter('binaryPropertyName', i) as string;
if (item.binary[propertyNameUpload] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property "${propertyNameUpload}" does not exists on item!`);
}
if (item.binary[propertyNameUpload].mimeType) {
mimeType = item.binary[propertyNameUpload].mimeType;
}
if (item.binary[propertyNameUpload].fileName) {
originalFilename = item.binary[propertyNameUpload].fileName;
}
body = Buffer.from(item.binary[propertyNameUpload].data, BINARY_ENCODING);
} else {
// Is text file
body = Buffer.from(this.getNodeParameter('fileContent', i) as string, 'utf8');
}
const name = this.getNodeParameter('name', i) as string;
const parents = this.getNodeParameter('parents', i) as string[];
let qs: IDataObject = {
fields: queryFields,
uploadType: 'media',
};
const requestOptions = {
headers: {
'Content-Type': mimeType,
'Content-Length': body.byteLength,
},
encoding: null,
json: false,
};
let response = await googleApiRequest.call(this, 'POST', `/upload/drive/v3/files`, body, qs, undefined, requestOptions);
body = {
mimeType,
name,
originalFilename,
};
const properties = this.getNodeParameter('options.propertiesUi.propertyValues', i, []) as IDataObject[];
if (properties.length) {
Object.assign(body, { properties: properties.reduce((obj, value) => Object.assign(obj, { [`${value.key}`]: value.value }), {}) } );
}
const appProperties = this.getNodeParameter('options.appPropertiesUi.appPropertyValues', i, []) as IDataObject[];
if (properties.length) {
Object.assign(body, { appProperties: appProperties.reduce((obj, value) => Object.assign(obj, { [`${value.key}`]: value.value }), {}) });
}
qs = {
addParents: parents.join(','),
// When set to true shared drives can be used.
supportsAllDrives: true,
};
response = await googleApiRequest.call(this, 'PATCH', `/drive/v3/files/${JSON.parse(response).id}`, body, qs);
if (resolveData === true) {
response = await googleApiRequest.call(this, 'GET', `/drive/v3/files/${response.id}`, {}, { fields: '*' });
}
returnData.push(response as IDataObject);
} else if (operation === 'update') {
// ----------------------------------
// file:update
// ----------------------------------
const id = this.getNodeParameter('fileId', i) as string;
const updateFields = this.getNodeParameter('updateFields', i, {}) as IDataObject;
const qs: IDataObject = {
supportsAllDrives: true,
};
Object.assign(qs, options);
qs.fields = queryFields;
if (updateFields.parentId && updateFields.parentId !== '') {
qs.addParents = updateFields.parentId;
}
const responseData = await googleApiRequest.call(this, 'PATCH', `/drive/v3/files/${id}`, {}, qs);
returnData.push(responseData as IDataObject);
}
const pageSize = this.getNodeParameter('limit', i) as number;
}
if (resource === 'folder') {
if (operation === 'create') {
// ----------------------------------
// folder:create
// ----------------------------------
const qs = {
pageSize,
orderBy: 'modifiedTime',
fields: `nextPageToken, files(${queryFields})`,
spaces: querySpaces,
q: queryString,
includeItemsFromAllDrives: (queryCorpora !== '' || driveId !== ''),
supportsAllDrives: (queryCorpora !== '' || driveId !== ''),
};
const name = this.getNodeParameter('name', i) as string;
const response = await googleApiRequest.call(this, 'GET', `/drive/v3/files`, {}, qs);
const body = {
name,
mimeType: 'application/vnd.google-apps.folder',
parents: options.parents || [],
};
const files = response!.files;
const qs = {
fields: queryFields,
supportsAllDrives: true,
};
return [this.helpers.returnJsonArray(files as IDataObject[])];
const response = await googleApiRequest.call(this, 'POST', '/drive/v3/files', body, qs);
} else if (operation === 'upload') {
// ----------------------------------
// upload
// ----------------------------------
const resolveData = this.getNodeParameter('resolveData', 0) as boolean;
returnData.push(response as IDataObject);
}
}
if (['file', 'folder'].includes(resource)) {
if (operation === 'delete') {
// ----------------------------------
// delete
// ----------------------------------
let mimeType = 'text/plain';
let body;
let originalFilename: string | undefined;
if (this.getNodeParameter('binaryData', i) === true) {
// Is binary file to upload
const item = items[i];
const fileId = this.getNodeParameter('fileId', i) as string;
if (item.binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
const response = await googleApiRequest.call(this, 'DELETE', `/drive/v3/files/${fileId}`);
// If we are still here it did succeed
returnData.push({
fileId,
success: true,
});
}
if (operation === 'share') {
const fileId = this.getNodeParameter('fileId', i) as string;
const permissions = this.getNodeParameter('permissionsUi', i) as IDataObject;
const options = this.getNodeParameter('options', i) as IDataObject;
const body: IDataObject = {};
const qs: IDataObject = {};
if (permissions.permissionsValues) {
Object.assign(body, permissions.permissionsValues);
}
const propertyNameUpload = this.getNodeParameter('binaryPropertyName', i) as string;
Object.assign(qs, options);
if (item.binary[propertyNameUpload] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property "${propertyNameUpload}" does not exists on item!`);
}
const response = await googleApiRequest.call(this, 'POST', `/drive/v3/files/${fileId}/permissions`, body, qs);
if (item.binary[propertyNameUpload].mimeType) {
mimeType = item.binary[propertyNameUpload].mimeType;
}
if (item.binary[propertyNameUpload].fileName) {
originalFilename = item.binary[propertyNameUpload].fileName;
}
body = Buffer.from(item.binary[propertyNameUpload].data, BINARY_ENCODING);
returnData.push(response as IDataObject);
}
}
} catch (error) {
if (this.continueOnFail()) {
if (resource === 'file' && operation === 'download') {
items[i].json = { error: error.message };
} else {
// Is text file
body = Buffer.from(this.getNodeParameter('fileContent', i) as string, 'utf8');
returnData.push({ error: error.message });
}
const name = this.getNodeParameter('name', i) as string;
const parents = this.getNodeParameter('parents', i) as string[];
let qs: IDataObject = {
fields: queryFields,
uploadType: 'media',
};
const requestOptions = {
headers: {
'Content-Type': mimeType,
'Content-Length': body.byteLength,
},
encoding: null,
json: false,
};
let response = await googleApiRequest.call(this, 'POST', `/upload/drive/v3/files`, body, qs, undefined, requestOptions);
body = {
mimeType,
name,
originalFilename,
};
const properties = this.getNodeParameter('options.propertiesUi.propertyValues', i, []) as IDataObject[];
if (properties.length) {
Object.assign(body, { properties: properties.reduce((obj, value) => Object.assign(obj, { [`${value.key}`]: value.value }), {}) } );
}
const appProperties = this.getNodeParameter('options.appPropertiesUi.appPropertyValues', i, []) as IDataObject[];
if (properties.length) {
Object.assign(body, { appProperties: appProperties.reduce((obj, value) => Object.assign(obj, { [`${value.key}`]: value.value }), {}) });
}
qs = {
addParents: parents.join(','),
// When set to true shared drives can be used.
supportsAllDrives: true,
};
response = await googleApiRequest.call(this, 'PATCH', `/drive/v3/files/${JSON.parse(response).id}`, body, qs);
if (resolveData === true) {
response = await googleApiRequest.call(this, 'GET', `/drive/v3/files/${response.id}`, {}, { fields: '*' });
}
returnData.push(response as IDataObject);
} else if (operation === 'update') {
// ----------------------------------
// file:update
// ----------------------------------
const id = this.getNodeParameter('fileId', i) as string;
const updateFields = this.getNodeParameter('updateFields', i, {}) as IDataObject;
const qs: IDataObject = {
supportsAllDrives: true,
};
Object.assign(qs, options);
qs.fields = queryFields;
if (updateFields.parentId && updateFields.parentId !== '') {
qs.addParents = updateFields.parentId;
}
const responseData = await googleApiRequest.call(this, 'PATCH', `/drive/v3/files/${id}`, {}, qs);
returnData.push(responseData as IDataObject);
}
}
if (resource === 'folder') {
if (operation === 'create') {
// ----------------------------------
// folder:create
// ----------------------------------
const name = this.getNodeParameter('name', i) as string;
const body = {
name,
mimeType: 'application/vnd.google-apps.folder',
parents: options.parents || [],
};
const qs = {
fields: queryFields,
supportsAllDrives: true,
};
const response = await googleApiRequest.call(this, 'POST', '/drive/v3/files', body, qs);
returnData.push(response as IDataObject);
}
}
if (['file', 'folder'].includes(resource)) {
if (operation === 'delete') {
// ----------------------------------
// delete
// ----------------------------------
const fileId = this.getNodeParameter('fileId', i) as string;
const response = await googleApiRequest.call(this, 'DELETE', `/drive/v3/files/${fileId}`);
// If we are still here it did succeed
returnData.push({
fileId,
success: true,
});
}
if (operation === 'share') {
const fileId = this.getNodeParameter('fileId', i) as string;
const permissions = this.getNodeParameter('permissionsUi', i) as IDataObject;
const options = this.getNodeParameter('options', i) as IDataObject;
const body: IDataObject = {};
const qs: IDataObject = {};
if (permissions.permissionsValues) {
Object.assign(body, permissions.permissionsValues);
}
Object.assign(qs, options);
const response = await googleApiRequest.call(this, 'POST', `/drive/v3/files/${fileId}/permissions`, body, qs);
returnData.push(response as IDataObject);
continue;
}
throw error;
}
}
if (resource === 'file' && operation === 'download') {

View file

@ -150,49 +150,56 @@ export class RealtimeDatabase implements INodeType {
}
for (let i = 0; i < length; i++) {
const projectId = this.getNodeParameter('projectId', i) as string;
let method = 'GET', attributes = '';
const document: IDataObject = {};
if (operation === 'create') {
method = 'PUT';
attributes = this.getNodeParameter('attributes', i) as string;
} else if (operation === 'delete') {
method = 'DELETE';
} else if (operation === 'get') {
method = 'GET';
} else if (operation === 'push') {
method = 'POST';
attributes = this.getNodeParameter('attributes', i) as string;
} else if (operation === 'update') {
method = 'PATCH';
attributes = this.getNodeParameter('attributes', i) as string;
}
if (attributes) {
const attributeList = attributes.split(',').map(el => el.trim());
attributeList.map((attribute: string) => {
if (items[i].json.hasOwnProperty(attribute)) {
document[attribute] = items[i].json[attribute];
}
});
}
responseData = await googleApiRequest.call(
this,
projectId,
method,
this.getNodeParameter('path', i) as string,
document,
);
if (responseData === null) {
if (operation === 'get') {
throw new NodeApiError(this.getNode(), responseData, { message: `Requested entity was not found.` });
} else if (method === 'DELETE') {
responseData = { success: true };
try {
const projectId = this.getNodeParameter('projectId', i) as string;
let method = 'GET', attributes = '';
const document: IDataObject = {};
if (operation === 'create') {
method = 'PUT';
attributes = this.getNodeParameter('attributes', i) as string;
} else if (operation === 'delete') {
method = 'DELETE';
} else if (operation === 'get') {
method = 'GET';
} else if (operation === 'push') {
method = 'POST';
attributes = this.getNodeParameter('attributes', i) as string;
} else if (operation === 'update') {
method = 'PATCH';
attributes = this.getNodeParameter('attributes', i) as string;
}
}
if (attributes) {
const attributeList = attributes.split(',').map(el => el.trim());
attributeList.map((attribute: string) => {
if (items[i].json.hasOwnProperty(attribute)) {
document[attribute] = items[i].json[attribute];
}
});
}
responseData = await googleApiRequest.call(
this,
projectId,
method,
this.getNodeParameter('path', i) as string,
document,
);
if (responseData === null) {
if (operation === 'get') {
throw new NodeApiError(this.getNode(), responseData, { message: `Requested entity was not found.` });
} else if (method === 'DELETE') {
responseData = { success: true };
}
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else if (typeof responseData === 'string' || typeof responseData === 'number') {

File diff suppressed because it is too large Load diff

View file

@ -1034,60 +1034,81 @@ export class GoogleSheets implements INodeType {
// ----------------------------------
// append
// ----------------------------------
const keyRow = parseInt(this.getNodeParameter('keyRow', 0) as string, 10);
try {
const keyRow = parseInt(this.getNodeParameter('keyRow', 0) as string, 10);
const items = this.getInputData();
const items = this.getInputData();
const setData: IDataObject[] = [];
items.forEach((item) => {
setData.push(item.json);
});
const setData: IDataObject[] = [];
items.forEach((item) => {
setData.push(item.json);
});
// Convert data into array format
const data = await sheet.appendSheetData(setData, sheet.encodeRange(range), keyRow, valueInputMode);
// Convert data into array format
const data = await sheet.appendSheetData(setData, sheet.encodeRange(range), keyRow, valueInputMode);
// TODO: Should add this data somewhere
// TODO: Should have something like add metadata which does not get passed through
// TODO: Should add this data somewhere
// TODO: Should have something like add metadata which does not get passed through
return this.prepareOutputData(items);
return this.prepareOutputData(items);
} catch (error) {
if (this.continueOnFail()) {
return this.prepareOutputData([{json:{ error: error.message }}]);
}
throw error;
}
} else if (operation === 'clear') {
// ----------------------------------
// clear
// ----------------------------------
try {
await sheet.clearData(sheet.encodeRange(range));
await sheet.clearData(sheet.encodeRange(range));
const items = this.getInputData();
return this.prepareOutputData(items);
const items = this.getInputData();
return this.prepareOutputData(items);
} catch (error) {
if (this.continueOnFail()) {
return this.prepareOutputData([{json:{ error: error.message }}]);
}
throw error;
}
} else if (operation === 'create') {
const returnData: IDataObject[] = [];
let responseData;
for (let i = 0; i < this.getInputData().length; i++) {
const spreadsheetId = this.getNodeParameter('sheetId', i) as string;
const options = this.getNodeParameter('options', i, {}) as IDataObject;
const simple = this.getNodeParameter('simple', 0) as boolean;
const properties = { ...options };
try {
const spreadsheetId = this.getNodeParameter('sheetId', i) as string;
const options = this.getNodeParameter('options', i, {}) as IDataObject;
const simple = this.getNodeParameter('simple', 0) as boolean;
const properties = { ...options };
if (options.tabColor) {
const { red, green, blue } = hexToRgb(options.tabColor as string)!;
properties.tabColor = { red: red / 255, green: green / 255, blue: blue / 255 };
if (options.tabColor) {
const { red, green, blue } = hexToRgb(options.tabColor as string)!;
properties.tabColor = { red: red / 255, green: green / 255, blue: blue / 255 };
}
const requests = [{
addSheet: {
properties,
},
}];
responseData = await googleApiRequest.call(this, 'POST', `/v4/spreadsheets/${spreadsheetId}:batchUpdate`, { requests });
if (simple === true) {
Object.assign(responseData, responseData.replies[0].addSheet.properties);
delete responseData.replies;
}
returnData.push(responseData);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
const requests = [{
addSheet: {
properties,
},
}];
responseData = await googleApiRequest.call(this, 'POST', `/v4/spreadsheets/${spreadsheetId}:batchUpdate`, { requests });
if (simple === true) {
Object.assign(responseData, responseData.replies[0].addSheet.properties);
delete responseData.replies;
}
returnData.push(responseData);
}
return [this.helpers.returnJsonArray(returnData)];
@ -1096,119 +1117,145 @@ export class GoogleSheets implements INodeType {
// ----------------------------------
// delete
// ----------------------------------
try {
const requests: IDataObject[] = [];
const requests: IDataObject[] = [];
const toDelete = this.getNodeParameter('toDelete', 0) as IToDelete;
const toDelete = this.getNodeParameter('toDelete', 0) as IToDelete;
const deletePropertyToDimensions: IDataObject = {
'columns': 'COLUMNS',
'rows': 'ROWS',
};
const deletePropertyToDimensions: IDataObject = {
'columns': 'COLUMNS',
'rows': 'ROWS',
};
for (const propertyName of Object.keys(deletePropertyToDimensions)) {
if (toDelete[propertyName] !== undefined) {
toDelete[propertyName]!.forEach(range => {
requests.push({
deleteDimension: {
range: {
sheetId: range.sheetId,
dimension: deletePropertyToDimensions[propertyName] as string,
startIndex: range.startIndex,
endIndex: parseInt(range.startIndex.toString(), 10) + parseInt(range.amount.toString(), 10),
for (const propertyName of Object.keys(deletePropertyToDimensions)) {
if (toDelete[propertyName] !== undefined) {
toDelete[propertyName]!.forEach(range => {
requests.push({
deleteDimension: {
range: {
sheetId: range.sheetId,
dimension: deletePropertyToDimensions[propertyName] as string,
startIndex: range.startIndex,
endIndex: parseInt(range.startIndex.toString(), 10) + parseInt(range.amount.toString(), 10),
},
},
},
});
});
});
}
}
const data = await sheet.spreadsheetBatchUpdate(requests);
const items = this.getInputData();
return this.prepareOutputData(items);
} catch (error) {
if (this.continueOnFail()) {
return this.prepareOutputData([{json:{ error: error.message }}]);
}
throw error;
}
const data = await sheet.spreadsheetBatchUpdate(requests);
const items = this.getInputData();
return this.prepareOutputData(items);
} else if (operation === 'lookup') {
// ----------------------------------
// lookup
// ----------------------------------
try {
const sheetData = await sheet.getData(sheet.encodeRange(range), valueRenderMode);
const sheetData = await sheet.getData(sheet.encodeRange(range), valueRenderMode);
if (sheetData === undefined) {
return [];
}
if (sheetData === undefined) {
return [];
const dataStartRow = parseInt(this.getNodeParameter('dataStartRow', 0) as string, 10);
const keyRow = parseInt(this.getNodeParameter('keyRow', 0) as string, 10);
const items = this.getInputData();
const lookupValues: ILookupValues[] = [];
for (let i = 0; i < items.length; i++) {
lookupValues.push({
lookupColumn: this.getNodeParameter('lookupColumn', i) as string,
lookupValue: this.getNodeParameter('lookupValue', i) as string,
});
}
let returnData = await sheet.lookupValues(sheetData, keyRow, dataStartRow, lookupValues, options.returnAllMatches as boolean | undefined);
if (returnData.length === 0 && options.continue && options.returnAllMatches) {
returnData = [{}];
} else if (returnData.length === 1 && Object.keys(returnData[0]).length === 0 && !options.continue && !options.returnAllMatches) {
returnData = [];
}
return [this.helpers.returnJsonArray(returnData)];
} catch (error) {
if (this.continueOnFail()) {
return [this.helpers.returnJsonArray({ error: error.message })];
}
throw error;
}
const dataStartRow = parseInt(this.getNodeParameter('dataStartRow', 0) as string, 10);
const keyRow = parseInt(this.getNodeParameter('keyRow', 0) as string, 10);
const items = this.getInputData();
const lookupValues: ILookupValues[] = [];
for (let i = 0; i < items.length; i++) {
lookupValues.push({
lookupColumn: this.getNodeParameter('lookupColumn', i) as string,
lookupValue: this.getNodeParameter('lookupValue', i) as string,
});
}
let returnData = await sheet.lookupValues(sheetData, keyRow, dataStartRow, lookupValues, options.returnAllMatches as boolean | undefined);
if (returnData.length === 0 && options.continue && options.returnAllMatches) {
returnData = [{}];
} else if (returnData.length === 1 && Object.keys(returnData[0]).length === 0 && !options.continue && !options.returnAllMatches) {
returnData = [];
}
return [this.helpers.returnJsonArray(returnData)];
} else if (operation === 'read') {
// ----------------------------------
// read
// ----------------------------------
try {
const rawData = this.getNodeParameter('rawData', 0) as boolean;
const rawData = this.getNodeParameter('rawData', 0) as boolean;
const sheetData = await sheet.getData(sheet.encodeRange(range), valueRenderMode);
const sheetData = await sheet.getData(sheet.encodeRange(range), valueRenderMode);
let returnData: IDataObject[];
if (!sheetData) {
returnData = [];
} else if (rawData === true) {
const dataProperty = this.getNodeParameter('dataProperty', 0) as string;
returnData = [
{
[dataProperty]: sheetData,
},
];
} else {
const dataStartRow = parseInt(this.getNodeParameter('dataStartRow', 0) as string, 10);
const keyRow = parseInt(this.getNodeParameter('keyRow', 0) as string, 10);
let returnData: IDataObject[];
if (!sheetData) {
returnData = [];
} else if (rawData === true) {
const dataProperty = this.getNodeParameter('dataProperty', 0) as string;
returnData = [
{
[dataProperty]: sheetData,
},
];
} else {
const dataStartRow = parseInt(this.getNodeParameter('dataStartRow', 0) as string, 10);
const keyRow = parseInt(this.getNodeParameter('keyRow', 0) as string, 10);
returnData = sheet.structureArrayDataByColumn(sheetData, keyRow, dataStartRow);
}
returnData = sheet.structureArrayDataByColumn(sheetData, keyRow, dataStartRow);
if (returnData.length === 0 && options.continue) {
returnData = [{}];
}
return [this.helpers.returnJsonArray(returnData)];
} catch (error) {
if (this.continueOnFail()) {
return [this.helpers.returnJsonArray({ error: error.message })];
}
throw error;
}
if (returnData.length === 0 && options.continue) {
returnData = [{}];
}
return [this.helpers.returnJsonArray(returnData)];
} else if (operation === 'remove') {
const returnData: IDataObject[] = [];
let responseData;
for (let i = 0; i < this.getInputData().length; i++) {
const sheetId = this.getNodeParameter('id', i) as string;
const spreadsheetId = this.getNodeParameter('sheetId', i) as string;
try {
const sheetId = this.getNodeParameter('id', i) as string;
const spreadsheetId = this.getNodeParameter('sheetId', i) as string;
const requests = [{
deleteSheet: {
sheetId,
},
}];
const requests = [{
deleteSheet: {
sheetId,
},
}];
responseData = await googleApiRequest.call(this, 'POST', `/v4/spreadsheets/${spreadsheetId}:batchUpdate`, { requests });
delete responseData.replies;
returnData.push(responseData);
responseData = await googleApiRequest.call(this, 'POST', `/v4/spreadsheets/${spreadsheetId}:batchUpdate`, { requests });
delete responseData.replies;
returnData.push(responseData);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];
@ -1216,40 +1263,46 @@ export class GoogleSheets implements INodeType {
// ----------------------------------
// update
// ----------------------------------
try {
const rawData = this.getNodeParameter('rawData', 0) as boolean;
const rawData = this.getNodeParameter('rawData', 0) as boolean;
const items = this.getInputData();
const items = this.getInputData();
if (rawData === true) {
const dataProperty = this.getNodeParameter('dataProperty', 0) as string;
if (rawData === true) {
const dataProperty = this.getNodeParameter('dataProperty', 0) as string;
const updateData: ISheetUpdateData[] = [];
for (let i = 0; i < items.length; i++) {
updateData.push({
range,
values: items[i].json[dataProperty] as string[][],
});
}
const updateData: ISheetUpdateData[] = [];
for (let i = 0; i < items.length; i++) {
updateData.push({
range,
values: items[i].json[dataProperty] as string[][],
const data = await sheet.batchUpdate(updateData, valueInputMode);
} else {
const keyName = this.getNodeParameter('key', 0) as string;
const keyRow = parseInt(this.getNodeParameter('keyRow', 0) as string, 10);
const dataStartRow = parseInt(this.getNodeParameter('dataStartRow', 0) as string, 10);
const setData: IDataObject[] = [];
items.forEach((item) => {
setData.push(item.json);
});
const data = await sheet.updateSheetData(setData, keyName, range, keyRow, dataStartRow, valueInputMode, valueRenderMode);
}
// TODO: Should add this data somewhere
// TODO: Should have something like add metadata which does not get passed through
const data = await sheet.batchUpdate(updateData, valueInputMode);
} else {
const keyName = this.getNodeParameter('key', 0) as string;
const keyRow = parseInt(this.getNodeParameter('keyRow', 0) as string, 10);
const dataStartRow = parseInt(this.getNodeParameter('dataStartRow', 0) as string, 10);
const setData: IDataObject[] = [];
items.forEach((item) => {
setData.push(item.json);
});
const data = await sheet.updateSheetData(setData, keyName, range, keyRow, dataStartRow, valueInputMode, valueRenderMode);
return this.prepareOutputData(items);
} catch (error) {
if (this.continueOnFail()) {
return this.prepareOutputData([{json:{ error: error.message }}]);
}
throw error;
}
// TODO: Should add this data somewhere
// TODO: Should have something like add metadata which does not get passed through
return this.prepareOutputData(items);
}
}
@ -1267,39 +1320,46 @@ export class GoogleSheets implements INodeType {
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/create
for (let i = 0; i < this.getInputData().length; i++) {
try {
const title = this.getNodeParameter('title', i) as string;
const sheetsUi = this.getNodeParameter('sheetsUi', i, {}) as IDataObject;
const title = this.getNodeParameter('title', i) as string;
const sheetsUi = this.getNodeParameter('sheetsUi', i, {}) as IDataObject;
const body = {
properties: {
title,
autoRecalc: undefined as undefined | string,
locale: undefined as undefined | string,
},
sheets: [] as IDataObject[],
};
const body = {
properties: {
title,
autoRecalc: undefined as undefined | string,
locale: undefined as undefined | string,
},
sheets: [] as IDataObject[],
};
const options = this.getNodeParameter('options', i, {}) as IDataObject;
const options = this.getNodeParameter('options', i, {}) as IDataObject;
if (Object.keys(sheetsUi).length) {
const data = [];
const sheets = sheetsUi.sheetValues as IDataObject[];
for (const sheet of sheets) {
const properties = sheet.propertiesUi as IDataObject;
if (properties) {
data.push({ properties });
if (Object.keys(sheetsUi).length) {
const data = [];
const sheets = sheetsUi.sheetValues as IDataObject[];
for (const sheet of sheets) {
const properties = sheet.propertiesUi as IDataObject;
if (properties) {
data.push({ properties });
}
}
body.sheets = data;
}
body.sheets = data;
body.properties!.autoRecalc = options.autoRecalc ? (options.autoRecalc as string) : undefined;
body.properties!.locale = options.locale ? (options.locale as string) : undefined;
responseData = await googleApiRequest.call(this, 'POST', `/v4/spreadsheets`, body);
returnData.push(responseData);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
body.properties!.autoRecalc = options.autoRecalc ? (options.autoRecalc as string) : undefined;
body.properties!.locale = options.locale ? (options.locale as string) : undefined;
responseData = await googleApiRequest.call(this, 'POST', `/v4/spreadsheets`, body);
returnData.push(responseData);
}
}

View file

@ -416,136 +416,146 @@ export class GoogleSlides implements INodeType {
for (let i = 0; i < items.length; i++) {
if (resource === 'page') {
try {
// *********************************************************************
// page
// *********************************************************************
if (resource === 'page') {
if (operation === 'get') {
// *********************************************************************
// page
// *********************************************************************
// ----------------------------------
// page: get
// ----------------------------------
if (operation === 'get') {
const presentationId = this.getNodeParameter('presentationId', i) as string;
const pageObjectId = this.getNodeParameter('pageObjectId', i) as string;
responseData = await googleApiRequest.call(this, 'GET', `/presentations/${presentationId}/pages/${pageObjectId}`);
returnData.push({ json: responseData });
// ----------------------------------
// page: get
// ----------------------------------
} else if (operation === 'getThumbnail') {
// ----------------------------------
// page: getThumbnail
// ----------------------------------
const presentationId = this.getNodeParameter('presentationId', i) as string;
const pageObjectId = this.getNodeParameter('pageObjectId', i) as string;
responseData = await googleApiRequest.call(this, 'GET', `/presentations/${presentationId}/pages/${pageObjectId}/thumbnail`);
const download = this.getNodeParameter('download', 0) as boolean;
if (download === true) {
const binaryProperty = this.getNodeParameter('binaryProperty', i) as string;
const data = await this.helpers.request({
uri: responseData.contentUrl,
method: 'GET',
json: false,
encoding: null,
});
const fileName = pageObjectId + '.png';
const binaryData = await this.helpers.prepareBinaryData(data, fileName || fileName);
returnData.push({
json: responseData,
binary: {
[binaryProperty]: binaryData,
},
});
} else {
const presentationId = this.getNodeParameter('presentationId', i) as string;
const pageObjectId = this.getNodeParameter('pageObjectId', i) as string;
responseData = await googleApiRequest.call(this, 'GET', `/presentations/${presentationId}/pages/${pageObjectId}`);
returnData.push({ json: responseData });
}
}
} else if (resource === 'presentation') {
} else if (operation === 'getThumbnail') {
// *********************************************************************
// presentation
// *********************************************************************
// ----------------------------------
// page: getThumbnail
// ----------------------------------
if (operation === 'create') {
const presentationId = this.getNodeParameter('presentationId', i) as string;
const pageObjectId = this.getNodeParameter('pageObjectId', i) as string;
responseData = await googleApiRequest.call(this, 'GET', `/presentations/${presentationId}/pages/${pageObjectId}/thumbnail`);
// ----------------------------------
// presentation: create
// ----------------------------------
const download = this.getNodeParameter('download', 0) as boolean;
if (download === true) {
const binaryProperty = this.getNodeParameter('binaryProperty', i) as string;
const body = {
title: this.getNodeParameter('title', i) as string,
};
const data = await this.helpers.request({
uri: responseData.contentUrl,
method: 'GET',
json: false,
encoding: null,
});
responseData = await googleApiRequest.call(this, 'POST', '/presentations', body);
returnData.push({ json: responseData });
} else if (operation === 'get') {
// ----------------------------------
// presentation: get
// ----------------------------------
const presentationId = this.getNodeParameter('presentationId', i) as string;
responseData = await googleApiRequest.call(this, 'GET', `/presentations/${presentationId}`);
returnData.push({ json: responseData });
} else if (operation === 'getSlides') {
// ----------------------------------
// presentation: getSlides
// ----------------------------------
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const presentationId = this.getNodeParameter('presentationId', i) as string;
responseData = await googleApiRequest.call(this, 'GET', `/presentations/${presentationId}`, {}, { fields: 'slides' });
responseData = responseData.slides;
if (returnAll === false) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.slice(0, limit);
}
returnData.push(...this.helpers.returnJsonArray(responseData));
} else if (operation === 'replaceText') {
// ----------------------------------
// presentation: replaceText
// ----------------------------------
const presentationId = this.getNodeParameter('presentationId', i) as string;
const texts = this.getNodeParameter('textUi.textValues', i, []) as IDataObject[];
const options = this.getNodeParameter('options', i) as IDataObject;
const requests = texts.map((text => {
return {
replaceAllText: {
replaceText: text.replaceText,
pageObjectIds: text.pageObjectIds || [],
containsText: {
text: text.text,
matchCase: text.matchCase,
const fileName = pageObjectId + '.png';
const binaryData = await this.helpers.prepareBinaryData(data, fileName || fileName);
returnData.push({
json: responseData,
binary: {
[binaryProperty]: binaryData,
},
},
};
}));
const body: IDataObject = {
requests,
};
if (options.revisionId) {
body['writeControl'] = {
requiredRevisionId: options.revisionId as string,
};
});
} else {
returnData.push({ json: responseData });
}
}
responseData = await googleApiRequest.call(this, 'POST', `/presentations/${presentationId}:batchUpdate`, { requests });
returnData.push({ json: responseData });
} else if (resource === 'presentation') {
// *********************************************************************
// presentation
// *********************************************************************
if (operation === 'create') {
// ----------------------------------
// presentation: create
// ----------------------------------
const body = {
title: this.getNodeParameter('title', i) as string,
};
responseData = await googleApiRequest.call(this, 'POST', '/presentations', body);
returnData.push({ json: responseData });
} else if (operation === 'get') {
// ----------------------------------
// presentation: get
// ----------------------------------
const presentationId = this.getNodeParameter('presentationId', i) as string;
responseData = await googleApiRequest.call(this, 'GET', `/presentations/${presentationId}`);
returnData.push({ json: responseData });
} else if (operation === 'getSlides') {
// ----------------------------------
// presentation: getSlides
// ----------------------------------
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
const presentationId = this.getNodeParameter('presentationId', i) as string;
responseData = await googleApiRequest.call(this, 'GET', `/presentations/${presentationId}`, {}, { fields: 'slides' });
responseData = responseData.slides;
if (returnAll === false) {
const limit = this.getNodeParameter('limit', i) as number;
responseData = responseData.slice(0, limit);
}
returnData.push(...this.helpers.returnJsonArray(responseData));
} else if (operation === 'replaceText') {
// ----------------------------------
// presentation: replaceText
// ----------------------------------
const presentationId = this.getNodeParameter('presentationId', i) as string;
const texts = this.getNodeParameter('textUi.textValues', i, []) as IDataObject[];
const options = this.getNodeParameter('options', i) as IDataObject;
const requests = texts.map((text => {
return {
replaceAllText: {
replaceText: text.replaceText,
pageObjectIds: text.pageObjectIds || [],
containsText: {
text: text.text,
matchCase: text.matchCase,
},
},
};
}));
const body: IDataObject = {
requests,
};
if (options.revisionId) {
body['writeControl'] = {
requiredRevisionId: options.revisionId as string,
};
}
responseData = await googleApiRequest.call(this, 'POST', `/presentations/${presentationId}:batchUpdate`, { requests });
returnData.push({ json: responseData });
}
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({json:{ error: error.message }});
continue;
}
throw error;
}
}

View file

@ -97,181 +97,189 @@ export class GoogleTasks implements INodeType {
const operation = this.getNodeParameter('operation', 0) as string;
let body: IDataObject = {};
for (let i = 0; i < length; i++) {
if (resource === 'task') {
if (operation === 'create') {
body = {};
//https://developers.google.com/tasks/v1/reference/tasks/insert
const taskId = this.getNodeParameter('task', i) as string;
body.title = this.getNodeParameter('title', i) as string;
const additionalFields = this.getNodeParameter(
'additionalFields',
i,
) as IDataObject;
try {
if (resource === 'task') {
if (operation === 'create') {
body = {};
//https://developers.google.com/tasks/v1/reference/tasks/insert
const taskId = this.getNodeParameter('task', i) as string;
body.title = this.getNodeParameter('title', i) as string;
const additionalFields = this.getNodeParameter(
'additionalFields',
i,
) as IDataObject;
if (additionalFields.parent) {
qs.parent = additionalFields.parent as string;
}
if (additionalFields.previous) {
qs.previous = additionalFields.previous as string;
}
if (additionalFields.parent) {
qs.parent = additionalFields.parent as string;
}
if (additionalFields.previous) {
qs.previous = additionalFields.previous as string;
}
if (additionalFields.status) {
body.status = additionalFields.status as string;
}
if (additionalFields.status) {
body.status = additionalFields.status as string;
}
if (additionalFields.notes) {
body.notes = additionalFields.notes as string;
}
if (additionalFields.dueDate) {
body.dueDate = additionalFields.dueDate as string;
}
if (additionalFields.notes) {
body.notes = additionalFields.notes as string;
}
if (additionalFields.dueDate) {
body.dueDate = additionalFields.dueDate as string;
}
if (additionalFields.completed) {
body.completed = additionalFields.completed as string;
}
if (additionalFields.completed) {
body.completed = additionalFields.completed as string;
}
if (additionalFields.deleted) {
body.deleted = additionalFields.deleted as boolean;
}
if (additionalFields.deleted) {
body.deleted = additionalFields.deleted as boolean;
}
responseData = await googleApiRequest.call(
this,
'POST',
`/tasks/v1/lists/${taskId}/tasks`,
body,
qs,
);
}
if (operation === 'delete') {
//https://developers.google.com/tasks/v1/reference/tasks/delete
const taskListId = this.getNodeParameter('task', i) as string;
const taskId = this.getNodeParameter('taskId', i) as string;
responseData = await googleApiRequest.call(
this,
'DELETE',
`/tasks/v1/lists/${taskListId}/tasks/${taskId}`,
{},
);
responseData = { success: true };
}
if (operation === 'get') {
//https://developers.google.com/tasks/v1/reference/tasks/get
const taskListId = this.getNodeParameter('task', i) as string;
const taskId = this.getNodeParameter('taskId', i) as string;
responseData = await googleApiRequest.call(
this,
'GET',
`/tasks/v1/lists/${taskListId}/tasks/${taskId}`,
{},
qs,
);
}
if (operation === 'getAll') {
//https://developers.google.com/tasks/v1/reference/tasks/list
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const taskListId = this.getNodeParameter('task', i) as string;
const options = this.getNodeParameter(
'additionalFields',
i,
) as IDataObject;
if (options.completedMax) {
qs.completedMax = options.completedMax as string;
}
if (options.completedMin) {
qs.completedMin = options.completedMin as string;
}
if (options.dueMin) {
qs.dueMin = options.dueMin as string;
}
if (options.dueMax) {
qs.dueMax = options.dueMax as string;
}
if (options.showCompleted) {
qs.showCompleted = options.showCompleted as boolean;
}
if (options.showDeleted) {
qs.showDeleted = options.showDeleted as boolean;
}
if (options.showHidden) {
qs.showHidden = options.showHidden as boolean;
}
if (options.updatedMin) {
qs.updatedMin = options.updatedMin as string;
}
if (returnAll) {
responseData = await googleApiRequestAllItems.call(
responseData = await googleApiRequest.call(
this,
'items',
'GET',
`/tasks/v1/lists/${taskListId}/tasks`,
{},
'POST',
`/tasks/v1/lists/${taskId}/tasks`,
body,
qs,
);
} else {
qs.maxResults = this.getNodeParameter('limit', i) as number;
}
if (operation === 'delete') {
//https://developers.google.com/tasks/v1/reference/tasks/delete
const taskListId = this.getNodeParameter('task', i) as string;
const taskId = this.getNodeParameter('taskId', i) as string;
responseData = await googleApiRequest.call(
this,
'DELETE',
`/tasks/v1/lists/${taskListId}/tasks/${taskId}`,
{},
);
responseData = { success: true };
}
if (operation === 'get') {
//https://developers.google.com/tasks/v1/reference/tasks/get
const taskListId = this.getNodeParameter('task', i) as string;
const taskId = this.getNodeParameter('taskId', i) as string;
responseData = await googleApiRequest.call(
this,
'GET',
`/tasks/v1/lists/${taskListId}/tasks`,
`/tasks/v1/lists/${taskListId}/tasks/${taskId}`,
{},
qs,
);
responseData = responseData.items;
}
if (operation === 'getAll') {
//https://developers.google.com/tasks/v1/reference/tasks/list
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const taskListId = this.getNodeParameter('task', i) as string;
const options = this.getNodeParameter(
'additionalFields',
i,
) as IDataObject;
if (options.completedMax) {
qs.completedMax = options.completedMax as string;
}
if (options.completedMin) {
qs.completedMin = options.completedMin as string;
}
if (options.dueMin) {
qs.dueMin = options.dueMin as string;
}
if (options.dueMax) {
qs.dueMax = options.dueMax as string;
}
if (options.showCompleted) {
qs.showCompleted = options.showCompleted as boolean;
}
if (options.showDeleted) {
qs.showDeleted = options.showDeleted as boolean;
}
if (options.showHidden) {
qs.showHidden = options.showHidden as boolean;
}
if (options.updatedMin) {
qs.updatedMin = options.updatedMin as string;
}
if (returnAll) {
responseData = await googleApiRequestAllItems.call(
this,
'items',
'GET',
`/tasks/v1/lists/${taskListId}/tasks`,
{},
qs,
);
} else {
qs.maxResults = this.getNodeParameter('limit', i) as number;
responseData = await googleApiRequest.call(
this,
'GET',
`/tasks/v1/lists/${taskListId}/tasks`,
{},
qs,
);
responseData = responseData.items;
}
}
if (operation === 'update') {
body = {};
//https://developers.google.com/tasks/v1/reference/tasks/patch
const taskListId = this.getNodeParameter('task', i) as string;
const taskId = this.getNodeParameter('taskId', i) as string;
const updateFields = this.getNodeParameter(
'updateFields',
i,
) as IDataObject;
if (updateFields.previous) {
qs.previous = updateFields.previous as string;
}
if (updateFields.status) {
body.status = updateFields.status as string;
}
if (updateFields.notes) {
body.notes = updateFields.notes as string;
}
if (updateFields.title) {
body.title = updateFields.title as string;
}
if (updateFields.dueDate) {
body.dueDate = updateFields.dueDate as string;
}
if (updateFields.completed) {
body.completed = updateFields.completed as string;
}
if (updateFields.deleted) {
body.deleted = updateFields.deleted as boolean;
}
responseData = await googleApiRequest.call(
this,
'PATCH',
`/tasks/v1/lists/${taskListId}/tasks/${taskId}`,
body,
qs,
);
}
}
if (operation === 'update') {
body = {};
//https://developers.google.com/tasks/v1/reference/tasks/patch
const taskListId = this.getNodeParameter('task', i) as string;
const taskId = this.getNodeParameter('taskId', i) as string;
const updateFields = this.getNodeParameter(
'updateFields',
i,
) as IDataObject;
if (updateFields.previous) {
qs.previous = updateFields.previous as string;
}
if (updateFields.status) {
body.status = updateFields.status as string;
}
if (updateFields.notes) {
body.notes = updateFields.notes as string;
}
if (updateFields.title) {
body.title = updateFields.title as string;
}
if (updateFields.dueDate) {
body.dueDate = updateFields.dueDate as string;
}
if (updateFields.completed) {
body.completed = updateFields.completed as string;
}
if (updateFields.deleted) {
body.deleted = updateFields.deleted as boolean;
}
responseData = await googleApiRequest.call(
this,
'PATCH',
`/tasks/v1/lists/${taskListId}/tasks/${taskId}`,
body,
qs,
);
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else if (responseData !== undefined) {
returnData.push(responseData as IDataObject);
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else if (responseData !== undefined) {
returnData.push(responseData as IDataObject);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];

File diff suppressed because it is too large Load diff

View file

@ -194,67 +194,75 @@ export class Gotify implements INodeType {
const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string;
for (let i = 0; i < length; i++) {
if (resource === 'message') {
if (operation === 'create') {
try {
if (resource === 'message') {
if (operation === 'create') {
const message = this.getNodeParameter('message', i) as string;
const message = this.getNodeParameter('message', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IDataObject = {
message,
};
const body: IDataObject = {
message,
};
Object.assign(body, additionalFields);
Object.assign(body, additionalFields);
responseData = await gotifyApiRequest.call(
this,
'POST',
`/message`,
body,
);
}
if (operation === 'delete') {
const messageId = this.getNodeParameter('messageId', i) as string;
responseData = await gotifyApiRequest.call(
this,
'DELETE',
`/message/${messageId}`,
);
responseData = { success: true };
}
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
if (returnAll) {
responseData = await gotifyApiRequestAllItems.call(
this,
'messages',
'GET',
'/message',
{},
qs,
);
} else {
qs.limit = this.getNodeParameter('limit', i) as number;
responseData = await gotifyApiRequest.call(
this,
'GET',
'POST',
`/message`,
{},
qs,
body,
);
responseData = responseData.messages;
}
if (operation === 'delete') {
const messageId = this.getNodeParameter('messageId', i) as string;
responseData = await gotifyApiRequest.call(
this,
'DELETE',
`/message/${messageId}`,
);
responseData = { success: true };
}
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
if (returnAll) {
responseData = await gotifyApiRequestAllItems.call(
this,
'messages',
'GET',
'/message',
{},
qs,
);
} else {
qs.limit = this.getNodeParameter('limit', i) as number;
responseData = await gotifyApiRequest.call(
this,
'GET',
`/message`,
{},
qs,
);
responseData = responseData.messages;
}
}
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else if (responseData !== undefined) {
returnData.push(responseData as IDataObject);
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else if (responseData !== undefined) {
returnData.push(responseData as IDataObject);
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];

View file

@ -236,81 +236,89 @@ export class GraphQL implements INodeType {
const returnItems: INodeExecutionData[] = [];
for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
const requestMethod = this.getNodeParameter('requestMethod', itemIndex, 'POST') as string;
const endpoint = this.getNodeParameter('endpoint', itemIndex, '') as string;
const requestFormat = this.getNodeParameter('requestFormat', itemIndex, 'graphql') as string;
const responseFormat = this.getNodeParameter('responseFormat', 0) as string;
try {
const requestMethod = this.getNodeParameter('requestMethod', itemIndex, 'POST') as string;
const endpoint = this.getNodeParameter('endpoint', itemIndex, '') as string;
const requestFormat = this.getNodeParameter('requestFormat', itemIndex, 'graphql') as string;
const responseFormat = this.getNodeParameter('responseFormat', 0) as string;
const { parameter }: { parameter?: Array<{ name: string, value: string }> } = this
.getNodeParameter('headerParametersUi', itemIndex, {}) as IDataObject;
const headerParameters = (parameter || []).reduce((result, item) => ({
...result,
[item.name]: item.value,
}), {});
const { parameter }: { parameter?: Array<{ name: string, value: string }> } = this
.getNodeParameter('headerParametersUi', itemIndex, {}) as IDataObject;
const headerParameters = (parameter || []).reduce((result, item) => ({
...result,
[item.name]: item.value,
}), {});
requestOptions = {
headers: {
'content-type': `application/${requestFormat}`,
...headerParameters,
},
method: requestMethod,
uri: endpoint,
simple: false,
rejectUnauthorized: !this.getNodeParameter('allowUnauthorizedCerts', itemIndex, false) as boolean,
};
// Add credentials if any are set
if (httpHeaderAuth !== undefined) {
requestOptions.headers![httpHeaderAuth.name as string] = httpHeaderAuth.value;
}
const gqlQuery = this.getNodeParameter('query', itemIndex, '') as string;
if (requestMethod === 'GET') {
requestOptions.qs = {
query: gqlQuery,
};
} else {
if (requestFormat === 'json') {
requestOptions.body = {
query: gqlQuery,
variables: this.getNodeParameter('variables', itemIndex, {}) as object,
operationName: this.getNodeParameter('operationName', itemIndex) as string,
};
if (typeof requestOptions.body.variables === 'string') {
try {
requestOptions.body.variables = JSON.parse(requestOptions.body.variables || '{}');
} catch (error) {
throw new NodeOperationError(this.getNode(), 'Using variables failed:\n' + requestOptions.body.variables + '\n\nWith error message:\n' + error);
}
}
if (requestOptions.body.operationName === '') {
requestOptions.body.operationName = null;
}
requestOptions.json = true;
} else {
requestOptions.body = gqlQuery;
}
}
const response = await this.helpers.request(requestOptions);
if (responseFormat === 'string') {
const dataPropertyName = this.getNodeParameter('dataPropertyName', 0) as string;
returnItems.push({
json: {
[dataPropertyName]: response,
requestOptions = {
headers: {
'content-type': `application/${requestFormat}`,
...headerParameters,
},
});
} else {
if (typeof response === 'string') {
try {
returnItems.push({ json: JSON.parse(response) });
} catch (error) {
throw new NodeOperationError(this.getNode(), 'Response body is not valid JSON. Change "Response Format" to "String"');
}
} else {
returnItems.push({ json: response });
method: requestMethod,
uri: endpoint,
simple: false,
rejectUnauthorized: !this.getNodeParameter('allowUnauthorizedCerts', itemIndex, false) as boolean,
};
// Add credentials if any are set
if (httpHeaderAuth !== undefined) {
requestOptions.headers![httpHeaderAuth.name as string] = httpHeaderAuth.value;
}
const gqlQuery = this.getNodeParameter('query', itemIndex, '') as string;
if (requestMethod === 'GET') {
requestOptions.qs = {
query: gqlQuery,
};
} else {
if (requestFormat === 'json') {
requestOptions.body = {
query: gqlQuery,
variables: this.getNodeParameter('variables', itemIndex, {}) as object,
operationName: this.getNodeParameter('operationName', itemIndex) as string,
};
if (typeof requestOptions.body.variables === 'string') {
try {
requestOptions.body.variables = JSON.parse(requestOptions.body.variables || '{}');
} catch (error) {
throw new NodeOperationError(this.getNode(), 'Using variables failed:\n' + requestOptions.body.variables + '\n\nWith error message:\n' + error);
}
}
if (requestOptions.body.operationName === '') {
requestOptions.body.operationName = null;
}
requestOptions.json = true;
} else {
requestOptions.body = gqlQuery;
}
}
const response = await this.helpers.request(requestOptions);
if (responseFormat === 'string') {
const dataPropertyName = this.getNodeParameter('dataPropertyName', 0) as string;
returnItems.push({
json: {
[dataPropertyName]: response,
},
});
} else {
if (typeof response === 'string') {
try {
returnItems.push({ json: JSON.parse(response) });
} catch (error) {
throw new NodeOperationError(this.getNode(), 'Response body is not valid JSON. Change "Response Format" to "String"');
}
} else {
returnItems.push({ json: response });
}
}
} catch (error) {
if (this.continueOnFail()) {
returnItems.push({ json: { error: error.message } });
continue;
}
throw error;
}
}

View file

@ -303,80 +303,86 @@ export class HackerNews implements INodeType {
let returnAll = false;
for (let i = 0; i < items.length; i++) {
try {
let qs: IDataObject = {};
let endpoint = '';
let includeComments = false;
let qs: IDataObject = {};
let endpoint = '';
let includeComments = false;
if (resource === 'all') {
if (operation === 'getAll') {
if (resource === 'all') {
if (operation === 'getAll') {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const keyword = additionalFields.keyword as string;
const tags = additionalFields.tags as string[];
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const keyword = additionalFields.keyword as string;
const tags = additionalFields.tags as string[];
qs = {
query: keyword,
tags: tags ? tags.join() : '',
};
qs = {
query: keyword,
tags: tags ? tags.join() : '',
};
returnAll = this.getNodeParameter('returnAll', i) as boolean;
returnAll = this.getNodeParameter('returnAll', i) as boolean;
if (!returnAll) {
qs.hitsPerPage = this.getNodeParameter('limit', i) as number;
}
if (!returnAll) {
qs.hitsPerPage = this.getNodeParameter('limit', i) as number;
endpoint = 'search?';
} else {
throw new NodeOperationError(this.getNode(), `The operation '${operation}' is unknown!`);
}
} else if (resource === 'article') {
if (operation === 'get') {
endpoint = `items/${this.getNodeParameter('articleId', i)}`;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
includeComments = additionalFields.includeComments as boolean;
} else {
throw new NodeOperationError(this.getNode(), `The operation '${operation}' is unknown!`);
}
endpoint = 'search?';
} else if (resource === 'user') {
if (operation === 'get') {
endpoint = `users/${this.getNodeParameter('username', i)}`;
} else {
throw new NodeOperationError(this.getNode(), `The operation '${operation}' is unknown!`);
}
} else {
throw new NodeOperationError(this.getNode(), `The operation '${operation}' is unknown!`);
throw new NodeOperationError(this.getNode(), `The resource '${resource}' is unknown!`);
}
} else if (resource === 'article') {
if (operation === 'get') {
endpoint = `items/${this.getNodeParameter('articleId', i)}`;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
includeComments = additionalFields.includeComments as boolean;
let responseData;
if (returnAll === true) {
responseData = await hackerNewsApiRequestAllItems.call(this, 'GET', endpoint, qs);
} else {
throw new NodeOperationError(this.getNode(), `The operation '${operation}' is unknown!`);
responseData = await hackerNewsApiRequest.call(this, 'GET', endpoint, qs);
if (resource === 'all' && operation === 'getAll') {
responseData = responseData.hits;
}
}
} else if (resource === 'user') {
if (operation === 'get') {
endpoint = `users/${this.getNodeParameter('username', i)}`;
if (resource === 'article' && operation === 'get' && !includeComments) {
delete responseData.children;
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
throw new NodeOperationError(this.getNode(), `The operation '${operation}' is unknown!`);
returnData.push(responseData as IDataObject);
}
} else {
throw new NodeOperationError(this.getNode(), `The resource '${resource}' is unknown!`);
}
let responseData;
if (returnAll === true) {
responseData = await hackerNewsApiRequestAllItems.call(this, 'GET', endpoint, qs);
} else {
responseData = await hackerNewsApiRequest.call(this, 'GET', endpoint, qs);
if (resource === 'all' && operation === 'getAll') {
responseData = responseData.hits;
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
if (resource === 'article' && operation === 'get' && !includeComments) {
delete responseData.children;
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
}
}
return [this.helpers.returnJsonArray(returnData)];

File diff suppressed because it is too large Load diff

View file

@ -172,262 +172,270 @@ export class HelpScout implements INodeType {
const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string;
for (let i = 0; i < length; i++) {
if (resource === 'conversation') {
//https://developer.helpscout.com/mailbox-api/endpoints/conversations/create
if (operation === 'create') {
const mailboxId = this.getNodeParameter('mailboxId', i) as number;
const status = this.getNodeParameter('status', i) as string;
const subject = this.getNodeParameter('subject', i) as string;
const type = this.getNodeParameter('type', i) as string;
const resolveData = this.getNodeParameter('resolveData', i) as boolean;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const threads = (this.getNodeParameter('threadsUi', i) as IDataObject).threadsValues as IDataObject[];
const body: IConversation = {
mailboxId,
status,
subject,
type,
};
Object.assign(body, additionalFields);
if (additionalFields.customerId) {
body.customer = {
id: additionalFields.customerId,
try {
if (resource === 'conversation') {
//https://developer.helpscout.com/mailbox-api/endpoints/conversations/create
if (operation === 'create') {
const mailboxId = this.getNodeParameter('mailboxId', i) as number;
const status = this.getNodeParameter('status', i) as string;
const subject = this.getNodeParameter('subject', i) as string;
const type = this.getNodeParameter('type', i) as string;
const resolveData = this.getNodeParameter('resolveData', i) as boolean;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const threads = (this.getNodeParameter('threadsUi', i) as IDataObject).threadsValues as IDataObject[];
const body: IConversation = {
mailboxId,
status,
subject,
type,
};
//@ts-ignore
delete body.customerId;
}
if (additionalFields.customerEmail) {
body.customer = {
email: additionalFields.customerEmail,
};
//@ts-ignore
delete body.customerEmail;
}
if (body.customer === undefined) {
throw new NodeOperationError(this.getNode(), 'Either customer email or customer ID must be set');
}
if (threads) {
for (let i = 0; i < threads.length; i++) {
if (threads[i].type === '' || threads[i].text === '') {
throw new NodeOperationError(this.getNode(), 'Chat Threads cannot be empty');
}
if (threads[i].type !== 'note') {
threads[i].customer = body.customer;
}
}
body.threads = threads;
}
responseData = await helpscoutApiRequest.call(this, 'POST', '/v2/conversations', body, qs, undefined, { resolveWithFullResponse: true });
const id = responseData.headers['resource-id'];
const uri = responseData.headers.location;
if (resolveData) {
responseData = await helpscoutApiRequest.call(this, 'GET', '', {}, {}, uri);
} else {
responseData = {
id,
uri,
};
}
}
//https://developer.helpscout.com/mailbox-api/endpoints/conversations/delete
if (operation === 'delete') {
const conversationId = this.getNodeParameter('conversationId', i) as string;
responseData = await helpscoutApiRequest.call(this, 'DELETE', `/v2/conversations/${conversationId}`);
responseData = { success: true };
}
//https://developer.helpscout.com/mailbox-api/endpoints/conversations/get
if (operation === 'get') {
const conversationId = this.getNodeParameter('conversationId', i) as string;
responseData = await helpscoutApiRequest.call(this, 'GET', `/v2/conversations/${conversationId}`);
}
//https://developer.helpscout.com/mailbox-api/endpoints/conversations/list
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const options = this.getNodeParameter('options', i) as IDataObject;
Object.assign(qs, options);
if (returnAll) {
responseData = await helpscoutApiRequestAllItems.call(this, '_embedded.conversations', 'GET', '/v2/conversations', {}, qs);
} else {
qs.limit = this.getNodeParameter('limit', i) as number;
responseData = await helpscoutApiRequestAllItems.call(this, '_embedded.conversations', 'GET', '/v2/conversations', {}, qs);
responseData = responseData.splice(0, qs.limit);
}
}
}
if (resource === 'customer') {
//https://developer.helpscout.com/mailbox-api/endpoints/customers/create
if (operation === 'create') {
const resolveData = this.getNodeParameter('resolveData', i) as boolean;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const chats = (this.getNodeParameter('chatsUi', i) as IDataObject).chatsValues as IDataObject[];
const address = (this.getNodeParameter('addressUi', i) as IDataObject).addressValue as IDataObject;
const emails = (this.getNodeParameter('emailsUi', i) as IDataObject).emailsValues as IDataObject[];
const phones = (this.getNodeParameter('phonesUi', i) as IDataObject).phonesValues as IDataObject[];
const socialProfiles = (this.getNodeParameter('socialProfilesUi', i) as IDataObject).socialProfilesValues as IDataObject[];
const websites = (this.getNodeParameter('websitesUi', i) as IDataObject).websitesValues as IDataObject[];
let body: ICustomer = {};
body = Object.assign({}, additionalFields);
if (body.age) {
body.age = body.age.toString();
}
if (chats) {
body.chats = chats;
}
if (address) {
body.address = address;
body.address.lines = [address.line1, address.line2];
}
if (emails) {
body.emails = emails;
}
if (phones) {
body.phones = phones;
}
if (socialProfiles) {
body.socialProfiles = socialProfiles;
}
if (websites) {
body.websites = websites;
}
if (Object.keys(body).length === 0) {
throw new NodeOperationError(this.getNode(), 'You have to set at least one field');
}
responseData = await helpscoutApiRequest.call(this, 'POST', '/v2/customers', body, qs, undefined, { resolveWithFullResponse: true });
const id = responseData.headers['resource-id'];
const uri = responseData.headers.location;
if (resolveData) {
responseData = await helpscoutApiRequest.call(this, 'GET', '', {}, {}, uri);
} else {
responseData = {
id,
uri,
};
}
}
//https://developer.helpscout.com/mailbox-api/endpoints/customer_properties/list
if (operation === 'properties') {
responseData = await helpscoutApiRequestAllItems.call(this, '_embedded.customer-properties', 'GET', '/v2/customer-properties', {}, qs);
}
//https://developer.helpscout.com/mailbox-api/endpoints/customers/get
if (operation === 'get') {
const customerId = this.getNodeParameter('customerId', i) as string;
responseData = await helpscoutApiRequest.call(this, 'GET', `/v2/customers/${customerId}`);
}
//https://developer.helpscout.com/mailbox-api/endpoints/customers/list
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const options = this.getNodeParameter('options', i) as IDataObject;
Object.assign(qs, options);
if (returnAll) {
responseData = await helpscoutApiRequestAllItems.call(this, '_embedded.customers', 'GET', '/v2/customers', {}, qs);
} else {
qs.limit = this.getNodeParameter('limit', i) as number;
responseData = await helpscoutApiRequestAllItems.call(this, '_embedded.customers', 'GET', '/v2/customers', {}, qs);
responseData = responseData.splice(0, qs.limit);
}
}
//https://developer.helpscout.com/mailbox-api/endpoints/customers/overwrite/
if (operation === 'update') {
const customerId = this.getNodeParameter('customerId', i) as string;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
let body: ICustomer = {};
body = Object.assign({}, updateFields);
if (body.age) {
body.age = body.age.toString();
}
if (Object.keys(body).length === 0) {
throw new NodeOperationError(this.getNode(), 'You have to set at least one field');
}
responseData = await helpscoutApiRequest.call(this, 'PUT', `/v2/customers/${customerId}`, body, qs, undefined, { resolveWithFullResponse: true });
responseData = { success: true };
}
}
if (resource === 'mailbox') {
//https://developer.helpscout.com/mailbox-api/endpoints/mailboxes/get
if (operation === 'get') {
const mailboxId = this.getNodeParameter('mailboxId', i) as string;
responseData = await helpscoutApiRequest.call(this, 'GET', `/v2/mailboxes/${mailboxId}`, {}, qs);
}
//https://developer.helpscout.com/mailbox-api/endpoints/mailboxes/list
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
if (returnAll) {
responseData = await helpscoutApiRequestAllItems.call(this, '_embedded.mailboxes', 'GET', '/v2/mailboxes', {}, qs);
} else {
qs.limit = this.getNodeParameter('limit', i) as number;
responseData = await helpscoutApiRequestAllItems.call(this, '_embedded.mailboxes', 'GET', '/v2/mailboxes', {}, qs);
responseData = responseData.splice(0, qs.limit);
}
}
}
if (resource === 'thread') {
//https://developer.helpscout.com/mailbox-api/endpoints/conversations/threads/chat
if (operation === 'create') {
const conversationId = this.getNodeParameter('conversationId', i) as string;
const type = this.getNodeParameter('type', i) as string;
const text = this.getNodeParameter('text', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const attachments = this.getNodeParameter('attachmentsUi', i) as IDataObject;
const body: IThread = {
text,
attachments: [],
};
Object.assign(body, additionalFields);
if (additionalFields.customerId) {
body.customer = {
id: additionalFields.customerId,
};
//@ts-ignore
delete body.customerId;
}
if (additionalFields.customerEmail) {
body.customer = {
email: additionalFields.customerEmail,
};
//@ts-ignore
delete body.customerEmail;
}
if (body.customer === undefined) {
throw new NodeOperationError(this.getNode(), 'Either customer email or customer ID must be set');
}
if (attachments) {
if (attachments.attachmentsValues
&& (attachments.attachmentsValues as IDataObject[]).length !== 0) {
body.attachments?.push.apply(body.attachments, attachments.attachmentsValues as IAttachment[]);
}
if (attachments.attachmentsBinary
&& (attachments.attachmentsBinary as IDataObject[]).length !== 0
&& items[i].binary) {
const mapFunction = (value: IDataObject): IAttachment => {
const binaryProperty = (items[i].binary as IBinaryKeyData)[value.property as string];
if (binaryProperty) {
return {
fileName: binaryProperty.fileName || 'unknown',
data: binaryProperty.data,
mimeType: binaryProperty.mimeType,
};
} else {
throw new NodeOperationError(this.getNode(), `Binary property ${value.property} does not exist on input`);
}
Object.assign(body, additionalFields);
if (additionalFields.customerId) {
body.customer = {
id: additionalFields.customerId,
};
//@ts-ignore
delete body.customerId;
}
if (additionalFields.customerEmail) {
body.customer = {
email: additionalFields.customerEmail,
};
//@ts-ignore
delete body.customerEmail;
}
if (body.customer === undefined) {
throw new NodeOperationError(this.getNode(), 'Either customer email or customer ID must be set');
}
if (threads) {
for (let i = 0; i < threads.length; i++) {
if (threads[i].type === '' || threads[i].text === '') {
throw new NodeOperationError(this.getNode(), 'Chat Threads cannot be empty');
}
if (threads[i].type !== 'note') {
threads[i].customer = body.customer;
}
}
body.threads = threads;
}
responseData = await helpscoutApiRequest.call(this, 'POST', '/v2/conversations', body, qs, undefined, { resolveWithFullResponse: true });
const id = responseData.headers['resource-id'];
const uri = responseData.headers.location;
if (resolveData) {
responseData = await helpscoutApiRequest.call(this, 'GET', '', {}, {}, uri);
} else {
responseData = {
id,
uri,
};
body.attachments?.push.apply(body.attachments, (attachments.attachmentsBinary as IDataObject[]).map(mapFunction) as IAttachment[]);
}
}
responseData = await helpscoutApiRequest.call(this, 'POST', `/v2/conversations/${conversationId}/chats`, body);
responseData = { success: true };
}
//https://developer.helpscout.com/mailbox-api/endpoints/conversations/threads/list
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const conversationId = this.getNodeParameter('conversationId', i) as string;
if (returnAll) {
responseData = await helpscoutApiRequestAllItems.call(this, '_embedded.threads', 'GET', `/v2/conversations/${conversationId}/threads`);
} else {
qs.limit = this.getNodeParameter('limit', i) as number;
responseData = await helpscoutApiRequestAllItems.call(this, '_embedded.threads', 'GET', `/v2/conversations/${conversationId}/threads`, {}, qs);
responseData = responseData.splice(0, qs.limit);
//https://developer.helpscout.com/mailbox-api/endpoints/conversations/delete
if (operation === 'delete') {
const conversationId = this.getNodeParameter('conversationId', i) as string;
responseData = await helpscoutApiRequest.call(this, 'DELETE', `/v2/conversations/${conversationId}`);
responseData = { success: true };
}
//https://developer.helpscout.com/mailbox-api/endpoints/conversations/get
if (operation === 'get') {
const conversationId = this.getNodeParameter('conversationId', i) as string;
responseData = await helpscoutApiRequest.call(this, 'GET', `/v2/conversations/${conversationId}`);
}
//https://developer.helpscout.com/mailbox-api/endpoints/conversations/list
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const options = this.getNodeParameter('options', i) as IDataObject;
Object.assign(qs, options);
if (returnAll) {
responseData = await helpscoutApiRequestAllItems.call(this, '_embedded.conversations', 'GET', '/v2/conversations', {}, qs);
} else {
qs.limit = this.getNodeParameter('limit', i) as number;
responseData = await helpscoutApiRequestAllItems.call(this, '_embedded.conversations', 'GET', '/v2/conversations', {}, qs);
responseData = responseData.splice(0, qs.limit);
}
}
}
if (resource === 'customer') {
//https://developer.helpscout.com/mailbox-api/endpoints/customers/create
if (operation === 'create') {
const resolveData = this.getNodeParameter('resolveData', i) as boolean;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const chats = (this.getNodeParameter('chatsUi', i) as IDataObject).chatsValues as IDataObject[];
const address = (this.getNodeParameter('addressUi', i) as IDataObject).addressValue as IDataObject;
const emails = (this.getNodeParameter('emailsUi', i) as IDataObject).emailsValues as IDataObject[];
const phones = (this.getNodeParameter('phonesUi', i) as IDataObject).phonesValues as IDataObject[];
const socialProfiles = (this.getNodeParameter('socialProfilesUi', i) as IDataObject).socialProfilesValues as IDataObject[];
const websites = (this.getNodeParameter('websitesUi', i) as IDataObject).websitesValues as IDataObject[];
let body: ICustomer = {};
body = Object.assign({}, additionalFields);
if (body.age) {
body.age = body.age.toString();
}
if (chats) {
body.chats = chats;
}
if (address) {
body.address = address;
body.address.lines = [address.line1, address.line2];
}
if (emails) {
body.emails = emails;
}
if (phones) {
body.phones = phones;
}
if (socialProfiles) {
body.socialProfiles = socialProfiles;
}
if (websites) {
body.websites = websites;
}
if (Object.keys(body).length === 0) {
throw new NodeOperationError(this.getNode(), 'You have to set at least one field');
}
responseData = await helpscoutApiRequest.call(this, 'POST', '/v2/customers', body, qs, undefined, { resolveWithFullResponse: true });
const id = responseData.headers['resource-id'];
const uri = responseData.headers.location;
if (resolveData) {
responseData = await helpscoutApiRequest.call(this, 'GET', '', {}, {}, uri);
} else {
responseData = {
id,
uri,
};
}
}
//https://developer.helpscout.com/mailbox-api/endpoints/customer_properties/list
if (operation === 'properties') {
responseData = await helpscoutApiRequestAllItems.call(this, '_embedded.customer-properties', 'GET', '/v2/customer-properties', {}, qs);
}
//https://developer.helpscout.com/mailbox-api/endpoints/customers/get
if (operation === 'get') {
const customerId = this.getNodeParameter('customerId', i) as string;
responseData = await helpscoutApiRequest.call(this, 'GET', `/v2/customers/${customerId}`);
}
//https://developer.helpscout.com/mailbox-api/endpoints/customers/list
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const options = this.getNodeParameter('options', i) as IDataObject;
Object.assign(qs, options);
if (returnAll) {
responseData = await helpscoutApiRequestAllItems.call(this, '_embedded.customers', 'GET', '/v2/customers', {}, qs);
} else {
qs.limit = this.getNodeParameter('limit', i) as number;
responseData = await helpscoutApiRequestAllItems.call(this, '_embedded.customers', 'GET', '/v2/customers', {}, qs);
responseData = responseData.splice(0, qs.limit);
}
}
//https://developer.helpscout.com/mailbox-api/endpoints/customers/overwrite/
if (operation === 'update') {
const customerId = this.getNodeParameter('customerId', i) as string;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
let body: ICustomer = {};
body = Object.assign({}, updateFields);
if (body.age) {
body.age = body.age.toString();
}
if (Object.keys(body).length === 0) {
throw new NodeOperationError(this.getNode(), 'You have to set at least one field');
}
responseData = await helpscoutApiRequest.call(this, 'PUT', `/v2/customers/${customerId}`, body, qs, undefined, { resolveWithFullResponse: true });
responseData = { success: true };
}
}
if (resource === 'mailbox') {
//https://developer.helpscout.com/mailbox-api/endpoints/mailboxes/get
if (operation === 'get') {
const mailboxId = this.getNodeParameter('mailboxId', i) as string;
responseData = await helpscoutApiRequest.call(this, 'GET', `/v2/mailboxes/${mailboxId}`, {}, qs);
}
//https://developer.helpscout.com/mailbox-api/endpoints/mailboxes/list
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
if (returnAll) {
responseData = await helpscoutApiRequestAllItems.call(this, '_embedded.mailboxes', 'GET', '/v2/mailboxes', {}, qs);
} else {
qs.limit = this.getNodeParameter('limit', i) as number;
responseData = await helpscoutApiRequestAllItems.call(this, '_embedded.mailboxes', 'GET', '/v2/mailboxes', {}, qs);
responseData = responseData.splice(0, qs.limit);
}
}
}
if (resource === 'thread') {
//https://developer.helpscout.com/mailbox-api/endpoints/conversations/threads/chat
if (operation === 'create') {
const conversationId = this.getNodeParameter('conversationId', i) as string;
const type = this.getNodeParameter('type', i) as string;
const text = this.getNodeParameter('text', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const attachments = this.getNodeParameter('attachmentsUi', i) as IDataObject;
const body: IThread = {
text,
attachments: [],
};
Object.assign(body, additionalFields);
if (additionalFields.customerId) {
body.customer = {
id: additionalFields.customerId,
};
//@ts-ignore
delete body.customerId;
}
if (additionalFields.customerEmail) {
body.customer = {
email: additionalFields.customerEmail,
};
//@ts-ignore
delete body.customerEmail;
}
if (body.customer === undefined) {
throw new NodeOperationError(this.getNode(), 'Either customer email or customer ID must be set');
}
if (attachments) {
if (attachments.attachmentsValues
&& (attachments.attachmentsValues as IDataObject[]).length !== 0) {
body.attachments?.push.apply(body.attachments, attachments.attachmentsValues as IAttachment[]);
}
if (attachments.attachmentsBinary
&& (attachments.attachmentsBinary as IDataObject[]).length !== 0
&& items[i].binary) {
const mapFunction = (value: IDataObject): IAttachment => {
const binaryProperty = (items[i].binary as IBinaryKeyData)[value.property as string];
if (binaryProperty) {
return {
fileName: binaryProperty.fileName || 'unknown',
data: binaryProperty.data,
mimeType: binaryProperty.mimeType,
};
} else {
throw new NodeOperationError(this.getNode(), `Binary property ${value.property} does not exist on input`);
}
};
body.attachments?.push.apply(body.attachments, (attachments.attachmentsBinary as IDataObject[]).map(mapFunction) as IAttachment[]);
}
}
responseData = await helpscoutApiRequest.call(this, 'POST', `/v2/conversations/${conversationId}/chats`, body);
responseData = { success: true };
}
//https://developer.helpscout.com/mailbox-api/endpoints/conversations/threads/list
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const conversationId = this.getNodeParameter('conversationId', i) as string;
if (returnAll) {
responseData = await helpscoutApiRequestAllItems.call(this, '_embedded.threads', 'GET', `/v2/conversations/${conversationId}/threads`);
} else {
qs.limit = this.getNodeParameter('limit', i) as number;
responseData = await helpscoutApiRequestAllItems.call(this, '_embedded.threads', 'GET', `/v2/conversations/${conversationId}/threads`, {}, qs);
responseData = responseData.splice(0, qs.limit);
}
}
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);

View file

@ -219,59 +219,67 @@ export class HtmlExtract implements INodeType {
let item: INodeExecutionData;
for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
const dataPropertyName = this.getNodeParameter('dataPropertyName', itemIndex) as string;
const extractionValues = this.getNodeParameter('extractionValues', itemIndex) as IDataObject;
const options = this.getNodeParameter('options', itemIndex, {}) as IDataObject;
const sourceData = this.getNodeParameter('sourceData', itemIndex) as string;
try {
const dataPropertyName = this.getNodeParameter('dataPropertyName', itemIndex) as string;
const extractionValues = this.getNodeParameter('extractionValues', itemIndex) as IDataObject;
const options = this.getNodeParameter('options', itemIndex, {}) as IDataObject;
const sourceData = this.getNodeParameter('sourceData', itemIndex) as string;
item = items[itemIndex];
item = items[itemIndex];
let htmlArray: string[] | string = [];
if (sourceData === 'json') {
if (item.json[dataPropertyName] === undefined) {
throw new NodeOperationError(this.getNode(), `No property named "${dataPropertyName}" exists!`);
}
htmlArray = item.json[dataPropertyName] as string;
} else {
if (item.binary === undefined) {
throw new NodeOperationError(this.getNode(), `No item does not contain binary data!`);
}
if (item.binary[dataPropertyName] === undefined) {
throw new NodeOperationError(this.getNode(), `No property named "${dataPropertyName}" exists!`);
}
htmlArray = Buffer.from(item.binary[dataPropertyName].data, 'base64').toString('utf8');
}
// Convert it always to array that it works with a string or an array of strings
if (!Array.isArray(htmlArray)) {
htmlArray = [htmlArray];
}
for (const html of htmlArray as string[]) {
const $ = cheerio.load(html);
const newItem: INodeExecutionData = {
json: {},
};
// Itterate over all the defined values which should be extracted
let htmlElement;
for (const valueData of extractionValues.values as IValueData[]) {
htmlElement = $(valueData.cssSelector);
if (valueData.returnArray === true) {
// An array should be returned so itterate over one
// value at a time
newItem.json[valueData.key as string] = [];
htmlElement.each((i, el) => {
(newItem.json[valueData.key as string] as Array<string | undefined>).push(getValue($(el), valueData, options));
});
} else {
// One single value should be returned
newItem.json[valueData.key as string] = getValue(htmlElement, valueData, options);
let htmlArray: string[] | string = [];
if (sourceData === 'json') {
if (item.json[dataPropertyName] === undefined) {
throw new NodeOperationError(this.getNode(), `No property named "${dataPropertyName}" exists!`);
}
htmlArray = item.json[dataPropertyName] as string;
} else {
if (item.binary === undefined) {
throw new NodeOperationError(this.getNode(), `No item does not contain binary data!`);
}
if (item.binary[dataPropertyName] === undefined) {
throw new NodeOperationError(this.getNode(), `No property named "${dataPropertyName}" exists!`);
}
htmlArray = Buffer.from(item.binary[dataPropertyName].data, 'base64').toString('utf8');
}
returnData.push(newItem);
// Convert it always to array that it works with a string or an array of strings
if (!Array.isArray(htmlArray)) {
htmlArray = [htmlArray];
}
for (const html of htmlArray as string[]) {
const $ = cheerio.load(html);
const newItem: INodeExecutionData = {
json: {},
};
// Itterate over all the defined values which should be extracted
let htmlElement;
for (const valueData of extractionValues.values as IValueData[]) {
htmlElement = $(valueData.cssSelector);
if (valueData.returnArray === true) {
// An array should be returned so itterate over one
// value at a time
newItem.json[valueData.key as string] = [];
htmlElement.each((i, el) => {
(newItem.json[valueData.key as string] as Array<string | undefined>).push(getValue($(el), valueData, options));
});
} else {
// One single value should be returned
newItem.json[valueData.key as string] = getValue(htmlElement, valueData, options);
}
}
returnData.push(newItem);
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ json: { error: error.message } });
continue;
}
throw error;
}
}

File diff suppressed because it is too large Load diff

View file

@ -292,85 +292,93 @@ export class Hunter implements INodeType {
const qs: IDataObject = {};
let responseData;
for (let i = 0; i < length; i++) {
const operation = this.getNodeParameter('operation', 0) as string;
//https://hunter.io/api-documentation/v2#domain-search
if (operation === 'domainSearch') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const filters = this.getNodeParameter('filters', i) as IDataObject;
const domain = this.getNodeParameter('domain', i) as string;
const onlyEmails = this.getNodeParameter('onlyEmails', i, false) as boolean;
try {
const operation = this.getNodeParameter('operation', 0) as string;
//https://hunter.io/api-documentation/v2#domain-search
if (operation === 'domainSearch') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const filters = this.getNodeParameter('filters', i) as IDataObject;
const domain = this.getNodeParameter('domain', i) as string;
const onlyEmails = this.getNodeParameter('onlyEmails', i, false) as boolean;
qs.domain = domain;
if (filters.type){
qs.type = filters.type;
}
if (filters.seniority){
qs.seniority = (filters.seniority as string[]).join(',');
}
if (filters.department){
qs.department = (filters.department as string[]).join(',');
}
if (returnAll) {
responseData = await hunterApiRequestAllItems.call(this, 'data', 'GET', '/domain-search', {}, qs);
qs.domain = domain;
if (filters.type){
qs.type = filters.type;
}
if (filters.seniority){
qs.seniority = (filters.seniority as string[]).join(',');
}
if (filters.department){
qs.department = (filters.department as string[]).join(',');
}
if (returnAll) {
responseData = await hunterApiRequestAllItems.call(this, 'data', 'GET', '/domain-search', {}, qs);
// Make sure that the company information is there only once and
// the emails are combined underneath it.
if (onlyEmails === false) {
let tempReturnData: IDataObject = {};
// Make sure that the company information is there only once and
// the emails are combined underneath it.
if (onlyEmails === false) {
let tempReturnData: IDataObject = {};
for (let i = 0; i < responseData.length; i++) {
if (i === 0) {
tempReturnData = responseData[i];
continue;
for (let i = 0; i < responseData.length; i++) {
if (i === 0) {
tempReturnData = responseData[i];
continue;
}
((tempReturnData as IDataObject).emails as IDataObject[]).push.apply(tempReturnData.emails, responseData[i].emails);
}
((tempReturnData as IDataObject).emails as IDataObject[]).push.apply(tempReturnData.emails, responseData[i].emails);
responseData = tempReturnData;
}
} else {
const limit = this.getNodeParameter('limit', i) as number;
qs.limit = limit;
responseData = await hunterApiRequest.call(this, 'GET', '/domain-search', {}, qs);
responseData = responseData.data;
}
if (onlyEmails === true) {
let tempReturnData: IDataObject[] = [];
if (Array.isArray(responseData)) {
for (const data of responseData) {
tempReturnData.push.apply(tempReturnData, data.emails);
}
} else {
tempReturnData = responseData.emails;
}
responseData = tempReturnData;
}
} else {
const limit = this.getNodeParameter('limit', i) as number;
qs.limit = limit;
responseData = await hunterApiRequest.call(this, 'GET', '/domain-search', {}, qs);
}
//https://hunter.io/api-documentation/v2#email-finder
if (operation === 'emailFinder') {
const domain = this.getNodeParameter('domain', i) as string;
const firstname = this.getNodeParameter('firstname', i) as string;
const lastname = this.getNodeParameter('lastname', i) as string;
qs.first_name = firstname;
qs.last_name = lastname;
qs.domain = domain;
responseData = await hunterApiRequest.call(this, 'GET', '/email-finder', {}, qs);
responseData = responseData.data;
}
if (onlyEmails === true) {
let tempReturnData: IDataObject[] = [];
if (Array.isArray(responseData)) {
for (const data of responseData) {
tempReturnData.push.apply(tempReturnData, data.emails);
}
} else {
tempReturnData = responseData.emails;
}
responseData = tempReturnData;
//https://hunter.io/api-documentation/v2#email-verifier
if (operation === 'emailVerifier') {
const email = this.getNodeParameter('email', i) as string;
qs.email = email;
responseData = await hunterApiRequest.call(this, 'GET', '/email-verifier', {}, qs);
responseData = responseData.data;
}
}
//https://hunter.io/api-documentation/v2#email-finder
if (operation === 'emailFinder') {
const domain = this.getNodeParameter('domain', i) as string;
const firstname = this.getNodeParameter('firstname', i) as string;
const lastname = this.getNodeParameter('lastname', i) as string;
qs.first_name = firstname;
qs.last_name = lastname;
qs.domain = domain;
responseData = await hunterApiRequest.call(this, 'GET', '/email-finder', {}, qs);
responseData = responseData.data;
}
//https://hunter.io/api-documentation/v2#email-verifier
if (operation === 'emailVerifier') {
const email = this.getNodeParameter('email', i) as string;
qs.email = email;
responseData = await hunterApiRequest.call(this, 'GET', '/email-verifier', {}, qs);
responseData = responseData.data;
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];

View file

@ -127,429 +127,437 @@ export class Intercom implements INodeType {
let qs: IDataObject;
let responseData;
for (let i = 0; i < length; i++) {
qs = {};
const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string;
//https://developers.intercom.com/intercom-api-reference/reference#leads
if (resource === 'lead') {
if (operation === 'create' || operation === 'update') {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const jsonActive = this.getNodeParameter('jsonParameters', i) as boolean;
const body: ILead = {};
if (operation === 'create') {
body.email = this.getNodeParameter('email', i) as string;
}
if (additionalFields.email) {
body.email = additionalFields.email as string;
}
if (additionalFields.phone) {
body.phone = additionalFields.phone as string;
}
if (additionalFields.name) {
body.name = additionalFields.name as string;
}
if (additionalFields.unsubscribedFromEmails) {
body.unsubscribed_from_emails = additionalFields.unsubscribedFromEmails as boolean;
}
if (additionalFields.updateLastRequestAt) {
body.update_last_request_at = additionalFields.updateLastRequestAt as boolean;
}
if (additionalFields.utmSource) {
body.utm_source = additionalFields.utmSource as string;
}
if (additionalFields.utmMedium) {
body.utm_medium = additionalFields.utmMedium as string;
}
if (additionalFields.utmCampaign) {
body.utm_campaign = additionalFields.utmCampaign as string;
}
if (additionalFields.utmTerm) {
body.utm_term = additionalFields.utmTerm as string;
}
if (additionalFields.utmContent) {
body.utm_content = additionalFields.utmContent as string;
}
if (additionalFields.avatar) {
const avatar: IAvatar = {
type: 'avatar',
image_url: additionalFields.avatar as string,
};
body.avatar = avatar;
}
if (additionalFields.companies) {
const companies: ILeadCompany[] = [];
// @ts-ignore
additionalFields.companies.forEach(o => {
const company: ILeadCompany = {};
company.company_id = o;
companies.push(company);
});
body.companies = companies;
}
if (!jsonActive) {
const customAttributesValues = (this.getNodeParameter('customAttributesUi', i) as IDataObject).customAttributesValues as IDataObject[];
if (customAttributesValues) {
const customAttributes = {};
for (let i = 0; i < customAttributesValues.length; i++) {
// @ts-ignore
customAttributes[customAttributesValues[i].name] = customAttributesValues[i].value;
try {
qs = {};
const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string;
//https://developers.intercom.com/intercom-api-reference/reference#leads
if (resource === 'lead') {
if (operation === 'create' || operation === 'update') {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const jsonActive = this.getNodeParameter('jsonParameters', i) as boolean;
const body: ILead = {};
if (operation === 'create') {
body.email = this.getNodeParameter('email', i) as string;
}
if (additionalFields.email) {
body.email = additionalFields.email as string;
}
if (additionalFields.phone) {
body.phone = additionalFields.phone as string;
}
if (additionalFields.name) {
body.name = additionalFields.name as string;
}
if (additionalFields.unsubscribedFromEmails) {
body.unsubscribed_from_emails = additionalFields.unsubscribedFromEmails as boolean;
}
if (additionalFields.updateLastRequestAt) {
body.update_last_request_at = additionalFields.updateLastRequestAt as boolean;
}
if (additionalFields.utmSource) {
body.utm_source = additionalFields.utmSource as string;
}
if (additionalFields.utmMedium) {
body.utm_medium = additionalFields.utmMedium as string;
}
if (additionalFields.utmCampaign) {
body.utm_campaign = additionalFields.utmCampaign as string;
}
if (additionalFields.utmTerm) {
body.utm_term = additionalFields.utmTerm as string;
}
if (additionalFields.utmContent) {
body.utm_content = additionalFields.utmContent as string;
}
if (additionalFields.avatar) {
const avatar: IAvatar = {
type: 'avatar',
image_url: additionalFields.avatar as string,
};
body.avatar = avatar;
}
if (additionalFields.companies) {
const companies: ILeadCompany[] = [];
// @ts-ignore
additionalFields.companies.forEach(o => {
const company: ILeadCompany = {};
company.company_id = o;
companies.push(company);
});
body.companies = companies;
}
if (!jsonActive) {
const customAttributesValues = (this.getNodeParameter('customAttributesUi', i) as IDataObject).customAttributesValues as IDataObject[];
if (customAttributesValues) {
const customAttributes = {};
for (let i = 0; i < customAttributesValues.length; i++) {
// @ts-ignore
customAttributes[customAttributesValues[i].name] = customAttributesValues[i].value;
}
body.custom_attributes = customAttributes;
}
} else {
const customAttributesJson = validateJSON(this.getNodeParameter('customAttributesJson', i) as string);
if (customAttributesJson) {
body.custom_attributes = customAttributesJson;
}
body.custom_attributes = customAttributes;
}
} else {
const customAttributesJson = validateJSON(this.getNodeParameter('customAttributesJson', i) as string);
if (customAttributesJson) {
body.custom_attributes = customAttributesJson;
if (operation === 'update') {
const updateBy = this.getNodeParameter('updateBy', 0) as string;
const value = this.getNodeParameter('value', i) as string;
if (updateBy === 'userId') {
body.user_id = value;
}
if (updateBy === 'id') {
body.id = value;
}
}
try {
responseData = await intercomApiRequest.call(this, '/contacts', 'POST', body);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
}
if (operation === 'update') {
const updateBy = this.getNodeParameter('updateBy', 0) as string;
if (operation === 'get') {
const selectBy = this.getNodeParameter('selectBy', 0) as string;
const value = this.getNodeParameter('value', i) as string;
if (updateBy === 'userId') {
body.user_id = value;
if (selectBy === 'email') {
qs.email = value;
}
if (updateBy === 'id') {
body.id = value;
}
}
try {
responseData = await intercomApiRequest.call(this, '/contacts', 'POST', body);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
}
if (operation === 'get') {
const selectBy = this.getNodeParameter('selectBy', 0) as string;
const value = this.getNodeParameter('value', i) as string;
if (selectBy === 'email') {
qs.email = value;
}
if (selectBy === 'userId') {
qs.user_id = value;
}
if (selectBy === 'phone') {
qs.phone = value;
}
try {
if (selectBy === 'id') {
responseData = await intercomApiRequest.call(this, `/contacts/${value}`, 'GET');
} else {
responseData = await intercomApiRequest.call(this, '/contacts', 'GET', {}, qs);
responseData = responseData.contacts;
}
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
}
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const filters = this.getNodeParameter('filters', i) as IDataObject;
Object.assign(qs, filters);
try {
if (returnAll === true) {
responseData = await intercomApiRequestAllItems.call(this, 'contacts', '/contacts', 'GET', {}, qs);
} else {
qs.per_page = this.getNodeParameter('limit', i) as number;
responseData = await intercomApiRequest.call(this, '/contacts', 'GET', {}, qs);
responseData = responseData.contacts;
}
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
}
if (operation === 'delete') {
const deleteBy = this.getNodeParameter('deleteBy', 0) as string;
const value = this.getNodeParameter('value', i) as string;
try {
if (deleteBy === 'id') {
responseData = await intercomApiRequest.call(this, `/contacts/${value}`, 'DELETE');
} else {
if (selectBy === 'userId') {
qs.user_id = value;
responseData = await intercomApiRequest.call(this, '/contacts', 'DELETE', {}, qs);
}
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
}
}
//https://developers.intercom.com/intercom-api-reference/reference#users
if (resource === 'user') {
if (operation === 'create' || operation === 'update') {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const jsonActive = this.getNodeParameter('jsonParameters', i) as boolean;
const body: IUser = {};
if (operation === 'create') {
const identifierType = this.getNodeParameter('identifierType', i) as string;
if (identifierType === 'email') {
body.email = this.getNodeParameter('idValue', i) as string;
} else if (identifierType === 'userId') {
body.user_id = this.getNodeParameter('idValue', i) as string;
if (selectBy === 'phone') {
qs.phone = value;
}
}
if (additionalFields.email) {
body.email = additionalFields.email as string;
}
if (additionalFields.userId) {
body.user_id = additionalFields.userId as string;
}
if (additionalFields.phone) {
body.phone = additionalFields.phone as string;
}
if (additionalFields.name) {
body.name = additionalFields.name as string;
}
if (additionalFields.unsubscribedFromEmails) {
body.unsubscribed_from_emails = additionalFields.unsubscribedFromEmails as boolean;
}
if (additionalFields.updateLastRequestAt) {
body.update_last_request_at = additionalFields.updateLastRequestAt as boolean;
}
if (additionalFields.sessionCount) {
body.session_count = additionalFields.sessionCount as number;
}
if (additionalFields.avatar) {
const avatar: IAvatar = {
type: 'avatar',
image_url: additionalFields.avatar as string,
};
body.avatar = avatar;
}
if (additionalFields.utmSource) {
body.utm_source = additionalFields.utmSource as string;
}
if (additionalFields.utmMedium) {
body.utm_medium = additionalFields.utmMedium as string;
}
if (additionalFields.utmCampaign) {
body.utm_campaign = additionalFields.utmCampaign as string;
}
if (additionalFields.utmTerm) {
body.utm_term = additionalFields.utmTerm as string;
}
if (additionalFields.utmContent) {
body.utm_content = additionalFields.utmContent as string;
}
if (additionalFields.companies) {
const companies: IUserCompany[] = [];
// @ts-ignore
additionalFields.companies.forEach(o => {
const company: IUserCompany = {};
company.company_id = o;
companies.push(company);
});
body.companies = companies;
}
if (additionalFields.sessionCount) {
body.session_count = additionalFields.sessionCount as number;
}
if (!jsonActive) {
const customAttributesValues = (this.getNodeParameter('customAttributesUi', i) as IDataObject).customAttributesValues as IDataObject[];
if (customAttributesValues) {
const customAttributes = {};
for (let i = 0; i < customAttributesValues.length; i++) {
// @ts-ignore
customAttributes[customAttributesValues[i].name] = customAttributesValues[i].value;
try {
if (selectBy === 'id') {
responseData = await intercomApiRequest.call(this, `/contacts/${value}`, 'GET');
} else {
responseData = await intercomApiRequest.call(this, '/contacts', 'GET', {}, qs);
responseData = responseData.contacts;
}
body.custom_attributes = customAttributes;
}
} else {
const customAttributesJson = validateJSON(this.getNodeParameter('customAttributesJson', i) as string);
if (customAttributesJson) {
body.custom_attributes = customAttributesJson;
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
}
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const filters = this.getNodeParameter('filters', i) as IDataObject;
Object.assign(qs, filters);
if (operation === 'update') {
const updateBy = this.getNodeParameter('updateBy', 0) as string;
const value = this.getNodeParameter('value', i) as string;
if (updateBy === 'userId') {
body.user_id = value;
}
if (updateBy === 'id') {
body.id = value;
}
if (updateBy === 'email') {
body.email = value;
}
}
try {
responseData = await intercomApiRequest.call(this, '/users', 'POST', body, qs);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
}
if (operation === 'get') {
const selectBy = this.getNodeParameter('selectBy', 0) as string;
const value = this.getNodeParameter('value', i) as string;
if (selectBy === 'userId') {
qs.user_id = value;
}
try {
if (selectBy === 'id') {
responseData = await intercomApiRequest.call(this, `/users/${value}`, 'GET', {}, qs);
} else {
responseData = await intercomApiRequest.call(this, '/users', 'GET', {}, qs);
}
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
}
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const filters = this.getNodeParameter('filters', i) as IDataObject;
Object.assign(qs, filters);
try {
if (returnAll === true) {
responseData = await intercomApiRequestAllItems.call(this, 'users', '/users', 'GET', {}, qs);
} else {
qs.per_page = this.getNodeParameter('limit', i) as number;
responseData = await intercomApiRequest.call(this, '/users', 'GET', {}, qs);
responseData = responseData.users;
}
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
}
if (operation === 'delete') {
const id = this.getNodeParameter('id', i) as string;
try {
responseData = await intercomApiRequest.call(this, `/users/${id}`, 'DELETE');
} catch (error) {
throw new NodeOperationError(this.getNode(), `Intercom Error: ${JSON.stringify(error)}`);
}
}
}
//https://developers.intercom.com/intercom-api-reference/reference#companies
if (resource === 'company') {
if (operation === 'create' || operation === 'update') {
const id = this.getNodeParameter('companyId', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const jsonActive = this.getNodeParameter('jsonParameters', i) as boolean;
const body: ICompany = {
company_id: id,
};
if (additionalFields.monthlySpend) {
body.monthly_spend = additionalFields.monthlySpend as number;
}
if (additionalFields.name) {
body.name = additionalFields.name as string;
}
if (additionalFields.plan) {
body.plan = additionalFields.plan as string;
}
if (additionalFields.size) {
body.size = additionalFields.size as number;
}
if (additionalFields.website) {
body.website = additionalFields.website as string;
}
if (additionalFields.industry) {
body.industry = additionalFields.industry as string;
}
if (!jsonActive) {
const customAttributesValues = (this.getNodeParameter('customAttributesUi', i) as IDataObject).customAttributesValues as IDataObject[];
if (customAttributesValues) {
const customAttributes = {};
for (let i = 0; i < customAttributesValues.length; i++) {
// @ts-ignore
customAttributes[customAttributesValues[i].name] = customAttributesValues[i].value;
}
body.custom_attributes = customAttributes;
}
} else {
const customAttributesJson = validateJSON(this.getNodeParameter('customAttributesJson', i) as string);
if (customAttributesJson) {
body.custom_attributes = customAttributesJson;
}
}
try {
responseData = await intercomApiRequest.call(this, '/companies', 'POST', body, qs);
} catch (error) {
throw new NodeOperationError(this.getNode(), `Intercom Error: ${JSON.stringify(error)}`);
}
}
if (operation === 'get') {
const selectBy = this.getNodeParameter('selectBy', 0) as string;
const value = this.getNodeParameter('value', i) as string;
if (selectBy === 'companyId') {
qs.company_id = value;
}
if (selectBy === 'name') {
qs.name = value;
}
try {
if (selectBy === 'id') {
responseData = await intercomApiRequest.call(this, `/companies/${value}`, 'GET', {}, qs);
} else {
responseData = await intercomApiRequest.call(this, '/companies', 'GET', {}, qs);
}
} catch (error) {
throw new NodeOperationError(this.getNode(), `Intercom Error: ${JSON.stringify(error)}`);
}
}
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const filters = this.getNodeParameter('filters', i) as IDataObject;
Object.assign(qs, filters);
try {
if (returnAll === true) {
responseData = await intercomApiRequestAllItems.call(this, 'companies', '/companies', 'GET', {}, qs);
} else {
qs.per_page = this.getNodeParameter('limit', i) as number;
responseData = await intercomApiRequest.call(this, '/companies', 'GET', {}, qs);
responseData = responseData.companies;
}
} catch (error) {
throw new NodeOperationError(this.getNode(), `Intercom Error: ${JSON.stringify(error)}`);
}
}
if (operation === 'users') {
const listBy = this.getNodeParameter('listBy', 0) as string;
const value = this.getNodeParameter('value', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
if (listBy === 'companyId') {
qs.company_id = value;
}
try {
if (listBy === 'id') {
try {
if (returnAll === true) {
responseData = await intercomApiRequestAllItems.call(this, 'users', `/companies/${value}/users`, 'GET', {}, qs);
responseData = await intercomApiRequestAllItems.call(this, 'contacts', '/contacts', 'GET', {}, qs);
} else {
qs.per_page = this.getNodeParameter('limit', i) as number;
responseData = await intercomApiRequest.call(this, `/companies/${value}/users`, 'GET', {}, qs);
responseData = await intercomApiRequest.call(this, '/contacts', 'GET', {}, qs);
responseData = responseData.contacts;
}
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
}
if (operation === 'delete') {
const deleteBy = this.getNodeParameter('deleteBy', 0) as string;
const value = this.getNodeParameter('value', i) as string;
try {
if (deleteBy === 'id') {
responseData = await intercomApiRequest.call(this, `/contacts/${value}`, 'DELETE');
} else {
qs.user_id = value;
responseData = await intercomApiRequest.call(this, '/contacts', 'DELETE', {}, qs);
}
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
}
}
//https://developers.intercom.com/intercom-api-reference/reference#users
if (resource === 'user') {
if (operation === 'create' || operation === 'update') {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const jsonActive = this.getNodeParameter('jsonParameters', i) as boolean;
const body: IUser = {};
if (operation === 'create') {
const identifierType = this.getNodeParameter('identifierType', i) as string;
if (identifierType === 'email') {
body.email = this.getNodeParameter('idValue', i) as string;
} else if (identifierType === 'userId') {
body.user_id = this.getNodeParameter('idValue', i) as string;
}
}
if (additionalFields.email) {
body.email = additionalFields.email as string;
}
if (additionalFields.userId) {
body.user_id = additionalFields.userId as string;
}
if (additionalFields.phone) {
body.phone = additionalFields.phone as string;
}
if (additionalFields.name) {
body.name = additionalFields.name as string;
}
if (additionalFields.unsubscribedFromEmails) {
body.unsubscribed_from_emails = additionalFields.unsubscribedFromEmails as boolean;
}
if (additionalFields.updateLastRequestAt) {
body.update_last_request_at = additionalFields.updateLastRequestAt as boolean;
}
if (additionalFields.sessionCount) {
body.session_count = additionalFields.sessionCount as number;
}
if (additionalFields.avatar) {
const avatar: IAvatar = {
type: 'avatar',
image_url: additionalFields.avatar as string,
};
body.avatar = avatar;
}
if (additionalFields.utmSource) {
body.utm_source = additionalFields.utmSource as string;
}
if (additionalFields.utmMedium) {
body.utm_medium = additionalFields.utmMedium as string;
}
if (additionalFields.utmCampaign) {
body.utm_campaign = additionalFields.utmCampaign as string;
}
if (additionalFields.utmTerm) {
body.utm_term = additionalFields.utmTerm as string;
}
if (additionalFields.utmContent) {
body.utm_content = additionalFields.utmContent as string;
}
if (additionalFields.companies) {
const companies: IUserCompany[] = [];
// @ts-ignore
additionalFields.companies.forEach(o => {
const company: IUserCompany = {};
company.company_id = o;
companies.push(company);
});
body.companies = companies;
}
if (additionalFields.sessionCount) {
body.session_count = additionalFields.sessionCount as number;
}
if (!jsonActive) {
const customAttributesValues = (this.getNodeParameter('customAttributesUi', i) as IDataObject).customAttributesValues as IDataObject[];
if (customAttributesValues) {
const customAttributes = {};
for (let i = 0; i < customAttributesValues.length; i++) {
// @ts-ignore
customAttributes[customAttributesValues[i].name] = customAttributesValues[i].value;
}
body.custom_attributes = customAttributes;
}
} else {
const customAttributesJson = validateJSON(this.getNodeParameter('customAttributesJson', i) as string);
if (customAttributesJson) {
body.custom_attributes = customAttributesJson;
}
}
if (operation === 'update') {
const updateBy = this.getNodeParameter('updateBy', 0) as string;
const value = this.getNodeParameter('value', i) as string;
if (updateBy === 'userId') {
body.user_id = value;
}
if (updateBy === 'id') {
body.id = value;
}
if (updateBy === 'email') {
body.email = value;
}
}
try {
responseData = await intercomApiRequest.call(this, '/users', 'POST', body, qs);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
}
if (operation === 'get') {
const selectBy = this.getNodeParameter('selectBy', 0) as string;
const value = this.getNodeParameter('value', i) as string;
if (selectBy === 'userId') {
qs.user_id = value;
}
try {
if (selectBy === 'id') {
responseData = await intercomApiRequest.call(this, `/users/${value}`, 'GET', {}, qs);
} else {
responseData = await intercomApiRequest.call(this, '/users', 'GET', {}, qs);
}
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
}
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const filters = this.getNodeParameter('filters', i) as IDataObject;
Object.assign(qs, filters);
try {
if (returnAll === true) {
responseData = await intercomApiRequestAllItems.call(this, 'users', '/users', 'GET', {}, qs);
} else {
qs.per_page = this.getNodeParameter('limit', i) as number;
responseData = await intercomApiRequest.call(this, '/users', 'GET', {}, qs);
responseData = responseData.users;
}
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
}
if (operation === 'delete') {
const id = this.getNodeParameter('id', i) as string;
try {
responseData = await intercomApiRequest.call(this, `/users/${id}`, 'DELETE');
} catch (error) {
throw new NodeOperationError(this.getNode(), `Intercom Error: ${JSON.stringify(error)}`);
}
}
}
//https://developers.intercom.com/intercom-api-reference/reference#companies
if (resource === 'company') {
if (operation === 'create' || operation === 'update') {
const id = this.getNodeParameter('companyId', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const jsonActive = this.getNodeParameter('jsonParameters', i) as boolean;
const body: ICompany = {
company_id: id,
};
if (additionalFields.monthlySpend) {
body.monthly_spend = additionalFields.monthlySpend as number;
}
if (additionalFields.name) {
body.name = additionalFields.name as string;
}
if (additionalFields.plan) {
body.plan = additionalFields.plan as string;
}
if (additionalFields.size) {
body.size = additionalFields.size as number;
}
if (additionalFields.website) {
body.website = additionalFields.website as string;
}
if (additionalFields.industry) {
body.industry = additionalFields.industry as string;
}
if (!jsonActive) {
const customAttributesValues = (this.getNodeParameter('customAttributesUi', i) as IDataObject).customAttributesValues as IDataObject[];
if (customAttributesValues) {
const customAttributes = {};
for (let i = 0; i < customAttributesValues.length; i++) {
// @ts-ignore
customAttributes[customAttributesValues[i].name] = customAttributesValues[i].value;
}
body.custom_attributes = customAttributes;
}
} else {
qs.type = 'users';
const customAttributesJson = validateJSON(this.getNodeParameter('customAttributesJson', i) as string);
if (customAttributesJson) {
body.custom_attributes = customAttributesJson;
}
}
try {
responseData = await intercomApiRequest.call(this, '/companies', 'POST', body, qs);
} catch (error) {
throw new NodeOperationError(this.getNode(), `Intercom Error: ${JSON.stringify(error)}`);
}
}
if (operation === 'get') {
const selectBy = this.getNodeParameter('selectBy', 0) as string;
const value = this.getNodeParameter('value', i) as string;
if (selectBy === 'companyId') {
qs.company_id = value;
}
if (selectBy === 'name') {
qs.name = value;
}
try {
if (selectBy === 'id') {
responseData = await intercomApiRequest.call(this, `/companies/${value}`, 'GET', {}, qs);
} else {
responseData = await intercomApiRequest.call(this, '/companies', 'GET', {}, qs);
}
} catch (error) {
throw new NodeOperationError(this.getNode(), `Intercom Error: ${JSON.stringify(error)}`);
}
}
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const filters = this.getNodeParameter('filters', i) as IDataObject;
Object.assign(qs, filters);
try {
if (returnAll === true) {
responseData = await intercomApiRequestAllItems.call(this, 'users', '/companies', 'GET', {}, qs);
responseData = await intercomApiRequestAllItems.call(this, 'companies', '/companies', 'GET', {}, qs);
} else {
qs.per_page = this.getNodeParameter('limit', i) as number;
responseData = await intercomApiRequest.call(this, '/companies', 'GET', {}, qs);
responseData = responseData.users;
responseData = responseData.companies;
}
} catch (error) {
throw new NodeOperationError(this.getNode(), `Intercom Error: ${JSON.stringify(error)}`);
}
}
if (operation === 'users') {
const listBy = this.getNodeParameter('listBy', 0) as string;
const value = this.getNodeParameter('value', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
if (listBy === 'companyId') {
qs.company_id = value;
}
try {
if (listBy === 'id') {
if (returnAll === true) {
responseData = await intercomApiRequestAllItems.call(this, 'users', `/companies/${value}/users`, 'GET', {}, qs);
} else {
qs.per_page = this.getNodeParameter('limit', i) as number;
responseData = await intercomApiRequest.call(this, `/companies/${value}/users`, 'GET', {}, qs);
responseData = responseData.users;
}
} else {
qs.type = 'users';
if (returnAll === true) {
responseData = await intercomApiRequestAllItems.call(this, 'users', '/companies', 'GET', {}, qs);
} else {
qs.per_page = this.getNodeParameter('limit', i) as number;
responseData = await intercomApiRequest.call(this, '/companies', 'GET', {}, qs);
responseData = responseData.users;
}
}
} catch (error) {
throw new NodeOperationError(this.getNode(), `Intercom Error: ${JSON.stringify(error)}`);
}
} catch (error) {
throw new NodeOperationError(this.getNode(), `Intercom Error: ${JSON.stringify(error)}`);
}
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];

File diff suppressed because it is too large Load diff

View file

@ -207,126 +207,134 @@ export class Kafka implements INodeType {
let responseData: IDataObject[];
const options = this.getNodeParameter('options', 0) as IDataObject;
const sendInputData = this.getNodeParameter('sendInputData', 0) as boolean;
try {
const options = this.getNodeParameter('options', 0) as IDataObject;
const sendInputData = this.getNodeParameter('sendInputData', 0) as boolean;
const useSchemaRegistry = this.getNodeParameter('useSchemaRegistry', 0) as boolean;
const useSchemaRegistry = this.getNodeParameter('useSchemaRegistry', 0) as boolean;
const timeout = options.timeout as number;
const timeout = options.timeout as number;
let compression = CompressionTypes.None;
let compression = CompressionTypes.None;
const acks = (options.acks === true) ? 1 : 0;
const acks = (options.acks === true) ? 1 : 0;
if (options.compression === true) {
compression = CompressionTypes.GZIP;
}
const credentials = this.getCredentials('kafka') as IDataObject;
const brokers = (credentials.brokers as string || '').split(',').map(item => item.trim()) as string[];
const clientId = credentials.clientId as string;
const ssl = credentials.ssl as boolean;
const config: KafkaConfig = {
clientId,
brokers,
ssl,
};
if (credentials.authentication === true) {
if(!(credentials.username && credentials.password)) {
throw new NodeOperationError(this.getNode(), 'Username and password are required for authentication');
}
config.sasl = {
username: credentials.username as string,
password: credentials.password as string,
mechanism: credentials.saslMechanism as string,
} as SASLOptions;
}
const kafka = new apacheKafka(config);
const producer = kafka.producer();
await producer.connect();
let message: string | Buffer;
for (let i = 0; i < length; i++) {
if (sendInputData === true) {
message = JSON.stringify(items[i].json);
} else {
message = this.getNodeParameter('message', i) as string;
if (options.compression === true) {
compression = CompressionTypes.GZIP;
}
if (useSchemaRegistry) {
try {
const schemaRegistryUrl = this.getNodeParameter('schemaRegistryUrl', 0) as string;
const eventName = this.getNodeParameter('eventName', 0) as string;
const credentials = this.getCredentials('kafka') as IDataObject;
const registry = new SchemaRegistry({ host: schemaRegistryUrl });
const id = await registry.getLatestSchemaId(eventName);
const brokers = (credentials.brokers as string || '').split(',').map(item => item.trim()) as string[];
message = await registry.encode(id, JSON.parse(message));
} catch (exception) {
throw new NodeOperationError(this.getNode(), 'Verify your Schema Registry configuration');
const clientId = credentials.clientId as string;
const ssl = credentials.ssl as boolean;
const config: KafkaConfig = {
clientId,
brokers,
ssl,
};
if (credentials.authentication === true) {
if(!(credentials.username && credentials.password)) {
throw new NodeOperationError(this.getNode(), 'Username and password are required for authentication');
}
config.sasl = {
username: credentials.username as string,
password: credentials.password as string,
mechanism: credentials.saslMechanism as string,
} as SASLOptions;
}
const topic = this.getNodeParameter('topic', i) as string;
const kafka = new apacheKafka(config);
const jsonParameters = this.getNodeParameter('jsonParameters', i) as boolean;
const producer = kafka.producer();
let headers;
await producer.connect();
if (jsonParameters === true) {
headers = this.getNodeParameter('headerParametersJson', i) as string;
try {
headers = JSON.parse(headers);
} catch (exception) {
throw new NodeOperationError(this.getNode(), 'Headers must be a valid json');
let message: string | Buffer;
for (let i = 0; i < length; i++) {
if (sendInputData === true) {
message = JSON.stringify(items[i].json);
} else {
message = this.getNodeParameter('message', i) as string;
}
} else {
const values = (this.getNodeParameter('headersUi', i) as IDataObject).headerValues as IDataObject[];
headers = {};
if (values !== undefined) {
for (const value of values) {
//@ts-ignore
headers[value.key] = value.value;
if (useSchemaRegistry) {
try {
const schemaRegistryUrl = this.getNodeParameter('schemaRegistryUrl', 0) as string;
const eventName = this.getNodeParameter('eventName', 0) as string;
const registry = new SchemaRegistry({ host: schemaRegistryUrl });
const id = await registry.getLatestSchemaId(eventName);
message = await registry.encode(id, JSON.parse(message));
} catch (exception) {
throw new NodeOperationError(this.getNode(), 'Verify your Schema Registry configuration');
}
}
const topic = this.getNodeParameter('topic', i) as string;
const jsonParameters = this.getNodeParameter('jsonParameters', i) as boolean;
let headers;
if (jsonParameters === true) {
headers = this.getNodeParameter('headerParametersJson', i) as string;
try {
headers = JSON.parse(headers);
} catch (exception) {
throw new NodeOperationError(this.getNode(), 'Headers must be a valid json');
}
} else {
const values = (this.getNodeParameter('headersUi', i) as IDataObject).headerValues as IDataObject[];
headers = {};
if (values !== undefined) {
for (const value of values) {
//@ts-ignore
headers[value.key] = value.value;
}
}
}
topicMessages.push(
{
topic,
messages: [{
value: message,
headers,
}],
});
}
topicMessages.push(
responseData = await producer.sendBatch(
{
topic,
messages: [{
value: message,
headers,
}],
topicMessages,
timeout,
compression,
acks,
},
);
if (responseData.length === 0) {
responseData.push({
success: true,
});
}
await producer.disconnect();
return [this.helpers.returnJsonArray(responseData)];
} catch (error) {
if (this.continueOnFail()) {
return [this.helpers.returnJsonArray({ error: error.message })];
} else {
throw error;
}
}
responseData = await producer.sendBatch(
{
topicMessages,
timeout,
compression,
acks,
},
);
if (responseData.length === 0) {
responseData.push({
success: true,
});
}
await producer.disconnect();
return [this.helpers.returnJsonArray(responseData)];
}
}

View file

@ -78,67 +78,75 @@ export class Line implements INodeType {
const operation = this.getNodeParameter('operation', 0) as string;
for (let i = 0; i < length; i++) {
if (resource === 'notification') {
//https://notify-bot.line.me/doc/en/
if (operation === 'send') {
const message = this.getNodeParameter('message', i) as string;
try {
if (resource === 'notification') {
//https://notify-bot.line.me/doc/en/
if (operation === 'send') {
const message = this.getNodeParameter('message', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IDataObject = {
message,
};
const body: IDataObject = {
message,
};
Object.assign(body, additionalFields);
Object.assign(body, additionalFields);
if (body.hasOwnProperty('notificationDisabled')) {
body.notificationDisabled = (body.notificationDisabled) ? 'true' : 'false';
}
if (body.stickerUi) {
const sticker = (body.stickerUi as IDataObject).stickerValue as IDataObject;
if (sticker) {
body.stickerId = sticker.stickerId;
body.stickerPackageId = sticker.stickerPackageId;
if (body.hasOwnProperty('notificationDisabled')) {
body.notificationDisabled = (body.notificationDisabled) ? 'true' : 'false';
}
delete body.stickerUi;
}
if (body.imageUi) {
const image = (body.imageUi as IDataObject).imageValue as IDataObject;
if (image && image.binaryData === true) {
if (items[i].binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
if (body.stickerUi) {
const sticker = (body.stickerUi as IDataObject).stickerValue as IDataObject;
if (sticker) {
body.stickerId = sticker.stickerId;
body.stickerPackageId = sticker.stickerPackageId;
}
//@ts-ignore
if (items[i].binary[image.binaryProperty] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property "${image.binaryProperty}" does not exists on item!`);
}
const binaryData = (items[i].binary as IBinaryKeyData)[image.binaryProperty as string];
body.imageFile = {
value: Buffer.from(binaryData.data, BINARY_ENCODING),
options: {
filename: binaryData.fileName,
},
};
} else {
body.imageFullsize = image.imageFullsize;
body.imageThumbnail = image.imageThumbnail;
delete body.stickerUi;
}
delete body.imageUi;
if (body.imageUi) {
const image = (body.imageUi as IDataObject).imageValue as IDataObject;
if (image && image.binaryData === true) {
if (items[i].binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
}
//@ts-ignore
if (items[i].binary[image.binaryProperty] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property "${image.binaryProperty}" does not exists on item!`);
}
const binaryData = (items[i].binary as IBinaryKeyData)[image.binaryProperty as string];
body.imageFile = {
value: Buffer.from(binaryData.data, BINARY_ENCODING),
options: {
filename: binaryData.fileName,
},
};
} else {
body.imageFullsize = image.imageFullsize;
body.imageThumbnail = image.imageThumbnail;
}
delete body.imageUi;
}
responseData = await lineApiRequest.call(this, 'POST', '', {}, {}, 'https://notify-api.line.me/api/notify', { formData: body });
}
responseData = await lineApiRequest.call(this, 'POST', '', {}, {}, 'https://notify-api.line.me/api/notify', { formData: body });
}
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else if (responseData !== undefined) {
returnData.push(responseData as IDataObject);
} else if (responseData !== undefined) {
returnData.push(responseData as IDataObject);
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];
}

View file

@ -81,173 +81,181 @@ export class LinkedIn implements INodeType {
let body = {};
for (let i = 0; i < items.length; i++) {
if (resource === 'post') {
if (operation === 'create') {
const text = this.getNodeParameter('text', i) as string;
const shareMediaCategory = this.getNodeParameter('shareMediaCategory', i) as string;
const postAs = this.getNodeParameter('postAs', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
let authorUrn = '';
let visibility = 'PUBLIC';
if (postAs === 'person') {
const personUrn = this.getNodeParameter('person', i) as string;
// Only if posting as a person can user decide if post visible by public or connections
visibility = additionalFields.visibility as string || 'PUBLIC';
authorUrn = `urn:li:person:${personUrn}`;
} else {
const organizationUrn = this.getNodeParameter('organization', i) as string;
authorUrn = `urn:li:organization:${organizationUrn}`;
}
let description = '';
let title = '';
let originalUrl = '';
if (shareMediaCategory === 'IMAGE') {
if (additionalFields.description) {
description = additionalFields.description as string;
}
if (additionalFields.title) {
title = additionalFields.title as string;
}
// Send a REQUEST to prepare a register of a media image file
const registerRequest = {
registerUploadRequest: {
recipes: [
'urn:li:digitalmediaRecipe:feedshare-image',
],
owner: authorUrn,
serviceRelationships: [
{
relationshipType: 'OWNER',
identifier: 'urn:li:userGeneratedContent',
},
],
},
};
const registerObject = await linkedInApiRequest.call(this, 'POST', '/assets?action=registerUpload', registerRequest);
// Response provides a specific upload URL that is used to upload the binary image file
const uploadUrl = registerObject.value.uploadMechanism['com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest'].uploadUrl as string;
const asset = registerObject.value.asset as string;
// Prepare binary file upload
const item = items[i];
if (item.binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
}
const propertyNameUpload = this.getNodeParameter('binaryPropertyName', i) as string;
if (item.binary[propertyNameUpload] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property "${propertyNameUpload}" does not exists on item!`);
}
// Buffer binary data
const buffer = Buffer.from(item.binary[propertyNameUpload].data, BINARY_ENCODING) as Buffer;
// Upload image
await linkedInApiRequest.call(this, 'POST', uploadUrl, buffer, true);
body = {
author: authorUrn,
lifecycleState: 'PUBLISHED',
specificContent: {
'com.linkedin.ugc.ShareContent': {
shareCommentary: {
text,
},
shareMediaCategory: 'IMAGE',
media: [
{
status: 'READY',
description: {
text: description,
},
media: asset,
title: {
text: title,
},
},
],
},
},
visibility: {
'com.linkedin.ugc.MemberNetworkVisibility': visibility,
},
};
} else if (shareMediaCategory === 'ARTICLE') {
try {
if (resource === 'post') {
if (operation === 'create') {
const text = this.getNodeParameter('text', i) as string;
const shareMediaCategory = this.getNodeParameter('shareMediaCategory', i) as string;
const postAs = this.getNodeParameter('postAs', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (additionalFields.description) {
description = additionalFields.description as string;
}
if (additionalFields.title) {
title = additionalFields.title as string;
}
if (additionalFields.originalUrl) {
originalUrl = additionalFields.originalUrl as string;
let authorUrn = '';
let visibility = 'PUBLIC';
if (postAs === 'person') {
const personUrn = this.getNodeParameter('person', i) as string;
// Only if posting as a person can user decide if post visible by public or connections
visibility = additionalFields.visibility as string || 'PUBLIC';
authorUrn = `urn:li:person:${personUrn}`;
} else {
const organizationUrn = this.getNodeParameter('organization', i) as string;
authorUrn = `urn:li:organization:${organizationUrn}`;
}
body = {
author: `${authorUrn}`,
lifecycleState: 'PUBLISHED',
specificContent: {
'com.linkedin.ugc.ShareContent': {
shareCommentary: {
text,
},
shareMediaCategory,
media: [
let description = '';
let title = '';
let originalUrl = '';
if (shareMediaCategory === 'IMAGE') {
if (additionalFields.description) {
description = additionalFields.description as string;
}
if (additionalFields.title) {
title = additionalFields.title as string;
}
// Send a REQUEST to prepare a register of a media image file
const registerRequest = {
registerUploadRequest: {
recipes: [
'urn:li:digitalmediaRecipe:feedshare-image',
],
owner: authorUrn,
serviceRelationships: [
{
status: 'READY',
description: {
text: description,
},
originalUrl,
title: {
text: title,
},
relationshipType: 'OWNER',
identifier: 'urn:li:userGeneratedContent',
},
],
},
},
visibility: {
'com.linkedin.ugc.MemberNetworkVisibility': visibility,
},
};
} else {
body = {
author: authorUrn,
lifecycleState: 'PUBLISHED',
specificContent: {
'com.linkedin.ugc.ShareContent': {
shareCommentary: {
text,
};
const registerObject = await linkedInApiRequest.call(this, 'POST', '/assets?action=registerUpload', registerRequest);
// Response provides a specific upload URL that is used to upload the binary image file
const uploadUrl = registerObject.value.uploadMechanism['com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest'].uploadUrl as string;
const asset = registerObject.value.asset as string;
// Prepare binary file upload
const item = items[i];
if (item.binary === undefined) {
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
}
const propertyNameUpload = this.getNodeParameter('binaryPropertyName', i) as string;
if (item.binary[propertyNameUpload] === undefined) {
throw new NodeOperationError(this.getNode(), `No binary data property "${propertyNameUpload}" does not exists on item!`);
}
// Buffer binary data
const buffer = Buffer.from(item.binary[propertyNameUpload].data, BINARY_ENCODING) as Buffer;
// Upload image
await linkedInApiRequest.call(this, 'POST', uploadUrl, buffer, true);
body = {
author: authorUrn,
lifecycleState: 'PUBLISHED',
specificContent: {
'com.linkedin.ugc.ShareContent': {
shareCommentary: {
text,
},
shareMediaCategory: 'IMAGE',
media: [
{
status: 'READY',
description: {
text: description,
},
media: asset,
title: {
text: title,
},
},
],
},
shareMediaCategory,
},
},
visibility: {
'com.linkedin.ugc.MemberNetworkVisibility': visibility,
},
};
visibility: {
'com.linkedin.ugc.MemberNetworkVisibility': visibility,
},
};
} else if (shareMediaCategory === 'ARTICLE') {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (additionalFields.description) {
description = additionalFields.description as string;
}
if (additionalFields.title) {
title = additionalFields.title as string;
}
if (additionalFields.originalUrl) {
originalUrl = additionalFields.originalUrl as string;
}
body = {
author: `${authorUrn}`,
lifecycleState: 'PUBLISHED',
specificContent: {
'com.linkedin.ugc.ShareContent': {
shareCommentary: {
text,
},
shareMediaCategory,
media: [
{
status: 'READY',
description: {
text: description,
},
originalUrl,
title: {
text: title,
},
},
],
},
},
visibility: {
'com.linkedin.ugc.MemberNetworkVisibility': visibility,
},
};
} else {
body = {
author: authorUrn,
lifecycleState: 'PUBLISHED',
specificContent: {
'com.linkedin.ugc.ShareContent': {
shareCommentary: {
text,
},
shareMediaCategory,
},
},
visibility: {
'com.linkedin.ugc.MemberNetworkVisibility': visibility,
},
};
}
const endpoint = '/ugcPosts';
responseData = await linkedInApiRequest.call(this, 'POST', endpoint, body);
}
const endpoint = '/ugcPosts';
responseData = await linkedInApiRequest.call(this, 'POST', endpoint, body);
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}

View file

@ -95,11 +95,19 @@ export class Mailcheck implements INodeType {
const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string;
for (let i = 0; i < length; i++) {
if (resource === 'email') {
if (operation === 'check') {
const email = this.getNodeParameter('email', i) as string;
responseData = await mailCheckApiRequest.call(this, 'POST', '/singleEmail:check', { email });
try {
if (resource === 'email') {
if (operation === 'check') {
const email = this.getNodeParameter('email', i) as string;
responseData = await mailCheckApiRequest.call(this, 'POST', '/singleEmail:check', { email });
}
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
@ -109,4 +117,4 @@ export class Mailcheck implements INodeType {
}
return [this.helpers.returnJsonArray(returnData)];
}
}
}

View file

@ -1862,215 +1862,64 @@ export class Mailchimp implements INodeType {
const operation = this.getNodeParameter('operation', 0) as string;
for (let i = 0; i < length; i++) {
if (resource === 'listGroup') {
//https://mailchimp.com/developer/reference/lists/interest-categories/#get_/lists/-list_id-/interest-categories/-interest_category_id-
if (operation === 'getAll') {
const listId = this.getNodeParameter('list', i) as string;
const categoryId = this.getNodeParameter('groupCategory', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
try {
if (resource === 'listGroup') {
//https://mailchimp.com/developer/reference/lists/interest-categories/#get_/lists/-list_id-/interest-categories/-interest_category_id-
if (operation === 'getAll') {
const listId = this.getNodeParameter('list', i) as string;
const categoryId = this.getNodeParameter('groupCategory', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
if (returnAll === true) {
responseData = await mailchimpApiRequestAllItems.call(this, `/lists/${listId}/interest-categories/${categoryId}/interests`, 'GET', 'interests', {}, qs);
} else {
qs.count = this.getNodeParameter('limit', i) as number;
responseData = await mailchimpApiRequest.call(this, `/lists/${listId}/interest-categories/${categoryId}/interests`, 'GET', {}, qs);
responseData = responseData.interests;
if (returnAll === true) {
responseData = await mailchimpApiRequestAllItems.call(this, `/lists/${listId}/interest-categories/${categoryId}/interests`, 'GET', 'interests', {}, qs);
} else {
qs.count = this.getNodeParameter('limit', i) as number;
responseData = await mailchimpApiRequest.call(this, `/lists/${listId}/interest-categories/${categoryId}/interests`, 'GET', {}, qs);
responseData = responseData.interests;
}
}
}
}
if (resource === 'member') {
//https://mailchimp.com/developer/reference/lists/list-members/#post_/lists/-list_id-/members
if (operation === 'create') {
const listId = this.getNodeParameter('list', i) as string;
const email = this.getNodeParameter('email', i) as string;
const status = this.getNodeParameter('status', i) as Status;
const options = this.getNodeParameter('options', i) as IDataObject;
const jsonActive = this.getNodeParameter('jsonParameters', i) as IDataObject;
if (resource === 'member') {
//https://mailchimp.com/developer/reference/lists/list-members/#post_/lists/-list_id-/members
if (operation === 'create') {
const listId = this.getNodeParameter('list', i) as string;
const email = this.getNodeParameter('email', i) as string;
const status = this.getNodeParameter('status', i) as Status;
const options = this.getNodeParameter('options', i) as IDataObject;
const jsonActive = this.getNodeParameter('jsonParameters', i) as IDataObject;
const body: ICreateMemberBody = {
listId,
email_address: email,
status,
};
if (options.emailType) {
body.email_type = options.emailType as string;
}
if (options.language) {
body.language = options.language as string;
}
if (options.vip) {
body.vip = options.vip as boolean;
}
if (options.ipSignup) {
body.ip_signup = options.ipSignup as string;
}
if (options.ipOptIn) {
body.ip_opt = options.ipOptIn as string;
}
if (options.timestampOpt) {
body.timestamp_opt = moment(options.timestampOpt as string).format('YYYY-MM-DD HH:MM:SS') as string;
}
if (options.timestampSignup) {
body.timestamp_signup = moment(options.timestampSignup as string).format('YYYY-MM-DD HH:MM:SS') as string;
}
if (options.tags) {
// @ts-ignore
body.tags = options.tags.split(',') as string[];
}
if (!jsonActive) {
const locationValues = (this.getNodeParameter('locationFieldsUi', i) as IDataObject).locationFieldsValues as IDataObject;
if (locationValues) {
const location: ILocation = {};
for (const key of Object.keys(locationValues)) {
if (key === 'latitude') {
location.latitude = parseFloat(locationValues[key] as string) as number;
} else if (key === 'longitude') {
location.longitude = parseFloat(locationValues[key] as string) as number;
}
}
body.location = location;
const body: ICreateMemberBody = {
listId,
email_address: email,
status,
};
if (options.emailType) {
body.email_type = options.emailType as string;
}
const mergeFieldsValues = (this.getNodeParameter('mergeFieldsUi', i) as IDataObject).mergeFieldsValues as IDataObject[];
if (mergeFieldsValues) {
const mergeFields = {};
for (let i = 0; i < mergeFieldsValues.length; i++) {
// @ts-ignore
mergeFields[mergeFieldsValues[i].name] = mergeFieldsValues[i].value;
}
body.merge_fields = mergeFields;
if (options.language) {
body.language = options.language as string;
}
const groupsValues = (this.getNodeParameter('groupsUi', i) as IDataObject).groupsValues as IDataObject[];
if (groupsValues) {
const groups = {};
for (let i = 0; i < groupsValues.length; i++) {
// @ts-ignore
groups[groupsValues[i].categoryFieldId] = groupsValues[i].value;
}
body.interests = groups;
if (options.vip) {
body.vip = options.vip as boolean;
}
} else {
const locationJson = validateJSON(this.getNodeParameter('locationJson', i) as string);
const mergeFieldsJson = validateJSON(this.getNodeParameter('mergeFieldsJson', i) as string);
const groupJson = validateJSON(this.getNodeParameter('groupJson', i) as string);
if (locationJson) {
body.location = locationJson;
if (options.ipSignup) {
body.ip_signup = options.ipSignup as string;
}
if (mergeFieldsJson) {
body.merge_fields = mergeFieldsJson;
if (options.ipOptIn) {
body.ip_opt = options.ipOptIn as string;
}
if (groupJson) {
body.interests = groupJson;
if (options.timestampOpt) {
body.timestamp_opt = moment(options.timestampOpt as string).format('YYYY-MM-DD HH:MM:SS') as string;
}
}
responseData = await mailchimpApiRequest.call(this, `/lists/${listId}/members`, 'POST', body);
}
//https://mailchimp.com/developer/reference/lists/list-members/
if (operation === 'delete') {
const listId = this.getNodeParameter('list', i) as string;
const email = this.getNodeParameter('email', i) as string;
responseData = await mailchimpApiRequest.call(this, `/lists/${listId}/members/${email}/actions/delete-permanent`, 'POST');
responseData = { success: true };
}
//https://mailchimp.com/developer/reference/lists/list-members/#get_/lists/-list_id-/members/-subscriber_hash-
if (operation === 'get') {
const listId = this.getNodeParameter('list', i) as string;
const email = this.getNodeParameter('email', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
if (options.fields) {
qs.fields = options.fields as string;
}
if (options.excludeFields) {
qs.exclude_fields = options.excludeFields as string;
}
responseData = await mailchimpApiRequest.call(this, `/lists/${listId}/members/${email}`, 'GET', {}, qs);
}
//https://mailchimp.com/developer/reference/lists/list-members/#get_/lists/-list_id-/members
if (operation === 'getAll') {
const listId = this.getNodeParameter('list', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const options = this.getNodeParameter('options', i) as IDataObject;
if (options.beforeLastChanged) {
qs.before_last_changed = options.beforeLastChanged as string;
}
if (options.beforeTimestampOpt) {
qs.before_timestamp_opt = options.beforeTimestampOpt as string;
}
// TODO
//figure why for some reason when either fields or exclude_fields is set the endpoint returns nothing
// interestingly it works perfect when retriving just one member
// if (options.fields) {
// qs.fields = options.fields as string;
// }
// if (options.excludeFields) {
// qs.exclude_fields = options.excludeFields as string;
// }
if (options.emailType) {
qs.email_type = options.emailType as string;
}
if (options.status) {
qs.status = options.status as string;
}
if (options.sinceLastChanged) {
qs.since_last_changed = options.sinceLastChanged as string;
}
if (returnAll === true) {
responseData = await mailchimpApiRequestAllItems.call(this, `/lists/${listId}/members`, 'GET', 'members', {}, qs);
} else {
qs.count = this.getNodeParameter('limit', i) as number;
responseData = await mailchimpApiRequest.call(this, `/lists/${listId}/members`, 'GET', {}, qs);
responseData = responseData.members;
}
}
//https://mailchimp.com/developer/reference/lists/list-members/#put_/lists/-list_id-/members/-subscriber_hash-
if (operation === 'update') {
const listId = this.getNodeParameter('list', i) as string;
const email = this.getNodeParameter('email', i) as string;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const jsonActive = this.getNodeParameter('jsonParameters', i) as IDataObject;
const body: ICreateMemberBody = {
listId,
email_address: email,
};
if (updateFields.skipMergeValidation) {
qs.skip_merge_validation = updateFields.skipMergeValidation as boolean;
}
if (updateFields.status) {
body.status = updateFields.status as Status;
}
if (updateFields.emailType) {
body.email_type = updateFields.emailType as string;
}
if (updateFields.language) {
body.language = updateFields.language as string;
}
if (updateFields.vip) {
body.vip = updateFields.vip as boolean;
}
if (updateFields.ipSignup) {
body.ip_signup = updateFields.ipSignup as string;
}
if (updateFields.ipOptIn) {
body.ip_opt = updateFields.ipOptIn as string;
}
if (updateFields.timestampOpt) {
body.timestamp_opt = moment(updateFields.timestampOpt as string).format('YYYY-MM-DD HH:MM:SS') as string;
}
if (updateFields.timestampSignup) {
body.timestamp_signup = moment(updateFields.timestampSignup as string).format('YYYY-MM-DD HH:MM:SS') as string;
}
if (!jsonActive) {
if (updateFields.locationFieldsUi) {
const locationValues = (updateFields.locationFieldsUi as IDataObject).locationFieldsValues as IDataObject;
if (options.timestampSignup) {
body.timestamp_signup = moment(options.timestampSignup as string).format('YYYY-MM-DD HH:MM:SS') as string;
}
if (options.tags) {
// @ts-ignore
body.tags = options.tags.split(',') as string[];
}
if (!jsonActive) {
const locationValues = (this.getNodeParameter('locationFieldsUi', i) as IDataObject).locationFieldsValues as IDataObject;
if (locationValues) {
const location: ILocation = {};
for (const key of Object.keys(locationValues)) {
@ -2082,9 +1931,7 @@ export class Mailchimp implements INodeType {
}
body.location = location;
}
}
if (updateFields.mergeFieldsUi) {
const mergeFieldsValues = (updateFields.mergeFieldsUi as IDataObject).mergeFieldsValues as IDataObject[];
const mergeFieldsValues = (this.getNodeParameter('mergeFieldsUi', i) as IDataObject).mergeFieldsValues as IDataObject[];
if (mergeFieldsValues) {
const mergeFields = {};
for (let i = 0; i < mergeFieldsValues.length; i++) {
@ -2093,9 +1940,8 @@ export class Mailchimp implements INodeType {
}
body.merge_fields = mergeFields;
}
}
if (updateFields.groupsUi) {
const groupsValues = (updateFields.groupsUi as IDataObject).groupsValues as IDataObject[];
const groupsValues = (this.getNodeParameter('groupsUi', i) as IDataObject).groupsValues as IDataObject[];
if (groupsValues) {
const groups = {};
for (let i = 0; i < groupsValues.length; i++) {
@ -2104,168 +1950,330 @@ export class Mailchimp implements INodeType {
}
body.interests = groups;
}
} else {
const locationJson = validateJSON(this.getNodeParameter('locationJson', i) as string);
const mergeFieldsJson = validateJSON(this.getNodeParameter('mergeFieldsJson', i) as string);
const groupJson = validateJSON(this.getNodeParameter('groupJson', i) as string);
if (locationJson) {
body.location = locationJson;
}
if (mergeFieldsJson) {
body.merge_fields = mergeFieldsJson;
}
if (groupJson) {
body.interests = groupJson;
}
}
} else {
const locationJson = validateJSON(this.getNodeParameter('locationJson', i) as string);
const mergeFieldsJson = validateJSON(this.getNodeParameter('mergeFieldsJson', i) as string);
const groupJson = validateJSON(this.getNodeParameter('groupJson', i) as string);
responseData = await mailchimpApiRequest.call(this, `/lists/${listId}/members`, 'POST', body);
}
//https://mailchimp.com/developer/reference/lists/list-members/
if (operation === 'delete') {
if (locationJson) {
body.location = locationJson;
const listId = this.getNodeParameter('list', i) as string;
const email = this.getNodeParameter('email', i) as string;
responseData = await mailchimpApiRequest.call(this, `/lists/${listId}/members/${email}/actions/delete-permanent`, 'POST');
responseData = { success: true };
}
//https://mailchimp.com/developer/reference/lists/list-members/#get_/lists/-list_id-/members/-subscriber_hash-
if (operation === 'get') {
const listId = this.getNodeParameter('list', i) as string;
const email = this.getNodeParameter('email', i) as string;
const options = this.getNodeParameter('options', i) as IDataObject;
if (options.fields) {
qs.fields = options.fields as string;
}
if (mergeFieldsJson) {
body.merge_fields = mergeFieldsJson;
if (options.excludeFields) {
qs.exclude_fields = options.excludeFields as string;
}
if (groupJson) {
body.interests = groupJson;
responseData = await mailchimpApiRequest.call(this, `/lists/${listId}/members/${email}`, 'GET', {}, qs);
}
//https://mailchimp.com/developer/reference/lists/list-members/#get_/lists/-list_id-/members
if (operation === 'getAll') {
const listId = this.getNodeParameter('list', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const options = this.getNodeParameter('options', i) as IDataObject;
if (options.beforeLastChanged) {
qs.before_last_changed = options.beforeLastChanged as string;
}
if (options.beforeTimestampOpt) {
qs.before_timestamp_opt = options.beforeTimestampOpt as string;
}
// TODO
//figure why for some reason when either fields or exclude_fields is set the endpoint returns nothing
// interestingly it works perfect when retriving just one member
// if (options.fields) {
// qs.fields = options.fields as string;
// }
// if (options.excludeFields) {
// qs.exclude_fields = options.excludeFields as string;
// }
if (options.emailType) {
qs.email_type = options.emailType as string;
}
if (options.status) {
qs.status = options.status as string;
}
if (options.sinceLastChanged) {
qs.since_last_changed = options.sinceLastChanged as string;
}
if (returnAll === true) {
responseData = await mailchimpApiRequestAllItems.call(this, `/lists/${listId}/members`, 'GET', 'members', {}, qs);
} else {
qs.count = this.getNodeParameter('limit', i) as number;
responseData = await mailchimpApiRequest.call(this, `/lists/${listId}/members`, 'GET', {}, qs);
responseData = responseData.members;
}
}
responseData = await mailchimpApiRequest.call(this, `/lists/${listId}/members/${email}`, 'PUT', body);
}
}
if (resource === 'memberTag') {
//https://mailchimp.com/developer/reference/lists/list-members/list-member-tags/#post_/lists/-list_id-/members/-subscriber_hash-/tags
if (operation === 'create') {
const listId = this.getNodeParameter('list', i) as string;
const email = this.getNodeParameter('email', i) as string;
const tags = this.getNodeParameter('tags', i) as string[];
const options = this.getNodeParameter('options', i) as IDataObject;
//https://mailchimp.com/developer/reference/lists/list-members/#put_/lists/-list_id-/members/-subscriber_hash-
if (operation === 'update') {
const body: IDataObject = {
tags: [],
};
if (options.isSyncing) {
body.is_syncing = options.isSyncing as boolean;
}
for (const tag of tags) {
//@ts-ignore
body.tags.push({
name: tag,
status: 'active',
});
}
responseData = await mailchimpApiRequest.call(this, `/lists/${listId}/members/${email}/tags`, 'POST', body);
responseData = { success: true };
}
//https://mailchimp.com/developer/reference/lists/list-members/list-member-tags/#post_/lists/-list_id-/members/-subscriber_hash-/tags
if (operation === 'delete') {
const listId = this.getNodeParameter('list', i) as string;
const email = this.getNodeParameter('email', i) as string;
const tags = this.getNodeParameter('tags', i) as string[];
const options = this.getNodeParameter('options', i) as IDataObject;
const body: IDataObject = {
tags: [],
};
if (options.isSyncing) {
body.is_syncing = options.isSyncing as boolean;
}
for (const tag of tags) {
//@ts-ignore
body.tags.push({
name: tag,
status: 'inactive',
});
}
responseData = await mailchimpApiRequest.call(this, `/lists/${listId}/members/${email}/tags`, 'POST', body);
responseData = { success: true };
}
}
if (resource === 'campaign') {
//https://mailchimp.com/developer/api/marketing/campaigns/list-campaigns/
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const options = this.getNodeParameter('options', i) as IDataObject;
if (options.status) {
qs.status = options.status as string;
}
if (options.beforeCreateTime) {
qs.before_create_time = options.beforeCreateTime as string;
}
if (options.beforeSendTime) {
qs.before_send_time = options.beforeSendTime as string;
}
if (options.excludeFields) {
qs.exclude_fields = (options.exclude_fields as string[]).join(',');
}
if (options.fields) {
qs.fields = (options.fields as string[]).join(',');
if ((options.fields as string[]).includes('*')) {
qs.fields = campaignFieldsMetadata.join(',');
const listId = this.getNodeParameter('list', i) as string;
const email = this.getNodeParameter('email', i) as string;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const jsonActive = this.getNodeParameter('jsonParameters', i) as IDataObject;
const body: ICreateMemberBody = {
listId,
email_address: email,
};
if (updateFields.skipMergeValidation) {
qs.skip_merge_validation = updateFields.skipMergeValidation as boolean;
}
} else {
qs.fields = [
'campaigns.id',
'campaigns.status',
'campaigns.tracking',
'campaigns.settings.from_name',
'campaigns.settings.title',
'campaigns.settings.reply_to',
].join(',');
}
if (updateFields.status) {
body.status = updateFields.status as Status;
}
if (updateFields.emailType) {
body.email_type = updateFields.emailType as string;
}
if (updateFields.language) {
body.language = updateFields.language as string;
}
if (updateFields.vip) {
body.vip = updateFields.vip as boolean;
}
if (updateFields.ipSignup) {
body.ip_signup = updateFields.ipSignup as string;
}
if (updateFields.ipOptIn) {
body.ip_opt = updateFields.ipOptIn as string;
}
if (updateFields.timestampOpt) {
body.timestamp_opt = moment(updateFields.timestampOpt as string).format('YYYY-MM-DD HH:MM:SS') as string;
}
if (updateFields.timestampSignup) {
body.timestamp_signup = moment(updateFields.timestampSignup as string).format('YYYY-MM-DD HH:MM:SS') as string;
}
if (!jsonActive) {
if (updateFields.locationFieldsUi) {
const locationValues = (updateFields.locationFieldsUi as IDataObject).locationFieldsValues as IDataObject;
if (locationValues) {
const location: ILocation = {};
for (const key of Object.keys(locationValues)) {
if (key === 'latitude') {
location.latitude = parseFloat(locationValues[key] as string) as number;
} else if (key === 'longitude') {
location.longitude = parseFloat(locationValues[key] as string) as number;
}
}
body.location = location;
}
}
if (updateFields.mergeFieldsUi) {
const mergeFieldsValues = (updateFields.mergeFieldsUi as IDataObject).mergeFieldsValues as IDataObject[];
if (mergeFieldsValues) {
const mergeFields = {};
for (let i = 0; i < mergeFieldsValues.length; i++) {
// @ts-ignore
mergeFields[mergeFieldsValues[i].name] = mergeFieldsValues[i].value;
}
body.merge_fields = mergeFields;
}
}
if (updateFields.groupsUi) {
const groupsValues = (updateFields.groupsUi as IDataObject).groupsValues as IDataObject[];
if (groupsValues) {
const groups = {};
for (let i = 0; i < groupsValues.length; i++) {
// @ts-ignore
groups[groupsValues[i].categoryFieldId] = groupsValues[i].value;
}
body.interests = groups;
}
}
} else {
const locationJson = validateJSON(this.getNodeParameter('locationJson', i) as string);
const mergeFieldsJson = validateJSON(this.getNodeParameter('mergeFieldsJson', i) as string);
const groupJson = validateJSON(this.getNodeParameter('groupJson', i) as string);
if (options.listId) {
qs.list_id = options.listId as string;
}
if (options.sinceCreateTime) {
qs.since_create_time = options.sinceCreateTime as string;
}
if (options.sinceSendTime) {
qs.since_send_time = options.sinceSendTime as string;
}
if (options.sortDirection) {
qs.sort_dir = options.sortDirection as string;
}
if (options.sortField) {
qs.sort_field = options.sortField as string;
}
if (returnAll === true) {
responseData = await mailchimpApiRequestAllItems.call(this, `/campaigns`, 'GET', 'campaigns', {}, qs);
} else {
qs.count = this.getNodeParameter('limit', i) as number;
responseData = await mailchimpApiRequest.call(this, `/campaigns`, 'GET', {}, qs);
responseData = responseData.campaigns;
if (locationJson) {
body.location = locationJson;
}
if (mergeFieldsJson) {
body.merge_fields = mergeFieldsJson;
}
if (groupJson) {
body.interests = groupJson;
}
}
responseData = await mailchimpApiRequest.call(this, `/lists/${listId}/members/${email}`, 'PUT', body);
}
}
//https://mailchimp.com/developer/api/marketing/campaigns/send-campaign/
if (operation === 'send') {
const campaignId = this.getNodeParameter('campaignId', i) as string;
responseData = await mailchimpApiRequest.call(this, `/campaigns/${campaignId}/actions/send`, 'POST', {});
responseData = { success: true };
}
//https://mailchimp.com/developer/api/marketing/campaigns/get-campaign-info/
if (operation === 'get') {
const campaignId = this.getNodeParameter('campaignId', i) as string;
responseData = await mailchimpApiRequest.call(this, `/campaigns/${campaignId}`, 'GET', {});
}
//https://mailchimp.com/developer/api/marketing/campaigns/delete-campaign/
if (operation === 'delete') {
const campaignId = this.getNodeParameter('campaignId', i) as string;
responseData = await mailchimpApiRequest.call(this, `/campaigns/${campaignId}`, 'DELETE', {});
responseData = { success: true };
}
//https://mailchimp.com/developer/api/marketing/campaigns/replicate-campaign/
if (operation === 'replicate') {
const campaignId = this.getNodeParameter('campaignId', i) as string;
responseData = await mailchimpApiRequest.call(this, `/campaigns/${campaignId}/actions/replicate`, 'POST', {});
}
//https://mailchimp.com/developer/api/marketing/campaigns/resend-campaign/
if (operation === 'resend') {
const campaignId = this.getNodeParameter('campaignId', i) as string;
responseData = await mailchimpApiRequest.call(this, `/campaigns/${campaignId}/actions/create-resend`, 'POST', {});
}
}
if (resource === 'memberTag') {
//https://mailchimp.com/developer/reference/lists/list-members/list-member-tags/#post_/lists/-list_id-/members/-subscriber_hash-/tags
if (operation === 'create') {
const listId = this.getNodeParameter('list', i) as string;
const email = this.getNodeParameter('email', i) as string;
const tags = this.getNodeParameter('tags', i) as string[];
const options = this.getNodeParameter('options', i) as IDataObject;
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
const body: IDataObject = {
tags: [],
};
if (options.isSyncing) {
body.is_syncing = options.isSyncing as boolean;
}
for (const tag of tags) {
//@ts-ignore
body.tags.push({
name: tag,
status: 'active',
});
}
responseData = await mailchimpApiRequest.call(this, `/lists/${listId}/members/${email}/tags`, 'POST', body);
responseData = { success: true };
}
//https://mailchimp.com/developer/reference/lists/list-members/list-member-tags/#post_/lists/-list_id-/members/-subscriber_hash-/tags
if (operation === 'delete') {
const listId = this.getNodeParameter('list', i) as string;
const email = this.getNodeParameter('email', i) as string;
const tags = this.getNodeParameter('tags', i) as string[];
const options = this.getNodeParameter('options', i) as IDataObject;
const body: IDataObject = {
tags: [],
};
if (options.isSyncing) {
body.is_syncing = options.isSyncing as boolean;
}
for (const tag of tags) {
//@ts-ignore
body.tags.push({
name: tag,
status: 'inactive',
});
}
responseData = await mailchimpApiRequest.call(this, `/lists/${listId}/members/${email}/tags`, 'POST', body);
responseData = { success: true };
}
}
if (resource === 'campaign') {
//https://mailchimp.com/developer/api/marketing/campaigns/list-campaigns/
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const options = this.getNodeParameter('options', i) as IDataObject;
if (options.status) {
qs.status = options.status as string;
}
if (options.beforeCreateTime) {
qs.before_create_time = options.beforeCreateTime as string;
}
if (options.beforeSendTime) {
qs.before_send_time = options.beforeSendTime as string;
}
if (options.excludeFields) {
qs.exclude_fields = (options.exclude_fields as string[]).join(',');
}
if (options.fields) {
qs.fields = (options.fields as string[]).join(',');
if ((options.fields as string[]).includes('*')) {
qs.fields = campaignFieldsMetadata.join(',');
}
} else {
qs.fields = [
'campaigns.id',
'campaigns.status',
'campaigns.tracking',
'campaigns.settings.from_name',
'campaigns.settings.title',
'campaigns.settings.reply_to',
].join(',');
}
if (options.listId) {
qs.list_id = options.listId as string;
}
if (options.sinceCreateTime) {
qs.since_create_time = options.sinceCreateTime as string;
}
if (options.sinceSendTime) {
qs.since_send_time = options.sinceSendTime as string;
}
if (options.sortDirection) {
qs.sort_dir = options.sortDirection as string;
}
if (options.sortField) {
qs.sort_field = options.sortField as string;
}
if (returnAll === true) {
responseData = await mailchimpApiRequestAllItems.call(this, `/campaigns`, 'GET', 'campaigns', {}, qs);
} else {
qs.count = this.getNodeParameter('limit', i) as number;
responseData = await mailchimpApiRequest.call(this, `/campaigns`, 'GET', {}, qs);
responseData = responseData.campaigns;
}
}
//https://mailchimp.com/developer/api/marketing/campaigns/send-campaign/
if (operation === 'send') {
const campaignId = this.getNodeParameter('campaignId', i) as string;
responseData = await mailchimpApiRequest.call(this, `/campaigns/${campaignId}/actions/send`, 'POST', {});
responseData = { success: true };
}
//https://mailchimp.com/developer/api/marketing/campaigns/get-campaign-info/
if (operation === 'get') {
const campaignId = this.getNodeParameter('campaignId', i) as string;
responseData = await mailchimpApiRequest.call(this, `/campaigns/${campaignId}`, 'GET', {});
}
//https://mailchimp.com/developer/api/marketing/campaigns/delete-campaign/
if (operation === 'delete') {
const campaignId = this.getNodeParameter('campaignId', i) as string;
responseData = await mailchimpApiRequest.call(this, `/campaigns/${campaignId}`, 'DELETE', {});
responseData = { success: true };
}
//https://mailchimp.com/developer/api/marketing/campaigns/replicate-campaign/
if (operation === 'replicate') {
const campaignId = this.getNodeParameter('campaignId', i) as string;
responseData = await mailchimpApiRequest.call(this, `/campaigns/${campaignId}/actions/replicate`, 'POST', {});
}
//https://mailchimp.com/developer/api/marketing/campaigns/resend-campaign/
if (operation === 'resend') {
const campaignId = this.getNodeParameter('campaignId', i) as string;
responseData = await mailchimpApiRequest.call(this, `/campaigns/${campaignId}/actions/create-resend`, 'POST', {});
}
}
if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {
returnData.push(responseData as IDataObject);
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];

Some files were not shown because too many files have changed in this diff Show more