@limetech/n8n-nodes-lime 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.
Files changed (194) hide show
  1. package/.eslintrc.js +58 -0
  2. package/.github/copilot-instructions.md +20 -0
  3. package/.github/workflows/publish.yml +34 -0
  4. package/README.md +79 -0
  5. package/credentials/LimeCrmApi.credentials.ts +57 -0
  6. package/credentials/LimeGoApi.credentials.ts +31 -0
  7. package/dist/credentials/LimeCrmApi.credentials.d.ts +9 -0
  8. package/dist/credentials/LimeCrmApi.credentials.js +53 -0
  9. package/dist/credentials/LimeCrmApi.credentials.js.map +1 -0
  10. package/dist/credentials/LimeGoApi.credentials.d.ts +15 -0
  11. package/dist/credentials/LimeGoApi.credentials.js +32 -0
  12. package/dist/credentials/LimeGoApi.credentials.js.map +1 -0
  13. package/dist/nodes/lime-crm/GenericTypes.d.ts +80 -0
  14. package/dist/nodes/lime-crm/GenericTypes.js +7 -0
  15. package/dist/nodes/lime-crm/GenericTypes.js.map +1 -0
  16. package/dist/nodes/lime-crm/LimeCrm.node.json +18 -0
  17. package/dist/nodes/lime-crm/LimeCrmNode.node.d.ts +17 -0
  18. package/dist/nodes/lime-crm/LimeCrmNode.node.js +114 -0
  19. package/dist/nodes/lime-crm/LimeCrmNode.node.js.map +1 -0
  20. package/dist/nodes/lime-crm/LimeCrmTrigger/LimeCrmTrigger.node.d.ts +17 -0
  21. package/dist/nodes/lime-crm/LimeCrmTrigger/LimeCrmTrigger.node.js +408 -0
  22. package/dist/nodes/lime-crm/LimeCrmTrigger/LimeCrmTrigger.node.js.map +1 -0
  23. package/dist/nodes/lime-crm/LimeCrmTrigger.node.d.ts +17 -0
  24. package/dist/nodes/lime-crm/LimeCrmTrigger.node.js +439 -0
  25. package/dist/nodes/lime-crm/LimeCrmTrigger.node.js.map +1 -0
  26. package/dist/nodes/lime-crm/lime-crm.svg +1 -0
  27. package/dist/nodes/lime-crm/methods/getAllSortableFields.d.ts +7 -0
  28. package/dist/nodes/lime-crm/methods/getAllSortableFields.js +53 -0
  29. package/dist/nodes/lime-crm/methods/getAllSortableFields.js.map +1 -0
  30. package/dist/nodes/lime-crm/methods/getLimeTypeProperties.d.ts +3 -0
  31. package/dist/nodes/lime-crm/methods/getLimeTypeProperties.js +40 -0
  32. package/dist/nodes/lime-crm/methods/getLimeTypeProperties.js.map +1 -0
  33. package/dist/nodes/lime-crm/methods/getLimeTypeRelations.d.ts +7 -0
  34. package/dist/nodes/lime-crm/methods/getLimeTypeRelations.js +30 -0
  35. package/dist/nodes/lime-crm/methods/getLimeTypeRelations.js.map +1 -0
  36. package/dist/nodes/lime-crm/methods/getLimeTypes.d.ts +3 -0
  37. package/dist/nodes/lime-crm/methods/getLimeTypes.js +33 -0
  38. package/dist/nodes/lime-crm/methods/getLimeTypes.js.map +1 -0
  39. package/dist/nodes/lime-crm/methods/getRelatedTypeProperties.d.ts +7 -0
  40. package/dist/nodes/lime-crm/methods/getRelatedTypeProperties.js +39 -0
  41. package/dist/nodes/lime-crm/methods/getRelatedTypeProperties.js.map +1 -0
  42. package/dist/nodes/lime-crm/methods/index.d.ts +5 -0
  43. package/dist/nodes/lime-crm/methods/index.js +14 -0
  44. package/dist/nodes/lime-crm/methods/index.js.map +1 -0
  45. package/dist/nodes/lime-crm/resources/limeObject/commonFields.d.ts +4 -0
  46. package/dist/nodes/lime-crm/resources/limeObject/commonFields.js +165 -0
  47. package/dist/nodes/lime-crm/resources/limeObject/commonFields.js.map +1 -0
  48. package/dist/nodes/lime-crm/resources/limeObject/index.d.ts +6 -0
  49. package/dist/nodes/lime-crm/resources/limeObject/index.js +79 -0
  50. package/dist/nodes/lime-crm/resources/limeObject/index.js.map +1 -0
  51. package/dist/nodes/lime-crm/resources/limeObject/operations/common.operation.d.ts +2 -0
  52. package/dist/nodes/lime-crm/resources/limeObject/operations/common.operation.js +36 -0
  53. package/dist/nodes/lime-crm/resources/limeObject/operations/common.operation.js.map +1 -0
  54. package/dist/nodes/lime-crm/resources/limeObject/operations/create.operation.d.ts +9 -0
  55. package/dist/nodes/lime-crm/resources/limeObject/operations/create.operation.js +234 -0
  56. package/dist/nodes/lime-crm/resources/limeObject/operations/create.operation.js.map +1 -0
  57. package/dist/nodes/lime-crm/resources/limeObject/operations/delete.operation.d.ts +9 -0
  58. package/dist/nodes/lime-crm/resources/limeObject/operations/delete.operation.js +136 -0
  59. package/dist/nodes/lime-crm/resources/limeObject/operations/delete.operation.js.map +1 -0
  60. package/dist/nodes/lime-crm/resources/limeObject/operations/get.operation.d.ts +9 -0
  61. package/dist/nodes/lime-crm/resources/limeObject/operations/get.operation.js +125 -0
  62. package/dist/nodes/lime-crm/resources/limeObject/operations/get.operation.js.map +1 -0
  63. package/dist/nodes/lime-crm/resources/limeObject/operations/getAll.operation.d.ts +3 -0
  64. package/dist/nodes/lime-crm/resources/limeObject/operations/getAll.operation.js +212 -0
  65. package/dist/nodes/lime-crm/resources/limeObject/operations/getAll.operation.js.map +1 -0
  66. package/dist/nodes/lime-crm/resources/limeObject/operations/search.operation.d.ts +9 -0
  67. package/dist/nodes/lime-crm/resources/limeObject/operations/search.operation.js +232 -0
  68. package/dist/nodes/lime-crm/resources/limeObject/operations/search.operation.js.map +1 -0
  69. package/dist/nodes/lime-crm/resources/limeObject/operations/update.operation.d.ts +9 -0
  70. package/dist/nodes/lime-crm/resources/limeObject/operations/update.operation.js +186 -0
  71. package/dist/nodes/lime-crm/resources/limeObject/operations/update.operation.js.map +1 -0
  72. package/dist/nodes/lime-crm/resources/limeType/index.d.ts +6 -0
  73. package/dist/nodes/lime-crm/resources/limeType/index.js +81 -0
  74. package/dist/nodes/lime-crm/resources/limeType/index.js.map +1 -0
  75. package/dist/nodes/lime-crm/resources/limeType/operations/getProperties.operation.d.ts +9 -0
  76. package/dist/nodes/lime-crm/resources/limeType/operations/getProperties.operation.js +112 -0
  77. package/dist/nodes/lime-crm/resources/limeType/operations/getProperties.operation.js.map +1 -0
  78. package/dist/nodes/lime-crm/resources/limeType/operations/getRelations.operation.d.ts +9 -0
  79. package/dist/nodes/lime-crm/resources/limeType/operations/getRelations.operation.js +112 -0
  80. package/dist/nodes/lime-crm/resources/limeType/operations/getRelations.operation.js.map +1 -0
  81. package/dist/nodes/lime-crm/resources/limeType/operations/getType.operation.d.ts +9 -0
  82. package/dist/nodes/lime-crm/resources/limeType/operations/getType.operation.js +70 -0
  83. package/dist/nodes/lime-crm/resources/limeType/operations/getType.operation.js.map +1 -0
  84. package/dist/nodes/lime-crm/resources/limeType/operations/listTypes.operation.d.ts +9 -0
  85. package/dist/nodes/lime-crm/resources/limeType/operations/listTypes.operation.js +86 -0
  86. package/dist/nodes/lime-crm/resources/limeType/operations/listTypes.operation.js.map +1 -0
  87. package/dist/nodes/lime-crm/resources/queryApi/index.d.ts +6 -0
  88. package/dist/nodes/lime-crm/resources/queryApi/index.js +57 -0
  89. package/dist/nodes/lime-crm/resources/queryApi/index.js.map +1 -0
  90. package/dist/nodes/lime-crm/resources/queryApi/operations/executeQuery.operation.d.ts +9 -0
  91. package/dist/nodes/lime-crm/resources/queryApi/operations/executeQuery.operation.js +559 -0
  92. package/dist/nodes/lime-crm/resources/queryApi/operations/executeQuery.operation.js.map +1 -0
  93. package/dist/nodes/lime-crm/transport/index.d.ts +2 -0
  94. package/dist/nodes/lime-crm/transport/index.js +50 -0
  95. package/dist/nodes/lime-crm/transport/index.js.map +1 -0
  96. package/dist/nodes/lime-go/LimeGo.node.d.ts +8 -0
  97. package/dist/nodes/lime-go/LimeGo.node.js +123 -0
  98. package/dist/nodes/lime-go/LimeGo.node.js.map +1 -0
  99. package/dist/nodes/lime-go/actions/organization/get.operation.d.ts +5 -0
  100. package/dist/nodes/lime-go/actions/organization/get.operation.js +39 -0
  101. package/dist/nodes/lime-go/actions/organization/get.operation.js.map +1 -0
  102. package/dist/nodes/lime-go/actions/organization/getByExternalKey.operation.d.ts +5 -0
  103. package/dist/nodes/lime-go/actions/organization/getByExternalKey.operation.js +54 -0
  104. package/dist/nodes/lime-go/actions/organization/getByExternalKey.operation.js.map +1 -0
  105. package/dist/nodes/lime-go/actions/organization/index.d.ts +7 -0
  106. package/dist/nodes/lime-go/actions/organization/index.js +92 -0
  107. package/dist/nodes/lime-go/actions/organization/index.js.map +1 -0
  108. package/dist/nodes/lime-go/actions/organization/organizationFields.d.ts +2 -0
  109. package/dist/nodes/lime-go/actions/organization/organizationFields.js +162 -0
  110. package/dist/nodes/lime-go/actions/organization/organizationFields.js.map +1 -0
  111. package/dist/nodes/lime-go/actions/organization/search.operation.d.ts +5 -0
  112. package/dist/nodes/lime-go/actions/organization/search.operation.js +70 -0
  113. package/dist/nodes/lime-go/actions/organization/search.operation.js.map +1 -0
  114. package/dist/nodes/lime-go/actions/organization/update.operation.d.ts +5 -0
  115. package/dist/nodes/lime-go/actions/organization/update.operation.js +125 -0
  116. package/dist/nodes/lime-go/actions/organization/update.operation.js.map +1 -0
  117. package/dist/nodes/lime-go/actions/person/createMail.operation.d.ts +7 -0
  118. package/dist/nodes/lime-go/actions/person/createMail.operation.js +130 -0
  119. package/dist/nodes/lime-go/actions/person/createMail.operation.js.map +1 -0
  120. package/dist/nodes/lime-go/actions/person/get.operation.d.ts +7 -0
  121. package/dist/nodes/lime-go/actions/person/get.operation.js +45 -0
  122. package/dist/nodes/lime-go/actions/person/get.operation.js.map +1 -0
  123. package/dist/nodes/lime-go/actions/person/index.d.ts +7 -0
  124. package/dist/nodes/lime-go/actions/person/index.js +92 -0
  125. package/dist/nodes/lime-go/actions/person/index.js.map +1 -0
  126. package/dist/nodes/lime-go/actions/person/personFields.d.ts +2 -0
  127. package/dist/nodes/lime-go/actions/person/personFields.js +134 -0
  128. package/dist/nodes/lime-go/actions/person/personFields.js.map +1 -0
  129. package/dist/nodes/lime-go/actions/person/search.operation.d.ts +7 -0
  130. package/dist/nodes/lime-go/actions/person/search.operation.js +81 -0
  131. package/dist/nodes/lime-go/actions/person/search.operation.js.map +1 -0
  132. package/dist/nodes/lime-go/actions/person/update.operation.d.ts +7 -0
  133. package/dist/nodes/lime-go/actions/person/update.operation.js +104 -0
  134. package/dist/nodes/lime-go/actions/person/update.operation.js.map +1 -0
  135. package/dist/nodes/lime-go/lime-go.svg +1 -0
  136. package/dist/nodes/lime-go/transport/graphqlRequest.d.ts +2 -0
  137. package/dist/nodes/lime-go/transport/graphqlRequest.js +23 -0
  138. package/dist/nodes/lime-go/transport/graphqlRequest.js.map +1 -0
  139. package/dist/nodes/lime-go/transport/transport.d.ts +3 -0
  140. package/dist/nodes/lime-go/transport/transport.js +58 -0
  141. package/dist/nodes/lime-go/transport/transport.js.map +1 -0
  142. package/dist/nodes/lime-go/triggers/webhook.d.ts +10 -0
  143. package/dist/nodes/lime-go/triggers/webhook.js +92 -0
  144. package/dist/nodes/lime-go/triggers/webhook.js.map +1 -0
  145. package/dist/package.json +49 -0
  146. package/dist/tsconfig.tsbuildinfo +1 -0
  147. package/docker-compose.yml +44 -0
  148. package/index.js +3 -0
  149. package/nodes/lime-crm/GenericTypes.ts +114 -0
  150. package/nodes/lime-crm/LimeCrm.node.json +18 -0
  151. package/nodes/lime-crm/LimeCrmNode.node.ts +154 -0
  152. package/nodes/lime-crm/LimeCrmTrigger/LimeCrmTrigger.node.ts +461 -0
  153. package/nodes/lime-crm/LimeCrmTrigger.node.ts +505 -0
  154. package/nodes/lime-crm/lime-crm.svg +1 -0
  155. package/nodes/lime-crm/methods/getAllSortableFields.ts +73 -0
  156. package/nodes/lime-crm/methods/getLimeTypeProperties.ts +48 -0
  157. package/nodes/lime-crm/methods/getLimeTypeRelations.ts +32 -0
  158. package/nodes/lime-crm/methods/getLimeTypes.ts +33 -0
  159. package/nodes/lime-crm/methods/getRelatedTypeProperties.ts +47 -0
  160. package/nodes/lime-crm/methods/index.ts +5 -0
  161. package/nodes/lime-crm/resources/limeObject/commonFields.ts +179 -0
  162. package/nodes/lime-crm/resources/limeObject/index.ts +64 -0
  163. package/nodes/lime-crm/resources/limeObject/operations/common.operation.ts +35 -0
  164. package/nodes/lime-crm/resources/limeObject/operations/create.operation.ts +234 -0
  165. package/nodes/lime-crm/resources/limeObject/operations/delete.operation.ts +136 -0
  166. package/nodes/lime-crm/resources/limeObject/operations/get.operation.ts +124 -0
  167. package/nodes/lime-crm/resources/limeObject/operations/getAll.operation.ts +242 -0
  168. package/nodes/lime-crm/resources/limeObject/operations/search.operation.ts +242 -0
  169. package/nodes/lime-crm/resources/limeObject/operations/update.operation.ts +201 -0
  170. package/nodes/lime-crm/resources/limeType/index.ts +66 -0
  171. package/nodes/lime-crm/resources/limeType/operations/getProperties.operation.ts +105 -0
  172. package/nodes/lime-crm/resources/limeType/operations/getRelations.operation.ts +105 -0
  173. package/nodes/lime-crm/resources/limeType/operations/getType.operation.ts +58 -0
  174. package/nodes/lime-crm/resources/limeType/operations/listTypes.operation.ts +76 -0
  175. package/nodes/lime-crm/resources/queryApi/index.ts +42 -0
  176. package/nodes/lime-crm/resources/queryApi/operations/executeQuery.operation.ts +605 -0
  177. package/nodes/lime-crm/transport/index.ts +74 -0
  178. package/nodes/lime-go/LimeGo.node.ts +146 -0
  179. package/nodes/lime-go/actions/organization/get.operation.ts +42 -0
  180. package/nodes/lime-go/actions/organization/getByExternalKey.operation.ts +57 -0
  181. package/nodes/lime-go/actions/organization/index.ts +69 -0
  182. package/nodes/lime-go/actions/organization/organizationFields.ts +160 -0
  183. package/nodes/lime-go/actions/organization/search.operation.ts +73 -0
  184. package/nodes/lime-go/actions/organization/update.operation.ts +140 -0
  185. package/nodes/lime-go/actions/person/createMail.operation.ts +140 -0
  186. package/nodes/lime-go/actions/person/get.operation.ts +51 -0
  187. package/nodes/lime-go/actions/person/index.ts +69 -0
  188. package/nodes/lime-go/actions/person/personFields.ts +132 -0
  189. package/nodes/lime-go/actions/person/search.operation.ts +88 -0
  190. package/nodes/lime-go/actions/person/update.operation.ts +122 -0
  191. package/nodes/lime-go/lime-go.svg +1 -0
  192. package/nodes/lime-go/transport/graphqlRequest.ts +30 -0
  193. package/package.json +50 -0
  194. package/tsconfig.json +30 -0
@@ -0,0 +1,505 @@
1
+ import {
2
+ IHookFunctions,
3
+ IWebhookFunctions,
4
+ IDataObject,
5
+ INodeType,
6
+ INodeTypeDescription,
7
+ IWebhookResponseData,
8
+ NodeOperationError,
9
+ ILoadOptionsFunctions,
10
+ INodePropertyOptions,
11
+ INodeExecutionData,
12
+ NodeConnectionType,
13
+ LoggerProxy as Logger
14
+ } from 'n8n-workflow';
15
+
16
+ import { IWebhookObject, IWebhookEventData } from './GenericTypes';
17
+ import * as crypto from 'crypto';
18
+
19
+ export class LimeCrmTrigger implements INodeType {
20
+ description: INodeTypeDescription = {
21
+ displayName: 'Lime CRM Trigger',
22
+ name: 'limeCrmTrigger',
23
+ icon: 'file:lime.svg',
24
+ group: ['trigger'],
25
+ version: 1,
26
+ description: 'Handle Lime CRM webhook events',
27
+ defaults: {
28
+ name: 'Lime CRM Trigger',
29
+ },
30
+ inputs: [],
31
+ outputs: [NodeConnectionType.Main],
32
+ credentials: [
33
+ {
34
+ name: 'limeCrmApi',
35
+ required: true,
36
+ },
37
+ ],
38
+ webhooks: [
39
+ {
40
+ name: 'default',
41
+ httpMethod: 'POST',
42
+ responseMode: 'onReceived',
43
+ path: 'webhook',
44
+ },
45
+ ],
46
+ properties: [
47
+ {
48
+ displayName: 'Events',
49
+ name: 'events',
50
+ type: 'fixedCollection',
51
+ typeOptions: {
52
+ multipleValues: true,
53
+ required: true,
54
+ },
55
+ default: {},
56
+ placeholder: 'Add Event',
57
+ description: 'Events to subscribe to',
58
+ options: [
59
+ {
60
+ name: 'event',
61
+ displayName: 'Event',
62
+ values: [
63
+ {
64
+ displayName: 'Lime Type',
65
+ name: 'limeType',
66
+ type: 'options',
67
+ typeOptions: {
68
+ loadOptionsMethod: 'getLimeTypes',
69
+ },
70
+ default: '',
71
+ description: 'Lime Type to subscribe to events for',
72
+ },
73
+ {
74
+ displayName: 'Event Type',
75
+ name: 'eventType',
76
+ type: 'options',
77
+ options: [
78
+ {
79
+ name: 'New',
80
+ value: 'new',
81
+ description: 'When a new record is created',
82
+ },
83
+ {
84
+ name: 'Update',
85
+ value: 'update',
86
+ description: 'When a record is updated',
87
+ },
88
+ {
89
+ name: 'Delete',
90
+ value: 'delete',
91
+ description: 'When a record is deleted',
92
+ },
93
+ ],
94
+ default: 'new',
95
+ description: 'Type of event to subscribe to',
96
+ },
97
+ ],
98
+ },
99
+ ],
100
+ },
101
+ {
102
+ displayName: 'Name',
103
+ name: 'name',
104
+ type: 'string',
105
+ default: '',
106
+ placeholder: 'my-lime-webhook',
107
+ required: true,
108
+ description: 'Name for this webhook subscription',
109
+ },
110
+ {
111
+ displayName: 'Options',
112
+ name: 'options',
113
+ type: 'collection',
114
+ placeholder: 'Add Option',
115
+ default: {},
116
+ options: [
117
+ {
118
+ displayName: 'Include Headers',
119
+ name: 'includeHeaders',
120
+ type: 'fixedCollection',
121
+ typeOptions: {
122
+ multipleValues: true,
123
+ },
124
+ default: {},
125
+ placeholder: 'Add Header',
126
+ description: 'Headers to add to webhook requests',
127
+ options: [
128
+ {
129
+ name: 'header',
130
+ displayName: 'Header',
131
+ values: [
132
+ {
133
+ displayName: 'Name',
134
+ name: 'name',
135
+ type: 'string',
136
+ default: '',
137
+ description: 'Name of the header',
138
+ },
139
+ {
140
+ displayName: 'Value',
141
+ name: 'value',
142
+ type: 'string',
143
+ default: '',
144
+ description: 'Value of the header',
145
+ },
146
+ {
147
+ displayName: 'Is Secret',
148
+ name: 'isSecret',
149
+ type: 'boolean',
150
+ default: false,
151
+ description: 'Whether this value is a secret',
152
+ },
153
+ ],
154
+ },
155
+ ],
156
+ },
157
+ {
158
+ displayName: 'Secret',
159
+ name: 'secret',
160
+ type: 'string',
161
+ typeOptions: {
162
+ password: true,
163
+ },
164
+ default: '',
165
+ description: 'Secret to verify the authenticity of received data',
166
+ },
167
+ ],
168
+ },
169
+ ],
170
+ };
171
+
172
+ methods = {
173
+ loadOptions: {
174
+ // Load available Lime types
175
+ async getLimeTypes(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
176
+ const returnData: INodePropertyOptions[] = [];
177
+
178
+ try {
179
+ // Get credentials for the API
180
+ const credentials = await this.getCredentials('limeCrmApi');
181
+
182
+ if (!credentials) {
183
+ throw new Error('No credentials provided');
184
+ }
185
+
186
+ const endpoint = '/api/v1/limetype/';
187
+
188
+ // Make sure baseURL is properly configured
189
+ const options = {
190
+ method: 'GET' as 'GET',
191
+ uri: endpoint,
192
+ json: true,
193
+ baseURL: credentials.url as string, // Add the base URL from credentials
194
+ headers: {
195
+ 'X-API-Key': credentials.apiKey as string,
196
+ 'Accept': 'application/json',
197
+ },
198
+ };
199
+
200
+ const response = await this.helpers.requestWithAuthentication.call(
201
+ this,
202
+ 'limeCrmApi',
203
+ options,
204
+ );
205
+
206
+ if (response._links && response._links.limetypes) {
207
+ // Parse response to extract lime types
208
+ for (const limeType of response._links.limetypes) {
209
+ if (limeType.name) {
210
+ returnData.push({
211
+ name: limeType.name,
212
+ value: limeType.name,
213
+ });
214
+ }
215
+ }
216
+ }
217
+
218
+ return returnData;
219
+ } catch (error) {
220
+ throw new NodeOperationError(this.getNode(), `Failed to load Lime Types: ${error}`);
221
+ }
222
+ },
223
+ },
224
+ };
225
+
226
+ webhookMethods = {
227
+ default: {
228
+ async checkExists(this: IHookFunctions): Promise<boolean> {
229
+ const nodeId = this.getNode().id;
230
+ const workflowId = this.getWorkflow().id;
231
+ const workflowName = this.getWorkflow().name;
232
+ const webhookData = this.getWorkflowStaticData('node');
233
+ const webhookUrl = this.getNodeWebhookUrl('default');
234
+
235
+ // If we have a webhook ID stored, check if it still exists
236
+ if (webhookData.webhookId) {
237
+ try {
238
+ // Get credentials for the API
239
+ const credentials = await this.getCredentials('limeCrmApi');
240
+ if (!credentials) {
241
+ throw new Error('No credentials provided');
242
+ }
243
+
244
+ // Fetch the webhook to see if it exists
245
+ const currentWebhook = await this.helpers.requestWithAuthentication.call(
246
+ this,
247
+ 'limeCrmApi',
248
+ {
249
+ method: 'GET',
250
+ uri: `/api/v1/subscription/${webhookData.webhookId}/`,
251
+ json: true,
252
+ baseURL: credentials.url as string,
253
+ headers: {
254
+ 'X-API-Key': credentials.apiKey as string,
255
+ 'Accept': 'application/json',
256
+ },
257
+ },
258
+ );
259
+
260
+ // Check if the webhook exists and has the right URL
261
+ if (currentWebhook && currentWebhook.target_url === webhookUrl) {
262
+ Logger.debug(`Webhook exists: ${webhookData.webhookId}`, { webhookId: webhookData.webhookId, nodeId, workflowId, workflowName });
263
+ return true;
264
+ }
265
+ } catch (error) {
266
+ // If we get an error, the webhook likely doesn't exist
267
+ Logger.warn(`Webhook check failed: ${error}`, { webhookId: webhookData.webhookId, nodeId, workflowId, workflowName, error });
268
+ delete webhookData.webhookId;
269
+ return false;
270
+ }
271
+ }
272
+
273
+ return false;
274
+ },
275
+
276
+ async create(this: IHookFunctions): Promise<boolean> {
277
+ const nodeId = this.getNode().id;
278
+ const workflowId = this.getWorkflow().id;
279
+ const workflowName = this.getWorkflow().name;
280
+ const webhookData = this.getWorkflowStaticData('node');
281
+ const webhookUrl = this.getNodeWebhookUrl('default');
282
+
283
+ if (!webhookUrl) {
284
+ throw new NodeOperationError(this.getNode(), 'No webhook URL was returned by the system');
285
+ }
286
+
287
+ const name = this.getNodeParameter('name') as string;
288
+ const eventsCollection = this.getNodeParameter('events.event', []) as Array<{ limeType: string, eventType: string }>;
289
+ const options = this.getNodeParameter('options', {}) as IDataObject;
290
+
291
+ // Get credentials for the API
292
+ const credentials = await this.getCredentials('limeCrmApi');
293
+ if (!credentials) {
294
+ throw new Error('No credentials provided');
295
+ }
296
+
297
+ // Format events array for the Lime CRM API format
298
+ const events: string[] = [];
299
+ for (const eventItem of eventsCollection) {
300
+ events.push(`${eventItem.limeType}.${eventItem.eventType}`);
301
+ }
302
+
303
+ // Sort events for consistent comparison
304
+ events.sort();
305
+
306
+ // Format headers if they exist
307
+ const headersCollection = (options.includeHeaders as IDataObject || {}).header as Array<{ name: string; value: string; isSecret: boolean }> || [];
308
+ const headers: Array<{ name: string; value: string; secret_value?: string; type: string }> = [];
309
+
310
+ for (const header of headersCollection) {
311
+ if (header.isSecret) {
312
+ headers.push({
313
+ name: header.name,
314
+ value: '',
315
+ secret_value: header.value,
316
+ type: 'text',
317
+ });
318
+ } else {
319
+ headers.push({
320
+ name: header.name,
321
+ value: header.value,
322
+ type: 'text',
323
+ });
324
+ }
325
+ }
326
+
327
+ // Prepare request body
328
+ const body: IWebhookObject = {
329
+ name,
330
+ events,
331
+ target_url: webhookUrl,
332
+ enabled: true,
333
+ headers,
334
+ };
335
+
336
+ // If a secret is provided, add it
337
+ const secret = options.secret as string;
338
+ if (secret) {
339
+ body.secret = secret;
340
+ }
341
+
342
+ try {
343
+ // Create the webhook
344
+ Logger.info('Creating new webhook subscription', { nodeId, workflowId, workflowName });
345
+ const webhookResponse = await this.helpers.requestWithAuthentication.call(
346
+ this,
347
+ 'limeCrmApi',
348
+ {
349
+ method: 'POST',
350
+ uri: '/api/v1/subscription/',
351
+ body,
352
+ json: true,
353
+ baseURL: credentials.url as string,
354
+ headers: {
355
+ 'X-API-Key': credentials.apiKey as string,
356
+ 'Accept': 'application/json',
357
+ 'Content-Type': 'application/json',
358
+ },
359
+ },
360
+ );
361
+
362
+ // Store webhook ID in workflow data for later use
363
+ if (webhookResponse.id) {
364
+ webhookData.webhookId = webhookResponse.id;
365
+ Logger.info(`Created webhook with ID: ${webhookResponse.id}`, { webhookId: webhookResponse.id, nodeId, workflowId, workflowName });
366
+ return true;
367
+ }
368
+
369
+ throw new NodeOperationError(this.getNode(), 'Webhook creation failed: No ID was returned');
370
+ } catch (error) {
371
+ Logger.error(`Webhook creation failed: ${error}`, { nodeId, workflowId, workflowName, error });
372
+ throw new NodeOperationError(this.getNode(), `Webhook creation failed: ${error}`);
373
+ }
374
+ },
375
+
376
+ async delete(this: IHookFunctions): Promise<boolean> {
377
+ const nodeId = this.getNode().id;
378
+ const workflowId = this.getWorkflow().id;
379
+ const workflowName = this.getWorkflow().name;
380
+ const webhookData = this.getWorkflowStaticData('node');
381
+ const webhookId = webhookData.webhookId as string | undefined;
382
+
383
+ if (webhookId !== undefined) {
384
+ try {
385
+ Logger.info(`Deleting webhook with ID: ${webhookId}`, { webhookId, nodeId, workflowId, workflowName });
386
+ // Get credentials for the API
387
+ const credentials = await this.getCredentials('limeCrmApi');
388
+ if (!credentials) {
389
+ throw new Error('No credentials provided');
390
+ }
391
+
392
+ await this.helpers.requestWithAuthentication.call(
393
+ this,
394
+ 'limeCrmApi',
395
+ {
396
+ method: 'DELETE' as 'DELETE',
397
+ uri: `/api/v1/subscription/${webhookId}/`,
398
+ json: true,
399
+ baseURL: credentials.url as string,
400
+ headers: {
401
+ 'X-API-Key': credentials.apiKey as string,
402
+ 'Accept': 'application/json',
403
+ },
404
+ },
405
+ );
406
+
407
+ delete webhookData.webhookId;
408
+ Logger.info('Webhook deleted successfully', { webhookId, nodeId, workflowId, workflowName });
409
+ return true;
410
+ } catch (error) {
411
+ Logger.error(`Webhook deletion failed: ${error}`, { webhookId, nodeId, workflowId, workflowName, error });
412
+ return false;
413
+ }
414
+ }
415
+
416
+ return true;
417
+ },
418
+ },
419
+ };
420
+
421
+ async webhook(this: IWebhookFunctions): Promise<IWebhookResponseData> {
422
+ const nodeId = this.getNode().id;
423
+ const workflowId = this.getWorkflow().id;
424
+ const workflowName = this.getWorkflow().name;
425
+
426
+ Logger.info('Webhook received. Starting webhook processing...', { nodeId, workflowId, workflowName });
427
+ try {
428
+ const options = this.getNodeParameter('options', {}) as IDataObject;
429
+ const secret = options.secret as string;
430
+
431
+ const bodyData = this.getBodyData();
432
+ const headerData = this.getHeaderData();
433
+
434
+ // If a secret is set, verify the signature
435
+ if (secret && headerData['x-lime-signature']) {
436
+ Logger.debug('Verifying webhook signature...', { nodeId, workflowId, workflowName });
437
+ const signature = headerData['x-lime-signature'] as string;
438
+
439
+ const req = this.getRequestObject();
440
+ const rawBody = req.rawBody || JSON.stringify(bodyData);
441
+
442
+ // Create the expected signature
443
+ const hmac = crypto.createHmac('sha256', secret);
444
+ hmac.update(rawBody);
445
+ const expectedSignature = hmac.digest('hex');
446
+
447
+ // Compare signatures
448
+ if (signature !== expectedSignature) {
449
+ Logger.warn('Signature verification FAILED!', { nodeId, workflowId, workflowName });
450
+ throw new NodeOperationError(this.getNode(), 'Invalid webhook signature');
451
+ }
452
+ Logger.debug('Signature verification successful', { nodeId, workflowId, workflowName });
453
+ }
454
+
455
+ // Cast bodyData to expected type after logging
456
+ const typedBodyData = bodyData as unknown as IWebhookEventData;
457
+
458
+ // Extract the relevant data
459
+ if (!typedBodyData || !typedBodyData.event || !typedBodyData.body) {
460
+ Logger.warn('Webhook data is invalid. Missing event or body', { nodeId, workflowId, workflowName });
461
+ throw new NodeOperationError(this.getNode(), 'Webhook data is invalid');
462
+ }
463
+
464
+ // Process the event
465
+ const eventParts = typedBodyData.event.split('.');
466
+ if (eventParts.length !== 2) {
467
+ Logger.warn(`Invalid event format: ${typedBodyData.event}`, { nodeId, workflowId, workflowName, event: typedBodyData.event });
468
+ throw new NodeOperationError(this.getNode(), `Invalid event format: ${typedBodyData.event}`);
469
+ }
470
+
471
+ const limeType = eventParts[0];
472
+ const eventType = eventParts[1];
473
+ Logger.info(`Processing ${limeType}.${eventType} event for ID: ${typedBodyData.body.id}`, {
474
+ limeType,
475
+ eventType,
476
+ recordId: typedBodyData.body.id,
477
+ nodeId,
478
+ workflowId,
479
+ workflowName
480
+ });
481
+
482
+ // Create a standardized response as a single object instead of an array
483
+ const data: INodeExecutionData[] = [
484
+ {
485
+ json: {
486
+ limeType,
487
+ eventType,
488
+ id: typedBodyData.body.id,
489
+ data: typedBodyData.body.values || {}, // Ensure values is an object, default to empty object if null
490
+ rawEvent: typedBodyData,
491
+ },
492
+ },
493
+ ];
494
+
495
+ Logger.debug('Webhook processing complete', { nodeId, workflowId, workflowName });
496
+
497
+ return {
498
+ workflowData: [data],
499
+ };
500
+ } catch (error) {
501
+ Logger.error('Error in webhook execution', { error, nodeId, workflowId, workflowName });
502
+ throw error;
503
+ }
504
+ }
505
+ }
@@ -0,0 +1 @@
1
+ <svg viewBox="0 0 1024 1025" xmlns="http://www.w3.org/2000/svg" xml:space="preserve"><clipPath id="a"><path d="M0 .03h1024v1024H0z"/></clipPath><g clip-path="url(#a)"><path d="M92.399 480.888c0-257.059 208.719-465.779 465.78-465.779C815.28 15.109 1024 223.829 1024 480.888c0 133.713-55.806 271.139-193.403 385.355-166.779 138.45-390.39 157.35-736.15 134.525-102.653-6.785-117.502-24.319-64.468-63.444 166.694-123.047 62.42-217.167 62.42-456.436Z" style="fill:#bee034"/><clipPath id="b"><path d="M92.399 480.888c0-257.059 208.719-465.779 465.78-465.779C815.28 15.109 1024 223.829 1024 480.888c0 133.713-55.806 271.139-193.403 385.355-166.779 138.45-390.39 157.35-736.15 134.525-102.653-6.785-117.502-24.319-64.468-63.444 166.694-123.047 62.42-217.167 62.42-456.436Z"/></clipPath><g clip-path="url(#b)"><path d="M1023-361.59c0 784.587-711.326 1420.62-1588.79 1420.62C-1402.638-283.55 1023-1146.18 1023-361.59Z" style="fill:#a6efff;filter:blur(200px)"/></g><path d="M433.85 723.911c-24.702-12.757-47.23-29.226-66.813-48.596-9.088-9.002-23.765-8.959-32.768.129-9.001 9.087-8.916 23.763.171 32.766 22.911 22.698 49.236 41.941 78.121 56.873 11.392 5.888 25.385 1.409 31.231-9.94 5.888-11.349 1.409-25.344-9.942-31.232Zm367.266-363.98a270.163 270.163 0 0 1 25.556 78.547c2.048 12.629 13.952 21.206 26.581 19.158 12.586-2.006 21.204-13.951 19.156-26.539a316.387 316.387 0 0 0-29.907-92.029c-5.803-11.434-19.754-15.999-31.146-10.24-11.393 5.76-16 19.713-10.24 31.103Zm-51.497 315.384c-19.584 19.37-42.069 35.839-66.815 48.596-11.349 5.888-15.786 19.883-9.94 31.232 5.887 11.349 19.881 15.828 31.229 9.94 28.929-14.932 55.253-34.175 78.164-56.873 9.045-9.003 9.131-23.679.128-32.766-9.002-9.088-23.678-9.131-32.766-.129ZM517.006 213.546a274.904 274.904 0 0 1 41.343-3.114c14.036 0 27.861 1.066 41.343 3.114 12.629 1.919 24.448-6.784 26.367-19.413 1.962-12.628-6.741-24.446-19.371-26.409a322.626 322.626 0 0 0-48.339-3.627 322.201 322.201 0 0 0-48.34 3.627c-12.672 1.963-21.332 13.781-19.413 26.409 1.92 12.629 13.739 21.332 26.41 19.413Zm41.343 490.355c-40.489 0-73.385 32.853-73.385 73.342s32.896 73.385 73.385 73.385c40.489 0 73.342-32.896 73.342-73.385 0-40.489-32.853-73.342-73.342-73.342ZM290.025 438.478c4.481-27.818 13.227-54.227 25.514-78.547 5.761-11.39 1.195-25.343-10.239-31.103-11.392-5.759-25.343-1.194-31.104 10.24a313.893 313.893 0 0 0-29.908 92.029c-2.048 12.588 6.527 24.533 19.157 26.539 12.629 2.048 24.532-6.529 26.58-19.158Zm479.092 112.254c-12.501 38.527 8.618 79.955 47.102 92.456 38.528 12.502 79.956-8.618 92.457-47.104 12.501-38.525-8.619-79.953-47.103-92.455-38.527-12.501-79.955 8.619-92.456 47.103Zm-80.51-247.802c32.766 23.808 78.675 16.554 102.482-16.212 23.808-32.767 16.512-78.675-16.256-102.482-32.723-23.809-78.675-16.512-102.439 16.254-23.808 32.725-16.555 78.633 16.213 102.44Zm-260.558 0c32.766-23.807 40.063-69.715 16.254-102.44-23.807-32.766-69.715-40.063-102.482-16.254-32.766 23.807-40.02 69.715-16.255 102.482 23.806 32.766 69.758 40.02 102.483 16.212Zm-80.51 247.802c-12.501-38.484-53.929-59.604-92.415-47.103-38.526 12.502-59.645 53.93-47.102 92.455 12.501 38.486 53.929 59.606 92.413 47.104 38.528-12.501 59.605-53.929 47.104-92.456Z" style="fill:#fff"/></g></svg>
@@ -0,0 +1,73 @@
1
+ import { ILoadOptionsFunctions, IDataObject } from 'n8n-workflow';
2
+ import { apiRequest } from '../transport';
3
+
4
+ /**
5
+ * Interface for sortable fields
6
+ */
7
+ interface SortableField {
8
+ name: string;
9
+ value: string;
10
+ }
11
+
12
+ /**
13
+ * Get all sortable fields (properties from main type and related types)
14
+ */
15
+ export async function getAllSortableFields(this: ILoadOptionsFunctions): Promise<SortableField[]> {
16
+ const limeType = this.getNodeParameter('limetype', '') as string;
17
+ const includeRelations = this.getNodeParameter('includeRelations', false) as boolean;
18
+
19
+ if (!limeType) return [];
20
+
21
+ try {
22
+ // Get main type properties
23
+ const propertiesResponse = await apiRequest.call(this, {
24
+ method: 'GET',
25
+ endpoint: `/api/v1/limetype/${limeType}/property`,
26
+ });
27
+
28
+ let sortableFields: SortableField[] = [];
29
+
30
+ if (propertiesResponse && Array.isArray(propertiesResponse)) {
31
+ sortableFields = propertiesResponse.map((property: IDataObject) => ({
32
+ name: property.name as string,
33
+ value: property.name as string,
34
+ }));
35
+ }
36
+
37
+ // If includeRelations is true, get related type properties
38
+ if (includeRelations) {
39
+ const relationsResponse = await apiRequest.call(this, {
40
+ method: 'GET',
41
+ endpoint: `/api/v1/limetype/${limeType}/relation`,
42
+ });
43
+
44
+ if (relationsResponse && Array.isArray(relationsResponse)) {
45
+ for (const relation of relationsResponse) {
46
+ const targetType = relation.targettype as string;
47
+ const relationName = relation.name as string;
48
+
49
+ const targetPropertiesResponse = await apiRequest.call(this, {
50
+ method: 'GET',
51
+ endpoint: `/api/v1/limetype/${targetType}/property`,
52
+ });
53
+
54
+ if (targetPropertiesResponse && Array.isArray(targetPropertiesResponse)) {
55
+ sortableFields.push(
56
+ ...targetPropertiesResponse.map((property: IDataObject) => ({
57
+ name: `${relationName}.${property.name}`,
58
+ value: `${relationName}.${property.name}`,
59
+ }))
60
+ );
61
+ }
62
+ }
63
+ }
64
+ }
65
+
66
+ return sortableFields;
67
+ } catch (error) {
68
+ console.error(`Error loading sortable fields for ${limeType}:`, error);
69
+ return [];
70
+ }
71
+ }
72
+
73
+ export default getAllSortableFields;
@@ -0,0 +1,48 @@
1
+ import { ILoadOptionsFunctions, IDataObject, INodePropertyOptions } from 'n8n-workflow';
2
+ import { apiRequest } from '../transport';
3
+
4
+ /**
5
+ * Load properties for a selected Lime type
6
+ */
7
+ export async function getLimeTypeProperties(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
8
+ const limeType = this.getNodeParameter('limeType', '') as string;
9
+ console.log('Fetching properties for Lime type:', limeType); // Log the Lime type being fetched
10
+ if (!limeType) return [];
11
+
12
+ try {
13
+ const response = await apiRequest.call(this, {
14
+ method: 'GET',
15
+ endpoint: `/api/v1/limetype/${limeType}/`,
16
+ qs: {
17
+ _embed: 'properties',
18
+ },
19
+ });
20
+
21
+ // Define the system properties that should always be included
22
+ const systemProperties: INodePropertyOptions[] = [
23
+ { name: 'ID', value: 'id', description: 'Unique identifier (integer)' },
24
+ { name: 'Updated (System)', value: 'timestamp', description: 'Last update timestamp (datetime)' },
25
+ { name: 'Created (System)', value: 'createdtime', description: 'Creation timestamp (datetime)' },
26
+ { name: 'Created By', value: 'createduser', description: 'User ID that created the record (integer)' },
27
+ { name: 'Updated By', value: 'updateduser', description: 'User ID that last updated the record (integer)' },
28
+ ];
29
+
30
+ // Handle API response properties
31
+ let apiProperties: INodePropertyOptions[] = [];
32
+
33
+ // Check if response contains embedded properties
34
+ apiProperties = response._embedded.properties.map((property: IDataObject) => ({
35
+ name: (property.localname as string) || (property.name as string),
36
+ value: property.name as string,
37
+ description: `Type: ${property.type as string}${(property.required as boolean) ? ' (Required)' : ''} | DB: ${property.name as string}`,
38
+ }));
39
+
40
+ // Combine system properties with API properties
41
+ return [...systemProperties, ...apiProperties];
42
+ } catch (error) {
43
+ console.error(`Error loading properties for ${limeType}:`, error);
44
+ return [];
45
+ }
46
+ }
47
+
48
+ export default getLimeTypeProperties;
@@ -0,0 +1,32 @@
1
+ import { ILoadOptionsFunctions, IDataObject } from 'n8n-workflow';
2
+ import { apiRequest } from '../transport';
3
+
4
+ /**
5
+ * Load relations for a selected Lime type
6
+ */
7
+ export async function getLimeTypeRelations(this: ILoadOptionsFunctions) {
8
+ const limeType = this.getNodeParameter('limetype', '') as string;
9
+ if (!limeType) return [];
10
+
11
+ try {
12
+ const response = await apiRequest.call(this, {
13
+ method: 'GET',
14
+ endpoint: `/api/v1/limetype/${limeType}/`,
15
+ });
16
+
17
+ if (!response || !Array.isArray(response)) {
18
+ return [];
19
+ }
20
+
21
+ return response.map((relation: IDataObject) => ({
22
+ name: relation.name as string,
23
+ value: relation.name as string,
24
+ description: `Target: ${relation.targettype}`,
25
+ }));
26
+ } catch (error) {
27
+ console.error(`Error loading relations for ${limeType}:`, error);
28
+ return [];
29
+ }
30
+ }
31
+
32
+ export default getLimeTypeRelations;