n8n-nodes-foxreach 0.1.0
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/dist/credentials/FoxReachApi.credentials.d.ts +8 -0
- package/dist/credentials/FoxReachApi.credentials.js +31 -0
- package/dist/nodes/FoxReach/FoxReach.node.d.ts +5 -0
- package/dist/nodes/FoxReach/FoxReach.node.js +117 -0
- package/dist/nodes/FoxReach/FoxReachTrigger.node.d.ts +12 -0
- package/dist/nodes/FoxReach/FoxReachTrigger.node.js +136 -0
- package/dist/nodes/FoxReach/descriptions/CampaignDescription.d.ts +3 -0
- package/dist/nodes/FoxReach/descriptions/CampaignDescription.js +58 -0
- package/dist/nodes/FoxReach/descriptions/LeadDescription.d.ts +3 -0
- package/dist/nodes/FoxReach/descriptions/LeadDescription.js +144 -0
- package/dist/nodes/FoxReach/foxreach.svg +40 -0
- package/package.json +44 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { IAuthenticateGeneric, ICredentialType, INodeProperties } from 'n8n-workflow';
|
|
2
|
+
export declare class FoxReachApi implements ICredentialType {
|
|
3
|
+
name: string;
|
|
4
|
+
displayName: string;
|
|
5
|
+
documentationUrl: string;
|
|
6
|
+
properties: INodeProperties[];
|
|
7
|
+
authenticate: IAuthenticateGeneric;
|
|
8
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FoxReachApi = void 0;
|
|
4
|
+
class FoxReachApi {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.name = 'foxReachApi';
|
|
7
|
+
this.displayName = 'FoxReach API';
|
|
8
|
+
this.documentationUrl = 'https://docs.foxreach.io/authentication';
|
|
9
|
+
this.properties = [
|
|
10
|
+
{
|
|
11
|
+
displayName: 'API Key',
|
|
12
|
+
name: 'apiKey',
|
|
13
|
+
type: 'string',
|
|
14
|
+
typeOptions: { password: true },
|
|
15
|
+
default: '',
|
|
16
|
+
placeholder: 'otr_...',
|
|
17
|
+
required: true,
|
|
18
|
+
description: 'Your FoxReach API key. Find it in Settings > API Keys.',
|
|
19
|
+
},
|
|
20
|
+
];
|
|
21
|
+
this.authenticate = {
|
|
22
|
+
type: 'generic',
|
|
23
|
+
properties: {
|
|
24
|
+
headers: {
|
|
25
|
+
'X-API-Key': '={{$credentials.apiKey}}',
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.FoxReachApi = FoxReachApi;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FoxReach = void 0;
|
|
4
|
+
const LeadDescription_1 = require("./descriptions/LeadDescription");
|
|
5
|
+
const CampaignDescription_1 = require("./descriptions/CampaignDescription");
|
|
6
|
+
const BASE_URL = 'https://api.foxreach.io/api/v1';
|
|
7
|
+
class FoxReach {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.description = {
|
|
10
|
+
displayName: 'FoxReach',
|
|
11
|
+
name: 'foxReach',
|
|
12
|
+
icon: 'file:foxreach.svg',
|
|
13
|
+
group: ['transform'],
|
|
14
|
+
version: 1,
|
|
15
|
+
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
|
16
|
+
description: 'Manage leads and campaigns in FoxReach cold email outreach platform',
|
|
17
|
+
defaults: {
|
|
18
|
+
name: 'FoxReach',
|
|
19
|
+
},
|
|
20
|
+
inputs: ['main'],
|
|
21
|
+
outputs: ['main'],
|
|
22
|
+
credentials: [
|
|
23
|
+
{
|
|
24
|
+
name: 'foxReachApi',
|
|
25
|
+
required: true,
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
properties: [
|
|
29
|
+
{
|
|
30
|
+
displayName: 'Resource',
|
|
31
|
+
name: 'resource',
|
|
32
|
+
type: 'options',
|
|
33
|
+
noDataExpression: true,
|
|
34
|
+
options: [
|
|
35
|
+
{
|
|
36
|
+
name: 'Lead',
|
|
37
|
+
value: 'lead',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: 'Campaign',
|
|
41
|
+
value: 'campaign',
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
default: 'lead',
|
|
45
|
+
},
|
|
46
|
+
...LeadDescription_1.leadOperations,
|
|
47
|
+
...LeadDescription_1.leadFields,
|
|
48
|
+
...CampaignDescription_1.campaignOperations,
|
|
49
|
+
...CampaignDescription_1.campaignFields,
|
|
50
|
+
],
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
async execute() {
|
|
54
|
+
const items = this.getInputData();
|
|
55
|
+
const returnData = [];
|
|
56
|
+
const resource = this.getNodeParameter('resource', 0);
|
|
57
|
+
const operation = this.getNodeParameter('operation', 0);
|
|
58
|
+
for (let i = 0; i < items.length; i++) {
|
|
59
|
+
try {
|
|
60
|
+
let responseData;
|
|
61
|
+
if (resource === 'lead') {
|
|
62
|
+
if (operation === 'create') {
|
|
63
|
+
const email = this.getNodeParameter('email', i);
|
|
64
|
+
const additionalFields = this.getNodeParameter('additionalFields', i);
|
|
65
|
+
const body = { email };
|
|
66
|
+
Object.assign(body, additionalFields);
|
|
67
|
+
responseData = await this.helpers.httpRequestWithAuthentication.call(this, 'foxReachApi', {
|
|
68
|
+
method: 'POST',
|
|
69
|
+
url: `${BASE_URL}/leads`,
|
|
70
|
+
body,
|
|
71
|
+
json: true,
|
|
72
|
+
});
|
|
73
|
+
responseData = responseData.data;
|
|
74
|
+
}
|
|
75
|
+
if (operation === 'findByEmail') {
|
|
76
|
+
const email = this.getNodeParameter('email', i);
|
|
77
|
+
responseData = await this.helpers.httpRequestWithAuthentication.call(this, 'foxReachApi', {
|
|
78
|
+
method: 'GET',
|
|
79
|
+
url: `${BASE_URL}/leads`,
|
|
80
|
+
qs: { search: email, pageSize: 5 },
|
|
81
|
+
json: true,
|
|
82
|
+
});
|
|
83
|
+
responseData = responseData.data;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (resource === 'campaign') {
|
|
87
|
+
if (operation === 'addLead') {
|
|
88
|
+
const campaignId = this.getNodeParameter('campaignId', i);
|
|
89
|
+
const leadId = this.getNodeParameter('leadId', i);
|
|
90
|
+
responseData = await this.helpers.httpRequestWithAuthentication.call(this, 'foxReachApi', {
|
|
91
|
+
method: 'POST',
|
|
92
|
+
url: `${BASE_URL}/campaigns/${campaignId}/leads`,
|
|
93
|
+
body: { leadIds: [leadId] },
|
|
94
|
+
json: true,
|
|
95
|
+
});
|
|
96
|
+
responseData = responseData.data;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (Array.isArray(responseData)) {
|
|
100
|
+
returnData.push(...responseData.map((item) => ({ json: item })));
|
|
101
|
+
}
|
|
102
|
+
else if (responseData) {
|
|
103
|
+
returnData.push({ json: responseData });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
if (this.continueOnFail()) {
|
|
108
|
+
returnData.push({ json: { error: error.message } });
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
throw error;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return [returnData];
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
exports.FoxReach = FoxReach;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { IHookFunctions, IWebhookFunctions, INodeType, INodeTypeDescription, IWebhookResponseData } from 'n8n-workflow';
|
|
2
|
+
export declare class FoxReachTrigger implements INodeType {
|
|
3
|
+
description: INodeTypeDescription;
|
|
4
|
+
webhookMethods: {
|
|
5
|
+
default: {
|
|
6
|
+
checkExists(this: IHookFunctions): Promise<boolean>;
|
|
7
|
+
create(this: IHookFunctions): Promise<boolean>;
|
|
8
|
+
delete(this: IHookFunctions): Promise<boolean>;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
webhook(this: IWebhookFunctions): Promise<IWebhookResponseData>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FoxReachTrigger = void 0;
|
|
4
|
+
const BASE_URL = 'https://api.foxreach.io/api/v1';
|
|
5
|
+
class FoxReachTrigger {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.description = {
|
|
8
|
+
displayName: 'FoxReach Trigger',
|
|
9
|
+
name: 'foxReachTrigger',
|
|
10
|
+
icon: 'file:foxreach.svg',
|
|
11
|
+
group: ['trigger'],
|
|
12
|
+
version: 1,
|
|
13
|
+
subtitle: '={{$parameter["event"]}}',
|
|
14
|
+
description: 'Starts a workflow when a FoxReach event occurs',
|
|
15
|
+
defaults: {
|
|
16
|
+
name: 'FoxReach Trigger',
|
|
17
|
+
},
|
|
18
|
+
inputs: [],
|
|
19
|
+
outputs: ['main'],
|
|
20
|
+
credentials: [
|
|
21
|
+
{
|
|
22
|
+
name: 'foxReachApi',
|
|
23
|
+
required: true,
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
webhooks: [
|
|
27
|
+
{
|
|
28
|
+
name: 'default',
|
|
29
|
+
httpMethod: 'POST',
|
|
30
|
+
responseMode: 'onReceived',
|
|
31
|
+
path: 'webhook',
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
properties: [
|
|
35
|
+
{
|
|
36
|
+
displayName: 'Event',
|
|
37
|
+
name: 'event',
|
|
38
|
+
type: 'options',
|
|
39
|
+
required: true,
|
|
40
|
+
default: 'reply.received',
|
|
41
|
+
options: [
|
|
42
|
+
{
|
|
43
|
+
name: 'New Reply Received',
|
|
44
|
+
value: 'reply.received',
|
|
45
|
+
description: 'When a prospect replies to an outreach email',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: 'Reply Categorized',
|
|
49
|
+
value: 'reply.categorized',
|
|
50
|
+
description: 'When a reply is categorized (e.g. interested, not interested)',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'Email Bounced',
|
|
54
|
+
value: 'email.bounced',
|
|
55
|
+
description: 'When a sent email bounces back',
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
};
|
|
61
|
+
this.webhookMethods = {
|
|
62
|
+
default: {
|
|
63
|
+
async checkExists() {
|
|
64
|
+
const webhookUrl = this.getNodeWebhookUrl('default');
|
|
65
|
+
const webhookData = this.getWorkflowStaticData('node');
|
|
66
|
+
// If we have a stored webhook ID, verify it still exists
|
|
67
|
+
if (webhookData.webhookId) {
|
|
68
|
+
try {
|
|
69
|
+
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'foxReachApi', {
|
|
70
|
+
method: 'GET',
|
|
71
|
+
url: `${BASE_URL}/webhooks`,
|
|
72
|
+
qs: { pageSize: 100 },
|
|
73
|
+
json: true,
|
|
74
|
+
});
|
|
75
|
+
const webhooks = response.data || [];
|
|
76
|
+
const exists = webhooks.some((wh) => wh.id === webhookData.webhookId && wh.url === webhookUrl);
|
|
77
|
+
if (exists)
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// Webhook no longer exists, will recreate
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return false;
|
|
85
|
+
},
|
|
86
|
+
async create() {
|
|
87
|
+
const webhookUrl = this.getNodeWebhookUrl('default');
|
|
88
|
+
const event = this.getNodeParameter('event');
|
|
89
|
+
const webhookData = this.getWorkflowStaticData('node');
|
|
90
|
+
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'foxReachApi', {
|
|
91
|
+
method: 'POST',
|
|
92
|
+
url: `${BASE_URL}/webhooks`,
|
|
93
|
+
body: {
|
|
94
|
+
url: webhookUrl,
|
|
95
|
+
events: [event],
|
|
96
|
+
},
|
|
97
|
+
json: true,
|
|
98
|
+
});
|
|
99
|
+
webhookData.webhookId = response.data.id;
|
|
100
|
+
return true;
|
|
101
|
+
},
|
|
102
|
+
async delete() {
|
|
103
|
+
const webhookData = this.getWorkflowStaticData('node');
|
|
104
|
+
if (webhookData.webhookId) {
|
|
105
|
+
try {
|
|
106
|
+
await this.helpers.httpRequestWithAuthentication.call(this, 'foxReachApi', {
|
|
107
|
+
method: 'DELETE',
|
|
108
|
+
url: `${BASE_URL}/webhooks/${webhookData.webhookId}`,
|
|
109
|
+
json: true,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
// Webhook may have been deleted already
|
|
114
|
+
}
|
|
115
|
+
delete webhookData.webhookId;
|
|
116
|
+
}
|
|
117
|
+
return true;
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
async webhook() {
|
|
123
|
+
const body = this.getBodyData();
|
|
124
|
+
return {
|
|
125
|
+
workflowData: [
|
|
126
|
+
this.helpers.returnJsonArray({
|
|
127
|
+
eventId: body.id,
|
|
128
|
+
eventType: body.type,
|
|
129
|
+
timestamp: body.timestamp,
|
|
130
|
+
...body.payload,
|
|
131
|
+
}),
|
|
132
|
+
],
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
exports.FoxReachTrigger = FoxReachTrigger;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.campaignFields = exports.campaignOperations = void 0;
|
|
4
|
+
exports.campaignOperations = [
|
|
5
|
+
{
|
|
6
|
+
displayName: 'Operation',
|
|
7
|
+
name: 'operation',
|
|
8
|
+
type: 'options',
|
|
9
|
+
noDataExpression: true,
|
|
10
|
+
displayOptions: {
|
|
11
|
+
show: {
|
|
12
|
+
resource: ['campaign'],
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
options: [
|
|
16
|
+
{
|
|
17
|
+
name: 'Add Lead',
|
|
18
|
+
value: 'addLead',
|
|
19
|
+
description: 'Add a lead to a campaign',
|
|
20
|
+
action: 'Add a lead to a campaign',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
default: 'addLead',
|
|
24
|
+
},
|
|
25
|
+
];
|
|
26
|
+
exports.campaignFields = [
|
|
27
|
+
// ----------------------------------
|
|
28
|
+
// campaign:addLead
|
|
29
|
+
// ----------------------------------
|
|
30
|
+
{
|
|
31
|
+
displayName: 'Campaign ID',
|
|
32
|
+
name: 'campaignId',
|
|
33
|
+
type: 'string',
|
|
34
|
+
required: true,
|
|
35
|
+
default: '',
|
|
36
|
+
displayOptions: {
|
|
37
|
+
show: {
|
|
38
|
+
resource: ['campaign'],
|
|
39
|
+
operation: ['addLead'],
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
description: 'The ID of the campaign to add the lead to',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
displayName: 'Lead ID',
|
|
46
|
+
name: 'leadId',
|
|
47
|
+
type: 'string',
|
|
48
|
+
required: true,
|
|
49
|
+
default: '',
|
|
50
|
+
displayOptions: {
|
|
51
|
+
show: {
|
|
52
|
+
resource: ['campaign'],
|
|
53
|
+
operation: ['addLead'],
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
description: 'The ID of the lead to add',
|
|
57
|
+
},
|
|
58
|
+
];
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.leadFields = exports.leadOperations = void 0;
|
|
4
|
+
exports.leadOperations = [
|
|
5
|
+
{
|
|
6
|
+
displayName: 'Operation',
|
|
7
|
+
name: 'operation',
|
|
8
|
+
type: 'options',
|
|
9
|
+
noDataExpression: true,
|
|
10
|
+
displayOptions: {
|
|
11
|
+
show: {
|
|
12
|
+
resource: ['lead'],
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
options: [
|
|
16
|
+
{
|
|
17
|
+
name: 'Create',
|
|
18
|
+
value: 'create',
|
|
19
|
+
description: 'Create a new lead',
|
|
20
|
+
action: 'Create a lead',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: 'Find by Email',
|
|
24
|
+
value: 'findByEmail',
|
|
25
|
+
description: 'Find a lead by email address',
|
|
26
|
+
action: 'Find a lead by email',
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
default: 'create',
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
exports.leadFields = [
|
|
33
|
+
// ----------------------------------
|
|
34
|
+
// lead:create
|
|
35
|
+
// ----------------------------------
|
|
36
|
+
{
|
|
37
|
+
displayName: 'Email',
|
|
38
|
+
name: 'email',
|
|
39
|
+
type: 'string',
|
|
40
|
+
placeholder: 'name@email.com',
|
|
41
|
+
required: true,
|
|
42
|
+
default: '',
|
|
43
|
+
displayOptions: {
|
|
44
|
+
show: {
|
|
45
|
+
resource: ['lead'],
|
|
46
|
+
operation: ['create'],
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
description: 'Email address of the lead. Must be unique within the workspace.',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
displayName: 'Additional Fields',
|
|
53
|
+
name: 'additionalFields',
|
|
54
|
+
type: 'collection',
|
|
55
|
+
placeholder: 'Add Field',
|
|
56
|
+
default: {},
|
|
57
|
+
displayOptions: {
|
|
58
|
+
show: {
|
|
59
|
+
resource: ['lead'],
|
|
60
|
+
operation: ['create'],
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
options: [
|
|
64
|
+
{
|
|
65
|
+
displayName: 'First Name',
|
|
66
|
+
name: 'firstName',
|
|
67
|
+
type: 'string',
|
|
68
|
+
default: '',
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
displayName: 'Last Name',
|
|
72
|
+
name: 'lastName',
|
|
73
|
+
type: 'string',
|
|
74
|
+
default: '',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
displayName: 'Company',
|
|
78
|
+
name: 'company',
|
|
79
|
+
type: 'string',
|
|
80
|
+
default: '',
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
displayName: 'Job Title',
|
|
84
|
+
name: 'title',
|
|
85
|
+
type: 'string',
|
|
86
|
+
default: '',
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
displayName: 'Phone',
|
|
90
|
+
name: 'phone',
|
|
91
|
+
type: 'string',
|
|
92
|
+
default: '',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
displayName: 'LinkedIn URL',
|
|
96
|
+
name: 'linkedinUrl',
|
|
97
|
+
type: 'string',
|
|
98
|
+
default: '',
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
displayName: 'Website',
|
|
102
|
+
name: 'website',
|
|
103
|
+
type: 'string',
|
|
104
|
+
default: '',
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
displayName: 'Notes',
|
|
108
|
+
name: 'notes',
|
|
109
|
+
type: 'string',
|
|
110
|
+
default: '',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
displayName: 'Status',
|
|
114
|
+
name: 'status',
|
|
115
|
+
type: 'options',
|
|
116
|
+
options: [
|
|
117
|
+
{ name: 'Active', value: 'active' },
|
|
118
|
+
{ name: 'Bounced', value: 'bounced' },
|
|
119
|
+
{ name: 'Unsubscribed', value: 'unsubscribed' },
|
|
120
|
+
{ name: 'Replied', value: 'replied' },
|
|
121
|
+
],
|
|
122
|
+
default: 'active',
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
},
|
|
126
|
+
// ----------------------------------
|
|
127
|
+
// lead:findByEmail
|
|
128
|
+
// ----------------------------------
|
|
129
|
+
{
|
|
130
|
+
displayName: 'Email',
|
|
131
|
+
name: 'email',
|
|
132
|
+
type: 'string',
|
|
133
|
+
placeholder: 'name@email.com',
|
|
134
|
+
required: true,
|
|
135
|
+
default: '',
|
|
136
|
+
displayOptions: {
|
|
137
|
+
show: {
|
|
138
|
+
resource: ['lead'],
|
|
139
|
+
operation: ['findByEmail'],
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
description: 'The email address to search for',
|
|
143
|
+
},
|
|
144
|
+
];
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<svg width="512" height="512" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="fxGrad" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
4
|
+
<stop offset="0%" stop-color="#E89A84" />
|
|
5
|
+
<stop offset="100%" stop-color="#E07A5F" />
|
|
6
|
+
</linearGradient>
|
|
7
|
+
<linearGradient id="fxEarGrad" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
8
|
+
<stop offset="0%" stop-color="#E07A5F" />
|
|
9
|
+
<stop offset="100%" stop-color="#C4604A" />
|
|
10
|
+
</linearGradient>
|
|
11
|
+
</defs>
|
|
12
|
+
<!-- Left ear -->
|
|
13
|
+
<path d="M100 60 L60 220 L190 250 Z" fill="url(#fxEarGrad)" />
|
|
14
|
+
<!-- Right ear -->
|
|
15
|
+
<path d="M412 60 L452 220 L322 250 Z" fill="url(#fxEarGrad)" />
|
|
16
|
+
<!-- Inner left ear -->
|
|
17
|
+
<path d="M120 120 L95 210 L175 235 Z" fill="#F3D5CF" />
|
|
18
|
+
<!-- Inner right ear -->
|
|
19
|
+
<path d="M392 120 L417 210 L337 235 Z" fill="#F3D5CF" />
|
|
20
|
+
<!-- Head -->
|
|
21
|
+
<ellipse cx="256" cy="300" rx="190" ry="175" fill="url(#fxGrad)" />
|
|
22
|
+
<!-- White face/muzzle area -->
|
|
23
|
+
<ellipse cx="256" cy="350" rx="110" ry="100" fill="#FFF5F2" />
|
|
24
|
+
<!-- Left eye -->
|
|
25
|
+
<ellipse cx="195" cy="280" rx="22" ry="25" fill="#37322F" />
|
|
26
|
+
<ellipse cx="200" cy="275" rx="7" ry="8" fill="white" />
|
|
27
|
+
<!-- Right eye -->
|
|
28
|
+
<ellipse cx="317" cy="280" rx="22" ry="25" fill="#37322F" />
|
|
29
|
+
<ellipse cx="322" cy="275" rx="7" ry="8" fill="white" />
|
|
30
|
+
<!-- Nose -->
|
|
31
|
+
<ellipse cx="256" cy="340" rx="20" ry="14" fill="#37322F" />
|
|
32
|
+
<ellipse cx="252" cy="337" rx="6" ry="4" fill="#5A504C" />
|
|
33
|
+
<!-- Mouth -->
|
|
34
|
+
<path d="M256 354 Q240 370 230 365" fill="none" stroke="#37322F" stroke-width="4" stroke-linecap="round" />
|
|
35
|
+
<path d="M256 354 Q272 370 282 365" fill="none" stroke="#37322F" stroke-width="4" stroke-linecap="round" />
|
|
36
|
+
<!-- Cheek fluff left -->
|
|
37
|
+
<path d="M80 330 Q120 310 140 340 Q110 360 80 330Z" fill="#E07A5F" />
|
|
38
|
+
<!-- Cheek fluff right -->
|
|
39
|
+
<path d="M432 330 Q392 310 372 340 Q402 360 432 330Z" fill="#E07A5F" />
|
|
40
|
+
</svg>
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "n8n-nodes-foxreach",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "n8n community node for FoxReach cold email outreach platform",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"homepage": "https://foxreach.io",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/foxreach/n8n-nodes-foxreach"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"n8n-community-node-package",
|
|
13
|
+
"n8n",
|
|
14
|
+
"foxreach",
|
|
15
|
+
"cold-email",
|
|
16
|
+
"outreach"
|
|
17
|
+
],
|
|
18
|
+
"main": "dist/nodes/FoxReach/FoxReach.node.js",
|
|
19
|
+
"n8n": {
|
|
20
|
+
"n8nNodesApiVersion": 1,
|
|
21
|
+
"credentials": [
|
|
22
|
+
"dist/credentials/FoxReachApi.credentials.js"
|
|
23
|
+
],
|
|
24
|
+
"nodes": [
|
|
25
|
+
"dist/nodes/FoxReach/FoxReach.node.js",
|
|
26
|
+
"dist/nodes/FoxReach/FoxReachTrigger.node.js"
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsc && cp nodes/FoxReach/foxreach.svg dist/nodes/FoxReach/",
|
|
31
|
+
"lint": "tsc --noEmit",
|
|
32
|
+
"prepublishOnly": "npm run build"
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"dist"
|
|
36
|
+
],
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"typescript": "^5.3.0",
|
|
39
|
+
"n8n-workflow": "*"
|
|
40
|
+
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"n8n-workflow": "*"
|
|
43
|
+
}
|
|
44
|
+
}
|