diff --git a/n8n-nodes-dataverse-auth/credentials/dataverseAuth.credentials.ts b/n8n-nodes-dataverse-auth/credentials/dataverseAuth.credentials.ts index f0ad198..47ca1a3 100644 --- a/n8n-nodes-dataverse-auth/credentials/dataverseAuth.credentials.ts +++ b/n8n-nodes-dataverse-auth/credentials/dataverseAuth.credentials.ts @@ -233,6 +233,29 @@ export class dataverseAuth implements ICredentialType { } } + async DeleteRecord(entityName: string, recordId: string): Promise { + await this.ensureAuthenticated(); + if (!this.axiosInstance) throw new Error('Axios instance not available'); + + const modifiedEntityLogicalName = this.modifyEntityLogicalName(entityName); + const fullApiUrl = `/api/data/v9.2/${modifiedEntityLogicalName}(${recordId})`; + + const headers = { + "OData-MaxVersion": "4.0", + "Accept": "application/json", + "Prefer": "odata.include-annotations=*", + }; + + try { + await this.axiosInstance.delete(fullApiUrl, { headers }); + } catch (error: any) { + throw new Error( + `Dataverse API error: ${error.response?.status} - ${error.response?.statusText}. Details: ${JSON.stringify( + error.response?.data + )}` + ); + } + } async ListEntityColumns(entityName: string): Promise<{ columns: any[] }> { await this.ensureAuthenticated(); diff --git a/n8n-nodes-dataverse-auth/nodes/Dataverse.node.ts b/n8n-nodes-dataverse-auth/nodes/Dataverse.node.ts index ea291f2..6c963b4 100644 --- a/n8n-nodes-dataverse-auth/nodes/Dataverse.node.ts +++ b/n8n-nodes-dataverse-auth/nodes/Dataverse.node.ts @@ -20,6 +20,7 @@ import { globaloptionsetOperations } from "./globaloptionsetOperations"; import { entityLookupOperations } from "./entityLookupOperations"; import { Properties } from "./properties"; import { OperationType } from "./operationType"; +import { deleteOperations } from "./deleteOperations"; export class Dataverse implements INodeType { description: INodeTypeDescription = { @@ -49,7 +50,8 @@ export class Dataverse implements INodeType { ...postOperations, ...optionsetOperations, ...globaloptionsetOperations, - ...entityLookupOperations + ...entityLookupOperations, + ...deleteOperations ], }; @@ -106,9 +108,6 @@ export class Dataverse implements INodeType { }, }; - - - async execute(this: IExecuteFunctions): Promise { const items = this.getInputData(); @@ -146,6 +145,9 @@ export class Dataverse implements INodeType { case Operation.POST: columnsData = await handlePostOperation(this,columnsData, itemIndex, entityName, patch_data); break; + case Operation.DELETE: + await handleDeleteOperation(this, entityName, itemIndex); + break; case Operation.OPTIONSET: query = await handleOptionSetOperation(query, optionset_entityname, optionset_attributename, itemIndex); break; @@ -177,6 +179,18 @@ export class Dataverse implements INodeType { } return this.prepareOutputData(returnData); + async function handleDeleteOperation(func:IExecuteFunctions, entityName: string, itemIndex: number) { + const recordId = func.getNodeParameter(Properties.DELETE_RECORDID, itemIndex) as string; + await auth.DeleteRecord(entityName, recordId); + returnData.push({ + json: { + success: true, + message: `Record ${recordId} deleted successfully from ${entityName}`, + }, + pairedItem: itemIndex, + }); + } + async function handleEntityOperation(entityname: string, entity_id: string, entity_name: string, entityName: string, itemIndex: number) { const modifiedEntityLogicalName = auth.modifyEntityLogicalName(entityname); const entityquery = `${modifiedEntityLogicalName}?$select=${entity_id},${entity_name}&$orderby=${entity_name} asc`; diff --git a/n8n-nodes-dataverse-auth/nodes/deleteOperations.ts b/n8n-nodes-dataverse-auth/nodes/deleteOperations.ts new file mode 100644 index 0000000..fe7d216 --- /dev/null +++ b/n8n-nodes-dataverse-auth/nodes/deleteOperations.ts @@ -0,0 +1,35 @@ +import { INodeProperties } from "n8n-workflow"; +import { Operation } from "./operation"; +import { Properties } from "./properties"; + +export const deleteOperations: INodeProperties[] = [ + { + displayName: "Entity Name", + name: Properties.ENTITYNAME, + type: "options", + typeOptions: { + loadOptionsMethod: "getEntityList", + }, + required: true, + default: "", + displayOptions: { + show: { + operation: [Operation.DELETE], + }, + }, + description: "Name of the entity to delete from", + }, + { + displayName: "Record ID", + name: Properties.DELETE_RECORDID, + type: "string", + required: true, + default: "", + displayOptions: { + show: { + operation: [Operation.DELETE], + }, + }, + description: "ID of the record to delete", + }, +]; diff --git a/n8n-nodes-dataverse-auth/nodes/operation.ts b/n8n-nodes-dataverse-auth/nodes/operation.ts index 88c1027..7abd3f4 100644 --- a/n8n-nodes-dataverse-auth/nodes/operation.ts +++ b/n8n-nodes-dataverse-auth/nodes/operation.ts @@ -1,8 +1,9 @@ export enum Operation { - GET = "GET", - PATCH = "PATCH", - POST = "POST", - OPTIONSET = "OPTIONSET", - GLOBALOPTIONSET = "GLOBALOPTIONSET", - ENTITY = "ENTITY", - } \ No newline at end of file + GET = "GET", + PATCH = "PATCH", + POST = "POST", + OPTIONSET = "OPTIONSET", + GLOBALOPTIONSET = "GLOBALOPTIONSET", + ENTITY = "ENTITY", + DELETE = "DELETE", +} \ No newline at end of file diff --git a/n8n-nodes-dataverse-auth/nodes/operationOptions.ts b/n8n-nodes-dataverse-auth/nodes/operationOptions.ts index f89fccd..ebf1c91 100644 --- a/n8n-nodes-dataverse-auth/nodes/operationOptions.ts +++ b/n8n-nodes-dataverse-auth/nodes/operationOptions.ts @@ -37,6 +37,11 @@ export const operationOptions : INodeProperties = { value: Operation.ENTITY, action: "Retrieve lookup data from table", }, + { + name: "Delete record", + value: Operation.DELETE, + action: "Delete record", + }, ], default: Operation.GET, }; \ No newline at end of file diff --git a/n8n-nodes-dataverse-auth/nodes/properties.ts b/n8n-nodes-dataverse-auth/nodes/properties.ts index 19a08de..6923904 100644 --- a/n8n-nodes-dataverse-auth/nodes/properties.ts +++ b/n8n-nodes-dataverse-auth/nodes/properties.ts @@ -1,4 +1,3 @@ - export enum Properties { //GET GET_QUERY = "GET_QUERY", @@ -27,4 +26,7 @@ export enum Properties { TYPE = "TYPE", OPERATION = "OPERATION", - } \ No newline at end of file + + //DELETE + DELETE_RECORDID = "delete_recordid", +} \ No newline at end of file diff --git a/n8n-nodes-dataverse-auth/nodes/resources/image-1.png b/n8n-nodes-dataverse-auth/nodes/resources/image-1.png index 26bbac3..9fe754b 100644 Binary files a/n8n-nodes-dataverse-auth/nodes/resources/image-1.png and b/n8n-nodes-dataverse-auth/nodes/resources/image-1.png differ diff --git a/n8n-nodes-dataverse-auth/nodes/resources/image-14.png b/n8n-nodes-dataverse-auth/nodes/resources/image-14.png new file mode 100644 index 0000000..1e7b10a Binary files /dev/null and b/n8n-nodes-dataverse-auth/nodes/resources/image-14.png differ diff --git a/n8n-nodes-dataverse-auth/readme.md b/n8n-nodes-dataverse-auth/readme.md index 115359e..7cfcb40 100644 --- a/n8n-nodes-dataverse-auth/readme.md +++ b/n8n-nodes-dataverse-auth/readme.md @@ -119,6 +119,13 @@ The Dataverse node offers several operations, each with specific parameters: * **Type:** Column. * **Columns (for COLUMN type):** Specify the columns and their values. +### Delete Record (DELETE) + +![alt text](./nodes/resources/image-14.png) + +* **Entity Name:** Select the entity (table) from which to delete the record. +* **Record ID:** Provide the ID of the record to be deleted. + ### Get Lookup from Option Set Definitions (OPTIONSET)