From 50ae196768b116b20b0fbb315e173c3cf8372c0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Fri, 14 May 2021 16:50:58 +0200 Subject: [PATCH] :tada: Initial node scaffolding --- .../ElasticSearchApi.credentials.ts | 36 + .../nodes/ElasticSearch/ElasticSearch.node.ts | 275 ++++++ .../nodes/ElasticSearch/GenericFunctions.ts | 54 ++ .../descriptions/DocumentDescription.ts | 328 +++++++ .../descriptions/IndexDescription.ts | 878 ++++++++++++++++++ .../nodes/ElasticSearch/descriptions/index.ts | 2 + .../nodes/ElasticSearch/elasticSearch.svg | 14 + .../nodes-base/nodes/ElasticSearch/types.d.ts | 5 + packages/nodes-base/package.json | 2 + 9 files changed, 1594 insertions(+) create mode 100644 packages/nodes-base/credentials/ElasticSearchApi.credentials.ts create mode 100644 packages/nodes-base/nodes/ElasticSearch/ElasticSearch.node.ts create mode 100644 packages/nodes-base/nodes/ElasticSearch/GenericFunctions.ts create mode 100644 packages/nodes-base/nodes/ElasticSearch/descriptions/DocumentDescription.ts create mode 100644 packages/nodes-base/nodes/ElasticSearch/descriptions/IndexDescription.ts create mode 100644 packages/nodes-base/nodes/ElasticSearch/descriptions/index.ts create mode 100644 packages/nodes-base/nodes/ElasticSearch/elasticSearch.svg create mode 100644 packages/nodes-base/nodes/ElasticSearch/types.d.ts diff --git a/packages/nodes-base/credentials/ElasticSearchApi.credentials.ts b/packages/nodes-base/credentials/ElasticSearchApi.credentials.ts new file mode 100644 index 0000000000..11e748948c --- /dev/null +++ b/packages/nodes-base/credentials/ElasticSearchApi.credentials.ts @@ -0,0 +1,36 @@ +import { + ICredentialType, + NodePropertyTypes, +} from 'n8n-workflow'; + +export class ElasticSearchApi implements ICredentialType { + name = 'elasticSearchApi'; + displayName = 'Elastic Search API'; + documentationUrl = 'elasticSearch'; + properties = [ + { + displayName: 'Username', + name: 'username', + type: 'string' as NodePropertyTypes, + default: '', + placeholder: 'hello@n8n.io', + }, + { + displayName: 'Password', + name: 'password', + type: 'string' as NodePropertyTypes, + typeOptions: { + password: true, + }, + default: '', + }, + { + displayName: 'Base URL', + name: 'baseUrl', + type: 'string' as NodePropertyTypes, + default: '', + placeholder: 'https://a-b-optimized-deployment-ffc9df.es.us-west1.gcp.cloud.es.io:9243', + description: 'Referred to as \'endpoint\' in the ElasticSearch dashboard.', + }, + ]; +} diff --git a/packages/nodes-base/nodes/ElasticSearch/ElasticSearch.node.ts b/packages/nodes-base/nodes/ElasticSearch/ElasticSearch.node.ts new file mode 100644 index 0000000000..b8080822f7 --- /dev/null +++ b/packages/nodes-base/nodes/ElasticSearch/ElasticSearch.node.ts @@ -0,0 +1,275 @@ +import { + IExecuteFunctions, +} from 'n8n-core'; + +import { + IDataObject, + INodeExecutionData, + INodeType, + INodeTypeDescription, +} from 'n8n-workflow'; + +import { + elasticSearchApiRequest, +} from './GenericFunctions'; + +import { + documentFields, + documentOperations, + indexFields, + indexOperations, +} from './descriptions'; + +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'], + 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 { + const items = this.getInputData(); + const returnData: IDataObject[] = []; + + const resource = this.getNodeParameter('resource', 0) as string; + const operation = this.getNodeParameter('operation', 0) as string; + + let responseData; + + for (let i = 0; i < items.length; i++) { + + if (resource === 'document') { + + // ********************************************************************** + // document + // ********************************************************************** + + if (operation === 'get') { + + // ---------------------------------------- + // document: get + // ---------------------------------------- + + const indexId = this.getNodeParameter('indexId', i); + const documentId = this.getNodeParameter('documentId', i); + + const qs: IDataObject = {}; + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + + if (Object.keys(additionalFields).length) { + Object.assign(qs, additionalFields); + } + + const endpoint = `/${indexId}/_doc/${documentId}`; + responseData = await elasticSearchApiRequest.call(this, 'GET', endpoint); + + } else if (operation === 'delete') { + + // ---------------------------------------- + // document: delete + // ---------------------------------------- + + const indexId = this.getNodeParameter('indexId', i); + const documentId = this.getNodeParameter('documentId', i); + + const qs: IDataObject = {}; + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + + if (Object.keys(additionalFields).length) { + Object.assign(qs, additionalFields); + } + + const endpoint = `/${indexId}/_doc/${documentId}`; + responseData = await elasticSearchApiRequest.call(this, 'DELETE', endpoint); + + } else if (operation === 'getAll') { + + // ---------------------------------------- + // document: getAll + // ---------------------------------------- + + const body: IDataObject = {}; + const filters = this.getNodeParameter('filters', i) as IDataObject; + + if (Object.keys(filters).length) { + Object.assign(body, filters); + } + + const indexId = this.getNodeParameter('indexId', i); + + const qs: IDataObject = {}; + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + + if (Object.keys(additionalFields).length) { + Object.assign(qs, additionalFields); + } + + // responseData = await handleListing.call(this, i, 'GET', `/${indexId}/_mget`, body); + + } else if (operation === 'update') { + + // ---------------------------------------- + // document: update + // ---------------------------------------- + + const body: IDataObject = { + script: this.getNodeParameter('script', i), + }; + + 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 (operation === 'index') { + + // ---------------------------------------- + // document: index + // ---------------------------------------- + + const body: IDataObject = { + field: this.getNodeParameter('field', i), + }; + + const indexId = this.getNodeParameter('indexId', i); + const documentId = this.getNodeParameter('documentId', i); + + const qs: IDataObject = {}; + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + + if (Object.keys(additionalFields).length) { + Object.assign(qs, additionalFields); + } + + const endpoint = `/${indexId}/_doc/${documentId}`; + responseData = await elasticSearchApiRequest.call(this, 'PUT', endpoint, body); + + } + + } else if (resource === 'index') { + + // ********************************************************************** + // index + // ********************************************************************** + + if (operation === 'get') { + + // ---------------------------------------- + // index: get + // ---------------------------------------- + + const indexId = this.getNodeParameter('indexId', i); + + const qs: 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}`); + + } else if (operation === 'delete') { + + // ---------------------------------------- + // index: delete + // ---------------------------------------- + + const indexId = this.getNodeParameter('indexId', i); + + const qs: IDataObject = {}; + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + + if (Object.keys(additionalFields).length) { + Object.assign(qs, additionalFields); + } + + responseData = await elasticSearchApiRequest.call(this, 'DELETE', `/${indexId}`); + + } else if (operation === 'create') { + + // ---------------------------------------- + // index: create + // ---------------------------------------- + + const indexId = this.getNodeParameter('indexId', i); + + responseData = await elasticSearchApiRequest.call(this, 'PUT', `/${indexId}`); + + } else if (operation === 'getAll') { + + // ---------------------------------------- + // index: getAll + // ---------------------------------------- + + const qs: IDataObject = { + allow_no_indices: this.getNodeParameter('allow_no_indices', i), + expand_wildcards: this.getNodeParameter('expand_wildcards', i), + flat_settings: this.getNodeParameter('flat_settings', i), + ignore_unavailable: this.getNodeParameter('ignore_unavailable', i), + include_defaults: this.getNodeParameter('include_defaults', i), + local: this.getNodeParameter('local', i), + master_timeout: this.getNodeParameter('master_timeout', i), + }; + + // responseData = await handleListing.call(this, i, 'GET', '/_all', {}, qs); + + } else if (operation === 'search') { + + // ---------------------------------------- + // index: search + // ---------------------------------------- + + const indexId = this.getNodeParameter('indexId', i); + + const qs: IDataObject = {}; + + responseData = await elasticSearchApiRequest.call(this, 'GET', `/${indexId}/_search`, {}, qs); + + } + + } + + Array.isArray(responseData) + ? returnData.push(...responseData) + : returnData.push(responseData); + + } + + return [this.helpers.returnJsonArray(returnData)]; + } +} diff --git a/packages/nodes-base/nodes/ElasticSearch/GenericFunctions.ts b/packages/nodes-base/nodes/ElasticSearch/GenericFunctions.ts new file mode 100644 index 0000000000..e4fee5baae --- /dev/null +++ b/packages/nodes-base/nodes/ElasticSearch/GenericFunctions.ts @@ -0,0 +1,54 @@ +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: string, + 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); + } +} diff --git a/packages/nodes-base/nodes/ElasticSearch/descriptions/DocumentDescription.ts b/packages/nodes-base/nodes/ElasticSearch/descriptions/DocumentDescription.ts new file mode 100644 index 0000000000..ea72531cac --- /dev/null +++ b/packages/nodes-base/nodes/ElasticSearch/descriptions/DocumentDescription.ts @@ -0,0 +1,328 @@ +import { + INodeProperties, +} from 'n8n-workflow'; + +export const documentOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'document', + ], + }, + }, + options: [ + { + name: 'Delete', + value: 'delete', + }, + { + name: 'Get', + value: 'get', + }, + { + name: 'Get All', + value: 'getAll', + }, + { + name: 'Index', + value: 'index', + }, + { + name: 'Update', + value: 'update', + }, + ], + default: 'get', + description: 'Operation to perform', + }, +] as INodeProperties[]; + +export const documentFields = [ + // ---------------------------------------- + // document: get + // ---------------------------------------- + { + displayName: 'Index ID', + name: 'indexId', + description: 'ID of 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', + ], + }, + }, + }, + + // ---------------------------------------- + // document: delete + // ---------------------------------------- + { + displayName: 'Index ID', + name: 'indexId', + description: 'ID of 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: getAll + // ---------------------------------------- + { + displayName: 'Index ID', + name: 'indexId', + description: '', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'document', + ], + operation: [ + 'getAll', + ], + }, + }, + }, + { + displayName: 'Filters', + name: 'filters', + type: 'collection', + placeholder: 'Add Filter', + default: {}, + displayOptions: { + show: { + resource: [ + 'document', + ], + operation: [ + 'getAll', + ], + }, + }, + options: [ + { + displayName: 'Ids', + name: 'ids', + type: 'string', + default: '', + description: 'IDs of the documents to retrieve. Allowed when the index is specified in the request URI.', + }, + ], + }, + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + default: false, + description: 'Return all results.', + displayOptions: { + show: { + resource: [ + 'document', + ], + operation: [ + 'getAll', + ], + }, + }, + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + default: 50, + description: 'The number of results to return.', + typeOptions: { + minValue: 1, + }, + displayOptions: { + show: { + resource: [ + 'document', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + }, + + // ---------------------------------------- + // 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: 'Script', + name: 'script', + description: 'Script to update the document. See the guide to writing scripts.', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'document', + ], + operation: [ + 'update', + ], + }, + }, + }, + + // ---------------------------------------- + // document: index + // ---------------------------------------- + { + displayName: 'Index ID', + name: 'indexId', + description: '', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'document', + ], + operation: [ + 'index', + ], + }, + }, + }, + { + displayName: 'Document ID', + name: 'documentId', + description: '', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'document', + ], + operation: [ + 'index', + ], + }, + }, + }, + { + displayName: 'Field', + name: 'field', + description: 'JSON source for the document data.', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'document', + ], + operation: [ + 'index', + ], + }, + }, + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/ElasticSearch/descriptions/IndexDescription.ts b/packages/nodes-base/nodes/ElasticSearch/descriptions/IndexDescription.ts new file mode 100644 index 0000000000..bf6077e262 --- /dev/null +++ b/packages/nodes-base/nodes/ElasticSearch/descriptions/IndexDescription.ts @@ -0,0 +1,878 @@ +import { + INodeProperties, +} from 'n8n-workflow'; + +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', + }, + { + name: 'Search', + value: 'search', + }, + ], + default: 'get', + description: 'Operation to perform', + }, +] as INodeProperties[]; + +export const indexFields = [ + // ---------------------------------------- + // 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', + ], + }, + }, + }, + + // ---------------------------------------- + // 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: create + // ---------------------------------------- + { + displayName: 'Index ID', + name: 'indexId', + description: 'ID of the index to create.', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'create', + ], + }, + }, + }, + + // ---------------------------------------- + // index: getAll + // ---------------------------------------- + { + displayName: 'Allow No Indices', + name: 'allowNoIndices', + description: 'If false, the request returns an error if any wildcard expression, index alias, or _all value targets only missing or closed indices. Defaults to true.', + type: 'boolean', + default: true, + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'getAll', + ], + }, + }, + }, + { + displayName: 'Expand Wildcards', + name: 'expandWildcards', + description: 'Type of index that wildcard expressions can match. Defaults to open.', + type: 'options', + options: [ + { + name: 'All', + value: 'all', + }, + { + name: 'Open', + value: 'open', + }, + { + name: 'Closed', + value: 'closed', + }, + { + name: 'Hidden', + value: 'hidden', + }, + { + name: 'None', + value: 'none', + }, + ], + default: 'all', + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'getAll', + ], + }, + }, + }, + { + displayName: 'Flat Settings', + name: 'flatSettings', + description: 'If true, return settings in flat format. Defaults to false.', + type: 'boolean', + default: false, + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'getAll', + ], + }, + }, + }, + { + displayName: 'Ignore Unavailable', + name: 'ignoreUnavailable', + description: ' If false, requests that target a missing index return an error. Defaults to false.', + type: 'boolean', + default: false, + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'getAll', + ], + }, + }, + }, + { + displayName: 'Include Defaults', + name: 'includeDefaults', + description: 'If true, return all default settings in the response. Defaults to false.', + type: 'boolean', + default: false, + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'getAll', + ], + }, + }, + }, + { + displayName: 'Local', + name: 'local', + description: ' If true, retrieve information from the local node only. Defaults to false.', + type: 'boolean', + default: false, + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'getAll', + ], + }, + }, + }, + { + displayName: 'Master Timeout', + name: 'masterTimeout', + description: 'Period to wait for a connection to the master node. If no response is received before the timeout expires, the request fails and returns an error. Defaults to 1m. See the time units reference.', + type: 'string', + default: '', + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'getAll', + ], + }, + }, + }, + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + default: false, + description: 'Return all results.', + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'getAll', + ], + }, + }, + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + default: 50, + description: 'The number of results to return.', + typeOptions: { + minValue: 1, + }, + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + }, + + // ---------------------------------------- + // index: search + // ---------------------------------------- + { + displayName: 'Index ID', + name: 'indexId', + description: '', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: ' Source', + name: 'source', + description: 'Whether to include the _source field.', + type: 'boolean', + default: false, + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: ' Source Excludes', + name: 'sourceExcludes', + description: 'Comma-separated list of source fields to exclude from the response. If the _source parameter is false, this parameter is ignored.', + type: 'string', + default: '', + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: ' Source Includes', + name: 'sourceIncludes', + description: 'Comma-separated list of source fields to include in the response. If the _source parameter is false, this parameter is ignored.', + type: 'string', + default: '', + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Allow No Indices', + name: 'allowNoIndices', + description: 'If false, return an error if any wildcard expression, index alias, or _all value targets only missing or closed indices. Defaults to true.', + type: 'boolean', + default: true, + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Allow Partial Search Results', + name: 'allowPartialSearchResults', + description: 'If true, return partial results if there are shard request timeouts or shard failures. If false, returns an error with no partial results. Defaults to true.', + type: 'boolean', + default: true, + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Batched Reduce Size', + name: 'batchedReduceSize', + description: 'Number of shard results that should be reduced at once on the coordinating node. Defaults to 512.', + type: 'number', + default: 0, + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Ccs Minimize Roundtrips', + name: 'ccsMinimizeRoundtrips', + description: 'If true, network round-trips between the coordinating node and the remote clusters are minimized when executing cross-cluster search requests. Defaults to true.', + type: 'boolean', + default: true, + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Docvalue Fields', + name: 'docvalueFields', + description: 'Comma-separated list of fields to return as the docvalue representation of a field for each hit.', + type: 'string', + default: '', + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Expand Wildcards', + name: 'expandWildcards', + description: 'Type of index that wildcard expressions can match. Defaults to open.', + type: 'options', + options: [ + { + name: 'All', + value: 'all', + }, + { + name: 'Open', + value: 'open', + }, + { + name: 'Closed', + value: 'closed', + }, + { + name: 'Hidden', + value: 'hidden', + }, + { + name: 'None', + value: 'none', + }, + ], + default: 'all', + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + 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, + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Ignore Throttled', + name: 'ignoreThrottled', + description: 'If true, concrete, expanded or aliased indices are ignored when frozen. Defaults to true.', + type: 'boolean', + default: true, + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Ignore Unavailable', + name: 'ignoreUnavailable', + description: 'If true, missing or closed indices are not included in the response. Defaults to false.', + type: 'boolean', + default: false, + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Max Concurrent Shard Requests', + name: 'maxConcurrentShardRequests', + description: 'Define the number of concurrent shard requests per node this search executes concurrently. Defaults to 5.', + type: 'number', + default: 0, + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Pre Filter Shard Size', + name: 'preFilterShardSize', + description: 'Define a threshold that enforces a pre-filter roundtrip to prefilter search shards based on query rewriting if the number of shards the search request expands to exceeds the threshold.', + type: 'number', + default: 0, + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Query', + name: 'q', + description: 'Query in the Lucene query string syntax.', + type: 'string', + default: '', + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Request Cache', + name: 'requestCache', + description: 'If true, the caching of search results is enabled for requests where size is 0. See Shard request cache settings. Defaults to index level settings.', + type: 'boolean', + default: false, + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Rest Total Hits as Int', + name: 'restTotalHitsAsInt', + description: 'Whether hits.total should be rendered as an integer or an object in the rest search response. Defaults to false.', + type: 'boolean', + default: false, + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Routing', + name: 'routing', + description: 'Target this primary shard.', + type: 'string', + default: '', + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Search Type', + name: 'searchType', + description: 'How distributed term frequencies are calculated for relevance scoring. Defaults to Query then Fetch.', + type: 'options', + options: [ + { + name: 'Query Then Fetch', + value: 'query_then_fetch', + description: 'Distributed term frequencies are calculated locally for each shard running the search.', + }, + { + name: 'Dfs Query Then Fetch', + value: 'dfs_query_then_fetch', + description: 'Distributed term frequencies are calculated globally with information gathered from all shards running the search.', + }, + ], + default: 'query_then_fetch', + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Seq No Primary Term', + name: 'seqNoPrimaryTerm', + description: 'If true, return the sequence number and primary term of the last modification of each hit. See Optimistic concurrency control.', + type: 'boolean', + default: false, + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Size', + name: 'size', + description: '', + type: 'Define the number of hits to return. Defaults to 10.', + default: 10, + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Sort', + name: 'sort', + description: 'Comma-separated list of : pairs.', + type: 'string', + default: '', + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Stats', + name: 'stats', + description: 'Tag of the request for logging and statistical purposes.', + type: 'string', + default: '', + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Stored Fields', + name: 'storedFields', + description: 'If true, retrieve the document fields stored in the index rather than the document _source. Defaults to false.', + type: 'boolean', + default: false, + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Suggest Field', + name: 'suggestField', + description: 'Field to use for suggestions.', + type: 'string', + default: '', + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Suggest Text', + name: 'suggestText', + description: 'Source text for which the suggestions should be returned.', + type: 'string', + default: '', + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Terminate After', + name: 'terminateAfter', + description: 'Max number of documents to collect for each shard.', + type: 'number', + default: 0, + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Timeout', + name: 'timeout', + description: 'Period to wait for active shards. Defaults to 1m (one minute). See the time units reference.', + type: 'string', + default: '', + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Track Scores', + name: 'trackScores', + description: 'If true, calculate and return document scores, even if the scores are not used for sorting. Defaults to false.', + type: 'boolean', + default: false, + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Track Total Hits', + name: 'trackTotalHits', + description: 'Number of hits matching the query to count accurately. Defaults to 10000.', + type: 'number', + default: 10000, + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, + { + displayName: 'Version', + name: 'version', + description: 'If true, return document version as part of a hit. Defaults to false.', + type: 'boolean', + default: false, + displayOptions: { + show: { + resource: [ + 'index', + ], + operation: [ + 'search', + ], + }, + }, + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/ElasticSearch/descriptions/index.ts b/packages/nodes-base/nodes/ElasticSearch/descriptions/index.ts new file mode 100644 index 0000000000..f20c261442 --- /dev/null +++ b/packages/nodes-base/nodes/ElasticSearch/descriptions/index.ts @@ -0,0 +1,2 @@ +export * from './DocumentDescription'; +export * from './IndexDescription'; diff --git a/packages/nodes-base/nodes/ElasticSearch/elasticSearch.svg b/packages/nodes-base/nodes/ElasticSearch/elasticSearch.svg new file mode 100644 index 0000000000..7e2fad792c --- /dev/null +++ b/packages/nodes-base/nodes/ElasticSearch/elasticSearch.svg @@ -0,0 +1,14 @@ + + + + elastic-search-logo-color-64px + Created with Sketch. + + + + + + + + + diff --git a/packages/nodes-base/nodes/ElasticSearch/types.d.ts b/packages/nodes-base/nodes/ElasticSearch/types.d.ts new file mode 100644 index 0000000000..7698775029 --- /dev/null +++ b/packages/nodes-base/nodes/ElasticSearch/types.d.ts @@ -0,0 +1,5 @@ +export type ElasticSearchApiCredentials = { + username: string; + password: string; + baseUrl: string; +}; diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index fac858637f..afe7ecf1ae 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -74,6 +74,7 @@ "dist/credentials/DropboxApi.credentials.js", "dist/credentials/DropboxOAuth2Api.credentials.js", "dist/credentials/EgoiApi.credentials.js", + "dist/credentials/ElasticSearchApi.credentials.js", "dist/credentials/EmeliaApi.credentials.js", "dist/credentials/ERPNextApi.credentials.js", "dist/credentials/EventbriteApi.credentials.js", @@ -339,6 +340,7 @@ "dist/nodes/Dropbox/Dropbox.node.js", "dist/nodes/EditImage.node.js", "dist/nodes/Egoi/Egoi.node.js", + "dist/nodes/ElasticSearch/ElasticSearch.node.js", "dist/nodes/EmailReadImap.node.js", "dist/nodes/EmailSend.node.js", "dist/nodes/Emelia/Emelia.node.js",