n8n-nodes-lifespace 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.
@@ -0,0 +1,656 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LifeSpace = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ function parseJsonObject(context, itemIndex, value, fieldName) {
6
+ const parsed = typeof value === 'string' ? JSON.parse(value) : value;
7
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
8
+ throw new n8n_workflow_1.NodeOperationError(context.getNode(), `${fieldName} must be a JSON object`, { itemIndex });
9
+ }
10
+ return parsed;
11
+ }
12
+ function mappedValue(context, itemIndex, parameterName) {
13
+ const value = context.getNodeParameter(`${parameterName}.value`, itemIndex, {});
14
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
15
+ }
16
+ function queryParameters(context, itemIndex) {
17
+ var _a, _b, _c;
18
+ const qs = {};
19
+ const search = String(context.getNodeParameter('search', itemIndex, '')).trim();
20
+ const sortField = String(context.getNodeParameter('sortField', itemIndex, 'createdAt')).trim();
21
+ const sortDirection = String(context.getNodeParameter('sortDirection', itemIndex, 'desc')).trim();
22
+ const cursor = String(context.getNodeParameter('cursor', itemIndex, '')).trim();
23
+ const limit = context.getNodeParameter('limit', itemIndex, 50);
24
+ const filters = context.getNodeParameter('filters.filter', itemIndex, []);
25
+ if (search)
26
+ qs.q = search;
27
+ if (sortField)
28
+ qs.sort = `${sortField}:${sortDirection}`;
29
+ qs.limit = limit;
30
+ if (cursor)
31
+ qs.cursor = cursor;
32
+ const usedKeys = new Set();
33
+ for (const filter of filters) {
34
+ const field = String((_a = filter.field) !== null && _a !== void 0 ? _a : '').trim();
35
+ const value = String((_b = filter.value) !== null && _b !== void 0 ? _b : '');
36
+ const operator = (_c = filter.operator) !== null && _c !== void 0 ? _c : 'exact';
37
+ if (!field || value === '')
38
+ continue;
39
+ const key = operator === 'from' ? `${field}From` : operator === 'to' ? `${field}To` : field;
40
+ if (usedKeys.has(key)) {
41
+ throw new n8n_workflow_1.NodeOperationError(context.getNode(), `Query filter ${key} may be supplied only once`, { itemIndex });
42
+ }
43
+ usedKeys.add(key);
44
+ qs[key] = value;
45
+ }
46
+ return qs;
47
+ }
48
+ async function loadDiscovery() {
49
+ const credentials = await this.getCredentials('lifeSpaceApi');
50
+ const baseUrl = String(credentials.baseUrl).replace(/\/$/, '');
51
+ const options = {
52
+ method: 'GET',
53
+ url: `${baseUrl}/_discovery`,
54
+ json: true,
55
+ };
56
+ try {
57
+ return await this.helpers.httpRequestWithAuthentication.call(this, 'lifeSpaceApi', options);
58
+ }
59
+ catch (error) {
60
+ throw new n8n_workflow_1.NodeApiError(this.getNode(), error);
61
+ }
62
+ }
63
+ function selectedModel(discovery, route) {
64
+ return discovery.data.models.find((entry) => entry.route === route);
65
+ }
66
+ function requiredAccessForOperation(operation) {
67
+ return ['create', 'update', 'delete'].includes(operation) ? 'write' : 'read';
68
+ }
69
+ function resourceMapperType(field) {
70
+ switch (field.type) {
71
+ case 'integer':
72
+ case 'number':
73
+ return 'number';
74
+ case 'boolean':
75
+ return 'boolean';
76
+ case 'datetime':
77
+ return 'dateTime';
78
+ case 'person_list':
79
+ case 'record_list':
80
+ return 'array';
81
+ case 'enum':
82
+ return 'options';
83
+ default:
84
+ return 'string';
85
+ }
86
+ }
87
+ function mapperField(field, required) {
88
+ var _a;
89
+ return {
90
+ id: field.key,
91
+ displayName: field.key,
92
+ required,
93
+ defaultMatch: false,
94
+ canBeUsedToMatch: false,
95
+ display: true,
96
+ type: resourceMapperType(field),
97
+ options: field.type === 'enum'
98
+ ? ((_a = field.values) !== null && _a !== void 0 ? _a : []).map((value) => ({ name: value, value }))
99
+ : undefined,
100
+ };
101
+ }
102
+ class LifeSpace {
103
+ constructor() {
104
+ this.description = {
105
+ displayName: 'LifeSpace',
106
+ name: 'lifeSpace',
107
+ icon: {
108
+ light: 'file:lifespace.svg',
109
+ dark: 'file:lifespace.dark.svg',
110
+ },
111
+ group: ['transform'],
112
+ version: 1,
113
+ subtitle: '={{$parameter["resource"] + ": " + $parameter["operation"]}}',
114
+ description: 'Use LifeSpace in n8n workflows',
115
+ defaults: {
116
+ name: 'LifeSpace',
117
+ },
118
+ inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
119
+ outputs: [n8n_workflow_1.NodeConnectionTypes.Main],
120
+ usableAsTool: true,
121
+ credentials: [
122
+ {
123
+ name: 'lifeSpaceApi',
124
+ required: true,
125
+ },
126
+ ],
127
+ properties: [
128
+ {
129
+ displayName: 'Resource',
130
+ name: 'resource',
131
+ type: 'options',
132
+ noDataExpression: true,
133
+ options: [
134
+ {
135
+ name: 'Model Record',
136
+ value: 'modelRecord',
137
+ },
138
+ {
139
+ name: 'API Request',
140
+ value: 'apiRequest',
141
+ },
142
+ ],
143
+ default: 'modelRecord',
144
+ },
145
+ {
146
+ displayName: 'Operation',
147
+ name: 'operation',
148
+ type: 'options',
149
+ noDataExpression: true,
150
+ displayOptions: { show: { resource: ['modelRecord'] } },
151
+ options: [
152
+ {
153
+ name: 'Create',
154
+ value: 'create',
155
+ action: 'Create a model record',
156
+ description: 'Create a record through the LifeSpace Generic Runtime',
157
+ },
158
+ {
159
+ name: 'Delete',
160
+ value: 'delete',
161
+ action: 'Delete a model record',
162
+ description: 'Delete a record using optimistic concurrency',
163
+ },
164
+ {
165
+ name: 'Execute Action',
166
+ value: 'executeAction',
167
+ action: 'Execute a model action',
168
+ description: 'Execute a published Capability or workflow action on a record',
169
+ },
170
+ {
171
+ name: 'Get',
172
+ value: 'get',
173
+ action: 'Get a model record',
174
+ description: 'Get one model record by ID',
175
+ },
176
+ {
177
+ name: 'List / Query',
178
+ value: 'list',
179
+ action: 'List or query model records',
180
+ description: 'Query a model collection using its published query contract',
181
+ },
182
+ {
183
+ name: 'Update',
184
+ value: 'update',
185
+ action: 'Update a model record',
186
+ description: 'Update a record using optimistic concurrency',
187
+ },
188
+ ],
189
+ default: 'list',
190
+ },
191
+ {
192
+ displayName: 'Model Name or ID',
193
+ name: 'modelRoute',
194
+ type: 'options',
195
+ typeOptions: {
196
+ loadOptionsMethod: 'getModels',
197
+ },
198
+ options: [],
199
+ default: '',
200
+ required: true,
201
+ displayOptions: { show: { resource: ['modelRecord'] } },
202
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
203
+ },
204
+ {
205
+ displayName: 'Record ID',
206
+ name: 'recordId',
207
+ type: 'string',
208
+ default: '',
209
+ required: true,
210
+ displayOptions: {
211
+ show: {
212
+ resource: ['modelRecord'],
213
+ operation: ['get', 'update', 'delete', 'executeAction'],
214
+ },
215
+ },
216
+ },
217
+ {
218
+ displayName: 'Fields',
219
+ name: 'fields',
220
+ type: 'resourceMapper',
221
+ default: {
222
+ mappingMode: 'defineBelow',
223
+ value: null,
224
+ },
225
+ noDataExpression: true,
226
+ required: true,
227
+ typeOptions: {
228
+ loadOptionsDependsOn: ['modelRoute', 'operation'],
229
+ resourceMapper: {
230
+ resourceMapperMethod: 'getModelFields',
231
+ mode: 'add',
232
+ fieldWords: {
233
+ singular: 'field',
234
+ plural: 'fields',
235
+ },
236
+ addAllFields: true,
237
+ supportAutoMap: false,
238
+ noFieldsError: 'The selected LifeSpace model has no writable fields for this operation.',
239
+ },
240
+ },
241
+ displayOptions: {
242
+ show: {
243
+ resource: ['modelRecord'],
244
+ operation: ['create', 'update'],
245
+ },
246
+ },
247
+ description: 'Writable fields loaded from the selected model through LifeSpace Runtime Discovery',
248
+ },
249
+ {
250
+ displayName: 'Version',
251
+ name: 'version',
252
+ type: 'number',
253
+ typeOptions: { minValue: 1, numberPrecision: 0 },
254
+ default: 1,
255
+ required: true,
256
+ displayOptions: {
257
+ show: {
258
+ resource: ['modelRecord'],
259
+ operation: ['update', 'delete'],
260
+ },
261
+ },
262
+ description: 'Current record version used for optimistic concurrency',
263
+ },
264
+ {
265
+ displayName: 'Search',
266
+ name: 'search',
267
+ type: 'string',
268
+ default: '',
269
+ displayOptions: { show: { resource: ['modelRecord'], operation: ['list'] } },
270
+ description: 'Full-text search across the selected model fields declared searchable by LifeSpace. Leave empty to disable search.',
271
+ },
272
+ {
273
+ displayName: 'Filters',
274
+ name: 'filters',
275
+ type: 'fixedCollection',
276
+ default: {},
277
+ placeholder: 'Add Filter',
278
+ typeOptions: { multipleValues: true },
279
+ displayOptions: { show: { resource: ['modelRecord'], operation: ['list'] } },
280
+ options: [
281
+ {
282
+ displayName: 'Filter',
283
+ name: 'filter',
284
+ values: [
285
+ {
286
+ displayName: 'Field Name or ID',
287
+ name: 'field',
288
+ type: 'options',
289
+ typeOptions: { loadOptionsMethod: 'getFilterableFields' },
290
+ options: [],
291
+ default: '',
292
+ required: true,
293
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
294
+ },
295
+ {
296
+ displayName: 'Operator',
297
+ name: 'operator',
298
+ type: 'options',
299
+ options: [
300
+ { name: 'Equals', value: 'exact' },
301
+ { name: 'From / Greater Than or Equal', value: 'from' },
302
+ { name: 'To / Less Than or Equal', value: 'to' },
303
+ ],
304
+ default: 'exact',
305
+ description: 'Range operators are supported by LifeSpace only for date, datetime, integer and number fields',
306
+ },
307
+ {
308
+ displayName: 'Value',
309
+ name: 'value',
310
+ type: 'string',
311
+ default: '',
312
+ required: true,
313
+ description: 'For enum equality filters, comma-separated values select any of the listed values. Relation fields use LifeSpace IDs.',
314
+ },
315
+ ],
316
+ },
317
+ ],
318
+ },
319
+ {
320
+ displayName: 'Sort Field Name or ID',
321
+ name: 'sortField',
322
+ type: 'options',
323
+ typeOptions: { loadOptionsMethod: 'getSortableFields' },
324
+ options: [],
325
+ default: 'createdAt',
326
+ required: true,
327
+ displayOptions: { show: { resource: ['modelRecord'], operation: ['list'] } },
328
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
329
+ },
330
+ {
331
+ displayName: 'Sort Direction',
332
+ name: 'sortDirection',
333
+ type: 'options',
334
+ options: [
335
+ { name: 'Ascending', value: 'asc' },
336
+ { name: 'Descending', value: 'desc' },
337
+ ],
338
+ default: 'desc',
339
+ displayOptions: { show: { resource: ['modelRecord'], operation: ['list'] } },
340
+ },
341
+ {
342
+ displayName: 'Limit',
343
+ name: 'limit',
344
+ type: 'number',
345
+ typeOptions: { minValue: 1, maxValue: 200, numberPrecision: 0 },
346
+ default: 50,
347
+ displayOptions: { show: { resource: ['modelRecord'], operation: ['list'] } },
348
+ description: 'Max number of results to return',
349
+ },
350
+ {
351
+ displayName: 'Cursor',
352
+ name: 'cursor',
353
+ type: 'string',
354
+ default: '',
355
+ displayOptions: { show: { resource: ['modelRecord'], operation: ['list'] } },
356
+ description: 'Opaque nextCursor returned by a previous query. Leave empty for the first page.',
357
+ },
358
+ {
359
+ displayName: 'Action Name or ID',
360
+ name: 'actionKey',
361
+ type: 'options',
362
+ typeOptions: {
363
+ loadOptionsMethod: 'getActions',
364
+ },
365
+ options: [],
366
+ default: '',
367
+ required: true,
368
+ displayOptions: {
369
+ show: {
370
+ resource: ['modelRecord'],
371
+ operation: ['executeAction'],
372
+ },
373
+ },
374
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
375
+ },
376
+ {
377
+ displayName: 'Action Input',
378
+ name: 'actionInput',
379
+ type: 'resourceMapper',
380
+ default: {
381
+ mappingMode: 'defineBelow',
382
+ value: null,
383
+ },
384
+ noDataExpression: true,
385
+ required: true,
386
+ typeOptions: {
387
+ loadOptionsDependsOn: ['modelRoute', 'actionKey'],
388
+ resourceMapper: {
389
+ resourceMapperMethod: 'getActionInputFields',
390
+ mode: 'add',
391
+ fieldWords: {
392
+ singular: 'input',
393
+ plural: 'inputs',
394
+ },
395
+ addAllFields: true,
396
+ supportAutoMap: false,
397
+ noFieldsError: 'The selected LifeSpace action does not accept input fields.',
398
+ },
399
+ },
400
+ displayOptions: {
401
+ show: {
402
+ resource: ['modelRecord'],
403
+ operation: ['executeAction'],
404
+ },
405
+ },
406
+ description: 'Action input loaded from LifeSpace Runtime Discovery and validated again by Core at execution time',
407
+ },
408
+ {
409
+ displayName: 'Operation',
410
+ name: 'operation',
411
+ type: 'options',
412
+ noDataExpression: true,
413
+ displayOptions: { show: { resource: ['apiRequest'] } },
414
+ options: [
415
+ {
416
+ name: 'API Request',
417
+ value: 'apiRequest',
418
+ action: 'Make an API request',
419
+ description: 'Call a path relative to the configured LifeSpace Connection Base URL',
420
+ },
421
+ ],
422
+ default: 'apiRequest',
423
+ },
424
+ {
425
+ displayName: 'Method',
426
+ name: 'method',
427
+ type: 'options',
428
+ displayOptions: { show: { resource: ['apiRequest'] } },
429
+ options: [
430
+ { name: 'DELETE', value: 'DELETE' },
431
+ { name: 'GET', value: 'GET' },
432
+ { name: 'PATCH', value: 'PATCH' },
433
+ { name: 'POST', value: 'POST' },
434
+ { name: 'PUT', value: 'PUT' },
435
+ ],
436
+ default: 'GET',
437
+ },
438
+ {
439
+ displayName: 'Path',
440
+ name: 'path',
441
+ type: 'string',
442
+ default: '/',
443
+ required: true,
444
+ displayOptions: { show: { resource: ['apiRequest'] } },
445
+ description: 'Path relative to the configured LifeSpace Connection Base URL',
446
+ },
447
+ {
448
+ displayName: 'JSON Body',
449
+ name: 'jsonBody',
450
+ type: 'json',
451
+ default: '{}',
452
+ displayOptions: {
453
+ show: {
454
+ resource: ['apiRequest'],
455
+ method: ['POST', 'PATCH', 'PUT', 'DELETE'],
456
+ },
457
+ },
458
+ },
459
+ ],
460
+ };
461
+ this.methods = {
462
+ loadOptions: {
463
+ async getModels() {
464
+ const discovery = await loadDiscovery.call(this);
465
+ const operation = String(this.getNodeParameter('operation', 'list'));
466
+ return discovery.data.models
467
+ .filter((model) => operation === 'executeAction'
468
+ ? model.actions.length > 0
469
+ : model.access.includes(requiredAccessForOperation(operation)))
470
+ .map((model) => {
471
+ var _a;
472
+ return ({
473
+ name: `${model.display.plural} (${model.route})`,
474
+ value: model.route,
475
+ description: (_a = model.description) !== null && _a !== void 0 ? _a : undefined,
476
+ });
477
+ });
478
+ },
479
+ async getActions() {
480
+ const modelRoute = String(this.getNodeParameter('modelRoute', '')).trim();
481
+ if (!modelRoute)
482
+ return [];
483
+ const discovery = await loadDiscovery.call(this);
484
+ const model = selectedModel(discovery, modelRoute);
485
+ if (!model)
486
+ return [];
487
+ return model.actions.map((action) => ({
488
+ name: action.key,
489
+ value: action.key,
490
+ description: `${action.kind} action · ${action.access} access`,
491
+ }));
492
+ },
493
+ async getFilterableFields() {
494
+ const modelRoute = String(this.getNodeParameter('modelRoute', '')).trim();
495
+ if (!modelRoute)
496
+ return [];
497
+ const discovery = await loadDiscovery.call(this);
498
+ const model = selectedModel(discovery, modelRoute);
499
+ if (!model)
500
+ return [];
501
+ return model.query.filterable.map((fieldKey) => {
502
+ var _a, _b;
503
+ const field = model.fields.find((entry) => entry.key === fieldKey);
504
+ const rangeSupported = field && ['date', 'datetime', 'integer', 'number'].includes(field.type);
505
+ return {
506
+ name: fieldKey,
507
+ value: fieldKey,
508
+ description: rangeSupported ? `${(_a = field === null || field === void 0 ? void 0 : field.type) !== null && _a !== void 0 ? _a : 'field'} · equality and range filters` : `${(_b = field === null || field === void 0 ? void 0 : field.type) !== null && _b !== void 0 ? _b : 'field'} · equality filter`,
509
+ };
510
+ });
511
+ },
512
+ async getSortableFields() {
513
+ const modelRoute = String(this.getNodeParameter('modelRoute', '')).trim();
514
+ if (!modelRoute)
515
+ return [];
516
+ const discovery = await loadDiscovery.call(this);
517
+ const model = selectedModel(discovery, modelRoute);
518
+ if (!model)
519
+ return [];
520
+ return [
521
+ { name: 'Created At', value: 'createdAt' },
522
+ { name: 'Updated At', value: 'updatedAt' },
523
+ ...model.query.sortable.map((fieldKey) => ({ name: fieldKey, value: fieldKey })),
524
+ ];
525
+ },
526
+ },
527
+ resourceMapping: {
528
+ async getModelFields() {
529
+ const modelRoute = String(this.getNodeParameter('modelRoute', '')).trim();
530
+ if (!modelRoute)
531
+ return { fields: [] };
532
+ const operation = String(this.getNodeParameter('operation', 'create'));
533
+ const discovery = await loadDiscovery.call(this);
534
+ const model = selectedModel(discovery, modelRoute);
535
+ if (!model)
536
+ return { fields: [] };
537
+ const fields = model.fields
538
+ .filter((field) => !field.readOnly && (operation !== 'update' || !field.immutable))
539
+ .map((field) => mapperField(field, operation === 'create' && field.required === true));
540
+ return { fields };
541
+ },
542
+ async getActionInputFields() {
543
+ const modelRoute = String(this.getNodeParameter('modelRoute', '')).trim();
544
+ const actionKey = String(this.getNodeParameter('actionKey', '')).trim();
545
+ if (!modelRoute || !actionKey)
546
+ return { fields: [] };
547
+ const discovery = await loadDiscovery.call(this);
548
+ const model = selectedModel(discovery, modelRoute);
549
+ const action = model === null || model === void 0 ? void 0 : model.actions.find((entry) => entry.key === actionKey);
550
+ if (!action)
551
+ return { fields: [] };
552
+ return {
553
+ fields: action.input.fields.map((field) => mapperField(field, field.required === true)),
554
+ };
555
+ },
556
+ },
557
+ };
558
+ }
559
+ async execute() {
560
+ const items = this.getInputData();
561
+ const output = [];
562
+ const credentials = await this.getCredentials('lifeSpaceApi');
563
+ const baseUrl = String(credentials.baseUrl).replace(/\/$/, '');
564
+ for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
565
+ try {
566
+ const resource = this.getNodeParameter('resource', itemIndex);
567
+ let options;
568
+ if (resource === 'modelRecord') {
569
+ const operation = this.getNodeParameter('operation', itemIndex);
570
+ const modelRoute = encodeURIComponent(String(this.getNodeParameter('modelRoute', itemIndex)));
571
+ const collectionPath = `/${modelRoute}`;
572
+ if (operation === 'list') {
573
+ options = {
574
+ method: 'GET',
575
+ url: `${baseUrl}${collectionPath}`,
576
+ qs: queryParameters(this, itemIndex),
577
+ json: true,
578
+ };
579
+ }
580
+ else if (operation === 'create') {
581
+ options = {
582
+ method: 'POST',
583
+ url: `${baseUrl}${collectionPath}`,
584
+ body: mappedValue(this, itemIndex, 'fields'),
585
+ json: true,
586
+ };
587
+ }
588
+ else {
589
+ const recordId = encodeURIComponent(String(this.getNodeParameter('recordId', itemIndex)));
590
+ const recordPath = `${collectionPath}/${recordId}`;
591
+ if (operation === 'get') {
592
+ options = { method: 'GET', url: `${baseUrl}${recordPath}`, json: true };
593
+ }
594
+ else if (operation === 'update') {
595
+ options = {
596
+ method: 'PATCH',
597
+ url: `${baseUrl}${recordPath}`,
598
+ body: { ...mappedValue(this, itemIndex, 'fields'), version: this.getNodeParameter('version', itemIndex) },
599
+ json: true,
600
+ };
601
+ }
602
+ else if (operation === 'delete') {
603
+ options = {
604
+ method: 'DELETE',
605
+ url: `${baseUrl}${recordPath}`,
606
+ body: { version: this.getNodeParameter('version', itemIndex) },
607
+ json: true,
608
+ };
609
+ }
610
+ else {
611
+ const actionKey = encodeURIComponent(String(this.getNodeParameter('actionKey', itemIndex)));
612
+ options = {
613
+ method: 'POST',
614
+ url: `${baseUrl}${recordPath}/actions/${actionKey}`,
615
+ body: mappedValue(this, itemIndex, 'actionInput'),
616
+ json: true,
617
+ };
618
+ }
619
+ }
620
+ }
621
+ else {
622
+ const method = this.getNodeParameter('method', itemIndex);
623
+ const path = String(this.getNodeParameter('path', itemIndex));
624
+ options = {
625
+ method,
626
+ url: `${baseUrl}${path.startsWith('/') ? path : `/${path}`}`,
627
+ json: true,
628
+ };
629
+ if (['POST', 'PATCH', 'PUT', 'DELETE'].includes(String(method))) {
630
+ options.body = parseJsonObject(this, itemIndex, this.getNodeParameter('jsonBody', itemIndex, '{}'), 'JSON Body');
631
+ }
632
+ }
633
+ const response = await this.helpers.httpRequestWithAuthentication.call(this, 'lifeSpaceApi', options);
634
+ const json = typeof response === 'object' && response !== null
635
+ ? response
636
+ : response === undefined || response === null
637
+ ? { success: true }
638
+ : { data: response };
639
+ output.push({ json, pairedItem: { item: itemIndex } });
640
+ }
641
+ catch (error) {
642
+ if (this.continueOnFail()) {
643
+ output.push({
644
+ json: { error: error instanceof Error ? error.message : String(error) },
645
+ pairedItem: { item: itemIndex },
646
+ });
647
+ continue;
648
+ }
649
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), error, { itemIndex });
650
+ }
651
+ }
652
+ return [output];
653
+ }
654
+ }
655
+ exports.LifeSpace = LifeSpace;
656
+ //# sourceMappingURL=LifeSpace.node.js.map