n8n-nodes-dataforb2b 1.0.2 → 1.0.3

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.
@@ -3,6 +3,108 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DataForB2B = void 0;
4
4
  const n8n_workflow_1 = require("n8n-workflow");
5
5
  const DATAFORB2B_API_BASE_URL = "https://api.dataforb2b.ai";
6
+ // Operators disponibles par type
7
+ const textOperators = [
8
+ { name: "Equals", value: "=" },
9
+ { name: "Not Equals", value: "!=" },
10
+ { name: "Contains", value: "like" },
11
+ { name: "Not Contains", value: "not_like" },
12
+ { name: "In List", value: "in" },
13
+ { name: "Not In List", value: "not_in" },
14
+ ];
15
+ const numericOperators = [
16
+ { name: "Equals", value: "=" },
17
+ { name: "Not Equals", value: "!=" },
18
+ { name: "Greater Than", value: ">" },
19
+ { name: "Greater Than or Equal", value: ">=" },
20
+ { name: "Less Than", value: "<" },
21
+ { name: "Less Than or Equal", value: "<=" },
22
+ { name: "Between", value: "between" },
23
+ ];
24
+ // People filter fields
25
+ const peopleFilterFields = [
26
+ // Profile
27
+ { name: "First Name", value: "first_name" },
28
+ { name: "Last Name", value: "last_name" },
29
+ { name: "Profile Headline", value: "profile_headline" },
30
+ { name: "Summary", value: "summary" },
31
+ { name: "Profile Location", value: "profile_location" },
32
+ { name: "Profile Country", value: "profile_country" },
33
+ { name: "Profile Industry", value: "profile_industry" },
34
+ { name: "Follower Count", value: "follower_count" },
35
+ { name: "Keyword (Full-text)", value: "keyword" },
36
+ // Current Job
37
+ { name: "Current Company", value: "current_company" },
38
+ { name: "Current Title", value: "current_title" },
39
+ { name: "Current Job Location", value: "current_job_location" },
40
+ { name: "Current Job Country", value: "current_job_country" },
41
+ { name: "Current Company Industry", value: "current_company_industry" },
42
+ { name: "Current Company Size", value: "current_company_size" },
43
+ { name: "Current Company ID", value: "current_company_id" },
44
+ { name: "Current Employment Type", value: "current_employment_type" },
45
+ { name: "Years in Current Position", value: "years_in_current_position" },
46
+ { name: "Years at Current Company", value: "years_at_current_company" },
47
+ // Past Jobs
48
+ { name: "Past Company", value: "past_company" },
49
+ { name: "Past Title", value: "past_title" },
50
+ { name: "Past Job Location", value: "past_job_location" },
51
+ { name: "Past Job Country", value: "past_job_country" },
52
+ { name: "Past Company Industry", value: "past_company_industry" },
53
+ { name: "Past Company Size", value: "past_company_size" },
54
+ { name: "Past Company ID", value: "past_company_id" },
55
+ { name: "Past Employment Type", value: "past_employment_type" },
56
+ { name: "Years at Past Company", value: "years_at_past_company" },
57
+ // Skills
58
+ { name: "Skill", value: "skill" },
59
+ // Education
60
+ { name: "School", value: "school" },
61
+ { name: "Degree", value: "degree" },
62
+ { name: "Degree Level", value: "degree_level" },
63
+ { name: "Field of Study", value: "field_of_study" },
64
+ // Languages
65
+ { name: "Language", value: "language" },
66
+ { name: "Language ISO", value: "language_iso" },
67
+ { name: "Language Proficiency", value: "language_proficiency" },
68
+ // Certifications
69
+ { name: "Certification", value: "certification" },
70
+ { name: "Certification Authority", value: "certification_authority" },
71
+ // Experience
72
+ { name: "Years of Experience", value: "years_of_experience" },
73
+ { name: "Number of Total Jobs", value: "num_total_jobs" },
74
+ { name: "Is Currently Employed", value: "is_currently_employed" },
75
+ ];
76
+ // Company filter fields
77
+ const companyFilterFields = [
78
+ // Basic Info
79
+ { name: "Name", value: "name" },
80
+ { name: "Tagline", value: "tagline" },
81
+ { name: "Description", value: "description" },
82
+ { name: "Domain", value: "domain" },
83
+ { name: "Universal Name", value: "universal_name" },
84
+ { name: "Keyword (Full-text)", value: "keyword" },
85
+ { name: "Industry", value: "industry" },
86
+ // Size
87
+ { name: "Employee Count", value: "employee_count" },
88
+ // Headquarters
89
+ { name: "Country ISO Code", value: "country_iso_code" },
90
+ { name: "City", value: "city" },
91
+ { name: "Region", value: "region" },
92
+ // Offices
93
+ { name: "Office Country", value: "office_country" },
94
+ { name: "Office City", value: "office_city" },
95
+ { name: "Office Region", value: "office_region" },
96
+ // Growth
97
+ { name: "Employee Growth 1M (%)", value: "employee_growth_1m" },
98
+ { name: "Employee Growth 6M (%)", value: "employee_growth_6m" },
99
+ { name: "Employee Growth 12M (%)", value: "employee_growth_12m" },
100
+ { name: "Recent Hires Count", value: "recent_hires_count" },
101
+ // Metadata
102
+ { name: "Founded Year", value: "founded_year" },
103
+ { name: "Company Type", value: "company_type" },
104
+ { name: "Follower Count", value: "follower_count" },
105
+ { name: "Page Verified", value: "page_verified" },
106
+ { name: "Category", value: "category" },
107
+ ];
6
108
  class DataForB2B {
7
109
  constructor() {
8
110
  this.description = {
@@ -32,14 +134,8 @@ class DataForB2B {
32
134
  type: "options",
33
135
  noDataExpression: true,
34
136
  options: [
35
- {
36
- name: "Search",
37
- value: "search",
38
- },
39
- {
40
- name: "Enrich",
41
- value: "enrich",
42
- },
137
+ { name: "Search", value: "search" },
138
+ { name: "Enrich", value: "enrich" },
43
139
  ],
44
140
  default: "search",
45
141
  },
@@ -50,35 +146,13 @@ class DataForB2B {
50
146
  type: "options",
51
147
  noDataExpression: true,
52
148
  displayOptions: {
53
- show: {
54
- resource: ["search"],
55
- },
149
+ show: { resource: ["search"] },
56
150
  },
57
151
  options: [
58
- {
59
- name: "Search People",
60
- value: "searchPeople",
61
- description: "Find professionals using 50+ filters",
62
- action: "Search people",
63
- },
64
- {
65
- name: "Search Companies",
66
- value: "searchCompanies",
67
- description: "Find companies with advanced filters",
68
- action: "Search companies",
69
- },
70
- {
71
- name: "Agentic Search (LLM)",
72
- value: "agenticSearch",
73
- description: "Natural language queries with AI interpretation",
74
- action: "Agentic search LLM",
75
- },
76
- {
77
- name: "Text to Filters",
78
- value: "textToFilters",
79
- description: "Convert natural language to structured filters",
80
- action: "Text to filters",
81
- },
152
+ { name: "Search People", value: "searchPeople", description: "Find professionals using 50+ filters", action: "Search people" },
153
+ { name: "Search Companies", value: "searchCompanies", description: "Find companies with advanced filters", action: "Search companies" },
154
+ { name: "Agentic Search (LLM)", value: "agenticSearch", description: "Natural language queries with AI interpretation", action: "Agentic search LLM" },
155
+ { name: "Text to Filters", value: "textToFilters", description: "Convert natural language to structured filters", action: "Text to filters" },
82
156
  ],
83
157
  default: "searchPeople",
84
158
  },
@@ -89,40 +163,136 @@ class DataForB2B {
89
163
  type: "options",
90
164
  noDataExpression: true,
91
165
  displayOptions: {
92
- show: {
93
- resource: ["enrich"],
94
- },
166
+ show: { resource: ["enrich"] },
95
167
  },
96
168
  options: [
97
- {
98
- name: "Enrich Profile",
99
- value: "enrichProfile",
100
- description: "Retrieve detailed professional data",
101
- action: "Enrich profile",
102
- },
103
- {
104
- name: "Enrich Company",
105
- value: "enrichCompany",
106
- description: "Retrieve comprehensive company information",
107
- action: "Enrich company",
108
- },
169
+ { name: "Enrich Profile", value: "enrichProfile", description: "Retrieve detailed professional data", action: "Enrich profile" },
170
+ { name: "Enrich Company", value: "enrichCompany", description: "Retrieve comprehensive company information", action: "Enrich company" },
109
171
  ],
110
172
  default: "enrichProfile",
111
173
  },
112
- // === SEARCH PEOPLE PARAMETERS ===
174
+ // === FILTER LOGIC (AND/OR) ===
113
175
  {
114
- displayName: "Filters (JSON)",
115
- name: "filters",
116
- type: "json",
117
- default: '{"op": "and", "conditions": []}',
118
- description: 'FilterGroup object with conditions. Example: {"op": "and", "conditions": [{"field": "title", "op": "like", "value": "CEO"}]}',
176
+ displayName: "Filter Logic",
177
+ name: "filterLogic",
178
+ type: "options",
179
+ options: [
180
+ { name: "AND (All conditions must match)", value: "and" },
181
+ { name: "OR (Any condition can match)", value: "or" },
182
+ ],
183
+ default: "and",
184
+ description: "How to combine multiple filters",
185
+ displayOptions: {
186
+ show: { resource: ["search"], operation: ["searchPeople", "searchCompanies"] },
187
+ },
188
+ },
189
+ // === SEARCH PEOPLE FILTERS ===
190
+ {
191
+ displayName: "Filters",
192
+ name: "peopleFilters",
193
+ type: "fixedCollection",
194
+ typeOptions: { multipleValues: true },
195
+ default: {},
119
196
  displayOptions: {
120
- show: {
121
- resource: ["search"],
122
- operation: ["searchPeople", "searchCompanies"],
197
+ show: { resource: ["search"], operation: ["searchPeople"] },
198
+ },
199
+ options: [
200
+ {
201
+ name: "conditions",
202
+ displayName: "Conditions",
203
+ values: [
204
+ {
205
+ displayName: "Field",
206
+ name: "field",
207
+ type: "options",
208
+ options: peopleFilterFields,
209
+ default: "current_title",
210
+ },
211
+ {
212
+ displayName: "Operator",
213
+ name: "operator",
214
+ type: "options",
215
+ options: [
216
+ ...textOperators,
217
+ ...numericOperators.filter(op => !textOperators.find(t => t.value === op.value)),
218
+ ],
219
+ default: "like",
220
+ },
221
+ {
222
+ displayName: "Value",
223
+ name: "value",
224
+ type: "string",
225
+ default: "",
226
+ description: "For \"In List\" or \"Not In List\", use comma-separated values",
227
+ },
228
+ {
229
+ displayName: "Value 2 (for Between)",
230
+ name: "value2",
231
+ type: "string",
232
+ default: "",
233
+ description: "Second value for \"Between\" operator",
234
+ displayOptions: {
235
+ show: { operator: ["between"] },
236
+ },
237
+ },
238
+ ],
123
239
  },
240
+ ],
241
+ },
242
+ // === SEARCH COMPANIES FILTERS ===
243
+ {
244
+ displayName: "Filters",
245
+ name: "companyFilters",
246
+ type: "fixedCollection",
247
+ typeOptions: { multipleValues: true },
248
+ default: {},
249
+ displayOptions: {
250
+ show: { resource: ["search"], operation: ["searchCompanies"] },
124
251
  },
252
+ options: [
253
+ {
254
+ name: "conditions",
255
+ displayName: "Conditions",
256
+ values: [
257
+ {
258
+ displayName: "Field",
259
+ name: "field",
260
+ type: "options",
261
+ options: companyFilterFields,
262
+ default: "name",
263
+ },
264
+ {
265
+ displayName: "Operator",
266
+ name: "operator",
267
+ type: "options",
268
+ options: [
269
+ ...textOperators,
270
+ ...numericOperators.filter(op => !textOperators.find(t => t.value === op.value)),
271
+ ],
272
+ default: "like",
273
+ },
274
+ {
275
+ displayName: "Value",
276
+ name: "value",
277
+ type: "string",
278
+ default: "",
279
+ description: "For \"In List\" or \"Not In List\", use comma-separated values",
280
+ },
281
+ {
282
+ displayName: "Value 2 (for Between)",
283
+ name: "value2",
284
+ type: "string",
285
+ default: "",
286
+ description: "Second value for \"Between\" operator",
287
+ displayOptions: {
288
+ show: { operator: ["between"] },
289
+ },
290
+ },
291
+ ],
292
+ },
293
+ ],
125
294
  },
295
+ // === PAGINATION ===
126
296
  {
127
297
  displayName: "Count",
128
298
  name: "count",
@@ -130,10 +300,7 @@ class DataForB2B {
130
300
  default: 10,
131
301
  description: "Number of results to return (max 1000)",
132
302
  displayOptions: {
133
- show: {
134
- resource: ["search"],
135
- operation: ["searchPeople", "searchCompanies"],
136
- },
303
+ show: { resource: ["search"], operation: ["searchPeople", "searchCompanies"] },
137
304
  },
138
305
  },
139
306
  {
@@ -143,10 +310,7 @@ class DataForB2B {
143
310
  default: 0,
144
311
  description: "Pagination offset - number of results to skip",
145
312
  displayOptions: {
146
- show: {
147
- resource: ["search"],
148
- operation: ["searchPeople", "searchCompanies"],
149
- },
313
+ show: { resource: ["search"], operation: ["searchPeople", "searchCompanies"] },
150
314
  },
151
315
  },
152
316
  // === AGENTIC SEARCH PARAMETERS ===
@@ -158,10 +322,7 @@ class DataForB2B {
158
322
  required: true,
159
323
  description: "Natural language search query (min 3 characters)",
160
324
  displayOptions: {
161
- show: {
162
- resource: ["search"],
163
- operation: ["agenticSearch", "textToFilters"],
164
- },
325
+ show: { resource: ["search"], operation: ["agenticSearch", "textToFilters"] },
165
326
  },
166
327
  },
167
328
  {
@@ -169,22 +330,13 @@ class DataForB2B {
169
330
  name: "category",
170
331
  type: "options",
171
332
  options: [
172
- {
173
- name: "People",
174
- value: "people",
175
- },
176
- {
177
- name: "Company",
178
- value: "company",
179
- },
333
+ { name: "People", value: "people" },
334
+ { name: "Company", value: "company" },
180
335
  ],
181
336
  default: "people",
182
337
  description: "Search category",
183
338
  displayOptions: {
184
- show: {
185
- resource: ["search"],
186
- operation: ["agenticSearch", "textToFilters"],
187
- },
339
+ show: { resource: ["search"], operation: ["agenticSearch", "textToFilters"] },
188
340
  },
189
341
  },
190
342
  {
@@ -194,10 +346,7 @@ class DataForB2B {
194
346
  default: 10,
195
347
  description: "Number of results to return (max 100 for LLM search)",
196
348
  displayOptions: {
197
- show: {
198
- resource: ["search"],
199
- operation: ["agenticSearch"],
200
- },
349
+ show: { resource: ["search"], operation: ["agenticSearch"] },
201
350
  },
202
351
  },
203
352
  // === ENRICH PROFILE PARAMETERS ===
@@ -209,10 +358,7 @@ class DataForB2B {
209
358
  required: true,
210
359
  description: "LinkedIn URL, public ID, or encoded ID",
211
360
  displayOptions: {
212
- show: {
213
- resource: ["enrich"],
214
- operation: ["enrichProfile"],
215
- },
361
+ show: { resource: ["enrich"], operation: ["enrichProfile"] },
216
362
  },
217
363
  },
218
364
  {
@@ -222,10 +368,7 @@ class DataForB2B {
222
368
  default: true,
223
369
  description: "Whether to retrieve full profile data (1 credit)",
224
370
  displayOptions: {
225
- show: {
226
- resource: ["enrich"],
227
- operation: ["enrichProfile"],
228
- },
371
+ show: { resource: ["enrich"], operation: ["enrichProfile"] },
229
372
  },
230
373
  },
231
374
  {
@@ -235,10 +378,7 @@ class DataForB2B {
235
378
  default: false,
236
379
  description: "Whether to retrieve professional email (3 credits)",
237
380
  displayOptions: {
238
- show: {
239
- resource: ["enrich"],
240
- operation: ["enrichProfile"],
241
- },
381
+ show: { resource: ["enrich"], operation: ["enrichProfile"] },
242
382
  },
243
383
  },
244
384
  {
@@ -248,10 +388,7 @@ class DataForB2B {
248
388
  default: false,
249
389
  description: "Whether to retrieve personal email (1 credit)",
250
390
  displayOptions: {
251
- show: {
252
- resource: ["enrich"],
253
- operation: ["enrichProfile"],
254
- },
391
+ show: { resource: ["enrich"], operation: ["enrichProfile"] },
255
392
  },
256
393
  },
257
394
  {
@@ -261,10 +398,7 @@ class DataForB2B {
261
398
  default: false,
262
399
  description: "Whether to retrieve phone number (10 credits)",
263
400
  displayOptions: {
264
- show: {
265
- resource: ["enrich"],
266
- operation: ["enrichProfile"],
267
- },
401
+ show: { resource: ["enrich"], operation: ["enrichProfile"] },
268
402
  },
269
403
  },
270
404
  // === ENRICH COMPANY PARAMETERS ===
@@ -276,10 +410,7 @@ class DataForB2B {
276
410
  required: true,
277
411
  description: "Company slug, LinkedIn URL, or encoded ID",
278
412
  displayOptions: {
279
- show: {
280
- resource: ["enrich"],
281
- operation: ["enrichCompany"],
282
- },
413
+ show: { resource: ["enrich"], operation: ["enrichCompany"] },
283
414
  },
284
415
  },
285
416
  ],
@@ -294,24 +425,55 @@ class DataForB2B {
294
425
  try {
295
426
  let endpoint = "";
296
427
  let body = {};
297
- // Build request based on operation
298
428
  switch (operation) {
299
- case "searchPeople":
429
+ case "searchPeople": {
300
430
  endpoint = "/search/people";
431
+ const filterLogic = this.getNodeParameter("filterLogic", i);
432
+ const peopleFilters = this.getNodeParameter("peopleFilters", i);
433
+ const conditions = (peopleFilters.conditions || []).map((cond) => {
434
+ const condition = {
435
+ field: cond.field,
436
+ op: cond.operator,
437
+ value: cond.operator === "in" || cond.operator === "not_in"
438
+ ? cond.value.split(",").map((v) => v.trim())
439
+ : cond.value,
440
+ };
441
+ if (cond.operator === "between" && cond.value2) {
442
+ condition.value2 = cond.value2;
443
+ }
444
+ return condition;
445
+ });
301
446
  body = {
302
- filters: this.getNodeParameter("filters", i),
447
+ filters: { op: filterLogic, conditions },
303
448
  count: this.getNodeParameter("count", i),
304
449
  offset: this.getNodeParameter("offset", i),
305
450
  };
306
451
  break;
307
- case "searchCompanies":
452
+ }
453
+ case "searchCompanies": {
308
454
  endpoint = "/search/company";
455
+ const filterLogic = this.getNodeParameter("filterLogic", i);
456
+ const companyFilters = this.getNodeParameter("companyFilters", i);
457
+ const conditions = (companyFilters.conditions || []).map((cond) => {
458
+ const condition = {
459
+ field: cond.field,
460
+ op: cond.operator,
461
+ value: cond.operator === "in" || cond.operator === "not_in"
462
+ ? cond.value.split(",").map((v) => v.trim())
463
+ : cond.value,
464
+ };
465
+ if (cond.operator === "between" && cond.value2) {
466
+ condition.value2 = cond.value2;
467
+ }
468
+ return condition;
469
+ });
309
470
  body = {
310
- filters: this.getNodeParameter("filters", i),
471
+ filters: { op: filterLogic, conditions },
311
472
  count: this.getNodeParameter("count", i),
312
473
  offset: this.getNodeParameter("offset", i),
313
474
  };
314
475
  break;
476
+ }
315
477
  case "agenticSearch":
316
478
  endpoint = "/search/llm";
317
479
  body = {
@@ -347,9 +509,7 @@ class DataForB2B {
347
509
  const requestOptions = {
348
510
  method: "POST",
349
511
  url: `${DATAFORB2B_API_BASE_URL}${endpoint}`,
350
- headers: {
351
- "Content-Type": "application/json",
352
- },
512
+ headers: { "Content-Type": "application/json" },
353
513
  body,
354
514
  timeout: 60000,
355
515
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-dataforb2b",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "n8n node for DataForB2B API - Search people, companies and enrich B2B data",
5
5
  "keywords": [
6
6
  "n8n-community-node-package",