@ixiam/n8n-nodes-civicrm 0.2.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/README.md +12 -0
- package/dist/credentials/CiviCrmApi.credentials.d.ts +34 -0
- package/dist/credentials/CiviCrmApi.credentials.js +58 -0
- package/dist/nodes/CiviCrm/CiviCrm.node.d.ts +13 -0
- package/dist/nodes/CiviCrm/CiviCrm.node.js +187 -0
- package/dist/nodes/CiviCrm/civicrm.svg +28 -0
- package/dist/nodes/CiviCrm/descriptions/generic.d.ts +3 -0
- package/dist/nodes/CiviCrm/descriptions/generic.js +11 -0
- package/dist/nodes/CiviCrm/descriptions/resources.d.ts +3 -0
- package/dist/nodes/CiviCrm/descriptions/resources.js +36 -0
- package/dist/nodes/transport/GenericFunctions.d.ts +13 -0
- package/dist/nodes/transport/GenericFunctions.js +38 -0
- package/package.json +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# n8n-nodes-civicrm
|
|
2
|
+
Community node for **CiviCRM API v4** and **Form Processor**.
|
|
3
|
+
|
|
4
|
+
Install: Settings → Community Nodes → Install → `n8n-nodes-civicrm`
|
|
5
|
+
|
|
6
|
+
Credentials:
|
|
7
|
+
- Base URL: `https://crm.example.org` (no trailing slash)
|
|
8
|
+
- API Token: header `X-Civi-Auth: Bearer <token>`
|
|
9
|
+
- Use the **Save** button to verify connectivity.
|
|
10
|
+
|
|
11
|
+
Entities: Contact, Event, Case, Contribution, Membership → `get|getMany|create|update|delete`
|
|
12
|
+
Form Processor: `execute` with `recordsJson`
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ICredentialType, INodeProperties, IHttpRequestMethods } from 'n8n-workflow';
|
|
2
|
+
export declare class CiviCrmApi implements ICredentialType {
|
|
3
|
+
name: string;
|
|
4
|
+
displayName: string;
|
|
5
|
+
documentationUrl: string;
|
|
6
|
+
authenticate: {
|
|
7
|
+
type: "generic";
|
|
8
|
+
properties: {
|
|
9
|
+
headers: {
|
|
10
|
+
'X-Civi-Auth': string;
|
|
11
|
+
'Content-Type': string;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
test: {
|
|
16
|
+
request: {
|
|
17
|
+
method: IHttpRequestMethods;
|
|
18
|
+
url: string;
|
|
19
|
+
headers: {
|
|
20
|
+
'X-Civi-Auth': string;
|
|
21
|
+
'Content-Type': string;
|
|
22
|
+
};
|
|
23
|
+
body: {
|
|
24
|
+
entity: string;
|
|
25
|
+
action: string;
|
|
26
|
+
params: {
|
|
27
|
+
limit: number;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
json: boolean;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
properties: INodeProperties[];
|
|
34
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CiviCrmApi = void 0;
|
|
4
|
+
class CiviCrmApi {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.name = 'civiCrmApi';
|
|
7
|
+
this.displayName = 'CiviCRM API';
|
|
8
|
+
this.documentationUrl = 'https://docs.civicrm.org/dev/en/latest/api/v4/';
|
|
9
|
+
this.authenticate = {
|
|
10
|
+
type: 'generic',
|
|
11
|
+
properties: {
|
|
12
|
+
headers: {
|
|
13
|
+
'X-Civi-Auth': '={{"Bearer " + $credentials.apiToken}}',
|
|
14
|
+
'Content-Type': 'application/json',
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
// Button "Test" in credential UI
|
|
19
|
+
this.test = {
|
|
20
|
+
request: {
|
|
21
|
+
// IMPORTANT: method must be typed as IHttpRequestMethods
|
|
22
|
+
method: 'POST',
|
|
23
|
+
url: '={{$credentials.baseUrl.replace(/\\/$/, "")}}/civicrm/ajax/api4/Contact/get',
|
|
24
|
+
headers: {
|
|
25
|
+
'X-Civi-Auth': '={{"Bearer " + $credentials.apiToken}}',
|
|
26
|
+
'Content-Type': 'application/json',
|
|
27
|
+
},
|
|
28
|
+
body: {
|
|
29
|
+
entity: 'Contact',
|
|
30
|
+
action: 'get',
|
|
31
|
+
params: { limit: 1 },
|
|
32
|
+
},
|
|
33
|
+
json: true,
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
this.properties = [
|
|
37
|
+
{
|
|
38
|
+
displayName: 'Base URL',
|
|
39
|
+
name: 'baseUrl',
|
|
40
|
+
type: 'string',
|
|
41
|
+
default: '',
|
|
42
|
+
required: true,
|
|
43
|
+
placeholder: 'https://crm.example.org',
|
|
44
|
+
description: 'Sin la barra final',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
displayName: 'API Token',
|
|
48
|
+
name: 'apiToken',
|
|
49
|
+
type: 'string',
|
|
50
|
+
typeOptions: { password: true },
|
|
51
|
+
default: '',
|
|
52
|
+
required: true,
|
|
53
|
+
description: 'Se envía como X-Civi-Auth: Bearer <token>',
|
|
54
|
+
},
|
|
55
|
+
];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.CiviCrmApi = CiviCrmApi;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { IExecuteFunctions, ILoadOptionsFunctions, INodeExecutionData, INodePropertyOptions, INodeType, INodeTypeDescription } from 'n8n-workflow';
|
|
2
|
+
/**
|
|
3
|
+
* Nodo principal CiviCRM para n8n
|
|
4
|
+
*/
|
|
5
|
+
export declare class CiviCrm implements INodeType {
|
|
6
|
+
description: INodeTypeDescription;
|
|
7
|
+
methods: {
|
|
8
|
+
loadOptions: {
|
|
9
|
+
getOptionValues(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CiviCrm = void 0;
|
|
4
|
+
const GenericFunctions_1 = require("../transport/GenericFunctions");
|
|
5
|
+
const resources_1 = require("./descriptions/resources");
|
|
6
|
+
const generic_1 = require("./descriptions/generic");
|
|
7
|
+
const ENTITY_MAP = {
|
|
8
|
+
contact: 'Contact',
|
|
9
|
+
event: 'Event',
|
|
10
|
+
case: 'Case',
|
|
11
|
+
contribution: 'Contribution',
|
|
12
|
+
membership: 'Membership',
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Nodo principal CiviCRM para n8n
|
|
16
|
+
*/
|
|
17
|
+
class CiviCrm {
|
|
18
|
+
constructor() {
|
|
19
|
+
this.description = {
|
|
20
|
+
displayName: 'CiviCRM',
|
|
21
|
+
name: 'civiCrm',
|
|
22
|
+
icon: 'file:civicrm.svg',
|
|
23
|
+
group: ['transform'],
|
|
24
|
+
version: 1,
|
|
25
|
+
description: 'Interact with CiviCRM API v4',
|
|
26
|
+
defaults: { name: 'CiviCRM' },
|
|
27
|
+
inputs: ['main'],
|
|
28
|
+
outputs: ['main'],
|
|
29
|
+
credentials: [{ name: 'civiCrmApi', required: true }],
|
|
30
|
+
properties: [
|
|
31
|
+
resources_1.resourceProp,
|
|
32
|
+
resources_1.operationProp,
|
|
33
|
+
{
|
|
34
|
+
displayName: 'ID',
|
|
35
|
+
name: 'id',
|
|
36
|
+
type: 'number',
|
|
37
|
+
default: 0,
|
|
38
|
+
required: true,
|
|
39
|
+
displayOptions: { show: { operation: ['get', 'update', 'delete'] } },
|
|
40
|
+
},
|
|
41
|
+
...generic_1.genericFields,
|
|
42
|
+
...generic_1.upsertFields,
|
|
43
|
+
{
|
|
44
|
+
displayName: 'Processor Name',
|
|
45
|
+
name: 'processor',
|
|
46
|
+
type: 'string',
|
|
47
|
+
default: '',
|
|
48
|
+
placeholder: 'fp_volunteer_registration',
|
|
49
|
+
description: 'Technical name after FormProcessor_',
|
|
50
|
+
displayOptions: { show: { resource: ['formProcessor'], operation: ['execute'] } },
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
displayName: 'Records (JSON)',
|
|
54
|
+
name: 'recordsJson',
|
|
55
|
+
type: 'string',
|
|
56
|
+
default: '',
|
|
57
|
+
placeholder: `[{"first_name":"Alice"}]`,
|
|
58
|
+
displayOptions: { show: { resource: ['formProcessor'], operation: ['execute'] } },
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
};
|
|
62
|
+
this.methods = {
|
|
63
|
+
loadOptions: {
|
|
64
|
+
async getOptionValues() {
|
|
65
|
+
const { baseUrl, apiToken } = (await this.getCredentials('civiCrmApi'));
|
|
66
|
+
const url = `${baseUrl.replace(/\/$/, '')}/civicrm/ajax/api4/OptionValue/get`;
|
|
67
|
+
const res = await this.helpers.httpRequest({
|
|
68
|
+
method: 'POST',
|
|
69
|
+
url,
|
|
70
|
+
headers: {
|
|
71
|
+
'X-Civi-Auth': `Bearer ${apiToken}`,
|
|
72
|
+
'Content-Type': 'application/json',
|
|
73
|
+
},
|
|
74
|
+
body: (0, GenericFunctions_1.api4)('OptionValue', 'get', { limit: 5 }),
|
|
75
|
+
json: true,
|
|
76
|
+
});
|
|
77
|
+
const values = (res?.values || []);
|
|
78
|
+
return values.map((v) => ({
|
|
79
|
+
name: v.label,
|
|
80
|
+
value: v.id,
|
|
81
|
+
}));
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
async execute() {
|
|
87
|
+
const items = this.getInputData();
|
|
88
|
+
const out = [];
|
|
89
|
+
const resource = this.getNodeParameter('resource', 0);
|
|
90
|
+
const operation = this.getNodeParameter('operation', 0);
|
|
91
|
+
for (let i = 0; i < items.length; i++) {
|
|
92
|
+
// FORM PROCESSOR
|
|
93
|
+
if (resource === 'formProcessor' && operation === 'execute') {
|
|
94
|
+
const processor = this.getNodeParameter('processor', i);
|
|
95
|
+
const recordsJson = this.getNodeParameter('recordsJson', i, '');
|
|
96
|
+
const records = recordsJson ? JSON.parse(recordsJson) : [];
|
|
97
|
+
const res = await GenericFunctions_1.civicrmApiRequest.call(this, 'POST', `/civicrm/ajax/api4/FormProcessor_${processor}/save`, { params: { records } });
|
|
98
|
+
out.push({ json: res });
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
const entity = ENTITY_MAP[resource];
|
|
102
|
+
// GET
|
|
103
|
+
if (operation === 'get') {
|
|
104
|
+
const id = this.getNodeParameter('id', i);
|
|
105
|
+
const res = await GenericFunctions_1.civicrmApiRequest.call(this, 'POST', `/civicrm/ajax/api4/${entity}/get`, (0, GenericFunctions_1.api4)(entity, 'get', { where: [['id', '=', id]], limit: 1 }));
|
|
106
|
+
out.push({ json: (res?.values?.[0] ?? {}) });
|
|
107
|
+
}
|
|
108
|
+
// GET MANY
|
|
109
|
+
if (operation === 'getMany') {
|
|
110
|
+
const returnAll = this.getNodeParameter('returnAll', i, false);
|
|
111
|
+
const limit = this.getNodeParameter('limit', i, 100);
|
|
112
|
+
const whereJson = this.getNodeParameter('whereJson', i, '');
|
|
113
|
+
const where = whereJson ? JSON.parse(whereJson) : undefined;
|
|
114
|
+
if (returnAll) {
|
|
115
|
+
let offset = 0;
|
|
116
|
+
const page = 500;
|
|
117
|
+
while (true) {
|
|
118
|
+
const res = await GenericFunctions_1.civicrmApiRequest.call(this, 'POST', `/civicrm/ajax/api4/${entity}/get`, (0, GenericFunctions_1.api4)(entity, 'get', { where, limit: page, offset }));
|
|
119
|
+
const vals = (res?.values ?? []);
|
|
120
|
+
for (const v of vals)
|
|
121
|
+
out.push({ json: v });
|
|
122
|
+
if (vals.length < page)
|
|
123
|
+
break;
|
|
124
|
+
offset += page;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
const res = await GenericFunctions_1.civicrmApiRequest.call(this, 'POST', `/civicrm/ajax/api4/${entity}/get`, (0, GenericFunctions_1.api4)(entity, 'get', { where, limit }));
|
|
129
|
+
const vals = (res?.values ?? []);
|
|
130
|
+
for (const v of vals)
|
|
131
|
+
out.push({ json: v });
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// CREATE
|
|
135
|
+
if (operation === 'create') {
|
|
136
|
+
const pairs = this.getNodeParameter('fields.field', i, []);
|
|
137
|
+
const params = Object.fromEntries(pairs
|
|
138
|
+
.filter((p) => p.fieldName)
|
|
139
|
+
.map((p) => [p.fieldName, convertValue(p.fieldValue)]));
|
|
140
|
+
const res = await GenericFunctions_1.civicrmApiRequest.call(this, 'POST', `/civicrm/ajax/api4/${entity}/create`, (0, GenericFunctions_1.api4)(entity, 'create', params));
|
|
141
|
+
out.push({ json: res });
|
|
142
|
+
}
|
|
143
|
+
// UPDATE
|
|
144
|
+
if (operation === 'update') {
|
|
145
|
+
const id = this.getNodeParameter('id', i);
|
|
146
|
+
const pairs = this.getNodeParameter('fields.field', i, []);
|
|
147
|
+
const params = {
|
|
148
|
+
id,
|
|
149
|
+
...Object.fromEntries(pairs
|
|
150
|
+
.filter((p) => p.fieldName)
|
|
151
|
+
.map((p) => [p.fieldName, convertValue(p.fieldValue)])),
|
|
152
|
+
};
|
|
153
|
+
const res = await GenericFunctions_1.civicrmApiRequest.call(this, 'POST', `/civicrm/ajax/api4/${entity}/update`, (0, GenericFunctions_1.api4)(entity, 'update', params));
|
|
154
|
+
out.push({ json: res });
|
|
155
|
+
}
|
|
156
|
+
// DELETE
|
|
157
|
+
if (operation === 'delete') {
|
|
158
|
+
const id = this.getNodeParameter('id', i);
|
|
159
|
+
const res = await GenericFunctions_1.civicrmApiRequest.call(this, 'POST', `/civicrm/ajax/api4/${entity}/delete`, (0, GenericFunctions_1.api4)(entity, 'delete', { id }));
|
|
160
|
+
out.push({ json: res });
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return [out];
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
exports.CiviCrm = CiviCrm;
|
|
167
|
+
/**
|
|
168
|
+
* Convierte string a número, boolean, objeto o deja string
|
|
169
|
+
*/
|
|
170
|
+
function convertValue(val) {
|
|
171
|
+
const t = String(val ?? '').trim();
|
|
172
|
+
if (t === '')
|
|
173
|
+
return '';
|
|
174
|
+
if (t === 'true')
|
|
175
|
+
return true;
|
|
176
|
+
if (t === 'false')
|
|
177
|
+
return false;
|
|
178
|
+
if (/^-?\d+(\.\d+)?$/.test(t))
|
|
179
|
+
return Number(t);
|
|
180
|
+
try {
|
|
181
|
+
const j = JSON.parse(t);
|
|
182
|
+
if (typeof j === 'object')
|
|
183
|
+
return j;
|
|
184
|
+
}
|
|
185
|
+
catch { }
|
|
186
|
+
return val;
|
|
187
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<svg xml:space="preserve" style="max-height: 500px" viewBox="190.4982463465553 39.1683 70.07818371607516 70.33139999999999" y="0px" x="0px" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" id="Layer_1" version="1.1" width="70.07818371607516" height="70.33139999999999">
|
|
2
|
+
<style type="text/css">
|
|
3
|
+
.st0{fill:#086287;}
|
|
4
|
+
.st1{fill:#81C459;}
|
|
5
|
+
</style>
|
|
6
|
+
<g>
|
|
7
|
+
<g>
|
|
8
|
+
<g>
|
|
9
|
+
<path d="M216.26,104.26C216.26,104.26,216.26,104.26,216.26,104.26c-3.77-0.07-5.2-4.43-5.35-4.92l-12.85-42.11
				c-0.76-2.47-0.58-4.46,0.51-5.92c0.71-0.94,2.12-2.04,4.83-1.99c0.99,0.02,1.77,0.19,1.85,0.21l42.78,9.97
				c2.75,0.64,4.44,1.94,5.02,3.85c0.93,3.04-1.65,5.92-1.95,6.24l-29.94,32.12C219.57,103.43,217.91,104.29,216.26,104.26z
				 M203.19,53.73c-0.77-0.01-1.02,0.19-1.06,0.26c-0.22,0.31-0.26,0.44,0.19,1.93l12.85,42.11c0.29,0.9,0.76,1.74,1.18,1.77l0,0
				c0.01,0,0.52,0,1.57-1.13l29.94-32.12c0.55-0.61,1.06-1.6,0.95-1.9c-0.08-0.22-0.43-0.5-1.77-0.81l-42.78-9.97l0,0
				C204.24,53.87,203.7,53.74,203.19,53.73z" class="st0"/>
|
|
10
|
+
</g>
|
|
11
|
+
<g>
|
|
12
|
+
<path d="M211.45,100.83c-1.38,0.51-2.83,0.61-3.96,0.24c0,0,0,0,0,0c-3.57-1.17-3.68-5.74-3.68-6.26l0-41l4.21,0.94
				l0.02,40.15c0.01,0.94,0.25,1.84,0.83,1.94l0,0c0,0,0.3,0.09,1.15-0.3L211.45,100.83z M214.02,94.31l34.62-20.03
				c0.7-0.42,1.53-1.04,1.46-1.54c-0.01-0.07-0.17-0.52-0.92-1.05l2.9-3.3c1.64,1.25,2.47,2.71,2.47,4.35c0,3.17-3.3,5.17-3.68,5.39
				l-35.51,20.4L214.02,94.31z M245.14,69.42l-34.02-19.79c0,0-0.85-0.54-1.34-0.7c-0.73-0.24-1.08,0-1.15,0.05
				c-0.2,0.14-0.27,0.24-0.35,1.24l-4.38-0.82c0.24-1.82,0.95-3.17,2.12-4.03c0.95-0.69,2.62-1.33,5.19-0.5
				c0.94,0.31,1.63,0.7,1.71,0.74l35.39,20.42L245.14,69.42z" class="st1"/>
|
|
13
|
+
</g>
|
|
14
|
+
</g>
|
|
15
|
+
<g>
|
|
16
|
+
<path d="M183.02,66.82c-0.48-0.28-0.86-0.67-1.15-1.15c-0.28-0.48-0.42-1-0.42-1.57c0-0.56,0.14-1.09,0.42-1.57
			s0.66-0.86,1.15-1.15s1-0.42,1.57-0.42s1.09,0.14,1.57,0.42s0.86,0.66,1.15,1.15s0.42,1,0.42,1.57c0,0.57-0.14,1.09-0.42,1.57
			c-0.28,0.48-0.66,0.86-1.15,1.15s-1,0.42-1.57,0.42S183.5,67.1,183.02,66.82z M185.93,66.42c0.41-0.24,0.74-0.57,0.98-0.98
			c0.24-0.41,0.36-0.86,0.36-1.35c0-0.48-0.12-0.93-0.36-1.34c-0.24-0.41-0.57-0.73-0.98-0.98c-0.41-0.24-0.86-0.36-1.35-0.36
			c-0.48,0-0.93,0.12-1.34,0.36c-0.41,0.24-0.73,0.57-0.98,0.98c-0.24,0.41-0.36,0.85-0.36,1.34c0,0.49,0.12,0.94,0.36,1.35
			c0.24,0.41,0.57,0.74,0.98,0.98s0.85,0.36,1.34,0.36C185.07,66.79,185.52,66.66,185.93,66.42z M183.37,65.8
			c-0.06-0.05-0.08-0.12-0.08-0.21v-2.83c0-0.11,0.04-0.21,0.11-0.28s0.17-0.12,0.28-0.12h1.05c0.46,0,0.8,0.1,1.03,0.29
			s0.34,0.45,0.34,0.76c0,0.21-0.06,0.39-0.18,0.53c-0.12,0.14-0.28,0.25-0.46,0.32c0.16,0.06,0.3,0.18,0.42,0.35
			c0.12,0.18,0.18,0.42,0.18,0.74v0.24c0,0.08-0.03,0.15-0.09,0.21c-0.06,0.06-0.13,0.09-0.21,0.09s-0.15-0.03-0.21-0.09
			c-0.06-0.06-0.09-0.13-0.09-0.21v-0.16c0-0.25-0.04-0.46-0.11-0.63c-0.07-0.17-0.25-0.26-0.53-0.26h-0.95v1.06
			c0,0.08-0.03,0.15-0.09,0.21c-0.06,0.06-0.13,0.08-0.21,0.08C183.49,65.88,183.42,65.86,183.37,65.8z M184.7,64.02
			c0.25,0,0.45-0.05,0.6-0.15c0.15-0.1,0.22-0.25,0.22-0.44c0-0.18-0.06-0.32-0.19-0.42c-0.13-0.1-0.34-0.14-0.65-0.14h-0.81v1.15
			H184.7z" class="st0"/>
|
|
17
|
+
</g>
|
|
18
|
+
<g>
|
|
19
|
+
<path d="M31.72,88.55c-2.15-1.18-3.85-2.87-5.08-5.08c-1.23-2.21-1.85-4.79-1.85-7.74s0.62-5.53,1.85-7.74
			c1.23-2.21,2.93-3.9,5.08-5.08c2.15-1.18,4.58-1.77,7.29-1.77c1.84,0,3.49,0.22,4.94,0.65c1.45,0.43,2.89,1.06,4.33,1.87
			c0.6,0.32,0.89,0.84,0.89,1.54c0,0.41-0.15,0.77-0.45,1.08c-0.3,0.31-0.69,0.47-1.18,0.47c-0.27,0-0.51-0.05-0.73-0.16
			c-1.19-0.62-2.36-1.1-3.49-1.42c-1.14-0.32-2.45-0.49-3.94-0.49c-2.33,0-4.31,0.48-5.95,1.44c-1.64,0.96-2.87,2.28-3.7,3.94
			c-0.83,1.67-1.24,3.55-1.24,5.67s0.41,4,1.24,5.67c0.83,1.67,2.06,2.98,3.7,3.94c1.64,0.96,3.62,1.44,5.95,1.44
			c1.49,0,2.8-0.16,3.94-0.49c1.14-0.32,2.3-0.8,3.49-1.42c0.22-0.11,0.46-0.16,0.73-0.16c0.49,0,0.88,0.15,1.18,0.45
			c0.3,0.3,0.45,0.66,0.45,1.1c0,0.7-0.3,1.22-0.89,1.54c-1.44,0.81-2.88,1.44-4.33,1.87c-1.45,0.43-3.09,0.65-4.94,0.65
			C36.3,90.32,33.87,89.73,31.72,88.55z" class="st0"/>
|
|
20
|
+
<path d="M53.47,64.35c-0.41-0.41-0.61-0.89-0.61-1.46v-0.16c0-0.57,0.2-1.06,0.61-1.46c0.41-0.41,0.89-0.61,1.46-0.61
			h0.24c0.57,0,1.06,0.2,1.46,0.61s0.61,0.89,0.61,1.46v0.16c0,0.57-0.2,1.06-0.61,1.46c-0.41,0.41-0.89,0.61-1.46,0.61h-0.24
			C54.37,64.96,53.88,64.76,53.47,64.35z M53.72,89.58c-0.35-0.35-0.53-0.79-0.53-1.3V70.86c0-0.51,0.18-0.96,0.53-1.32
			c0.35-0.37,0.79-0.55,1.3-0.55c0.54,0,0.99,0.18,1.34,0.53c0.35,0.35,0.53,0.8,0.53,1.34v17.43c0,0.51-0.18,0.95-0.55,1.3
			c-0.37,0.35-0.81,0.53-1.32,0.53C54.5,90.11,54.07,89.94,53.72,89.58z" class="st0"/>
|
|
21
|
+
<path d="M68.5,89.69c-0.41-0.28-0.7-0.64-0.89-1.08l-7.07-16.9c-0.14-0.32-0.2-0.61-0.2-0.85
			c0-0.51,0.18-0.96,0.53-1.32c0.35-0.37,0.79-0.55,1.3-0.55c0.35,0,0.68,0.1,1,0.3c0.31,0.2,0.53,0.45,0.67,0.75l6.22,15.76
			l6.22-15.76c0.14-0.3,0.36-0.55,0.67-0.75c0.31-0.2,0.64-0.3,1-0.3c0.51,0,0.95,0.18,1.3,0.55c0.35,0.37,0.53,0.81,0.53,1.32
			c0,0.24-0.07,0.53-0.2,0.85l-7.07,16.9c-0.19,0.43-0.49,0.79-0.89,1.08s-0.85,0.43-1.34,0.43h-0.41
			C69.36,90.11,68.91,89.97,68.5,89.69z" class="st0"/>
|
|
22
|
+
<path d="M83.5,64.35c-0.41-0.41-0.61-0.89-0.61-1.46v-0.16c0-0.57,0.2-1.06,0.61-1.46c0.41-0.41,0.89-0.61,1.46-0.61
			h0.24c0.57,0,1.06,0.2,1.46,0.61s0.61,0.89,0.61,1.46v0.16c0,0.57-0.2,1.06-0.61,1.46c-0.41,0.41-0.89,0.61-1.46,0.61h-0.24
			C84.39,64.96,83.9,64.76,83.5,64.35z M83.74,89.58c-0.35-0.35-0.53-0.79-0.53-1.3V70.86c0-0.51,0.18-0.96,0.53-1.32
			c0.35-0.37,0.79-0.55,1.3-0.55c0.54,0,0.99,0.18,1.34,0.53c0.35,0.35,0.53,0.8,0.53,1.34v17.43c0,0.51-0.18,0.95-0.55,1.3
			c-0.37,0.35-0.81,0.53-1.32,0.53C84.53,90.11,84.09,89.94,83.74,89.58z" class="st0"/>
|
|
23
|
+
<path d="M97.65,88.55c-2.15-1.18-3.85-2.87-5.08-5.08c-1.23-2.21-1.85-4.79-1.85-7.74s0.62-5.53,1.85-7.74
			c1.23-2.21,2.93-3.9,5.08-5.08c2.15-1.18,4.58-1.77,7.29-1.77c1.84,0,3.49,0.22,4.94,0.65c1.45,0.43,2.89,1.06,4.33,1.87
			c0.6,0.32,0.89,0.84,0.89,1.54c0,0.41-0.15,0.77-0.45,1.08c-0.3,0.31-0.69,0.47-1.18,0.47c-0.27,0-0.51-0.05-0.73-0.16
			c-1.19-0.62-2.36-1.1-3.49-1.42c-1.14-0.32-2.45-0.49-3.94-0.49c-2.33,0-4.31,0.48-5.95,1.44c-1.64,0.96-2.87,2.28-3.7,3.94
			c-0.83,1.67-1.24,3.55-1.24,5.67s0.41,4,1.24,5.67c0.83,1.67,2.06,2.98,3.7,3.94c1.64,0.96,3.62,1.44,5.95,1.44
			c1.49,0,2.8-0.16,3.94-0.49c1.14-0.32,2.3-0.8,3.49-1.42c0.22-0.11,0.46-0.16,0.73-0.16c0.49,0,0.88,0.15,1.18,0.45
			c0.3,0.3,0.45,0.66,0.45,1.1c0,0.7-0.3,1.22-0.89,1.54c-1.44,0.81-2.88,1.44-4.33,1.87c-1.45,0.43-3.09,0.65-4.94,0.65
			C102.24,90.32,99.81,89.73,97.65,88.55z" class="st0"/>
|
|
24
|
+
<path d="M119.9,89.58c-0.35-0.35-0.53-0.79-0.53-1.3V63.42c0-0.51,0.18-0.96,0.53-1.32s0.79-0.55,1.3-0.55h9.47
			c3.68,0,6.45,0.76,8.29,2.28c1.84,1.52,2.76,3.51,2.76,5.97c0,1.62-0.45,3.11-1.36,4.45c-0.91,1.34-2.23,2.31-3.96,2.9
			c1.95,0.51,3.28,1.73,4,3.64c0.72,1.91,1.08,3.79,1.08,5.63v1.87c0,0.51-0.18,0.95-0.53,1.3c-0.35,0.35-0.79,0.53-1.3,0.53
			c-0.57,0-1.02-0.17-1.36-0.51c-0.34-0.34-0.51-0.78-0.51-1.32v-1.22c0-1.35-0.12-2.61-0.37-3.76s-0.83-2.18-1.75-3.09
			c-0.92-0.91-2.32-1.36-4.18-1.36h-8.41v9.43c0,0.51-0.18,0.95-0.55,1.3s-0.81,0.53-1.32,0.53
			C120.68,90.11,120.25,89.94,119.9,89.58z M130.42,75.37c2.33,0,4.18-0.46,5.55-1.38c1.37-0.92,2.05-2.22,2.05-3.9
			c0-1.62-0.59-2.87-1.77-3.74c-1.18-0.87-3.19-1.3-6.03-1.3h-7.15v10.32H130.42z" class="st0"/>
|
|
25
|
+
<path d="M146.71,89.58c-0.35-0.35-0.53-0.79-0.53-1.3V64.03c0-0.73,0.26-1.36,0.77-1.89
			c0.51-0.53,1.14-0.79,1.87-0.79h1.34c0.54,0,1.04,0.16,1.48,0.49c0.45,0.33,0.78,0.73,1,1.22l9.22,22.99l9.22-22.99
			c0.22-0.49,0.55-0.89,1-1.22c0.45-0.32,0.94-0.49,1.48-0.49h1.34c0.73,0,1.35,0.26,1.87,0.79c0.51,0.53,0.77,1.16,0.77,1.89v24.25
			c0,0.51-0.18,0.95-0.53,1.3c-0.35,0.35-0.79,0.53-1.3,0.53c-0.52,0-0.96-0.18-1.32-0.53c-0.37-0.35-0.55-0.79-0.55-1.3V65.21
			l-9.38,23.2c-0.22,0.51-0.56,0.93-1.04,1.24c-0.47,0.31-1,0.47-1.56,0.47s-1.09-0.16-1.56-0.47c-0.47-0.31-0.82-0.72-1.04-1.24
			l-9.38-23.2v23.08c0,0.51-0.18,0.95-0.55,1.3s-0.81,0.53-1.32,0.53C147.5,90.11,147.06,89.94,146.71,89.58z" class="st0"/>
|
|
26
|
+
</g>
|
|
27
|
+
</g>
|
|
28
|
+
</svg>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.upsertFields = exports.genericFields = void 0;
|
|
4
|
+
exports.genericFields = [
|
|
5
|
+
{ displayName: 'Return All', name: 'returnAll', type: 'boolean', default: false, displayOptions: { show: { operation: ['getMany'] } } },
|
|
6
|
+
{ displayName: 'Limit', name: 'limit', type: 'number', typeOptions: { minValue: 1, maxValue: 1000 }, default: 100, displayOptions: { show: { operation: ['getMany'], returnAll: [false] } } },
|
|
7
|
+
{ displayName: 'Where (JSON)', name: 'whereJson', type: 'string', default: '', placeholder: `[["first_name","=","Alice"]]`, displayOptions: { show: { operation: ['getMany'] } } },
|
|
8
|
+
];
|
|
9
|
+
exports.upsertFields = [
|
|
10
|
+
{ displayName: 'Fields', name: 'fields', type: 'fixedCollection', typeOptions: { multipleValues: true }, default: {}, options: [{ name: 'field', displayName: 'Field', values: [{ displayName: 'Name', name: 'fieldName', type: 'string', default: '' }, { displayName: 'Value', name: 'fieldValue', type: 'string', default: '' }] }], displayOptions: { show: { operation: ['create', 'update'] } } }
|
|
11
|
+
];
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.operationProp = exports.resourceProp = void 0;
|
|
4
|
+
const RESOURCE_OPTIONS = [
|
|
5
|
+
{ name: 'Contact', value: 'contact' },
|
|
6
|
+
{ name: 'Event', value: 'event' },
|
|
7
|
+
{ name: 'Case', value: 'case' },
|
|
8
|
+
{ name: 'Contribution', value: 'contribution' },
|
|
9
|
+
{ name: 'Membership', value: 'membership' },
|
|
10
|
+
{ name: 'Form Processor', value: 'formProcessor' },
|
|
11
|
+
];
|
|
12
|
+
exports.resourceProp = {
|
|
13
|
+
displayName: 'Resource',
|
|
14
|
+
name: 'resource',
|
|
15
|
+
type: 'options',
|
|
16
|
+
default: 'contact',
|
|
17
|
+
options: RESOURCE_OPTIONS, // sin readonly/as const
|
|
18
|
+
};
|
|
19
|
+
exports.operationProp = {
|
|
20
|
+
displayName: 'Operation',
|
|
21
|
+
name: 'operation',
|
|
22
|
+
type: 'options',
|
|
23
|
+
displayOptions: {
|
|
24
|
+
show: { resource: ['contact', 'event', 'case', 'contribution', 'membership', 'formProcessor'] },
|
|
25
|
+
},
|
|
26
|
+
default: 'get',
|
|
27
|
+
options: [
|
|
28
|
+
{ name: 'Get', value: 'get' },
|
|
29
|
+
{ name: 'Get Many', value: 'getMany' },
|
|
30
|
+
{ name: 'Create', value: 'create' },
|
|
31
|
+
{ name: 'Update', value: 'update' },
|
|
32
|
+
{ name: 'Delete', value: 'delete' },
|
|
33
|
+
// Solo para formProcessor
|
|
34
|
+
{ name: 'Execute', value: 'execute', action: 'Execute FormProcessor', description: 'Run a FormProcessor', },
|
|
35
|
+
], // tipo mutable
|
|
36
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type IExecuteFunctions } from 'n8n-workflow';
|
|
2
|
+
/**
|
|
3
|
+
* Ejecuta una llamada a la API de CiviCRM v4
|
|
4
|
+
*/
|
|
5
|
+
export declare function civicrmApiRequest(this: IExecuteFunctions, method: 'POST', path: string, body: Record<string, unknown>): Promise<any>;
|
|
6
|
+
/**
|
|
7
|
+
* Devuelve el formato estándar para una llamada API4
|
|
8
|
+
*/
|
|
9
|
+
export declare function api4(entity: string, action: string, params?: Record<string, unknown>): {
|
|
10
|
+
entity: string;
|
|
11
|
+
action: string;
|
|
12
|
+
params: Record<string, unknown>;
|
|
13
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.api4 = exports.civicrmApiRequest = void 0;
|
|
4
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
|
+
/**
|
|
6
|
+
* Ejecuta una llamada a la API de CiviCRM v4
|
|
7
|
+
*/
|
|
8
|
+
async function civicrmApiRequest(method, path, body) {
|
|
9
|
+
const { baseUrl, apiToken } = (await this.getCredentials('civiCrmApi'));
|
|
10
|
+
const options = {
|
|
11
|
+
method,
|
|
12
|
+
url: `${baseUrl}${path}`,
|
|
13
|
+
headers: {
|
|
14
|
+
'Content-Type': 'application/json',
|
|
15
|
+
'X-Civi-Auth': `Bearer ${apiToken}`,
|
|
16
|
+
},
|
|
17
|
+
body,
|
|
18
|
+
json: true,
|
|
19
|
+
};
|
|
20
|
+
try {
|
|
21
|
+
const response = await this.helpers.httpRequest(options);
|
|
22
|
+
if (response?.is_error) {
|
|
23
|
+
throw new n8n_workflow_1.NodeApiError(this.getNode(), response);
|
|
24
|
+
}
|
|
25
|
+
return response;
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
throw new n8n_workflow_1.NodeApiError(this.getNode(), error);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.civicrmApiRequest = civicrmApiRequest;
|
|
32
|
+
/**
|
|
33
|
+
* Devuelve el formato estándar para una llamada API4
|
|
34
|
+
*/
|
|
35
|
+
function api4(entity, action, params = {}) {
|
|
36
|
+
return { entity, action, params };
|
|
37
|
+
}
|
|
38
|
+
exports.api4 = api4;
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ixiam/n8n-nodes-civicrm",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "CiviCRM API v4 for n8n",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"n8n-community-node-package",
|
|
8
|
+
"civicrm",
|
|
9
|
+
"api4"
|
|
10
|
+
],
|
|
11
|
+
"main": "dist/index.js",
|
|
12
|
+
"types": "dist/index.d.ts",
|
|
13
|
+
"files": [
|
|
14
|
+
"dist",
|
|
15
|
+
"icons",
|
|
16
|
+
"README.md",
|
|
17
|
+
"LICENSE"
|
|
18
|
+
],
|
|
19
|
+
"n8n": {
|
|
20
|
+
"nodes": [
|
|
21
|
+
"dist/nodes/CiviCrm/CiviCrm.node.js"
|
|
22
|
+
],
|
|
23
|
+
"credentials": [
|
|
24
|
+
"dist/credentials/CiviCrmApi.credentials.js"
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public"
|
|
29
|
+
},
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://git.ixiam.com/dev/research.git"
|
|
33
|
+
},
|
|
34
|
+
"bugs": {
|
|
35
|
+
"url": "https://git.ixiam.com/dev/research/issues"
|
|
36
|
+
},
|
|
37
|
+
"homepage": "https://git.ixiam.com/dev/research#readme",
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@n8n/node-cli": "0.11.0",
|
|
40
|
+
"@types/node": "^20.11.30",
|
|
41
|
+
"@typescript-eslint/eslint-plugin": "6.21.0",
|
|
42
|
+
"@typescript-eslint/parser": "6.21.0",
|
|
43
|
+
"eslint": "8.57.0",
|
|
44
|
+
"eslint-plugin-n8n-nodes-base": "^1.16.3",
|
|
45
|
+
"n8n-core": "^1",
|
|
46
|
+
"n8n-workflow": "^1",
|
|
47
|
+
"typescript": "5.3.3"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"dev": "n8n-node dev",
|
|
51
|
+
"build": "n8n-node build",
|
|
52
|
+
"lint": "n8n-node lint",
|
|
53
|
+
"release": "n8n-node release"
|
|
54
|
+
}
|
|
55
|
+
}
|