n8n-nodes-cribops 0.1.18 → 0.1.20
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.
|
@@ -25,6 +25,13 @@ class CribopsApi {
|
|
|
25
25
|
required: true,
|
|
26
26
|
description: 'Base URL of the Cribops API',
|
|
27
27
|
},
|
|
28
|
+
{
|
|
29
|
+
displayName: 'Organization ID',
|
|
30
|
+
name: 'organizationId',
|
|
31
|
+
type: 'string',
|
|
32
|
+
default: '',
|
|
33
|
+
description: 'Organization ID (optional - if not provided, will use the default organization for the API token)',
|
|
34
|
+
},
|
|
28
35
|
];
|
|
29
36
|
authenticate = {
|
|
30
37
|
type: 'generic',
|
|
@@ -41,7 +41,7 @@ class CribopsTrigger {
|
|
|
41
41
|
loadOptionsMethod: 'getWebhooks',
|
|
42
42
|
},
|
|
43
43
|
default: '',
|
|
44
|
-
description: '
|
|
44
|
+
description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
displayName: 'Event Types',
|
|
@@ -109,14 +109,17 @@ class CribopsTrigger {
|
|
|
109
109
|
apiToken: credentials.apiToken,
|
|
110
110
|
});
|
|
111
111
|
try {
|
|
112
|
-
//
|
|
113
|
-
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
112
|
+
// Get organization ID from credentials if provided
|
|
113
|
+
const organizationId = credentials.organizationId;
|
|
114
|
+
const webhooks = await cribopsHttp.getWebhooks(organizationId);
|
|
115
|
+
// Filter for N8N type webhooks that are active and not linked
|
|
116
|
+
const availableWebhooks = webhooks.filter((webhook) => webhook.type === 'N8N' &&
|
|
117
|
+
webhook.status === 'active' &&
|
|
118
|
+
!webhook.linked_workflow_id);
|
|
119
|
+
return availableWebhooks.map((webhook) => ({
|
|
120
|
+
name: webhook.name,
|
|
118
121
|
value: webhook.id,
|
|
119
|
-
description: webhook.description || `
|
|
122
|
+
description: webhook.description || `Type: ${webhook.type}`,
|
|
120
123
|
}));
|
|
121
124
|
}
|
|
122
125
|
catch (error) {
|
|
@@ -135,37 +138,37 @@ class CribopsTrigger {
|
|
|
135
138
|
async create() {
|
|
136
139
|
const webhookUrl = this.getNodeWebhookUrl('default');
|
|
137
140
|
const webhookId = this.getNodeParameter('webhookId');
|
|
138
|
-
const eventTypes = this.getNodeParameter('eventTypes', []);
|
|
139
|
-
const additionalFields = this.getNodeParameter('additionalFields', {});
|
|
140
141
|
const credentials = await this.getCredentials('cribopsApi');
|
|
142
|
+
const workflowId = this.getWorkflow().id;
|
|
143
|
+
const workflowName = this.getWorkflow().name;
|
|
141
144
|
const cribopsHttp = new CribopsHttp_1.CribopsHttp({
|
|
142
145
|
baseUrl: credentials.baseUrl,
|
|
143
146
|
apiToken: credentials.apiToken,
|
|
144
147
|
});
|
|
145
148
|
try {
|
|
146
|
-
//
|
|
149
|
+
// Link this workflow to the webhook entity
|
|
147
150
|
const body = {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
151
|
+
workflow_id: workflowId,
|
|
152
|
+
webhook_url: webhookUrl,
|
|
153
|
+
test_webhook_url: webhookUrl.replace('/webhook/', '/webhook-test/'),
|
|
154
|
+
workflow_name: workflowName || 'Unnamed Workflow',
|
|
152
155
|
};
|
|
153
|
-
//
|
|
154
|
-
await cribopsHttp.request('POST', `/api/v1/webhooks/${webhookId}/
|
|
156
|
+
// Link the n8n workflow to the webhook entity
|
|
157
|
+
await cribopsHttp.request('POST', `/api/v1/webhooks/${webhookId}/link`, body);
|
|
155
158
|
// Store webhook data for later use
|
|
156
159
|
const webhookData = this.getWorkflowStaticData('node');
|
|
157
160
|
webhookData.webhookId = webhookId;
|
|
158
|
-
webhookData.
|
|
161
|
+
webhookData.webhookUrl = webhookUrl;
|
|
159
162
|
return true;
|
|
160
163
|
}
|
|
161
164
|
catch (error) {
|
|
162
|
-
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to
|
|
165
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to link webhook: ${error instanceof Error ? error.message : String(error)}`);
|
|
163
166
|
}
|
|
164
167
|
},
|
|
165
168
|
async delete() {
|
|
166
169
|
const webhookData = this.getWorkflowStaticData('node');
|
|
167
170
|
const credentials = await this.getCredentials('cribopsApi');
|
|
168
|
-
if (!webhookData.webhookId
|
|
171
|
+
if (!webhookData.webhookId) {
|
|
169
172
|
return true;
|
|
170
173
|
}
|
|
171
174
|
const cribopsHttp = new CribopsHttp_1.CribopsHttp({
|
|
@@ -173,17 +176,15 @@ class CribopsTrigger {
|
|
|
173
176
|
apiToken: credentials.apiToken,
|
|
174
177
|
});
|
|
175
178
|
try {
|
|
176
|
-
//
|
|
177
|
-
await cribopsHttp.request('DELETE', `/api/v1/webhooks/${webhookData.webhookId}/
|
|
178
|
-
target_url: webhookData.targetUrl,
|
|
179
|
-
});
|
|
179
|
+
// Unlink the workflow from the webhook entity
|
|
180
|
+
await cribopsHttp.request('DELETE', `/api/v1/webhooks/${webhookData.webhookId}/link`);
|
|
180
181
|
delete webhookData.webhookId;
|
|
181
|
-
delete webhookData.
|
|
182
|
+
delete webhookData.webhookUrl;
|
|
182
183
|
return true;
|
|
183
184
|
}
|
|
184
185
|
catch (error) {
|
|
185
186
|
// Log error but don't fail
|
|
186
|
-
console.error('Failed to
|
|
187
|
+
console.error('Failed to unlink webhook:', error);
|
|
187
188
|
return true;
|
|
188
189
|
}
|
|
189
190
|
},
|
package/dist/package.json
CHANGED
|
@@ -37,6 +37,18 @@ export interface CribopsQueueMessage {
|
|
|
37
37
|
};
|
|
38
38
|
inserted_at: string;
|
|
39
39
|
}
|
|
40
|
+
export interface CribopsWebhookEntity {
|
|
41
|
+
id: string;
|
|
42
|
+
name: string;
|
|
43
|
+
description?: string;
|
|
44
|
+
type: 'N8N' | 'GHL_API' | 'GENERIC';
|
|
45
|
+
status: 'active' | 'inactive';
|
|
46
|
+
linked_workflow_id?: string;
|
|
47
|
+
linked_workflow_name?: string;
|
|
48
|
+
organization_id: string;
|
|
49
|
+
created_at: string;
|
|
50
|
+
updated_at: string;
|
|
51
|
+
}
|
|
40
52
|
export declare class CribopsHttp {
|
|
41
53
|
private config;
|
|
42
54
|
constructor(config: CribopsHttpConfig);
|
|
@@ -57,5 +69,13 @@ export declare class CribopsHttp {
|
|
|
57
69
|
status: string;
|
|
58
70
|
updated_count: number;
|
|
59
71
|
}>;
|
|
72
|
+
getWebhooks(organizationId?: string): Promise<CribopsWebhookEntity[]>;
|
|
73
|
+
linkWebhook(webhookId: string, linkData: {
|
|
74
|
+
workflow_id: string;
|
|
75
|
+
webhook_url: string;
|
|
76
|
+
test_webhook_url: string;
|
|
77
|
+
workflow_name: string;
|
|
78
|
+
}): Promise<any>;
|
|
79
|
+
unlinkWebhook(webhookId: string): Promise<any>;
|
|
60
80
|
request<T = any>(method: IHttpRequestMethods, endpoint: string, data?: IDataObject, options?: Partial<IHttpRequestOptions>): Promise<T>;
|
|
61
81
|
}
|
|
@@ -10,7 +10,21 @@ class CribopsHttp {
|
|
|
10
10
|
};
|
|
11
11
|
}
|
|
12
12
|
async makeRequest(method, endpoint, data, options) {
|
|
13
|
-
|
|
13
|
+
let url = `${this.config.baseUrl}${endpoint}`;
|
|
14
|
+
// Handle query parameters
|
|
15
|
+
if (method === 'GET' && data?.params) {
|
|
16
|
+
const params = new URLSearchParams();
|
|
17
|
+
Object.entries(data.params).forEach(([key, value]) => {
|
|
18
|
+
if (value !== undefined && value !== null) {
|
|
19
|
+
params.append(key, String(value));
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
const queryString = params.toString();
|
|
23
|
+
if (queryString) {
|
|
24
|
+
url += `?${queryString}`;
|
|
25
|
+
}
|
|
26
|
+
delete data.params;
|
|
27
|
+
}
|
|
14
28
|
const requestHeaders = {
|
|
15
29
|
'Authorization': `Bearer ${this.config.apiToken}`,
|
|
16
30
|
'Content-Type': 'application/json',
|
|
@@ -25,7 +39,7 @@ class CribopsHttp {
|
|
|
25
39
|
const response = await fetch(url, {
|
|
26
40
|
method,
|
|
27
41
|
headers: requestHeaders,
|
|
28
|
-
body: data ? JSON.stringify(data) : undefined,
|
|
42
|
+
body: (method !== 'GET' && data) ? JSON.stringify(data) : undefined,
|
|
29
43
|
});
|
|
30
44
|
if (!response.ok) {
|
|
31
45
|
const errorText = await response.text();
|
|
@@ -144,6 +158,33 @@ class CribopsHttp {
|
|
|
144
158
|
throw new Error(`Failed to mark messages as failed for tenant ${tenantId}: ${error}`);
|
|
145
159
|
}
|
|
146
160
|
}
|
|
161
|
+
// Webhook-specific methods
|
|
162
|
+
async getWebhooks(organizationId) {
|
|
163
|
+
try {
|
|
164
|
+
const params = organizationId ? { params: { organization_id: organizationId } } : undefined;
|
|
165
|
+
const response = await this.makeRequest('GET', '/api/v1/webhooks', params);
|
|
166
|
+
return response.data || [];
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
throw new Error(`Failed to fetch webhooks: ${error}`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
async linkWebhook(webhookId, linkData) {
|
|
173
|
+
try {
|
|
174
|
+
return await this.makeRequest('POST', `/api/v1/webhooks/${webhookId}/link`, linkData);
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
throw new Error(`Failed to link webhook: ${error}`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
async unlinkWebhook(webhookId) {
|
|
181
|
+
try {
|
|
182
|
+
return await this.makeRequest('DELETE', `/api/v1/webhooks/${webhookId}/link`);
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
throw new Error(`Failed to unlink webhook: ${error}`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
147
188
|
// Generic request method for custom API calls
|
|
148
189
|
async request(method, endpoint, data, options) {
|
|
149
190
|
return this.makeRequest(method, endpoint, data, options);
|