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 +5 -0
- package/README.md +26 -0
- package/dist/credentials/DidarApi.credentials.d.ts +7 -0
- package/dist/credentials/DidarApi.credentials.js +46 -0
- package/dist/nodes/DidarCrm.node.d.ts +5 -0
- package/dist/nodes/DidarCrm.node.js +121 -0
- package/dist/nodes/DidarCrmTrigger.node.d.ts +5 -0
- package/dist/nodes/DidarCrmTrigger.node.js +70 -0
- package/package.json +38 -0
package/LICENSE
ADDED
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,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,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
|
+
}
|