From 882afed0585ae3917a306eb8b2cdb8de8e11fa9a Mon Sep 17 00:00:00 2001 From: ricardo Date: Sun, 22 Mar 2020 15:43:35 -0400 Subject: [PATCH 1/2] :sparkles: Microsoft One Drive --- .../MicrosoftOneDriveOAuth2Api.credentials.ts | 21 + .../Microsoft/OneDrive/FileDescription.ts | 377 ++++++++++++++++++ .../Microsoft/OneDrive/FolderDescriptiont.ts | 75 ++++ .../Microsoft/OneDrive/GenericFunctions.ts | 83 ++++ .../OneDrive/MicrosoftOneDrive.node.ts | 215 ++++++++++ .../nodes/Microsoft/OneDrive/oneDrive.png | Bin 0 -> 4123 bytes packages/nodes-base/package.json | 2 + 7 files changed, 773 insertions(+) create mode 100644 packages/nodes-base/credentials/MicrosoftOneDriveOAuth2Api.credentials.ts create mode 100644 packages/nodes-base/nodes/Microsoft/OneDrive/FileDescription.ts create mode 100644 packages/nodes-base/nodes/Microsoft/OneDrive/FolderDescriptiont.ts create mode 100644 packages/nodes-base/nodes/Microsoft/OneDrive/GenericFunctions.ts create mode 100644 packages/nodes-base/nodes/Microsoft/OneDrive/MicrosoftOneDrive.node.ts create mode 100644 packages/nodes-base/nodes/Microsoft/OneDrive/oneDrive.png diff --git a/packages/nodes-base/credentials/MicrosoftOneDriveOAuth2Api.credentials.ts b/packages/nodes-base/credentials/MicrosoftOneDriveOAuth2Api.credentials.ts new file mode 100644 index 0000000000..adeeb79670 --- /dev/null +++ b/packages/nodes-base/credentials/MicrosoftOneDriveOAuth2Api.credentials.ts @@ -0,0 +1,21 @@ +import { + ICredentialType, + NodePropertyTypes, +} from 'n8n-workflow'; + +export class MicrosoftOneDriveOAuth2Api implements ICredentialType { + name = 'microsoftOneDriveOAuth2Api'; + extends = [ + 'microsoftOAuth2Api', + ]; + displayName = 'Microsoft OAuth2 API'; + properties = [ + //https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent + { + displayName: 'Scope', + name: 'scope', + type: 'hidden' as NodePropertyTypes, + default: 'openid offline_access Files.ReadWrite.All', + }, + ]; +} diff --git a/packages/nodes-base/nodes/Microsoft/OneDrive/FileDescription.ts b/packages/nodes-base/nodes/Microsoft/OneDrive/FileDescription.ts new file mode 100644 index 0000000000..32fe70a948 --- /dev/null +++ b/packages/nodes-base/nodes/Microsoft/OneDrive/FileDescription.ts @@ -0,0 +1,377 @@ +import { INodeProperties } from "n8n-workflow"; + +export const fileOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'file', + ], + }, + }, + options: [ + { + name: 'Copy', + value: 'copy', + description: 'Copy a file', + }, + { + name: 'Delete', + value: 'delete', + description: 'Delete a file', + }, + { + name: 'Download', + value: 'download', + description: 'Download a file', + }, + { + name: 'Get', + value: 'get', + description: 'Get a file', + }, + { + name: 'Search', + value: 'search', + description: 'Search a file', + }, + { + name: 'Upload', + value: 'upload', + description: 'Upload a file up to 4MB in size', + }, + ], + default: 'upload', + description: 'The operation to perform.', + }, +] as INodeProperties[]; + +export const fileFields = [ + +/* -------------------------------------------------------------------------- */ +/* file:copy */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'File ID', + name: 'fileId', + type: 'string', + displayOptions: { + show: { + operation: [ + 'copy', + ], + resource: [ + 'file', + ], + }, + }, + default: '', + description: 'File ID', + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + displayOptions: { + show: { + operation: [ + 'copy', + ], + resource: [ + 'file', + ], + }, + }, + default: {}, + options: [ + { + displayName: 'Name', + name: 'name', + type: 'string', + default: '', + description: `The new name for the copy. If this isn't provided, the same name will be used as the original.`, + }, + ], + }, + { + displayName: 'Parent Reference', + name: 'parentReference', + type: 'collection', + placeholder: 'Add Parent Reference', + description: 'Reference to the parent item the copy will be created in Details ', + displayOptions: { + show: { + operation: [ + 'copy', + ], + resource: [ + 'file', + ], + }, + }, + default: {}, + options: [ + { + displayName: 'Drive ID', + name: 'driveId', + type: 'string', + default: '', + description: 'Identifier of the drive instance that contains the item.', + }, + { + displayName: 'Drive Type', + name: 'driveType', + type: 'string', + default: '', + description: 'Identifies the type of drive.', + }, + { + displayName: 'ID', + name: 'id', + type: 'string', + default: '', + description: 'Identifier of the item in the drive.', + }, + { + displayName: 'List ID', + name: 'listId', + type: 'string', + default: '', + description: 'Identifier of the list.', + }, + { + displayName: 'Name', + name: 'name', + type: 'string', + default: '', + description: 'The name of the item being referenced', + }, + { + displayName: 'Path', + name: 'path', + type: 'string', + default: '', + description: 'Path that can be used to navigate to the item', + }, + { + displayName: 'Share ID', + name: 'shareId', + type: 'string', + default: '', + description: 'Identifier for a shared resource that can be accessed via the Shares API.', + }, + { + displayName: 'Site ID', + name: 'siteId', + type: 'string', + default: '', + description: 'Identifier of the site.', + }, + ], + }, +/* -------------------------------------------------------------------------- */ +/* file:delete */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'File ID', + name: 'fileId', + type: 'string', + displayOptions: { + show: { + operation: [ + 'delete', + ], + resource: [ + 'file', + ], + }, + }, + default: '', + description: 'Field ID', + }, +/* -------------------------------------------------------------------------- */ +/* file:download */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'File ID', + name: 'fileId', + type: 'string', + displayOptions: { + show: { + operation: [ + 'download', + ], + resource: [ + 'file', + ], + }, + }, + default: '', + description: 'File ID', + }, + { + displayName: 'Binary Property', + name: 'binaryPropertyName', + type: 'string', + required: true, + default: 'data', + displayOptions: { + show: { + operation: [ + 'download' + ], + resource: [ + 'file', + ], + }, + }, + description: 'Name of the binary property to which to
write the data of the read file.', + }, +/* -------------------------------------------------------------------------- */ +/* file:get */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'File ID', + name: 'fileId', + type: 'string', + displayOptions: { + show: { + operation: [ + 'get', + ], + resource: [ + 'file', + ], + }, + }, + default: '', + description: 'Field ID', + }, +/* -------------------------------------------------------------------------- */ +/* file:search */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Query', + name: 'query', + type: 'string', + displayOptions: { + show: { + operation: [ + 'search', + ], + resource: [ + 'file', + ], + }, + }, + default: '', + description: `The query text used to search for items. Values may be matched + across several fields including filename, metadata, and file content.`, + }, +/* -------------------------------------------------------------------------- */ +/* file:upload */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'File Name', + name: 'fileName', + type: 'string', + displayOptions: { + show: { + operation: [ + 'upload', + ], + resource: [ + 'file', + ], + }, + }, + default: '', + description: 'The name the file should be saved as.', + }, + { + displayName: 'Parent ID', + name: 'parentId', + required: true, + type: 'string', + displayOptions: { + show: { + operation: [ + 'upload', + ], + resource: [ + 'file', + ], + }, + }, + default: '', + description: 'ID of the parent folder that will contain the file.', + }, + { + displayName: 'Binary Data', + name: 'binaryData', + type: 'boolean', + default: false, + required: true, + displayOptions: { + show: { + operation: [ + 'upload', + ], + resource: [ + 'file', + ], + }, + }, + description: 'If the data to upload should be taken from binary field.', + }, + { + displayName: 'File Content', + name: 'fileContent', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + binaryData: [ + false, + ], + operation: [ + 'upload', + ], + resource: [ + 'file', + ], + }, + + }, + placeholder: '', + description: 'The text content of the file.', + }, + { + displayName: 'Binary Property', + name: 'binaryPropertyName', + type: 'string', + default: 'data', + required: true, + displayOptions: { + show: { + binaryData: [ + true, + ], + operation: [ + 'upload', + ], + resource: [ + 'file', + ], + }, + + }, + placeholder: '', + description: 'Name of the binary property which contains
the data for the file.', + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Microsoft/OneDrive/FolderDescriptiont.ts b/packages/nodes-base/nodes/Microsoft/OneDrive/FolderDescriptiont.ts new file mode 100644 index 0000000000..83bd871143 --- /dev/null +++ b/packages/nodes-base/nodes/Microsoft/OneDrive/FolderDescriptiont.ts @@ -0,0 +1,75 @@ +import { INodeProperties } from "n8n-workflow"; + +export const folderOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'folder', + ], + }, + }, + options: [ + { + name: 'Get Children', + value: 'getChildren', + description: 'Get items inside a folder', + }, + { + name: 'Search', + value: 'search', + description: 'Search a folder', + }, + ], + default: 'getChildren', + description: 'The operation to perform.', + }, +] as INodeProperties[]; + +export const folderFields = [ + +/* -------------------------------------------------------------------------- */ +/* folder:getChildren */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Folder ID', + name: 'folderId', + type: 'string', + displayOptions: { + show: { + operation: [ + 'getChildren', + ], + resource: [ + 'folder', + ], + }, + }, + default: '', + description: 'Folder ID', + }, +/* -------------------------------------------------------------------------- */ +/* folder:search */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Query', + name: 'query', + type: 'string', + displayOptions: { + show: { + operation: [ + 'search', + ], + resource: [ + 'folder', + ], + }, + }, + default: '', + description: `The query text used to search for items. Values may be matched + across several fields including filename, metadata, and file content.`, + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Microsoft/OneDrive/GenericFunctions.ts b/packages/nodes-base/nodes/Microsoft/OneDrive/GenericFunctions.ts new file mode 100644 index 0000000000..9330437f77 --- /dev/null +++ b/packages/nodes-base/nodes/Microsoft/OneDrive/GenericFunctions.ts @@ -0,0 +1,83 @@ +import { + OptionsWithUri + } from 'request'; + +import { + IExecuteFunctions, + IExecuteSingleFunctions, + ILoadOptionsFunctions, +} from 'n8n-core'; + +import { + IDataObject +} from 'n8n-workflow'; + +export async function microsoftApiRequest(this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, resource: string, body: any = {}, qs: IDataObject = {}, uri?: string, headers: IDataObject = {}, option: IDataObject = { json: true }): Promise { // tslint:disable-line:no-any + const options: OptionsWithUri = { + headers: { + 'Content-Type': 'application/json', + }, + method, + body, + qs, + uri: uri || `https://graph.microsoft.com/v1.0/me${resource}`, + }; + try { + Object.assign(options, option); + if (Object.keys(headers).length !== 0) { + options.headers = Object.assign({}, options.headers, headers); + } + if (Object.keys(qs).length === 0) { + delete options.qs; + } + if (Object.keys(body).length === 0) { + delete options.body; + } + //@ts-ignore + return await this.helpers.requestOAuth.call(this, 'microsoftOneDriveOAuth2Api', options); + } catch (error) { + if (error.response && error.response.body && error.response.body.error && error.response.body.error.message) { + // Try to return the error prettier + throw new Error(`Microsoft OneDrive response [${error.statusCode}]: ${error.response.body.error.message}`); + } + throw error; + } +} + +export async function microsoftApiRequestAllItems(this: IExecuteFunctions | ILoadOptionsFunctions, propertyName: string ,method: string, endpoint: string, body: any = {}, query: IDataObject = {}): Promise { // tslint:disable-line:no-any + + const returnData: IDataObject[] = []; + + let responseData; + let uri: string | undefined; + query['$top'] = 100; + + do { + responseData = await microsoftApiRequest.call(this, method, endpoint, body, query, uri); + uri = responseData['@odata.nextLink']; + returnData.push.apply(returnData, responseData[propertyName]); + } while ( + responseData['@odata.nextLink'] !== undefined + ); + + return returnData; +} + +export async function microsoftApiRequestAllItemsSkip(this: IExecuteFunctions | ILoadOptionsFunctions, propertyName: string ,method: string, endpoint: string, body: any = {}, query: IDataObject = {}): Promise { // tslint:disable-line:no-any + + const returnData: IDataObject[] = []; + + let responseData; + query['$top'] = 100; + query['$skip'] = 0; + + do { + responseData = await microsoftApiRequest.call(this, method, endpoint, body, query); + query['$skip'] += query['$top']; + returnData.push.apply(returnData, responseData[propertyName]); + } while ( + responseData['value'].length !== 0 + ); + + return returnData; +} diff --git a/packages/nodes-base/nodes/Microsoft/OneDrive/MicrosoftOneDrive.node.ts b/packages/nodes-base/nodes/Microsoft/OneDrive/MicrosoftOneDrive.node.ts new file mode 100644 index 0000000000..cd263d854f --- /dev/null +++ b/packages/nodes-base/nodes/Microsoft/OneDrive/MicrosoftOneDrive.node.ts @@ -0,0 +1,215 @@ +import { + IExecuteFunctions, + BINARY_ENCODING, +} from 'n8n-core'; + +import { + IDataObject, + INodeExecutionData, + INodeTypeDescription, + INodeType, + ILoadOptionsFunctions, + INodePropertyOptions, + IBinaryKeyData, +} from 'n8n-workflow'; + +import { + microsoftApiRequest, + microsoftApiRequestAllItems, +} from './GenericFunctions'; + +import { + fileOperations, + fileFields, +} from './FileDescription'; + +import { + folderOperations, + folderFields +} from './FolderDescriptiont'; + +export class MicrosoftOneDrive implements INodeType { + description: INodeTypeDescription = { + displayName: 'Microsoft OneDrive', + name: 'microsoftOneDrive', + icon: 'file:oneDrive.png', + group: ['input'], + version: 1, + subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', + description: 'Consume Microsoft OneDrive API.', + defaults: { + name: 'Microsoft OneDrive', + color: '#1d4bab', + }, + inputs: ['main'], + outputs: ['main'], + credentials: [ + { + name: 'microsoftOneDriveOAuth2Api', + required: true, + }, + ], + properties: [ + { + displayName: 'Resource', + name: 'resource', + type: 'options', + options: [ + { + name: 'File', + value: 'file', + }, + { + name: 'Folder', + value: 'folder', + }, + ], + default: 'file', + description: 'The resource to operate on.', + }, + ...fileOperations, + ...fileFields, + ...folderOperations, + ...folderFields, + ], + }; + + async execute(this: IExecuteFunctions): Promise { + const items = this.getInputData(); + const returnData: IDataObject[] = []; + const length = items.length as unknown as number; + const qs: IDataObject = {}; + let responseData; + 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://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_copy?view=odsp-graph-online + if (operation === 'copy') { + const fileId = this.getNodeParameter('fileId', i) as string; + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + const parentReference = this.getNodeParameter('parentReference', i) as IDataObject; + const body: IDataObject = {}; + if (parentReference) { + body.parentReference = { ...parentReference }; + } + if (additionalFields.name) { + body.name = additionalFields.name as string; + } + responseData = await microsoftApiRequest.call(this, 'POST', `/drive/items/${fileId}/copy`, body, {}, undefined, {}, { json: true, resolveWithFullResponse: true }); + responseData = { location : responseData.headers.location }; + } + //https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_delete?view=odsp-graph-online + if (operation === 'delete') { + const fileId = this.getNodeParameter('fileId', i) as string; + responseData = await microsoftApiRequest.call(this, 'DELETE', `/drive/items/${fileId}`); + responseData = { success: true }; + } + //https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_list_children?view=odsp-graph-online + if (operation === 'download') { + const fileId = this.getNodeParameter('fileId', i) as string; + const dataPropertyNameDownload = this.getNodeParameter('binaryPropertyName', i) as string; + responseData = await microsoftApiRequest.call(this, 'GET', `/drive/items/${fileId}`); + + if (responseData.file === undefined) { + throw new Error('The ID you provided does not belong to a file.'); + } + + responseData = await microsoftApiRequest.call(this, 'GET', `/drive/items/${fileId}/content`, {}, {}, undefined, {}, { encoding: null, resolveWithFullResponse: true }); + + const newItem: INodeExecutionData = { + json: items[i].json, + binary: {}, + }; + + let mimeType: string | undefined; + if (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, undefined, mimeType); + } + //https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_get?view=odsp-graph-online + if (operation === 'get') { + const fileId = this.getNodeParameter('fileId', i) as string; + responseData = await microsoftApiRequest.call(this, 'GET', `/drive/items/${fileId}`); + } + //https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_search?view=odsp-graph-online + if (operation === 'search') { + const query = this.getNodeParameter('query', i) as string; + responseData = await microsoftApiRequestAllItems.call(this, 'value', 'GET', `/drive/root/search(q='{${query}}')`); + responseData = responseData.filter((item: IDataObject) => item.file); + } + //https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_put_content?view=odsp-graph-online#example-upload-a-new-file + if (operation === 'upload') { + const parentId = this.getNodeParameter('parentId', i) as string; + const binaryData = this.getNodeParameter('binaryData', 0) as boolean; + let fileName = this.getNodeParameter('fileName', 0) as string; + + if (binaryData) { + const binaryPropertyName = this.getNodeParameter('binaryPropertyName', 0) as string; + + if (items[i].binary === undefined) { + throw new Error('No binary data exists on item!'); + } + //@ts-ignore + if (items[i].binary[binaryPropertyName] === undefined) { + throw new Error(`No binary data property "${binaryPropertyName}" does not exists on item!`); + } + + const binaryData = (items[i].binary as IBinaryKeyData)[binaryPropertyName]; + + if (fileName !== '') { + fileName = `${fileName}.${binaryData.fileExtension}`; + } + + const body = Buffer.from(binaryData.data, BINARY_ENCODING); + responseData = await microsoftApiRequest.call(this, 'PUT', `/drive/items/${parentId}:/${fileName || binaryData.fileName}:/content`, body , {}, undefined, { 'Content-Type': binaryData.mimeType, 'Content-length': body.length } ); + + } else { + const body = Buffer.from(this.getNodeParameter('fileContent', i) as string, 'utf8'); + if (fileName === '') { + throw new Error('File name must be defined'); + } + responseData = await microsoftApiRequest.call(this, 'PUT', `/drive/items/${parentId}:/${fileName}.txt:/content`, body , {}, undefined, { 'Content-Type': 'text/plain' } ); + } + } + } + if (resource === 'folder') { + //https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_list_children?view=odsp-graph-online + if (operation === 'getChildren') { + const folderId = this.getNodeParameter('folderId', i) as string; + responseData = await microsoftApiRequestAllItems.call(this, 'value', 'GET', `/drive/items/${folderId}/children`); + } + //https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_search?view=odsp-graph-online + if (operation === 'search') { + const query = this.getNodeParameter('query', i) as string; + responseData = await microsoftApiRequestAllItems.call(this, 'value', 'GET', `/drive/root/search(q='{${query}}')`); + responseData = responseData.filter((item: IDataObject) => item.folder); + } + } + } + if (resource === 'file' && operation === 'download') { + // For file downloads the files get attached to the existing items + return this.prepareOutputData(items); + } else { + 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)]; + } + } +} diff --git a/packages/nodes-base/nodes/Microsoft/OneDrive/oneDrive.png b/packages/nodes-base/nodes/Microsoft/OneDrive/oneDrive.png new file mode 100644 index 0000000000000000000000000000000000000000..b33d98a8bb25e5b516df50c7769df1e617a38509 GIT binary patch literal 4123 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 Date: Sat, 28 Mar 2020 20:13:56 -0400 Subject: [PATCH 2/2] :zap: small fix --- .../nodes/Microsoft/OneDrive/MicrosoftOneDrive.node.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/nodes-base/nodes/Microsoft/OneDrive/MicrosoftOneDrive.node.ts b/packages/nodes-base/nodes/Microsoft/OneDrive/MicrosoftOneDrive.node.ts index cd263d854f..cee6733bd5 100644 --- a/packages/nodes-base/nodes/Microsoft/OneDrive/MicrosoftOneDrive.node.ts +++ b/packages/nodes-base/nodes/Microsoft/OneDrive/MicrosoftOneDrive.node.ts @@ -98,12 +98,14 @@ export class MicrosoftOneDrive implements INodeType { } responseData = await microsoftApiRequest.call(this, 'POST', `/drive/items/${fileId}/copy`, body, {}, undefined, {}, { json: true, resolveWithFullResponse: true }); responseData = { location : responseData.headers.location }; + returnData.push(responseData as IDataObject); } //https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_delete?view=odsp-graph-online if (operation === 'delete') { const fileId = this.getNodeParameter('fileId', i) as string; responseData = await microsoftApiRequest.call(this, 'DELETE', `/drive/items/${fileId}`); responseData = { success: true }; + returnData.push(responseData as IDataObject); } //https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_list_children?view=odsp-graph-online if (operation === 'download') { @@ -144,12 +146,14 @@ export class MicrosoftOneDrive implements INodeType { if (operation === 'get') { const fileId = this.getNodeParameter('fileId', i) as string; responseData = await microsoftApiRequest.call(this, 'GET', `/drive/items/${fileId}`); + returnData.push(responseData as IDataObject); } //https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_search?view=odsp-graph-online if (operation === 'search') { const query = this.getNodeParameter('query', i) as string; responseData = await microsoftApiRequestAllItems.call(this, 'value', 'GET', `/drive/root/search(q='{${query}}')`); responseData = responseData.filter((item: IDataObject) => item.file); + returnData.push(responseData as IDataObject); } //https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_put_content?view=odsp-graph-online#example-upload-a-new-file if (operation === 'upload') { @@ -176,6 +180,7 @@ export class MicrosoftOneDrive implements INodeType { const body = Buffer.from(binaryData.data, BINARY_ENCODING); responseData = await microsoftApiRequest.call(this, 'PUT', `/drive/items/${parentId}:/${fileName || binaryData.fileName}:/content`, body , {}, undefined, { 'Content-Type': binaryData.mimeType, 'Content-length': body.length } ); + returnData.push(responseData as IDataObject); } else { const body = Buffer.from(this.getNodeParameter('fileContent', i) as string, 'utf8'); @@ -183,6 +188,7 @@ export class MicrosoftOneDrive implements INodeType { throw new Error('File name must be defined'); } responseData = await microsoftApiRequest.call(this, 'PUT', `/drive/items/${parentId}:/${fileName}.txt:/content`, body , {}, undefined, { 'Content-Type': 'text/plain' } ); + returnData.push(responseData as IDataObject); } } } @@ -191,12 +197,14 @@ export class MicrosoftOneDrive implements INodeType { if (operation === 'getChildren') { const folderId = this.getNodeParameter('folderId', i) as string; responseData = await microsoftApiRequestAllItems.call(this, 'value', 'GET', `/drive/items/${folderId}/children`); + returnData.push(responseData as IDataObject); } //https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_search?view=odsp-graph-online if (operation === 'search') { const query = this.getNodeParameter('query', i) as string; responseData = await microsoftApiRequestAllItems.call(this, 'value', 'GET', `/drive/root/search(q='{${query}}')`); responseData = responseData.filter((item: IDataObject) => item.folder); + returnData.push(responseData as IDataObject); } } }