n8n-nodes-didar-crm 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,5 @@
1
+ MIT License
2
+
3
+ Copyright (c) …
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy…
package/README.md ADDED
@@ -0,0 +1,26 @@
1
+ # n8n-nodes-didar-crm
2
+
3
+ Didar CRM nodes for n8n — Trigger + Deal.create
4
+
5
+ ## Install (local dev)
6
+ 1. npm install
7
+ 2. npm run build
8
+ 3. **Local test without publish**:
9
+ - Copy the compiled files to a clean folder scanned by n8n, e.g. `%USERPROFILE%\.n8n\custom\didar-dist`:
10
+ - `dist/nodes/DidarCrm.node.js`
11
+ - `dist/nodes/DidarCrmTrigger.node.js`
12
+ - `dist/credentials/DidarApi.credentials.js`
13
+ - `nodes/didar.svg`
14
+ - (Optional) `setx N8N_CUSTOM_EXTENSIONS "%USERPROFILE%\.n8n\custom\didar-dist"`
15
+ - Restart n8n.
16
+
17
+ ## Publish on npm
18
+ - `npm login`
19
+ - `npm version patch`
20
+ - `npm publish --access public`
21
+ Then install from **Settings → Community Nodes → Install** using the package name.
22
+
23
+ ## Usage
24
+ - Create Credential "Didar API" with Base URL, API Key, optional Cookie.
25
+ - Use **Didar CRM** node → Resource: Deal → Operation: Create.
26
+ - Use **Didar CRM Trigger** node and register its Test/Prod URL in your CRM webhook settings.
@@ -0,0 +1,7 @@
1
+ import { ICredentialType, INodeProperties } from 'n8n-workflow';
2
+ export declare class DidarApi implements ICredentialType {
3
+ name: string;
4
+ displayName: string;
5
+ documentationUrl: string;
6
+ properties: INodeProperties[];
7
+ }
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DidarApi = void 0;
4
+ class DidarApi {
5
+ constructor() {
6
+ this.name = 'didarApi';
7
+ this.displayName = 'Didar API';
8
+ this.documentationUrl = '';
9
+ this.properties = [
10
+ {
11
+ displayName: 'Base URL',
12
+ name: 'baseUrl',
13
+ type: 'string',
14
+ default: 'https://app.didar.me',
15
+ placeholder: 'https://app.didar.me',
16
+ required: true,
17
+ description: 'Base URL of Didar CRM',
18
+ },
19
+ {
20
+ displayName: 'API Key',
21
+ name: 'apiKey',
22
+ type: 'string',
23
+ typeOptions: { password: true },
24
+ default: '',
25
+ required: true,
26
+ description: 'Value for the "apikey" query parameter',
27
+ },
28
+ {
29
+ displayName: 'Use Cookie Header',
30
+ name: 'useCookie',
31
+ type: 'boolean',
32
+ default: false,
33
+ description: 'Enable if a Cookie header (e.g., LocoAuthCookie) must be sent',
34
+ },
35
+ {
36
+ displayName: 'Cookie',
37
+ name: 'cookie',
38
+ type: 'string',
39
+ default: '',
40
+ placeholder: 'LocoAuthCookie=...',
41
+ displayOptions: { show: { useCookie: [true] } },
42
+ },
43
+ ];
44
+ }
45
+ }
46
+ exports.DidarApi = DidarApi;
@@ -0,0 +1,5 @@
1
+ import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
2
+ export declare class DidarCrm implements INodeType {
3
+ description: INodeTypeDescription;
4
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
5
+ }
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DidarCrm = void 0;
4
+ class DidarCrm {
5
+ constructor() {
6
+ this.description = {
7
+ displayName: 'Didar CRM',
8
+ name: 'didarCrm',
9
+ icon: 'file:didar.svg',
10
+ group: ['transform'],
11
+ version: 1,
12
+ description: 'Actions for Didar CRM',
13
+ defaults: { name: 'Didar CRM' },
14
+ inputs: ["main" /* NodeConnectionType.Main */],
15
+ outputs: ["main" /* NodeConnectionType.Main */],
16
+ credentials: [{ name: 'didarApi', required: true }],
17
+ properties: [
18
+ {
19
+ displayName: 'Resource',
20
+ name: 'resource',
21
+ type: 'options',
22
+ options: [{ name: 'Deal', value: 'deal' }],
23
+ default: 'deal',
24
+ },
25
+ {
26
+ displayName: 'Operation',
27
+ name: 'operation',
28
+ type: 'options',
29
+ displayOptions: { show: { resource: ['deal'] } },
30
+ options: [{ name: 'Create', value: 'create', action: 'Create a deal' }],
31
+ default: 'create',
32
+ },
33
+ // ---- Deal fields (based on your curl) ----
34
+ { displayName: 'Title', name: 'Title', type: 'string', required: true, default: '', displayOptions: { show: { resource: ['deal'], operation: ['create'] } } },
35
+ { displayName: 'Description', name: 'Description', type: 'string', default: '', displayOptions: { show: { resource: ['deal'], operation: ['create'] } } },
36
+ { displayName: 'Owner ID', name: 'OwnerId', type: 'string', default: '00000000-0000-0000-0000-000000000000', displayOptions: { show: { resource: ['deal'], operation: ['create'] } } },
37
+ { displayName: 'Person ID', name: 'PersonId', type: 'string', default: '00000000-0000-0000-0000-000000000000', displayOptions: { show: { resource: ['deal'], operation: ['create'] } } },
38
+ { displayName: 'Company ID', name: 'CompanyId', type: 'string', default: '00000000-0000-0000-0000-000000000000', displayOptions: { show: { resource: ['deal'], operation: ['create'] } } },
39
+ { displayName: 'Source ID', name: 'SourceId', type: 'string', default: '00000000-0000-0000-0000-000000000000', displayOptions: { show: { resource: ['deal'], operation: ['create'] } } },
40
+ { displayName: 'Pipeline ID', name: 'PipelineId', type: 'string', required: true, default: '', displayOptions: { show: { resource: ['deal'], operation: ['create'] } } },
41
+ { displayName: 'Pipeline Stage ID', name: 'PipelineStageId', type: 'string', required: true, default: '', displayOptions: { show: { resource: ['deal'], operation: ['create'] } } },
42
+ { displayName: 'Lost Reason ID', name: 'LostReasonId', type: 'string', default: '00000000-0000-0000-0000-000000000000', displayOptions: { show: { resource: ['deal'], operation: ['create'] } } },
43
+ { displayName: 'Creator ID', name: 'CreatorId', type: 'string', default: '00000000-0000-0000-0000-000000000000', displayOptions: { show: { resource: ['deal'], operation: ['create'] } } },
44
+ { displayName: 'Price', name: 'Price', type: 'string', default: '0', displayOptions: { show: { resource: ['deal'], operation: ['create'] } } },
45
+ { displayName: 'Currency ID', name: 'CurrencyId', type: 'string', required: true, default: '', displayOptions: { show: { resource: ['deal'], operation: ['create'] } } },
46
+ { displayName: 'Visibility Type', name: 'VisibilityType', type: 'string', default: '1', displayOptions: { show: { resource: ['deal'], operation: ['create'] } } },
47
+ { displayName: 'Status', name: 'Status', type: 'string', default: 'Pending', displayOptions: { show: { resource: ['deal'], operation: ['create'] } } },
48
+ { displayName: 'Source Other', name: 'SourceOther', type: 'string', default: '', displayOptions: { show: { resource: ['deal'], operation: ['create'] } } },
49
+ { displayName: 'Lost Reason Note', name: 'LostReasonNote', type: 'string', default: '', displayOptions: { show: { resource: ['deal'], operation: ['create'] } } },
50
+ { displayName: 'Lost Reason Other', name: 'LostReasonOther', type: 'string', default: '', displayOptions: { show: { resource: ['deal'], operation: ['create'] } } },
51
+ {
52
+ displayName: 'Custom Fields (JSON)',
53
+ name: 'Fields',
54
+ type: 'json',
55
+ default: '',
56
+ placeholder: '{ "Field_8783_12_4": 12 }',
57
+ description: 'JSON object for custom fields',
58
+ displayOptions: { show: { resource: ['deal'], operation: ['create'] } },
59
+ },
60
+ ],
61
+ };
62
+ }
63
+ async execute() {
64
+ const items = this.getInputData();
65
+ const returnData = [];
66
+ for (let i = 0; i < items.length; i++) {
67
+ const resource = this.getNodeParameter('resource', i);
68
+ const operation = this.getNodeParameter('operation', i);
69
+ if (resource === 'deal' && operation === 'create') {
70
+ const bodyDeal = {
71
+ OwnerId: this.getNodeParameter('OwnerId', i),
72
+ PersonId: this.getNodeParameter('PersonId', i),
73
+ CompanyId: this.getNodeParameter('CompanyId', i),
74
+ SourceId: this.getNodeParameter('SourceId', i),
75
+ PipelineId: this.getNodeParameter('PipelineId', i),
76
+ PipelineStageId: this.getNodeParameter('PipelineStageId', i),
77
+ LostReasonId: this.getNodeParameter('LostReasonId', i),
78
+ CreatorId: this.getNodeParameter('CreatorId', i),
79
+ Title: this.getNodeParameter('Title', i),
80
+ Description: this.getNodeParameter('Description', i),
81
+ SourceOther: this.getNodeParameter('SourceOther', i),
82
+ LostReasonNote: this.getNodeParameter('LostReasonNote', i),
83
+ LostReasonOther: this.getNodeParameter('LostReasonOther', i),
84
+ Price: this.getNodeParameter('Price', i),
85
+ CurrencyId: this.getNodeParameter('CurrencyId', i),
86
+ VisibilityType: this.getNodeParameter('VisibilityType', i),
87
+ Status: this.getNodeParameter('Status', i),
88
+ };
89
+ const fieldsJson = this.getNodeParameter('Fields', i, '');
90
+ if (fieldsJson) {
91
+ try {
92
+ bodyDeal['Fields'] = typeof fieldsJson === 'string' ? JSON.parse(fieldsJson) : fieldsJson;
93
+ }
94
+ catch {
95
+ throw new Error('Invalid JSON in "Custom Fields (JSON)".');
96
+ }
97
+ }
98
+ const creds = await this.getCredentials('didarApi');
99
+ const baseUrl = creds.baseUrl;
100
+ const apiKey = creds.apiKey;
101
+ const useCookie = creds.useCookie;
102
+ const cookie = creds.cookie;
103
+ const urlBase = (baseUrl || '').replace(/\/+$/, '');
104
+ const url = `${urlBase}/api/deal/save?apikey=${encodeURIComponent(apiKey)}`;
105
+ const options = {
106
+ method: 'POST',
107
+ url,
108
+ body: { Deal: bodyDeal },
109
+ json: true,
110
+ headers: { 'Content-Type': 'application/json' },
111
+ };
112
+ if (useCookie && cookie)
113
+ options.headers.Cookie = cookie;
114
+ const resp = await this.helpers.httpRequest(options);
115
+ returnData.push({ json: resp });
116
+ }
117
+ }
118
+ return [returnData];
119
+ }
120
+ }
121
+ exports.DidarCrm = DidarCrm;
@@ -0,0 +1,5 @@
1
+ import { INodeType, INodeTypeDescription, IWebhookFunctions, IWebhookResponseData } from 'n8n-workflow';
2
+ export declare class DidarCrmTrigger implements INodeType {
3
+ description: INodeTypeDescription;
4
+ webhook(this: IWebhookFunctions): Promise<IWebhookResponseData>;
5
+ }
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DidarCrmTrigger = void 0;
4
+ class DidarCrmTrigger {
5
+ constructor() {
6
+ this.description = {
7
+ displayName: 'Didar CRM Trigger',
8
+ name: 'didarCrmTrigger',
9
+ icon: 'file:didar.svg',
10
+ group: ['trigger'],
11
+ version: 1,
12
+ description: 'Starts the workflow on Didar CRM events',
13
+ defaults: { name: 'Didar CRM Trigger' },
14
+ inputs: [],
15
+ outputs: ["main" /* NodeConnectionType.Main */],
16
+ webhooks: [
17
+ {
18
+ name: 'default',
19
+ httpMethod: 'POST', // فقط POST
20
+ responseMode: 'onReceived',
21
+ path: 'didar/webhook',
22
+ },
23
+ ],
24
+ properties: [], // بدون هیچ تنظیم/فیلتری
25
+ };
26
+ }
27
+ async webhook() {
28
+ var _a, _b, _c, _d;
29
+ const req = this.getRequestObject();
30
+ const res = this.getResponseObject();
31
+ // فقط POST مجاز است
32
+ if (((_a = req.method) === null || _a === void 0 ? void 0 : _a.toUpperCase()) !== 'POST') {
33
+ res.status(405).send('Method Not Allowed');
34
+ return { noWebhookResponse: true };
35
+ }
36
+ // بدنه ممکن است رشته باشد (وبهوک برخی سرویس‌ها) → parse
37
+ let payload = req.body;
38
+ if (typeof payload === 'string') {
39
+ try {
40
+ payload = JSON.parse(payload);
41
+ }
42
+ catch {
43
+ res.status(400).send('Invalid JSON string payload');
44
+ return { noWebhookResponse: true };
45
+ }
46
+ }
47
+ // فیلدهای رایج دیدار: data / changes / meta (اگر باشند)
48
+ const data = ((_b = payload.data) !== null && _b !== void 0 ? _b : payload);
49
+ const changes = ((_c = payload.changes) !== null && _c !== void 0 ? _c : []);
50
+ const meta = ((_d = payload.meta) !== null && _d !== void 0 ? _d : {});
51
+ // تحویل به ورک‌فلو
52
+ return {
53
+ workflowData: [
54
+ [
55
+ {
56
+ json: {
57
+ data,
58
+ changes,
59
+ meta,
60
+ raw: payload,
61
+ receivedAt: new Date().toISOString(),
62
+ },
63
+ },
64
+ ],
65
+ ],
66
+ webhookResponse: 'OK',
67
+ };
68
+ }
69
+ }
70
+ exports.DidarCrmTrigger = DidarCrmTrigger;
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "n8n-nodes-didar-crm",
3
+ "version": "0.0.2",
4
+ "description": "Didar CRM nodes for n8n (Trigger + Deal.create)",
5
+ "author": "You",
6
+ "license": "MIT",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "files": [
10
+ "dist",
11
+ "README.md",
12
+ "LICENSE"
13
+ ],
14
+ "keywords": [
15
+ "n8n",
16
+ "n8n-community-node-package",
17
+ "crm",
18
+ "didar"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsc -p .",
22
+ "prepublishOnly": "npm run build"
23
+ },
24
+ "n8n": {
25
+ "nodes": [
26
+ "dist/nodes/DidarCrm.node.js",
27
+ "dist/nodes/DidarCrmTrigger.node.js"
28
+ ],
29
+ "credentials": [
30
+ "dist/credentials/DidarApi.credentials.js"
31
+ ]
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^20.0.0",
35
+ "n8n-workflow": "^1.0.0",
36
+ "typescript": "^5.4.0"
37
+ }
38
+ }