diff --git a/packages/nodes-base/credentials/AzureCosmosDbSharedKeyApi.credentials.ts b/packages/nodes-base/credentials/AzureCosmosDbSharedKeyApi.credentials.ts
index f739d61b84..499779c20c 100644
--- a/packages/nodes-base/credentials/AzureCosmosDbSharedKeyApi.credentials.ts
+++ b/packages/nodes-base/credentials/AzureCosmosDbSharedKeyApi.credentials.ts
@@ -17,9 +17,9 @@ export class AzureCosmosDbSharedKeyApi implements ICredentialType {
properties: INodeProperties[] = [
{
- displayName: 'Database',
- name: 'databaseAccount',
- description: 'Database account',
+ displayName: 'Account',
+ name: 'account',
+ description: 'Account name',
type: 'string',
default: '',
},
diff --git a/packages/nodes-base/nodes/Microsoft/AzureCosmosDB/AzureCosmosDb.node.ts b/packages/nodes-base/nodes/Microsoft/AzureCosmosDB/AzureCosmosDb.node.ts
index 752529bbc7..0373f08d30 100644
--- a/packages/nodes-base/nodes/Microsoft/AzureCosmosDB/AzureCosmosDb.node.ts
+++ b/packages/nodes-base/nodes/Microsoft/AzureCosmosDB/AzureCosmosDb.node.ts
@@ -2,7 +2,8 @@ import type { INodeType, INodeTypeDescription } from 'n8n-workflow';
import { NodeConnectionType } from 'n8n-workflow';
import { containerFields, containerOperations } from './descriptions/ContainerDescription';
-import { itemFields, itemOperations } from '../../Aws/DynamoDB/ItemDescription';
+import { itemFields, itemOperations } from './descriptions/ItemDescription';
+import { searchCollections, searchDatabases } from './GenericFunctions';
export class AzureCosmosDb implements INodeType {
description: INodeTypeDescription = {
@@ -33,7 +34,7 @@ export class AzureCosmosDb implements INodeType {
},
],
requestDefaults: {
- baseURL: '=https://{$credentials.databaseAccount}.documents.azure.com',
+ baseURL: '=https://{$credentials.account}.documents.azure.com',
headers: {
Accept: 'application/json',
},
@@ -68,8 +69,8 @@ export class AzureCosmosDb implements INodeType {
],
default: 'container',
},
- ...itemFields,
...itemOperations,
+ ...itemFields,
...containerOperations,
...containerFields,
],
@@ -77,8 +78,8 @@ export class AzureCosmosDb implements INodeType {
methods = {
listSearch: {
- // searchCollections,
- // searchDatabases,
+ searchCollections,
+ searchDatabases,
},
};
}
diff --git a/packages/nodes-base/nodes/Microsoft/AzureCosmosDB/CosmosDB.svg b/packages/nodes-base/nodes/Microsoft/AzureCosmosDB/CosmosDB.svg
new file mode 100644
index 0000000000..c4f1f8cabe
--- /dev/null
+++ b/packages/nodes-base/nodes/Microsoft/AzureCosmosDB/CosmosDB.svg
@@ -0,0 +1 @@
+
diff --git a/packages/nodes-base/nodes/Microsoft/AzureCosmosDB/GenericFunctions.ts b/packages/nodes-base/nodes/Microsoft/AzureCosmosDB/GenericFunctions.ts
index 0eae326328..51e3c1b187 100644
--- a/packages/nodes-base/nodes/Microsoft/AzureCosmosDB/GenericFunctions.ts
+++ b/packages/nodes-base/nodes/Microsoft/AzureCosmosDB/GenericFunctions.ts
@@ -1,41 +1,45 @@
import * as crypto from 'crypto';
import type {
+ DeclarativeRestApiSettings,
IDataObject,
+ IExecutePaginationFunctions,
IHttpRequestOptions,
ILoadOptionsFunctions,
+ INodeExecutionData,
INodeListSearchItems,
INodeListSearchResult,
} from 'n8n-workflow';
import { ApplicationError } from 'n8n-workflow';
import * as querystring from 'querystring';
-export const HeaderConstants = {
- // Required
- AUTHORIZATION: 'Authorization',
- CONTENT_TYPE: 'Content-Type',
- X_MS_DATE: 'x-ms-date',
- X_MS_VERSION: 'x-ms-version',
+// export const HeaderConstants = {
+// // Required
+// AUTHORIZATION: 'Authorization',
+// CONTENT_TYPE: 'Content-Type',
+// X_MS_DATE: 'x-ms-date',
+// X_MS_VERSION: 'x-ms-version',
- //Required - for session consistency only
- X_MS_SESSION_TOKEN: 'x-ms-session-token',
+// //Required - for session consistency only
+// X_MS_SESSION_TOKEN: 'x-ms-session-token',
- // Optional
- IF_MATCH: 'If-Match',
- IF_NONE_MATCH: 'If-None-Match',
- IF_MODIFIED_SINCE: 'If-Modified-Since',
- USER_AGENT: 'User-Agent',
- X_MS_ACTIVITY_ID: 'x-ms-activity-id',
- X_MS_CONSISTENCY_LEVEL: 'x-ms-consistency-level',
- X_MS_CONTINUATION: 'x-ms-continuation',
- X_MS_MAX_ITEM_COUNT: 'x-ms-max-item-count',
- X_MS_DOCUMENTDB_PARTITIONKEY: 'x-ms-documentdb-partitionkey',
- X_MS_DOCUMENTDB_QUERY_ENABLECROSSPARTITION: 'x-ms-documentdb-query-enablecrosspartition',
- A_IM: 'A-IM',
- X_MS_DOCUMENTDB_PARTITIONKEYRANGEID: 'x-ms-documentdb-partitionkeyrangeid',
- X_MS_COSMOS_ALLOW_TENTATIVE_WRITES: 'x-ms-cosmos-allow-tentative-writes',
+// // Optional
+// IF_MATCH: 'If-Match',
+// IF_NONE_MATCH: 'If-None-Match',
+// IF_MODIFIED_SINCE: 'If-Modified-Since',
+// USER_AGENT: 'User-Agent',
+// X_MS_ACTIVITY_ID: 'x-ms-activity-id',
+// X_MS_CONSISTENCY_LEVEL: 'x-ms-consistency-level',
+// X_MS_CONTINUATION: 'x-ms-continuation',
+// X_MS_MAX_ITEM_COUNT: 'x-ms-max-item-count',
+// X_MS_DOCUMENTDB_PARTITIONKEY: 'x-ms-documentdb-partitionkey',
+// X_MS_DOCUMENTDB_ISQUERY: 'x-ms-documentdb-isquery',
+// X_MS_DOCUMENTDB_QUERY_ENABLECROSSPARTITION: 'x-ms-documentdb-query-enablecrosspartition',
+// A_IM: 'A-IM',
+// X_MS_DOCUMENTDB_PARTITIONKEYRANGEID: 'x-ms-documentdb-partitionkeyrangeid',
+// X_MS_COSMOS_ALLOW_TENTATIVE_WRITES: 'x-ms-cosmos-allow-tentative-writes',
- PREFIX_FOR_STORAGE: 'x-ms-',
-};
+// PREFIX_FOR_STORAGE: 'x-ms-',
+// };
export function getAuthorizationTokenUsingMasterKey(
verb: string,
@@ -61,12 +65,67 @@ export function getAuthorizationTokenUsingMasterKey(
return authorizationString;
}
+export async function handlePagination(
+ this: IExecutePaginationFunctions,
+ resultOptions: DeclarativeRestApiSettings.ResultOptions,
+): Promise {
+ const aggregatedResult: IDataObject[] = [];
+ let nextPageToken: string | undefined;
+ const returnAll = this.getNodeParameter('returnAll') as boolean;
+ let limit = 60;
+
+ if (!returnAll) {
+ limit = this.getNodeParameter('limit') as number;
+ resultOptions.maxResults = limit;
+ }
+
+ resultOptions.paginate = true;
+
+ do {
+ if (nextPageToken) {
+ resultOptions.options.headers = resultOptions.options.headers ?? {};
+ resultOptions.options.headers['x-ms-continuation'] = nextPageToken;
+ }
+
+ const responseData = await this.makeRoutingRequest(resultOptions);
+
+ if (Array.isArray(responseData)) {
+ for (const responsePage of responseData) {
+ aggregatedResult.push(responsePage);
+
+ if (!returnAll && aggregatedResult.length >= limit) {
+ return aggregatedResult.slice(0, limit).map((result) => ({ json: result }));
+ }
+ }
+ }
+
+ //TO-DO-check-if-works
+ if (responseData.length > 0) {
+ const lastItem = responseData[responseData.length - 1];
+
+ if ('headers' in lastItem) {
+ const headers = (lastItem as unknown as { headers: { [key: string]: string } }).headers;
+
+ if (headers) {
+ nextPageToken = headers['x-ms-continuation'] as string | undefined;
+ }
+ }
+ }
+
+ if (!nextPageToken) {
+ break;
+ }
+ } while (nextPageToken);
+
+ return aggregatedResult.map((result) => ({ json: result }));
+}
+
export async function azureCosmosDbRequest(
this: ILoadOptionsFunctions,
opts: IHttpRequestOptions,
): Promise {
- const credentials = await this.getCredentials('azureCosmosDb');
- const databaseAccount = credentials?.database;
+ const credentials = await this.getCredentials('azureCosmosDbSharedKeyApi');
+ const databaseAccount = credentials?.account;
if (!databaseAccount) {
throw new ApplicationError('Database account not found in credentials!', { level: 'error' });
@@ -93,7 +152,7 @@ export async function azureCosmosDbRequest(
try {
return (await this.helpers.requestWithAuthentication.call(
this,
- 'azureCosmosDb',
+ 'azureCosmosDbSharedKeyApi',
requestOptions,
)) as IDataObject;
} catch (error) {
@@ -128,18 +187,17 @@ export async function azureCosmosDbRequest(
export async function searchCollections(
this: ILoadOptionsFunctions,
filter?: string,
- paginationToken?: string,
): Promise {
const dbId = this.getNodeParameter('dbId') as string;
if (!dbId) {
throw new ApplicationError('Database ID is required');
}
- const credentials = await this.getCredentials('azureCosmosDb');
- const databaseAccount = credentials?.databaseAccount;
+ const credentials = await this.getCredentials('azureCosmosDbSharedKeyApi');
+ const databaseAccount = credentials?.account;
if (!databaseAccount) {
- throw new ApplicationError('Database account not found in credentials!', { level: 'error' });
+ throw new ApplicationError('Account name not found in credentials!', { level: 'error' });
}
const opts: IHttpRequestOptions = {
@@ -154,9 +212,9 @@ export async function searchCollections(
const responseData: IDataObject = await azureCosmosDbRequest.call(this, opts);
const responseBody = responseData as {
- Collections: IDataObject[];
+ DocumentCollections: IDataObject[];
};
- const collections = responseBody.Collections;
+ const collections = responseBody.DocumentCollections;
if (!collections) {
return { results: [] };
diff --git a/packages/nodes-base/nodes/Microsoft/AzureCosmosDB/descriptions/ContainerDescription.ts b/packages/nodes-base/nodes/Microsoft/AzureCosmosDB/descriptions/ContainerDescription.ts
index bf651f7e89..317acc1275 100644
--- a/packages/nodes-base/nodes/Microsoft/AzureCosmosDB/descriptions/ContainerDescription.ts
+++ b/packages/nodes-base/nodes/Microsoft/AzureCosmosDB/descriptions/ContainerDescription.ts
@@ -49,7 +49,7 @@ export const containerOperations: INodeProperties[] = [
url: '=/dbs/{{ $parameter["dbId"] }}/colls/{{ $parameter["collId"] }}',
},
},
- action: 'Get item',
+ action: 'Get container',
},
{
name: 'Get Many',
@@ -159,12 +159,9 @@ export const createFields: INodeProperties[] = [
},
},
{
- displayName: 'Additional Keys',
- name: 'additionalKeys',
- type: 'fixedCollection',
+ displayName: 'Additional Fields',
+ name: 'additionalFields',
default: {},
- placeholder: '"paths": ["/AccountNumber"],"kind": "Hash", "Version": 2',
- description: 'User-defined JSON object representing the document properties',
displayOptions: {
show: {
resource: ['container'],
@@ -189,6 +186,8 @@ export const createFields: INodeProperties[] = [
},
},
],
+ placeholder: 'Add Option',
+ type: 'collection',
},
];
diff --git a/packages/nodes-base/nodes/Microsoft/AzureCosmosDB/descriptions/ItemDescription.ts b/packages/nodes-base/nodes/Microsoft/AzureCosmosDB/descriptions/ItemDescription.ts
index b794e145f5..4b08354a38 100644
--- a/packages/nodes-base/nodes/Microsoft/AzureCosmosDB/descriptions/ItemDescription.ts
+++ b/packages/nodes-base/nodes/Microsoft/AzureCosmosDB/descriptions/ItemDescription.ts
@@ -1,4 +1,6 @@
-import type { INodeProperties } from 'n8n-workflow';
+import type { IExecuteSingleFunctions, IHttpRequestOptions, INodeProperties } from 'n8n-workflow';
+
+import { handlePagination } from '../GenericFunctions';
export const itemOperations: INodeProperties[] = [
{
@@ -15,12 +17,12 @@ export const itemOperations: INodeProperties[] = [
{
name: 'Create',
value: 'create',
- description: 'Create an item',
+ description: 'Create a new item',
routing: {
request: {
ignoreHttpStatusErrors: true,
method: 'POST',
- url: '=/dbs/{{ $parameter["dbId"] }}/colls/{{ $parameter["collId"] }}/item',
+ url: '=/dbs/{{ $parameter["dbId"] }}/colls/{{ $parameter["collId"] }}/docs',
},
},
action: 'Create item',
@@ -28,12 +30,12 @@ export const itemOperations: INodeProperties[] = [
{
name: 'Delete',
value: 'delete',
- description: 'Delete an item',
+ description: 'Delete an existing item',
routing: {
request: {
ignoreHttpStatusErrors: true,
method: 'DELETE',
- url: '=/dbs/{{ $parameter["dbId"] }}/colls/{{ $parameter["collId"] }}/item/{{ $parameter["id"] }}',
+ url: '=/dbs/{{ $parameter["dbId"] }}/colls/{{ $parameter["collId"] }}/docs/{{ $parameter["id"] }}',
},
},
action: 'Delete item',
@@ -46,7 +48,7 @@ export const itemOperations: INodeProperties[] = [
request: {
ignoreHttpStatusErrors: true,
method: 'GET',
- url: '=/dbs/{{ $parameter["dbId"] }}/colls/{{ $parameter["collId"] }}/item/{{ $parameter["id"] }}',
+ url: '=/dbs/{{ $parameter["dbId"] }}/colls/{{ $parameter["collId"] }}/docs/{{ $parameter["id"] }}',
},
},
action: 'Get item',
@@ -56,6 +58,12 @@ export const itemOperations: INodeProperties[] = [
value: 'getAll',
description: 'Retrieve a list of items',
routing: {
+ send: {
+ paginate: true,
+ },
+ operations: {
+ pagination: handlePagination,
+ },
request: {
ignoreHttpStatusErrors: true,
method: 'GET',
@@ -72,7 +80,11 @@ export const itemOperations: INodeProperties[] = [
request: {
ignoreHttpStatusErrors: true,
method: 'POST',
- url: '=/dbs/{{ $parameter["dbId"] }}/colls/{{ $parameter["collId"] }}/item',
+ url: '=/dbs/{{ $parameter["dbId"] }}/colls/{{ $parameter["collId"] }}/docs',
+ headers: {
+ 'Content-Type': 'application/query+json',
+ 'x-ms-documentdb-isquery': 'True',
+ },
},
},
action: 'Query items',
@@ -80,15 +92,15 @@ export const itemOperations: INodeProperties[] = [
{
name: 'Update',
value: 'update',
- description: 'Update an item',
+ description: 'Update an existing item',
routing: {
request: {
ignoreHttpStatusErrors: true,
method: 'PATCH',
- url: '=/dbs/{{ $parameter["dbId"] }}/colls/{{ $parameter["collId"] }}/item/{{ $parameter["id"] }}',
+ url: '=/dbs/{{ $parameter["dbId"] }}/colls/{{ $parameter["collId"] }}/docs/{{ $parameter["id"] }}',
},
},
- action: 'Create item',
+ action: 'Update item',
},
],
default: 'getAll',
@@ -538,9 +550,58 @@ export const getAllFields: INodeProperties[] = [
},
],
},
+ {
+ displayName: 'Return All',
+ name: 'returnAll',
+ default: false,
+ description: 'Whether to return all results or only up to a given limit',
+ displayOptions: {
+ show: {
+ resource: ['item'],
+ operation: ['getAll'],
+ },
+ },
+ routing: {
+ send: {
+ preSend: [
+ async function (
+ this: IExecuteSingleFunctions,
+ requestOptions: IHttpRequestOptions,
+ ): Promise {
+ return requestOptions;
+ },
+ ],
+ },
+ },
+ type: 'boolean',
+ },
+ {
+ displayName: 'Limit',
+ name: 'limit',
+ default: 50,
+ description: 'Max number of results to return',
+ displayOptions: {
+ show: {
+ resource: ['item'],
+ operation: ['getAll'],
+ returnAll: [false],
+ },
+ },
+ routing: {
+ send: {
+ property: 'x-ms-max-item-count',
+ type: 'query',
+ value: '={{ $value }}',
+ },
+ },
+ type: 'number',
+ typeOptions: {
+ minValue: 1,
+ },
+ validateType: 'number',
+ },
];
-//TO-DO-check-fields
export const queryFields: INodeProperties[] = [
{
displayName: 'Database ID',
@@ -631,23 +692,63 @@ export const queryFields: INodeProperties[] = [
],
},
{
- displayName: 'ID',
- name: 'id',
+ displayName: 'Query',
+ name: 'query',
type: 'string',
default: '',
- placeholder: 'e.g. AndersenFamily',
- description: "Item's ID",
required: true,
+ description: 'The SQL query text to execute',
displayOptions: {
show: {
resource: ['item'],
operation: ['query'],
},
},
+ placeholder: 'SELECT * FROM c WHERE c.name = @name',
routing: {
send: {
type: 'body',
- property: 'id',
+ property: 'query',
+ value: '={{$value}}',
+ },
+ },
+ },
+ {
+ displayName: 'Parameters',
+ name: 'parameters',
+ type: 'fixedCollection',
+ required: true,
+ default: [],
+ placeholder: 'Add Parameter',
+ typeOptions: {
+ multipleValues: true,
+ },
+ options: [
+ {
+ name: 'parameters',
+ displayName: 'Parameter',
+ values: [
+ {
+ displayName: 'Name',
+ name: 'name',
+ type: 'string',
+ default: '',
+ placeholder: 'e.g., @name',
+ },
+ {
+ displayName: 'Value',
+ name: 'value',
+ type: 'string',
+ default: '',
+ placeholder: 'e.g., John',
+ },
+ ],
+ },
+ ],
+ routing: {
+ send: {
+ type: 'body',
+ property: 'parameters',
value: '={{$value}}',
},
},