@limetech/n8n-nodes-lime 2.6.1 → 2.7.0-dev.1

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 (67) hide show
  1. package/CHANGELOG.md +7 -2
  2. package/dist/nodes/lime-crm/LimeCrmNode.node.d.ts +4 -1
  3. package/dist/nodes/lime-crm/LimeCrmNode.node.js +3 -0
  4. package/dist/nodes/lime-crm/LimeCrmNode.node.js.map +1 -1
  5. package/dist/nodes/lime-crm/methods/getLimetypeProperties.d.ts +2 -0
  6. package/dist/nodes/lime-crm/methods/getLimetypeProperties.js +43 -0
  7. package/dist/nodes/lime-crm/methods/getLimetypeProperties.js.map +1 -1
  8. package/dist/nodes/lime-crm/methods/index.d.ts +2 -2
  9. package/dist/nodes/lime-crm/methods/index.js +4 -1
  10. package/dist/nodes/lime-crm/methods/index.js.map +1 -1
  11. package/dist/nodes/lime-crm/methods/resourceMapping.d.ts +1 -0
  12. package/dist/nodes/lime-crm/methods/resourceMapping.js +46 -0
  13. package/dist/nodes/lime-crm/methods/resourceMapping.js.map +1 -1
  14. package/dist/nodes/lime-crm/models/limetype.d.ts +1 -0
  15. package/dist/nodes/lime-crm/resources/data/index.d.ts +1 -1
  16. package/dist/nodes/lime-crm/resources/data/index.js +20 -0
  17. package/dist/nodes/lime-crm/resources/data/index.js.map +1 -1
  18. package/dist/nodes/lime-crm/resources/data/operations/bulkImportCommons.d.ts +5 -0
  19. package/dist/nodes/lime-crm/resources/data/operations/bulkImportCommons.js +230 -0
  20. package/dist/nodes/lime-crm/resources/data/operations/bulkImportCommons.js.map +1 -0
  21. package/dist/nodes/lime-crm/resources/data/operations/createManyObjects.operation.d.ts +9 -0
  22. package/dist/nodes/lime-crm/resources/data/operations/createManyObjects.operation.js +16 -0
  23. package/dist/nodes/lime-crm/resources/data/operations/createManyObjects.operation.js.map +1 -0
  24. package/dist/nodes/lime-crm/resources/data/operations/createOrUpdateManyObjects.operation.d.ts +9 -0
  25. package/dist/nodes/lime-crm/resources/data/operations/createOrUpdateManyObjects.operation.js +16 -0
  26. package/dist/nodes/lime-crm/resources/data/operations/createOrUpdateManyObjects.operation.js.map +1 -0
  27. package/dist/nodes/lime-crm/resources/data/operations/deprecated-startBulkImport.operation.d.ts +9 -0
  28. package/dist/nodes/lime-crm/resources/data/operations/deprecated-startBulkImport.operation.js +241 -0
  29. package/dist/nodes/lime-crm/resources/data/operations/deprecated-startBulkImport.operation.js.map +1 -0
  30. package/dist/nodes/lime-crm/resources/data/operations/index.d.ts +4 -0
  31. package/dist/nodes/lime-crm/resources/data/operations/index.js +5 -1
  32. package/dist/nodes/lime-crm/resources/data/operations/index.js.map +1 -1
  33. package/dist/nodes/lime-crm/resources/data/operations/updateManyObjects.operation.d.ts +9 -0
  34. package/dist/nodes/lime-crm/resources/data/operations/updateManyObjects.operation.js +16 -0
  35. package/dist/nodes/lime-crm/resources/data/operations/updateManyObjects.operation.js.map +1 -0
  36. package/dist/nodes/lime-crm/transport/bulkimport.d.ts +41 -0
  37. package/dist/nodes/lime-crm/transport/bulkimport.js +86 -0
  38. package/dist/nodes/lime-crm/transport/bulkimport.js.map +1 -0
  39. package/dist/nodes/lime-crm/transport/index.d.ts +1 -0
  40. package/dist/nodes/lime-crm/transport/index.js +6 -1
  41. package/dist/nodes/lime-crm/transport/index.js.map +1 -1
  42. package/dist/nodes/lime-crm/transport/limetypes.js +15 -4
  43. package/dist/nodes/lime-crm/transport/limetypes.js.map +1 -1
  44. package/dist/nodes/lime-forms/LimeFormsTrigger.node.js +3 -3
  45. package/dist/nodes/lime-forms/LimeFormsTrigger.node.js.map +1 -1
  46. package/dist/nodes/lime-forms/lime-forms.svg +6 -0
  47. package/dist/tsconfig.tsbuildinfo +1 -1
  48. package/nodes/lime-crm/LimeCrmNode.node.ts +6 -0
  49. package/nodes/lime-crm/methods/getLimetypeProperties.ts +84 -0
  50. package/nodes/lime-crm/methods/index.ts +3 -0
  51. package/nodes/lime-crm/methods/resourceMapping.ts +76 -0
  52. package/nodes/lime-crm/models/limetype.ts +1 -0
  53. package/nodes/lime-crm/resources/data/index.ts +34 -1
  54. package/nodes/lime-crm/resources/data/operations/bulkImportCommons.ts +323 -0
  55. package/nodes/lime-crm/resources/data/operations/createManyObjects.operation.ts +44 -0
  56. package/nodes/lime-crm/resources/data/operations/createOrUpdateManyObjects.operation.ts +44 -0
  57. package/nodes/lime-crm/resources/data/operations/deprecated-startBulkImport.operation.ts +364 -0
  58. package/nodes/lime-crm/resources/data/operations/index.ts +17 -0
  59. package/nodes/lime-crm/resources/data/operations/updateManyObjects.operation.ts +44 -0
  60. package/nodes/lime-crm/transport/bulkimport.ts +271 -0
  61. package/nodes/lime-crm/transport/index.ts +8 -0
  62. package/nodes/lime-crm/transport/limetypes.ts +26 -8
  63. package/nodes/lime-forms/LimeFormsTrigger.node.ts +3 -3
  64. package/nodes/lime-forms/lime-forms.svg +6 -0
  65. package/package.json +1 -1
  66. package/dist/nodes/lime-forms/assets/lime-crm.svg +0 -1
  67. package/nodes/lime-forms/assets/lime-crm.svg +0 -1
@@ -0,0 +1,364 @@
1
+ import {
2
+ IDataObject,
3
+ IExecuteFunctions,
4
+ INode,
5
+ INodeProperties,
6
+ LoggerProxy as Logger,
7
+ NodeOperationError,
8
+ } from 'n8n-workflow';
9
+ import { DATA_RESOURCE } from '../../../models';
10
+ import {
11
+ BulkImportJobPayload,
12
+ createBulkImportJob,
13
+ uploadBulkImportData,
14
+ } from '../../../transport';
15
+ import {
16
+ BulkImportPayloadObject,
17
+ waitForBulkImportJob,
18
+ } from '../../../transport/bulkimport';
19
+
20
+ /**
21
+ * Description and metadata for the "Bulk import objects" operation in Lime CRM.
22
+ *
23
+ * @public
24
+ */
25
+ export const description = {
26
+ name: 'Create or update many objects (deprecated)',
27
+ value: 'startBulkImport',
28
+ description:
29
+ 'Create or update multiple objects via a bulk import. Skipping business logic.',
30
+ action: 'Create or update many objects (deprecated)',
31
+ };
32
+
33
+ /**
34
+ * Node properties for the "Bulk import objects" operation.
35
+ *
36
+ * @param {string} limetype - The type of entity to update. Loaded from available Limetypes
37
+ * @param {string} id - The ID of the object to update
38
+ * @param {'simple' | 'json'} inputType - How the object data is provided: 'simple' for form inputs, 'json' for raw JSON
39
+ * @param {IDataObject} simpleFields - Used if `inputType` is 'simple'. List of field name/value pairs to update
40
+ * @param {string} jsonData - Used if `inputType` is 'json'. Full object data in JSON format
41
+ *
42
+ * @public
43
+ */
44
+ export const properties: INodeProperties[] = [
45
+ {
46
+ displayName:
47
+ '<h1>Deprecated</h1>' +
48
+ 'This action is deprecated and will be removed very soon. ' +
49
+ 'Please use the new "Create or Update Many Objects (Alpha)" operation instead.',
50
+ name: 'deprecatedNotice',
51
+ type: 'callout',
52
+ displayOptions: {
53
+ show: {
54
+ resource: [DATA_RESOURCE],
55
+ operation: ['startBulkImport'],
56
+ },
57
+ },
58
+ default: undefined,
59
+ },
60
+ {
61
+ displayName: 'Limetype',
62
+ name: 'limetype',
63
+ type: 'options',
64
+ typeOptions: {
65
+ loadOptionsMethod: 'getLimetypes',
66
+ },
67
+ required: true,
68
+ default: '',
69
+ description: 'The type of object to update',
70
+ displayOptions: {
71
+ show: {
72
+ resource: [DATA_RESOURCE],
73
+ operation: ['startBulkImport'],
74
+ },
75
+ },
76
+ },
77
+ {
78
+ displayName: 'Matching Property',
79
+ name: 'matchingProperty',
80
+ type: 'options',
81
+ typeOptions: {
82
+ loadOptionsMethod: 'getNoHasManyProperties',
83
+ loadOptionsDependsOn: ['limetype'],
84
+ },
85
+ required: true,
86
+ default: '',
87
+ description:
88
+ 'The property to use to match existing objects. Must be a unique property.',
89
+ displayOptions: {
90
+ show: {
91
+ resource: [DATA_RESOURCE],
92
+ operation: ['startBulkImport'],
93
+ },
94
+ },
95
+ },
96
+ {
97
+ displayName: 'Input Type',
98
+ name: 'inputType',
99
+ type: 'options',
100
+ options: [
101
+ {
102
+ name: 'Simple Fields',
103
+ value: 'simple',
104
+ description: 'Define fields using the UI',
105
+ },
106
+ {
107
+ name: 'JSON Object',
108
+ value: 'json',
109
+ description: 'Define fields using JSON',
110
+ },
111
+ ],
112
+ default: 'simple',
113
+ description: 'How to input the data',
114
+ displayOptions: {
115
+ show: {
116
+ resource: [DATA_RESOURCE],
117
+ operation: ['startBulkImport'],
118
+ },
119
+ },
120
+ },
121
+ {
122
+ displayName: 'Data',
123
+ name: 'jsonData',
124
+ type: 'json',
125
+ default:
126
+ '{\n "name": "Updated Company Name",\n "phone": "+987654321"\n}',
127
+ description:
128
+ 'Key-value pairs for fields to update. Property names must match the Lime CRM field names.',
129
+ typeOptions: {
130
+ alwaysOpenEditWindow: true,
131
+ },
132
+ displayOptions: {
133
+ show: {
134
+ resource: [DATA_RESOURCE],
135
+ operation: ['startBulkImport'],
136
+ inputType: ['json'],
137
+ },
138
+ },
139
+ },
140
+ {
141
+ displayName: 'Fields',
142
+ name: 'simpleFields',
143
+ placeholder: 'Add Field',
144
+ type: 'fixedCollection',
145
+ typeOptions: {
146
+ multipleValues: true,
147
+ sortable: true,
148
+ },
149
+ default: {},
150
+ displayOptions: {
151
+ show: {
152
+ resource: [DATA_RESOURCE],
153
+ operation: ['startBulkImport'],
154
+ inputType: ['simple'],
155
+ },
156
+ },
157
+ options: [
158
+ {
159
+ name: 'field',
160
+ displayName: 'Field',
161
+ values: [
162
+ {
163
+ displayName: 'Field Name',
164
+ name: 'fieldName',
165
+ type: 'options',
166
+ typeOptions: {
167
+ loadOptionsMethod: 'getNoHasManyProperties',
168
+ loadOptionsDependsOn: ['limetype'],
169
+ },
170
+ default: '',
171
+ description: 'The name of the field',
172
+ },
173
+ {
174
+ displayName: 'Field Value',
175
+ name: 'fieldValue',
176
+ type: 'string',
177
+ default: '',
178
+ description: 'The value of the field',
179
+ },
180
+ {
181
+ displayName: 'Relation Lookup',
182
+ name: 'fieldNameDotLookup',
183
+ type: 'options',
184
+ typeOptions: {
185
+ loadOptionsMethod:
186
+ 'getRelationPropertiesWithLookupField',
187
+ loadOptionsDependsOn: ['limetype'],
188
+ },
189
+ default: '',
190
+ description:
191
+ 'For relation fields: select which property on the related object to use for matching. Leave empty for non-relation fields.',
192
+ },
193
+ ],
194
+ },
195
+ ],
196
+ },
197
+ ];
198
+
199
+ /**
200
+ * Extract properties to import from JSON input.
201
+ * @param jsonData
202
+ */
203
+ function getPropertiesFromJson(jsonData: string): string[] {
204
+ const parsed = JSON.parse(jsonData);
205
+ return Object.keys(parsed);
206
+ }
207
+
208
+ /**
209
+ * Extract properties to import from simple fields input.
210
+ * Validates that relation lookups match their field names.
211
+ * @param simpleFields
212
+ * @param getNode
213
+ */
214
+ function getPropertiesFromSimpleFields(
215
+ simpleFields: IDataObject[],
216
+ getNode: () => INode
217
+ ): string[] {
218
+ const propertiesToImport: string[] = [];
219
+
220
+ for (const field of simpleFields) {
221
+ const fieldName = field.fieldName as string;
222
+ const fieldNameDotLookup = field.fieldNameDotLookup as string;
223
+
224
+ if (fieldNameDotLookup) {
225
+ const [relationField] = fieldNameDotLookup.split('.');
226
+
227
+ if (relationField !== fieldName) {
228
+ throw new NodeOperationError(
229
+ getNode(),
230
+ `Relation lookup "${fieldNameDotLookup}" does not match field name "${fieldName}".`
231
+ );
232
+ }
233
+ propertiesToImport.push(fieldNameDotLookup);
234
+ } else {
235
+ propertiesToImport.push(fieldName);
236
+ }
237
+ }
238
+
239
+ return propertiesToImport;
240
+ }
241
+
242
+ /**
243
+ * Build a payload object from simple fields.
244
+ * @param simpleFields
245
+ */
246
+ function buildPayloadFromSimpleFields(
247
+ simpleFields: IDataObject[]
248
+ ): BulkImportPayloadObject {
249
+ const obj: BulkImportPayloadObject = { values: {} };
250
+
251
+ for (const field of simpleFields) {
252
+ const fieldName = field.fieldName as string;
253
+ const fieldValue = field.fieldValue as string;
254
+
255
+ obj.values[fieldName] = fieldValue;
256
+ }
257
+
258
+ return obj;
259
+ }
260
+
261
+ /**
262
+ * Execute the "Bulk import objects" operation for Lime CRM.
263
+ *
264
+ * @remarks
265
+ * This method creates a bulk import job and uploads data.
266
+ *
267
+ * @param i - The index of the current item in the workflow execution
268
+ *
269
+ * @returns The bulk import job status and summary
270
+ *
271
+ * @public
272
+ */
273
+ export async function execute(
274
+ this: IExecuteFunctions,
275
+ i: number
276
+ ): Promise<IDataObject | undefined> {
277
+ if (i > 0) {
278
+ return undefined;
279
+ }
280
+
281
+ const limetype = this.getNodeParameter('limetype', i) as string;
282
+ const matchingProperty = this.getNodeParameter(
283
+ 'matchingProperty',
284
+ i
285
+ ) as string;
286
+ const inputType = this.getNodeParameter('inputType', i) as string;
287
+ const items = this.getInputData();
288
+
289
+ Logger.info(
290
+ `Preparing bulk import of ${items.length} objects for limetype: ${limetype}`
291
+ );
292
+
293
+ // Step 1: Compute the properties to import based on the first item
294
+ const propertiesToImport =
295
+ inputType === 'json'
296
+ ? getPropertiesFromJson(
297
+ this.getNodeParameter('jsonData', 0) as string
298
+ )
299
+ : getPropertiesFromSimpleFields(
300
+ this.getNodeParameter(
301
+ 'simpleFields.field',
302
+ 0,
303
+ []
304
+ ) as IDataObject[],
305
+ this.getNode.bind(this)
306
+ );
307
+
308
+ Logger.info(`Properties to import: ${propertiesToImport.join(', ')}`);
309
+
310
+ // Step 2: Prepare the body for all items
311
+ const body: BulkImportPayloadObject[] = items.map((_, idx) => {
312
+ if (inputType === 'json') {
313
+ return JSON.parse(this.getNodeParameter('jsonData', idx) as string);
314
+ }
315
+ return buildPayloadFromSimpleFields(
316
+ this.getNodeParameter(
317
+ 'simpleFields.field',
318
+ idx,
319
+ []
320
+ ) as IDataObject[]
321
+ );
322
+ });
323
+
324
+ // Step 3: Create the bulk import job
325
+ const jobPayload: BulkImportJobPayload = {
326
+ mode: 'create_or_update',
327
+ limetype,
328
+ matchingProperty,
329
+ properties: propertiesToImport,
330
+ };
331
+
332
+ const jobResponse = await createBulkImportJob(this, jobPayload);
333
+ const jobId = jobResponse.id;
334
+
335
+ // Step 4: Upload the data file
336
+ await uploadBulkImportData(this, jobId, body);
337
+
338
+ // Step 5: Poll for completion
339
+ const finalStatus = await waitForBulkImportJob(this, jobId, 2500);
340
+
341
+ if (finalStatus.status === 'failed') {
342
+ throw new NodeOperationError(
343
+ this.getNode(),
344
+ 'The bulk import job failed',
345
+ {
346
+ message: 'The bulk import job failed due to a server error.',
347
+ description: `Bulk import job with ID ${jobId} has failed. Check the Lime CRM server for more details.`,
348
+ }
349
+ );
350
+ }
351
+
352
+ // Step 6: Return the results summary
353
+ return {
354
+ jobId,
355
+ status: finalStatus.status,
356
+ summary: finalStatus.result || {
357
+ total: 0,
358
+ created: 0,
359
+ updated: 0,
360
+ skipped: 0,
361
+ failed: 0,
362
+ },
363
+ };
364
+ }
@@ -22,3 +22,20 @@ export * as getManyObjects from './getManyObjects.operation';
22
22
  * @group Resources
23
23
  */
24
24
  export * as getSingleFile from './getSingleFile.operation';
25
+ /**
26
+ * @group Resources
27
+ */
28
+ export * as createManyObjects from './createManyObjects.operation';
29
+ /**
30
+ * @group Resources
31
+ */
32
+ export * as updateManyObjects from './updateManyObjects.operation';
33
+ /**
34
+ * @group Resources
35
+ */
36
+ export * as createOrUpdateManyObjects from './createOrUpdateManyObjects.operation';
37
+ /**
38
+ * @group Resources
39
+ * @deprecated Use createManyObjects, updateManyObjects, or createOrUpdateManyObjects instead.
40
+ */
41
+ export * as startBulkImport from './deprecated-startBulkImport.operation';
@@ -0,0 +1,44 @@
1
+ import { IDataObject, IExecuteFunctions, INodeProperties } from 'n8n-workflow';
2
+ import {
3
+ getBulkImportProperties,
4
+ executeBulkImport,
5
+ } from './bulkImportCommons';
6
+
7
+ /**
8
+ * Description and metadata for the "Update many objects" operation in Lime CRM.
9
+ *
10
+ * @public
11
+ */
12
+ export const description = {
13
+ name: 'Update Many Objects (Alpha)',
14
+ value: 'updateManyObjects',
15
+ description:
16
+ 'Update multiple existing objects via bulk import. Skips business logic.',
17
+ action: 'Update many objects (alpha)',
18
+ };
19
+
20
+ /**
21
+ * Node properties for the "Update many objects" operation.
22
+ *
23
+ * @public
24
+ */
25
+ export const properties: INodeProperties[] = getBulkImportProperties(
26
+ 'updateManyObjects',
27
+ true // Matching property needed for update
28
+ );
29
+
30
+ /**
31
+ * Execute the "Update many objects" operation for Lime CRM.
32
+ *
33
+ * @param i - The index of the current item in the workflow execution
34
+ *
35
+ * @returns The bulk import job status and summary
36
+ *
37
+ * @public
38
+ */
39
+ export async function execute(
40
+ this: IExecuteFunctions,
41
+ i: number
42
+ ): Promise<IDataObject | undefined> {
43
+ return executeBulkImport(this, i, 'update');
44
+ }
@@ -0,0 +1,271 @@
1
+ import {
2
+ IExecuteFunctions,
3
+ LoggerProxy as Logger,
4
+ NodeApiError,
5
+ } from 'n8n-workflow';
6
+ import { callLimeApi } from './commons';
7
+ import { LIME_CRM_API_CREDENTIAL_KEY } from '../models';
8
+
9
+ /**
10
+ * Endpoint path for Lime CRM bulk import API.
11
+ *
12
+ * @internal
13
+ * @group Transport
14
+ */
15
+ const BULK_IMPORT_URL = 'limepkg-mbeku-bulk-import/bulk-imports/';
16
+
17
+ /**
18
+ * Response from creating a bulk import job.
19
+ *
20
+ * @property id - The unique ID of the bulk import job
21
+ * @property createdBy - The ID of the user who created the job
22
+ * @property fileId - The ID of the uploaded file (if any)
23
+ * @property status - The current status of the job (`waiting_for_data`, `ready`, `failed`, `succeeded`)
24
+ * @property startedAt - Timestamp when the job started (if any)
25
+ * @property endedAt - Timestamp when the job ended (if any)
26
+ * @property metadata - Metadata about the job configuration
27
+ * @property metadata.limetype - The Lime type being imported
28
+ * @property metadata.properties - Array of property names being imported
29
+ * @property metadata.mode - Import mode
30
+ * @property metadata.matchingProperty - Property used for matching existing records
31
+ * @property result - Summary of the job results (if finished)
32
+ * @property result.total - Total number of records processed
33
+ * @property result.created - Number of records created
34
+ * @property result.updated - Number of records updated
35
+ * @property result.skipped - Number of records skipped
36
+ * @property result.failed - Number of records failed
37
+ * @property extras - Optional extra metadata from the server/job runner
38
+ * @property extras.task_id - Optional background task id (snake_case)
39
+ * @property extras.taskId - Optional background task id (camelCase)
40
+ *
41
+ * @public
42
+ * @group Transport
43
+ */
44
+ export interface BulkImportJobResponse {
45
+ id: string;
46
+ createdBy: number;
47
+ fileId: number | null;
48
+ status: 'waiting_for_data' | 'ready' | 'failed' | 'succeeded';
49
+ startedAt: string | null;
50
+ endedAt: string | null;
51
+ metadata: {
52
+ limetype: string;
53
+ properties: string[];
54
+ mode: BulkImportMode;
55
+ matchingProperty: string;
56
+ };
57
+ result: null | {
58
+ total: number;
59
+ created: number;
60
+ updated: number;
61
+ skipped: number;
62
+ failed: number;
63
+ };
64
+ extras: null | {
65
+ task_id?: string;
66
+ taskId?: string;
67
+ };
68
+ }
69
+
70
+ /**
71
+ * The mode for a bulk import operation.
72
+ *
73
+ * @public
74
+ * @group Transport
75
+ */
76
+ export type BulkImportMode = 'create' | 'update' | 'create_or_update';
77
+
78
+ /**
79
+ * Payload for creating a bulk import job.
80
+ *
81
+ * @property limetype - The Limetype to import objects into
82
+ * @property properties - List of property names to import
83
+ * @property mode - The import mode
84
+ * @property matchingProperty - Property to use for matching existing records (required for 'update' and 'create_or_update' modes)
85
+ *
86
+ * @public
87
+ * @group Transport
88
+ */
89
+ export interface BulkImportJobPayload {
90
+ limetype: string;
91
+ properties: string[];
92
+ mode: BulkImportMode;
93
+ matchingProperty?: string;
94
+ }
95
+
96
+ /**
97
+ * Object representing a single object to import.
98
+ *
99
+ * @property values - Key-value pairs of property names and their values
100
+ * @property extras - (Optional) Additional informational data for the import
101
+ *
102
+ * @public
103
+ * @group Transport
104
+ */
105
+ export interface BulkImportPayloadObject {
106
+ values: Record<string, unknown>;
107
+ extras?: Record<string, unknown>;
108
+ }
109
+
110
+ /**
111
+ * Create a new bulk import job in Lime CRM.
112
+ *
113
+ * @param context - The n8n execution context
114
+ * @param payload - The bulk import job configuration
115
+ *
116
+ * @returns Promise resolving to the created job response with id and status
117
+ *
118
+ * @public
119
+ * @group Transport
120
+ */
121
+ export async function createBulkImportJob(
122
+ context: IExecuteFunctions,
123
+ payload: BulkImportJobPayload
124
+ ): Promise<BulkImportJobResponse> {
125
+ Logger.info(
126
+ `Creating bulk import job at ${BULK_IMPORT_URL} with payload: ${JSON.stringify(payload)}`
127
+ );
128
+ try {
129
+ const response = await callLimeApi<BulkImportJobResponse>(context, {
130
+ method: 'POST',
131
+ url: BULK_IMPORT_URL,
132
+ requestOptions: {
133
+ body: payload,
134
+ },
135
+ });
136
+ if (!response.success) {
137
+ throw new NodeApiError(context.getNode(), {
138
+ message: 'The bulk import job was rejected by the server.',
139
+ description: `${JSON.stringify(response.data)}`,
140
+ });
141
+ }
142
+ Logger.info(
143
+ `Created bulk import job at ${BULK_IMPORT_URL} with payload: ${JSON.stringify(payload)}`
144
+ );
145
+
146
+ return response.data;
147
+ } catch (error) {
148
+ Logger.error(
149
+ `Failed to create bulk import job at ${BULK_IMPORT_URL} with payload: ${JSON.stringify(payload)}`
150
+ );
151
+ throw error;
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Upload data to an existing bulk import job.
157
+ *
158
+ * @param context - The n8n execution context
159
+ * @param jobId - The ID of the bulk import job
160
+ * @param data - Array of objects to import
161
+ *
162
+ * @returns Promise resolving when upload is complete
163
+ *
164
+ * @public
165
+ * @group Transport
166
+ */
167
+ export async function uploadBulkImportData(
168
+ context: IExecuteFunctions,
169
+ jobId: string,
170
+ data: unknown
171
+ ): Promise<void> {
172
+ // Get the base URL for constructing the full endpoint
173
+ const credentials = await context.getCredentials(
174
+ LIME_CRM_API_CREDENTIAL_KEY
175
+ );
176
+ const baseUrl = credentials.url as string;
177
+ const fullUrl = `${baseUrl}/${BULK_IMPORT_URL}${jobId}`;
178
+
179
+ const message = `Uploading data to: ${fullUrl} for job ID: ${jobId}`;
180
+ Logger.info(message);
181
+
182
+ const jsonData = JSON.stringify(data);
183
+ const messageData = `First element of uploaded data: ${jsonData[0]}`;
184
+ Logger.info(messageData);
185
+ const formData = {
186
+ file: {
187
+ value: Buffer.from(jsonData, 'utf8'),
188
+ options: {
189
+ filename: 'import-data.json',
190
+ contentType: 'application/json',
191
+ },
192
+ },
193
+ };
194
+
195
+ Logger.info(`Uploading bulk import data to ${fullUrl}`);
196
+
197
+ await context.helpers.requestWithAuthentication.call(
198
+ context,
199
+ LIME_CRM_API_CREDENTIAL_KEY,
200
+ {
201
+ method: 'POST',
202
+ url: fullUrl,
203
+ formData,
204
+ }
205
+ );
206
+
207
+ Logger.info(`Successfully uploaded data for job ID: ${jobId}`);
208
+ }
209
+
210
+ /**
211
+ * Get the status of a bulk import job.
212
+ *
213
+ * @param context - The n8n execution context
214
+ * @param jobId - The ID of the bulk import job
215
+ *
216
+ * @returns Promise resolving to the job status response
217
+ *
218
+ * @public
219
+ * @group Transport
220
+ */
221
+ export async function getBulkImportJobStatus(
222
+ context: IExecuteFunctions,
223
+ jobId: string
224
+ ): Promise<BulkImportJobResponse> {
225
+ Logger.info(`Fetching status for bulk import job ID: ${jobId}`);
226
+ const response = await callLimeApi<BulkImportJobResponse>(context, {
227
+ method: 'GET',
228
+ url: `${BULK_IMPORT_URL}${jobId}`,
229
+ });
230
+
231
+ if (!response.success) {
232
+ throw new NodeApiError(context.getNode(), {
233
+ message: 'The bulk import job status could not be retrieved.',
234
+ description: `${JSON.stringify(response)}`,
235
+ });
236
+ }
237
+
238
+ return response.data;
239
+ }
240
+
241
+ /**
242
+ * Poll a bulk import job until it completes.
243
+ *
244
+ * @param context - The n8n execution context
245
+ * @param jobId - The ID of the bulk import job
246
+ * @param pollIntervalMs - Milliseconds to wait between polls (default: 2500)
247
+ *
248
+ * @returns Promise resolving to the final job status response
249
+ *
250
+ * @public
251
+ * @group Transport
252
+ */
253
+ export async function waitForBulkImportJob(
254
+ context: IExecuteFunctions,
255
+ jobId: string,
256
+ pollIntervalMs: number = 2500
257
+ ): Promise<BulkImportJobResponse> {
258
+ let status = 'running';
259
+ let response: BulkImportJobResponse;
260
+
261
+ while (['waiting_for_data', 'ready', 'running'].includes(status)) {
262
+ // Wait before polling
263
+ await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
264
+
265
+ Logger.info(`Polling bulk import job ID: ${jobId}`);
266
+ response = await getBulkImportJobStatus(context, jobId);
267
+ status = response.status;
268
+ }
269
+
270
+ return response!;
271
+ }
@@ -41,3 +41,11 @@ export {
41
41
  fetchSingleUserById,
42
42
  fetchSingleUserByLimeobjectId,
43
43
  } from './users';
44
+ export {
45
+ BulkImportJobResponse,
46
+ BulkImportJobPayload,
47
+ createBulkImportJob,
48
+ uploadBulkImportData,
49
+ getBulkImportJobStatus,
50
+ waitForBulkImportJob,
51
+ } from './bulkimport';