n8n-nodes-didar-crm 0.0.17 → 0.0.19

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.
@@ -13,7 +13,95 @@ async function noteCreate(i, returnData) {
13
13
  const doneDateUi = this.getNodeParameter('DoneDate', i, '');
14
14
  const dealId = this.getNodeParameter('DealId', i, ZERO_GUID);
15
15
  const caseId = this.getNodeParameter('CaseId', i, ZERO_GUID);
16
- const contactIds = this.getNodeParameter('ContactIds', i, []);
16
+ // const contactIds = this.getNodeParameter('ContactIds', i, []) as string[];
17
+ // ContactIds
18
+ const rawContactIds = this.getNodeParameter('ContactIds', i, []);
19
+ const parseIdList = (input) => {
20
+ const out = [];
21
+ const pushFromString = (raw) => {
22
+ if (!raw)
23
+ return;
24
+ const s = raw.trim();
25
+ if (!s)
26
+ return;
27
+ // الگوی نمایشی n8n: [Array: [...]]
28
+ const arrayLabel = s.match(/^\s*\[Array:\s*(\[[\s\S]*\])\s*\]\s*$/i);
29
+ if (arrayLabel) {
30
+ try {
31
+ const arr = JSON.parse(arrayLabel[1]);
32
+ recur(arr);
33
+ return;
34
+ }
35
+ catch { /* ignore and fall through */ }
36
+ }
37
+ // اگر JSON array باشد
38
+ if (/^\s*\[/.test(s)) {
39
+ try {
40
+ const arr = JSON.parse(s);
41
+ recur(arr);
42
+ return;
43
+ }
44
+ catch {
45
+ throw new Error('Invalid JSON in "Contact IDs". Expected a JSON array of strings.');
46
+ }
47
+ }
48
+ // در غیر این صورت: CSV / newline / semicolon
49
+ s.split(/[\n,;]+/)
50
+ .map((t) => t.trim())
51
+ .filter(Boolean)
52
+ .forEach((t) => out.push(t));
53
+ };
54
+ const recur = (val) => {
55
+ var _a, _b;
56
+ if (val == null)
57
+ return;
58
+ if (Array.isArray(val)) {
59
+ val.forEach(recur);
60
+ return;
61
+ }
62
+ switch (typeof val) {
63
+ case 'string':
64
+ pushFromString(val);
65
+ return;
66
+ case 'number':
67
+ case 'boolean':
68
+ out.push(String(val));
69
+ return;
70
+ case 'object': {
71
+ const obj = val;
72
+ // Map/Set
73
+ if (val instanceof Set) {
74
+ recur(Array.from(val));
75
+ return;
76
+ }
77
+ if (val instanceof Map) {
78
+ recur(Array.from(val.values()));
79
+ return;
80
+ }
81
+ // Wrapperهای رایج
82
+ if (obj === null || obj === void 0 ? void 0 : obj.values) {
83
+ recur(obj.values);
84
+ return;
85
+ }
86
+ if (obj === null || obj === void 0 ? void 0 : obj.Value) {
87
+ recur(obj.Value);
88
+ return;
89
+ }
90
+ // Fallback: تلاش با toString()
91
+ const s = ((_b = (_a = obj === null || obj === void 0 ? void 0 : obj.toString) === null || _a === void 0 ? void 0 : _a.call(obj)) !== null && _b !== void 0 ? _b : '').toString();
92
+ if (s)
93
+ pushFromString(s);
94
+ return;
95
+ }
96
+ default:
97
+ return;
98
+ }
99
+ };
100
+ recur(input);
101
+ // نرمال‌سازی و حذف تکراری‌ها
102
+ return Array.from(new Set(out.map((x) => x.trim()).filter(Boolean)));
103
+ };
104
+ const contactIdsArr = parseIdList(rawContactIds);
17
105
  // 2) اعتبارسنجی‌های ضروری
18
106
  if (!(resultNote === null || resultNote === void 0 ? void 0 : resultNote.trim())) {
19
107
  throw new Error('ResultNote is required for Note creation.');
@@ -39,7 +127,7 @@ async function noteCreate(i, returnData) {
39
127
  DueDateType: 'NoTime', // ثابت و نامنمایش
40
128
  DoneDateType: 'Notime', // ثابت و نامنمایش
41
129
  DealId: dealId || ZERO_GUID,
42
- ContactIds: Array.isArray(contactIds) ? contactIds : [],
130
+ ContactIds: contactIdsArr,
43
131
  CaseId: caseId || ZERO_GUID,
44
132
  },
45
133
  };
@@ -14,7 +14,95 @@ async function noteUpdate(i, returnData) {
14
14
  const doneDateUi = this.getNodeParameter('DoneDate', i, '');
15
15
  const dealId = this.getNodeParameter('DealId', i, ZERO_GUID);
16
16
  const caseId = this.getNodeParameter('CaseId', i, ZERO_GUID);
17
- const contactIds = this.getNodeParameter('ContactIds', i, []);
17
+ // const contactIds = this.getNodeParameter('ContactIds', i, []) as string[];
18
+ // ContactIds
19
+ const rawContactIds = this.getNodeParameter('ContactIds', i, []);
20
+ const parseIdList = (input) => {
21
+ const out = [];
22
+ const pushFromString = (raw) => {
23
+ if (!raw)
24
+ return;
25
+ const s = raw.trim();
26
+ if (!s)
27
+ return;
28
+ // الگوی نمایشی n8n: [Array: [...]]
29
+ const arrayLabel = s.match(/^\s*\[Array:\s*(\[[\s\S]*\])\s*\]\s*$/i);
30
+ if (arrayLabel) {
31
+ try {
32
+ const arr = JSON.parse(arrayLabel[1]);
33
+ recur(arr);
34
+ return;
35
+ }
36
+ catch { /* ignore and fall through */ }
37
+ }
38
+ // اگر JSON array باشد
39
+ if (/^\s*\[/.test(s)) {
40
+ try {
41
+ const arr = JSON.parse(s);
42
+ recur(arr);
43
+ return;
44
+ }
45
+ catch {
46
+ throw new Error('Invalid JSON in "Contact IDs". Expected a JSON array of strings.');
47
+ }
48
+ }
49
+ // در غیر این صورت: CSV / newline / semicolon
50
+ s.split(/[\n,;]+/)
51
+ .map((t) => t.trim())
52
+ .filter(Boolean)
53
+ .forEach((t) => out.push(t));
54
+ };
55
+ const recur = (val) => {
56
+ var _a, _b;
57
+ if (val == null)
58
+ return;
59
+ if (Array.isArray(val)) {
60
+ val.forEach(recur);
61
+ return;
62
+ }
63
+ switch (typeof val) {
64
+ case 'string':
65
+ pushFromString(val);
66
+ return;
67
+ case 'number':
68
+ case 'boolean':
69
+ out.push(String(val));
70
+ return;
71
+ case 'object': {
72
+ const obj = val;
73
+ // Map/Set
74
+ if (val instanceof Set) {
75
+ recur(Array.from(val));
76
+ return;
77
+ }
78
+ if (val instanceof Map) {
79
+ recur(Array.from(val.values()));
80
+ return;
81
+ }
82
+ // Wrapperهای رایج
83
+ if (obj === null || obj === void 0 ? void 0 : obj.values) {
84
+ recur(obj.values);
85
+ return;
86
+ }
87
+ if (obj === null || obj === void 0 ? void 0 : obj.Value) {
88
+ recur(obj.Value);
89
+ return;
90
+ }
91
+ // Fallback: تلاش با toString()
92
+ const s = ((_b = (_a = obj === null || obj === void 0 ? void 0 : obj.toString) === null || _a === void 0 ? void 0 : _a.call(obj)) !== null && _b !== void 0 ? _b : '').toString();
93
+ if (s)
94
+ pushFromString(s);
95
+ return;
96
+ }
97
+ default:
98
+ return;
99
+ }
100
+ };
101
+ recur(input);
102
+ // نرمال‌سازی و حذف تکراری‌ها
103
+ return Array.from(new Set(out.map((x) => x.trim()).filter(Boolean)));
104
+ };
105
+ const contactIdsArr = parseIdList(rawContactIds);
18
106
  // 2) Required validations
19
107
  if (!(id === null || id === void 0 ? void 0 : id.trim())) {
20
108
  throw new Error('Note ID is required for Note update.');
@@ -44,7 +132,7 @@ async function noteUpdate(i, returnData) {
44
132
  DueDateType: 'NoTime',
45
133
  DoneDateType: 'Notime',
46
134
  DealId: dealId || ZERO_GUID,
47
- ContactIds: Array.isArray(contactIds) ? contactIds : [],
135
+ ContactIds: contactIdsArr,
48
136
  CaseId: caseId || ZERO_GUID,
49
137
  },
50
138
  };
@@ -4,3 +4,5 @@ export { personGet } from './get.operation';
4
4
  export { personCreateProperties } from './create.properties';
5
5
  export { personUpdateProperties } from './update.properties';
6
6
  export { personGetProperties } from './get.properties';
7
+ export { personSearch } from './search.operation';
8
+ export { personSearchProperties } from './search.properties';
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.personGetProperties = exports.personUpdateProperties = exports.personCreateProperties = exports.personGet = exports.personUpdate = exports.personCreate = void 0;
3
+ exports.personSearchProperties = exports.personSearch = exports.personGetProperties = exports.personUpdateProperties = exports.personCreateProperties = exports.personGet = exports.personUpdate = exports.personCreate = void 0;
4
4
  var create_operation_1 = require("./create.operation");
5
5
  Object.defineProperty(exports, "personCreate", { enumerable: true, get: function () { return create_operation_1.personCreate; } });
6
6
  var update_operation_1 = require("./update.operation");
@@ -13,3 +13,7 @@ var update_properties_1 = require("./update.properties");
13
13
  Object.defineProperty(exports, "personUpdateProperties", { enumerable: true, get: function () { return update_properties_1.personUpdateProperties; } });
14
14
  var get_properties_1 = require("./get.properties");
15
15
  Object.defineProperty(exports, "personGetProperties", { enumerable: true, get: function () { return get_properties_1.personGetProperties; } });
16
+ var search_operation_1 = require("./search.operation");
17
+ Object.defineProperty(exports, "personSearch", { enumerable: true, get: function () { return search_operation_1.personSearch; } });
18
+ var search_properties_1 = require("./search.properties");
19
+ Object.defineProperty(exports, "personSearchProperties", { enumerable: true, get: function () { return search_properties_1.personSearchProperties; } });
@@ -0,0 +1,2 @@
1
+ import type { IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
2
+ export declare function personSearch(this: IExecuteFunctions, i: number, returnData: INodeExecutionData[]): Promise<INodeExecutionData[]>;
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.personSearch = personSearch;
4
+ const http_1 = require("../../lib/http");
5
+ async function personSearch(i, returnData) {
6
+ var _a, _b, _c, _d, _e, _f, _g;
7
+ // Helpers
8
+ const parseJsonFlexible = (val) => {
9
+ if (val == null || val === '')
10
+ return [];
11
+ if (Array.isArray(val))
12
+ return val;
13
+ if (typeof val === 'string') {
14
+ const s = val.trim();
15
+ if (!s)
16
+ return [];
17
+ const m = s.match(/^\s*\[Array:\s*(\[[\s\S]*\])\s*\]\s*$/i);
18
+ if (m) {
19
+ try {
20
+ return JSON.parse(m[1]);
21
+ }
22
+ catch {
23
+ throw new Error('Invalid JSON in Custom Fields.');
24
+ }
25
+ }
26
+ try {
27
+ const parsed = JSON.parse(s);
28
+ return Array.isArray(parsed) ? parsed : [];
29
+ }
30
+ catch {
31
+ throw new Error('Invalid JSON in Custom Fields.');
32
+ }
33
+ }
34
+ return [];
35
+ };
36
+ // Main (optional)
37
+ const keywords = this.getNodeParameter('Keywords', i, '').trim();
38
+ // Owner (select/manual) — optional
39
+ const ownerMode = this.getNodeParameter('OwnerMode', i, 'select');
40
+ const ownerSel = this.getNodeParameter('OwnerIdSelect', i, '');
41
+ const ownerMan = this.getNodeParameter('OwnerIdManual', i, '');
42
+ const ownerId = ownerMode === 'select' ? ownerSel : ownerMan;
43
+ // Additional
44
+ const add = this.getNodeParameter('additionalFields', i, {}) || {};
45
+ const searchFromTime = (_a = add.SearchFromTime) !== null && _a !== void 0 ? _a : '1000-01-01T00:00:00.000Z';
46
+ const searchToTime = (_b = add.SearchToTime) !== null && _b !== void 0 ? _b : '9999-12-01T00:00:00.000Z';
47
+ const sortOrder = (_c = add.SortOrder) !== null && _c !== void 0 ? _c : 0;
48
+ // Flags (send only if set)
49
+ const isDeleted = (_d = add.IsDeleted) !== null && _d !== void 0 ? _d : '';
50
+ const isPinned = (_e = add.IsPinned) !== null && _e !== void 0 ? _e : '';
51
+ const isVIP = (_f = add.IsVIP) !== null && _f !== void 0 ? _f : '';
52
+ const hasIsDeleted = Object.prototype.hasOwnProperty.call(add, 'IsDeleted') && isDeleted !== '';
53
+ const hasIsPinned = Object.prototype.hasOwnProperty.call(add, 'IsPinned') && isPinned !== '';
54
+ const hasIsVIP = Object.prototype.hasOwnProperty.call(add, 'IsVIP') && isVIP !== '';
55
+ const customFields = parseJsonFlexible(add.CustomFields);
56
+ const limit = typeof add.Limit === 'number' ? add.Limit : 10;
57
+ const from = 0;
58
+ // Build Criteria (only fixed defaults + provided filters)
59
+ const criteria = {
60
+ SearchFromTime: searchFromTime,
61
+ SearchToTime: searchToTime,
62
+ SortOrder: sortOrder,
63
+ };
64
+ if (keywords)
65
+ criteria['Keywords'] = keywords;
66
+ if (ownerId)
67
+ criteria['OwnerId'] = ownerId;
68
+ if (hasIsDeleted)
69
+ criteria['IsDeleted'] = isDeleted;
70
+ if (hasIsPinned)
71
+ criteria['IsPinned'] = isPinned;
72
+ if (hasIsVIP)
73
+ criteria['IsVIP'] = isVIP;
74
+ if (customFields.length)
75
+ criteria['CustomFields'] = customFields;
76
+ const body = { Criteria: criteria, From: from, Limit: limit };
77
+ const resp = await (0, http_1.didarRequest)(this, i, {
78
+ method: 'POST',
79
+ path: '/api/contact/PersonSearch',
80
+ body,
81
+ });
82
+ const out = ((_g = resp === null || resp === void 0 ? void 0 : resp.Response) !== null && _g !== void 0 ? _g : resp);
83
+ // returnData.push({ json: out });
84
+ returnData.push({ json: { search_respons: out, criteria: body } });
85
+ return returnData;
86
+ }
@@ -0,0 +1,2 @@
1
+ import type { INodeProperties } from 'n8n-workflow';
2
+ export declare const personSearchProperties: INodeProperties[];
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.personSearchProperties = void 0;
4
+ const showForPersonSearch = { show: { resource: ['person'], operation: ['search'] } };
5
+ exports.personSearchProperties = [
6
+ // ===== Main fields (ordered) =====
7
+ {
8
+ displayName: 'Keywords',
9
+ name: 'Keywords',
10
+ type: 'string',
11
+ default: '',
12
+ required: false,
13
+ displayOptions: showForPersonSearch,
14
+ description: 'Free-text search (optional).',
15
+ },
16
+ // Owner (select/manual) — optional
17
+ {
18
+ displayName: 'Owner Input Mode',
19
+ name: 'OwnerMode',
20
+ type: 'options',
21
+ options: [
22
+ { name: 'Select from list', value: 'select' },
23
+ { name: 'Enter ID manually', value: 'manual' },
24
+ ],
25
+ default: 'select',
26
+ displayOptions: showForPersonSearch,
27
+ description: 'Choose how to set the owner filter (optional).',
28
+ },
29
+ {
30
+ displayName: 'Owner',
31
+ name: 'OwnerIdSelect',
32
+ type: 'options',
33
+ typeOptions: { loadOptionsMethod: 'getUsers' },
34
+ default: '',
35
+ displayOptions: { show: { ...showForPersonSearch.show, OwnerMode: ['select'] } },
36
+ description: 'Select the owner user (leave empty to ignore).',
37
+ },
38
+ {
39
+ displayName: 'Owner ID',
40
+ name: 'OwnerIdManual',
41
+ type: 'string',
42
+ default: '',
43
+ displayOptions: { show: { ...showForPersonSearch.show, OwnerMode: ['manual'] } },
44
+ description: 'Enter owner user ID manually (leave empty to ignore).',
45
+ },
46
+ // ===== Additional filters (collection) =====
47
+ {
48
+ displayName: 'Additional Filters',
49
+ name: 'additionalFields',
50
+ type: 'collection',
51
+ placeholder: 'Add filter',
52
+ default: {},
53
+ displayOptions: showForPersonSearch,
54
+ options: [
55
+ // Time window (these three همیشه در بدنه می‌آیند با دیفالت‌ها)
56
+ {
57
+ displayName: 'Search From Time',
58
+ name: 'SearchFromTime',
59
+ type: 'dateTime',
60
+ default: '1000-01-01T00:00:00.000Z',
61
+ description: 'Lower bound for the selected time field.',
62
+ },
63
+ {
64
+ displayName: 'Search To Time',
65
+ name: 'SearchToTime',
66
+ type: 'dateTime',
67
+ default: '9999-12-01T00:00:00.000Z',
68
+ description: 'Upper bound for the selected time field.',
69
+ },
70
+ {
71
+ displayName: 'Sort Order',
72
+ name: 'SortOrder',
73
+ type: 'options',
74
+ options: [
75
+ { name: 'Alphabetical', value: 0 },
76
+ { name: 'Newest First', value: 1 },
77
+ ],
78
+ default: 0,
79
+ description: 'Sorting mode.',
80
+ },
81
+ // Flags (optional – با Not set)
82
+ {
83
+ displayName: 'Is Deleted',
84
+ name: 'IsDeleted',
85
+ type: 'options',
86
+ options: [
87
+ { name: 'Not set', value: '' },
88
+ { name: 'No (0)', value: 0 },
89
+ { name: 'Yes (1)', value: 1 },
90
+ ],
91
+ default: '',
92
+ description: 'Filter by deletion flag (optional).',
93
+ },
94
+ {
95
+ displayName: 'Is Pinned',
96
+ name: 'IsPinned',
97
+ type: 'options',
98
+ options: [
99
+ { name: 'Not set', value: '' },
100
+ { name: 'True (1)', value: 1 },
101
+ { name: 'False (-1)', value: -1 },
102
+ ],
103
+ default: '',
104
+ description: 'Filter by pin flag (optional).',
105
+ },
106
+ {
107
+ displayName: 'Is VIP',
108
+ name: 'IsVIP',
109
+ type: 'options',
110
+ options: [
111
+ { name: 'Not set', value: '' },
112
+ { name: 'True (1)', value: 1 },
113
+ { name: 'False (-1)', value: -1 },
114
+ ],
115
+ default: '',
116
+ description: 'Filter by VIP flag (optional).',
117
+ },
118
+ // CustomFields as JSON (optional)
119
+ {
120
+ displayName: 'Custom Fields (JSON)',
121
+ name: 'CustomFields',
122
+ type: 'json',
123
+ default: '[]',
124
+ description: 'JSON array of custom field filters (optional).',
125
+ },
126
+ // Pagination (Limit only; From=0 hidden)
127
+ {
128
+ displayName: 'Limit',
129
+ name: 'Limit',
130
+ type: 'number',
131
+ default: 10,
132
+ description: 'Number of results to return.',
133
+ },
134
+ ],
135
+ },
136
+ ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-didar-crm",
3
- "version": "0.0.17",
3
+ "version": "0.0.19",
4
4
  "description": "Didar CRM nodes for n8n (Trigger + Deal.create)",
5
5
  "author": "You",
6
6
  "license": "MIT",