@limetech/n8n-nodes-lime 2.3.1-dev.1 → 2.5.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 (51) hide show
  1. package/.github/workflows/lint.yml +1 -1
  2. package/.github/workflows/release.yml +16 -2
  3. package/.github/workflows/test-and-build.yml +0 -15
  4. package/CHANGELOG.md +35 -2
  5. package/nodes/errorHandling.ts +60 -0
  6. package/nodes/lime-crm/LimeCrmNode.node.ts +8 -0
  7. package/nodes/lime-crm/LimeCrmTrigger.node.ts +19 -5
  8. package/nodes/lime-crm/methods/getLimetypeProperties.ts +3 -1
  9. package/nodes/lime-crm/methods/getLimetypes.ts +2 -1
  10. package/nodes/lime-crm/methods/index.ts +5 -0
  11. package/nodes/lime-crm/methods/resourceMapping.ts +141 -0
  12. package/nodes/lime-crm/models/limetype.ts +18 -0
  13. package/nodes/lime-crm/resources/admin/index.ts +9 -4
  14. package/nodes/lime-crm/resources/admin/operations/getManyUsers.operation.ts +10 -2
  15. package/nodes/lime-crm/resources/admin/operations/getSingleUser.operation.ts +14 -15
  16. package/nodes/lime-crm/resources/data/index.ts +15 -6
  17. package/nodes/lime-crm/resources/data/operations/createSingleObject.operation.ts +25 -71
  18. package/nodes/lime-crm/resources/data/operations/deleteSingleObject.operation.ts +7 -2
  19. package/nodes/lime-crm/resources/data/operations/getManyObjects.operation.ts +6 -2
  20. package/nodes/lime-crm/resources/data/operations/getSingleFile.operation.ts +15 -3
  21. package/nodes/lime-crm/resources/data/operations/getSingleObject.operation.ts +15 -6
  22. package/nodes/lime-crm/resources/data/operations/updateSingleObject.operation.ts +41 -57
  23. package/nodes/lime-crm/resources/metadata/index.ts +7 -3
  24. package/nodes/lime-crm/resources/metadata/operations/getAllLimetypes.operation.ts +6 -2
  25. package/nodes/lime-crm/resources/metadata/operations/getSingleFileMetadata.operation.ts +18 -15
  26. package/nodes/lime-crm/resources/metadata/operations/getSingleLimetype.operation.ts +8 -3
  27. package/nodes/lime-crm/transport/commons.ts +34 -20
  28. package/nodes/lime-crm/transport/files.ts +72 -47
  29. package/nodes/lime-crm/transport/limeQuery.ts +2 -2
  30. package/nodes/lime-crm/transport/limeobjects.ts +22 -10
  31. package/nodes/lime-crm/transport/limetypes.ts +37 -16
  32. package/nodes/lime-crm/transport/users.ts +74 -38
  33. package/nodes/lime-crm/transport/webhooks.ts +5 -4
  34. package/nodes/lime-crm/utils/files.ts +27 -10
  35. package/nodes/lime-crm/utils/index.ts +1 -1
  36. package/nodes/response.ts +41 -3
  37. package/package.json +4 -2
  38. package/tests/nodes/lime-crm/methods.spec.ts +91 -0
  39. package/tests/nodes/lime-crm/utils.spec.ts +60 -25
  40. package/nodes/lime-crm/utils/propertyAdapters.ts +0 -75
  41. package/restore_script/README +0 -42
  42. package/restore_script/api_key_upload.txt +0 -0
  43. package/restore_script/cli.py +0 -73
  44. package/restore_script/download.py +0 -73
  45. package/restore_script/main.py +0 -19
  46. package/restore_script/poetry.lock +0 -162
  47. package/restore_script/pyproject.toml +0 -15
  48. package/restore_script/transfer.py +0 -41
  49. package/restore_script/upload.py +0 -66
  50. package/restore_script/utils.py +0 -42
  51. /package/{restore_script/api_key_download.txt → Dockerfile} +0 -0
@@ -1,13 +1,12 @@
1
1
  import { callLimeApi, getLimeobject } from '.';
2
+ import { IExecuteFunctions, IBinaryData, BINARY_ENCODING } from 'n8n-workflow';
3
+ import { prepareResponseWithoutKeys } from './commons';
2
4
  import {
3
- IExecuteFunctions,
4
- IBinaryData,
5
- BINARY_ENCODING,
6
- NodeOperationError,
7
- } from 'n8n-workflow';
8
- import { removeKeys } from './commons';
9
- import { getFilenameFromHeader, setFilename } from '../utils';
10
-
5
+ getFilenameFromHeader,
6
+ handleWorkflowError,
7
+ setFilename,
8
+ } from '../utils';
9
+ import { APIResponse } from '../../response';
11
10
  /**
12
11
  * Endpoint path for Lime CRM file API.
13
12
  *
@@ -71,13 +70,16 @@ export type FileMetadata = {
71
70
  export async function getFileMetadata(
72
71
  nodeContext: IExecuteFunctions,
73
72
  id: string | number
74
- ): Promise<FileMetadata> {
73
+ ): Promise<APIResponse<FileMetadata>> {
75
74
  const url = `${LIME_FILE_URL}${id}/`;
76
- const fileMetadata = await callLimeApi<FileMetadata>(nodeContext, {
75
+ const fileMetadataResponse = await callLimeApi<FileMetadata>(nodeContext, {
77
76
  method: 'GET',
78
77
  url: url,
79
78
  });
80
- return removeKeys(fileMetadata, ['_links']);
79
+
80
+ if (!fileMetadataResponse.success) return fileMetadataResponse;
81
+
82
+ return prepareResponseWithoutKeys(fileMetadataResponse, ['_links']);
81
83
  }
82
84
 
83
85
  /**
@@ -97,19 +99,27 @@ export async function getFileMetadataByLimeobject(
97
99
  limetype: string,
98
100
  id: string,
99
101
  fileTypeProperty: string
100
- ): Promise<FileMetadata> {
102
+ ): Promise<APIResponse<FileMetadata>> {
101
103
  const objectResponse = await getLimeobject(nodeContext, limetype, id);
102
- const fileId = objectResponse[fileTypeProperty] as string | undefined;
104
+ if (!objectResponse.success) return objectResponse;
105
+
106
+ const fileId = objectResponse.data[fileTypeProperty] as string | undefined;
103
107
 
104
108
  if (!fileId) {
105
- throw new NodeOperationError(
106
- nodeContext.getNode(),
107
- 'The specified Limeobject does not have an associated file.'
109
+ return handleWorkflowError(
110
+ nodeContext,
111
+ {
112
+ message:
113
+ 'The specified Limeobject does not have an associated file',
114
+ },
115
+ true
108
116
  );
109
117
  }
110
118
 
111
- const fileMetadata = await getFileMetadata(nodeContext, fileId);
112
- return removeKeys(fileMetadata, ['_links']);
119
+ const fileMetadataResponse = await getFileMetadata(nodeContext, fileId);
120
+ if (!fileMetadataResponse.success) return fileMetadataResponse;
121
+
122
+ return prepareResponseWithoutKeys(fileMetadataResponse, ['_links']);
113
123
  }
114
124
 
115
125
  /**
@@ -125,7 +135,7 @@ export async function getFileMetadataByLimeobject(
125
135
  export async function getFileContent(
126
136
  nodeContext: IExecuteFunctions,
127
137
  id: string | number
128
- ): Promise<IBinaryData> {
138
+ ): Promise<APIResponse<IBinaryData>> {
129
139
  const url = `${LIME_FILE_URL}${id}/contents/`;
130
140
 
131
141
  const response = await callLimeApi<FileApiResponse>(nodeContext, {
@@ -139,13 +149,19 @@ export async function getFileContent(
139
149
  json: false,
140
150
  });
141
151
 
142
- const fileName = getFilenameFromHeader(response.headers) || `file_${id}`;
152
+ if (!response.success) return response;
153
+
154
+ const fileName =
155
+ getFilenameFromHeader(response.data.headers) || `file_${id}`;
143
156
  const binaryData = await nodeContext.helpers.prepareBinaryData(
144
- response.body
157
+ response.data.body
145
158
  );
146
159
  binaryData.fileName = setFilename(binaryData, fileName);
147
160
 
148
- return binaryData;
161
+ return {
162
+ success: true,
163
+ data: binaryData,
164
+ };
149
165
  }
150
166
 
151
167
  /**
@@ -165,14 +181,22 @@ export async function getFileContentByLimetype(
165
181
  limetype: string,
166
182
  id: string,
167
183
  fileTypeProperty: string
168
- ): Promise<IBinaryData> {
184
+ ): Promise<APIResponse<IBinaryData>> {
169
185
  const limeObjectResponse = await getLimeobject(nodeContext, limetype, id);
170
- const fileId = limeObjectResponse[fileTypeProperty] as string | undefined;
186
+ if (!limeObjectResponse.success) return limeObjectResponse;
187
+
188
+ const fileId = limeObjectResponse.data[fileTypeProperty] as
189
+ | string
190
+ | undefined;
171
191
 
172
192
  if (!fileId) {
173
- throw new NodeOperationError(
174
- nodeContext.getNode(),
175
- 'The specified Limeobject does not have an associated file.'
193
+ return handleWorkflowError(
194
+ nodeContext,
195
+ {
196
+ message:
197
+ 'The specified Limeobject does not have an associated file.',
198
+ },
199
+ true
176
200
  );
177
201
  }
178
202
 
@@ -194,27 +218,28 @@ export async function createFile(
194
218
  nodeContext: IExecuteFunctions,
195
219
  binary: IBinaryData,
196
220
  fallbackFileName: string
197
- ): Promise<FileMetadata> {
198
- let response: FileMetadata;
199
- try {
200
- response = await callLimeApi<FileMetadata>(nodeContext, {
201
- method: 'POST',
202
- url: LIME_FILE_URL,
203
- requestOptions: {
204
- body: Buffer.from(binary.data, BINARY_ENCODING),
205
- headers: {
206
- 'Content-Disposition': `;filename*="UTF-8''${encodeURIComponent(binary.fileName || fallbackFileName)}"`,
207
- 'Content-Type': binary.mimeType,
221
+ ): Promise<APIResponse<FileMetadata>> {
222
+ const response = await callLimeApi<FileMetadata>(nodeContext, {
223
+ method: 'POST',
224
+ url: LIME_FILE_URL,
225
+ requestOptions: {
226
+ body: Buffer.from(binary.data, BINARY_ENCODING),
227
+ headers: {
228
+ 'Content-Disposition': `;filename*="UTF-8''${encodeURIComponent(binary.fileName || fallbackFileName)}"`,
229
+ 'Content-Type': binary.mimeType,
230
+ },
231
+ },
232
+ });
233
+ if (!response.success)
234
+ return {
235
+ success: false,
236
+ data: {
237
+ error: {
238
+ message: response.data.error.message,
239
+ status: response.data.error.status,
208
240
  },
209
241
  },
210
- });
211
- } catch (error) {
212
- // Remove metadata from the response to reduce its overall size
213
- throw new NodeOperationError(
214
- nodeContext.getNode(),
215
- JSON.parse(error).error
216
- );
217
- }
242
+ };
218
243
 
219
- return removeKeys(response, ['_links']);
244
+ return prepareResponseWithoutKeys(response, ['_links']);
220
245
  }
@@ -1,7 +1,7 @@
1
1
  import { IAllExecuteFunctions } from 'n8n-workflow';
2
2
  import { callLimeApi } from './commons';
3
3
  import { APIResponsePrimitiveValue } from '../models';
4
-
4
+ import { APIResponse } from '../../response';
5
5
  /**
6
6
  * Endpoint path for Lime CRM Lime Query API.
7
7
  *
@@ -47,7 +47,7 @@ export interface QueryResponse {
47
47
  export async function queryLimeobjects(
48
48
  nodeContext: IAllExecuteFunctions,
49
49
  q: string
50
- ): Promise<QueryResponse> {
50
+ ): Promise<APIResponse<QueryResponse>> {
51
51
  const queryParameters = {
52
52
  q: q,
53
53
  };
@@ -1,7 +1,7 @@
1
- import { callLimeApi, removeKeys } from './commons';
1
+ import { callLimeApi, prepareResponseWithoutKeys } from './commons';
2
2
  import { IAllExecuteFunctions } from 'n8n-workflow';
3
3
  import { Limeobject } from '../models';
4
-
4
+ import { APIResponse } from '../../response';
5
5
  /**
6
6
  * Endpoint path for Lime CRM Limeobject API.
7
7
  *
@@ -51,7 +51,7 @@ export async function createLimeobject(
51
51
  nodeContext: IAllExecuteFunctions,
52
52
  limetype: string,
53
53
  data: object
54
- ): Promise<Limeobject> {
54
+ ): Promise<APIResponse<Limeobject>> {
55
55
  const url = `${LIMEOBJECT_URL}${limetype}/`;
56
56
  const response = await callLimeApi<LimeobjectCrmApiResponse>(nodeContext, {
57
57
  method: 'POST',
@@ -63,7 +63,11 @@ export async function createLimeobject(
63
63
  limetype: limetype,
64
64
  },
65
65
  });
66
- return removeKeys(response, ['_links']);
66
+ if (response.success) {
67
+ return prepareResponseWithoutKeys(response, ['_links']);
68
+ } else {
69
+ return response;
70
+ }
67
71
  }
68
72
 
69
73
  /**
@@ -81,9 +85,9 @@ export async function deleteLimeobject(
81
85
  nodeContext: IAllExecuteFunctions,
82
86
  limetype: string,
83
87
  id: string
84
- ): Promise<void> {
88
+ ): Promise<APIResponse<Record<string, never>>> {
85
89
  const url = `${LIMEOBJECT_URL}${limetype}/${id}/`;
86
- return await callLimeApi(nodeContext, {
90
+ return await callLimeApi<Record<string, never>>(nodeContext, {
87
91
  method: 'DELETE',
88
92
  url: url,
89
93
  errorMetadata: {
@@ -108,7 +112,7 @@ export async function getLimeobject(
108
112
  nodeContext: IAllExecuteFunctions,
109
113
  limetype: string,
110
114
  id: string
111
- ): Promise<Limeobject> {
115
+ ): Promise<APIResponse<Limeobject>> {
112
116
  const url = `${LIMEOBJECT_URL}${limetype}/${id}/`;
113
117
  const response = await callLimeApi<LimeobjectCrmApiResponse>(nodeContext, {
114
118
  method: 'GET',
@@ -118,7 +122,11 @@ export async function getLimeobject(
118
122
  id: id,
119
123
  },
120
124
  });
121
- return removeKeys(response, ['_links']);
125
+ if (response.success) {
126
+ return prepareResponseWithoutKeys(response, ['_links']);
127
+ } else {
128
+ return response;
129
+ }
122
130
  }
123
131
 
124
132
  /**
@@ -138,7 +146,7 @@ export async function updateLimeobject(
138
146
  limetype: string,
139
147
  id: string,
140
148
  data: object
141
- ): Promise<Limeobject> {
149
+ ): Promise<APIResponse<Limeobject>> {
142
150
  const url = `${LIMEOBJECT_URL}${limetype}/${id}/`;
143
151
  const response = await callLimeApi<LimeobjectCrmApiResponse>(nodeContext, {
144
152
  method: 'PUT',
@@ -151,5 +159,9 @@ export async function updateLimeobject(
151
159
  id: id,
152
160
  },
153
161
  });
154
- return removeKeys(response, ['_links']);
162
+ if (response.success) {
163
+ return prepareResponseWithoutKeys(response, ['_links']);
164
+ } else {
165
+ return response;
166
+ }
155
167
  }
@@ -2,6 +2,7 @@ import { callLimeApi } from '.';
2
2
  import { IAllExecuteFunctions } from 'n8n-workflow';
3
3
  import { removeKeys } from './commons';
4
4
  import { Limetype, LimetypeProperty } from '../models';
5
+ import { APIResponse } from '../../response';
5
6
 
6
7
  /**
7
8
  * Endpoint path for Lime CRM Limetype API.
@@ -113,7 +114,7 @@ function deserializeLimetype(limetype: LimetypeCrmApiResponse): Limetype {
113
114
  */
114
115
  export async function getLimetypesFromApi(
115
116
  nodeContext: IAllExecuteFunctions
116
- ): Promise<Limetype[]> {
117
+ ): Promise<APIResponse<Limetype[]>> {
117
118
  const response = await callLimeApi<LimetypesCrmApiResponse>(nodeContext, {
118
119
  method: 'GET',
119
120
  url: LIMETYPE_URL,
@@ -123,7 +124,16 @@ export async function getLimetypesFromApi(
123
124
  },
124
125
  },
125
126
  });
126
- return response._embedded?.limetypes.map(deserializeLimetype) || [];
127
+ if (response.success) {
128
+ return {
129
+ success: true,
130
+ data:
131
+ response.data._embedded?.limetypes.map(deserializeLimetype) ||
132
+ [],
133
+ };
134
+ } else {
135
+ return response;
136
+ }
127
137
  }
128
138
 
129
139
  /**
@@ -139,7 +149,7 @@ export async function getLimetypesFromApi(
139
149
  export async function getLimetype(
140
150
  nodeContext: IAllExecuteFunctions,
141
151
  limetype: string
142
- ): Promise<Limetype> {
152
+ ): Promise<APIResponse<Limetype>> {
143
153
  const url = `${LIMETYPE_URL}${limetype}/`;
144
154
  const response = await callLimeApi<LimetypeCrmApiResponse>(nodeContext, {
145
155
  method: 'GET',
@@ -150,8 +160,14 @@ export async function getLimetype(
150
160
  },
151
161
  },
152
162
  });
153
-
154
- return deserializeLimetype(response);
163
+ if (response.success) {
164
+ return {
165
+ success: true,
166
+ data: deserializeLimetype(response.data),
167
+ };
168
+ } else {
169
+ return response;
170
+ }
155
171
  }
156
172
 
157
173
  /**
@@ -167,7 +183,7 @@ export async function getLimetype(
167
183
  export async function getProperties(
168
184
  nodeContext: IAllExecuteFunctions,
169
185
  limetype: string
170
- ): Promise<LimetypeProperty[]> {
186
+ ): Promise<APIResponse<LimetypeProperty[]>> {
171
187
  const url = `${LIMETYPE_URL}${limetype}/`;
172
188
  const response = await callLimeApi<LimetypePropertiesApiResponse>(
173
189
  nodeContext,
@@ -184,14 +200,19 @@ export async function getProperties(
184
200
  },
185
201
  }
186
202
  );
187
-
188
- return (
189
- response._embedded.properties.map(
190
- (property) =>
191
- removeKeys(property, [
192
- '_links',
193
- '_embedded',
194
- ]) as LimetypeProperty
195
- ) || []
196
- );
203
+ if (response.success) {
204
+ return {
205
+ success: true,
206
+ data:
207
+ response.data._embedded.properties.map(
208
+ (property) =>
209
+ removeKeys(property, [
210
+ '_links',
211
+ '_embedded',
212
+ ]) as LimetypeProperty
213
+ ) || [],
214
+ };
215
+ } else {
216
+ return response;
217
+ }
197
218
  }
@@ -2,7 +2,7 @@ import { callLimeApi } from './commons';
2
2
  import {
3
3
  IAllExecuteFunctions,
4
4
  LoggerProxy as Logger,
5
- NodeOperationError,
5
+ NodeApiError,
6
6
  } from 'n8n-workflow';
7
7
  import {
8
8
  User,
@@ -14,7 +14,8 @@ import {
14
14
  import { getLimetypesFromApi } from './limetypes';
15
15
  import { queryLimeobjects, QueryResponse } from './limeQuery';
16
16
  import { getLimeobject } from './limeobjects';
17
-
17
+ import { APIResponse } from '../../response';
18
+ import { handleWorkflowError } from '../../errorHandling';
18
19
  const USERS_URL = 'api/v1/admin/users/';
19
20
 
20
21
  type UserQueryParameters = {
@@ -49,21 +50,30 @@ function findCoworkerLimetype(limetypes: Limetype[]): Limetype | undefined {
49
50
  *
50
51
  * @param nodeContext - The n8n execution context
51
52
  * @returns The coworker limetype object
52
- * @throws NodeOperationError if no coworker limetype is found
53
+ * @throws NodeApiError if no coworker limetype is found
53
54
  * @internal
54
55
  */
55
56
  async function findCoworker(
56
57
  nodeContext: IAllExecuteFunctions
57
- ): Promise<Limetype> {
58
+ ): Promise<APIResponse<Limetype>> {
58
59
  const response = await getLimetypesFromApi(nodeContext);
59
- const coworker = findCoworkerLimetype(response);
60
+ if (!response.success) {
61
+ return response;
62
+ }
63
+ const coworker = findCoworkerLimetype(response.data);
60
64
  if (!coworker) {
61
- throw new NodeOperationError(
62
- nodeContext.getNode(),
63
- `No limetype with 'user' property found to get coworker`
65
+ return handleWorkflowError(
66
+ nodeContext,
67
+ {
68
+ message: `No limetype with 'user' property found to get coworker`,
69
+ },
70
+ true
64
71
  );
65
72
  }
66
- return coworker;
73
+ return {
74
+ success: true,
75
+ data: coworker,
76
+ };
67
77
  }
68
78
 
69
79
  /**
@@ -73,14 +83,14 @@ async function findCoworker(
73
83
  * @param coworker - The limetype definition for the coworker
74
84
  * @param userId - The ID of the user whose coworker data is to be fetched
75
85
  * @returns The coworker data response from the Lime Query API
76
- * @throws NodeOperationError if no 'user' property is found in the coworker limetype
86
+ * @throws NodeApiError' property is found in the coworker limetype
77
87
  * @internal
78
88
  */
79
89
  async function getCoworker(
80
90
  nodeContext: IAllExecuteFunctions,
81
91
  coworker: Limetype,
82
92
  userId: string | number
83
- ): Promise<QueryResponse> {
93
+ ): Promise<APIResponse<QueryResponse>> {
84
94
  // 'hasmany' properties are not supported in the response format of Lime Query API
85
95
  const properties = Object.fromEntries(
86
96
  coworker.properties
@@ -92,10 +102,9 @@ async function getCoworker(
92
102
  (prop) => prop.type === 'user'
93
103
  );
94
104
  if (!userProperty) {
95
- throw new NodeOperationError(
96
- nodeContext.getNode(),
97
- `No property of type 'user' found in ${coworker.name} limetype`
98
- );
105
+ throw new NodeApiError(nodeContext.getNode(), {
106
+ message: `No property of type 'user' found in ${coworker.name} limetype`,
107
+ });
99
108
  }
100
109
 
101
110
  const responseFormat = {
@@ -135,7 +144,7 @@ export async function fetchManyUsers(
135
144
  userType: UserType | NullOptionType = '',
136
145
  limit: number = DEFAULT_API_OBJECT_LIMIT,
137
146
  withCoworker: boolean = false
138
- ): Promise<User[]> {
147
+ ): Promise<APIResponse<User[]>> {
139
148
  const queryParams: UserQueryParameters = {
140
149
  _limit: limit,
141
150
  };
@@ -154,23 +163,31 @@ export async function fetchManyUsers(
154
163
  },
155
164
  });
156
165
 
157
- if (!withCoworker) return response;
158
- const coworker = await findCoworker(nodeContext);
166
+ if (!response.success || !withCoworker) return response;
167
+
168
+ const coworkerLimetypeResponse = await findCoworker(nodeContext);
169
+ if (!coworkerLimetypeResponse.success) return coworkerLimetypeResponse;
170
+
171
+ const coworkerLimetype = coworkerLimetypeResponse.data;
159
172
 
160
173
  const usersWithCoworkers: User[] = [];
161
- for (const user of response) {
174
+ for (const user of response.data) {
162
175
  const coworkerResponse = await getCoworker(
163
176
  nodeContext,
164
- coworker,
177
+ coworkerLimetype,
165
178
  user.id
166
179
  );
180
+ if (!coworkerResponse.success) return coworkerResponse;
167
181
  usersWithCoworkers.push({
168
182
  ...user,
169
- [coworker.name]: coworkerResponse.objects[0] || null,
183
+ [coworkerLimetype.name]: coworkerResponse.data.objects[0] || null,
170
184
  });
171
185
  }
172
186
 
173
- return usersWithCoworkers;
187
+ return {
188
+ success: true,
189
+ data: usersWithCoworkers,
190
+ };
174
191
  }
175
192
 
176
193
  /**
@@ -189,7 +206,7 @@ export async function fetchSingleUserById(
189
206
  nodeContext: IAllExecuteFunctions,
190
207
  id: string,
191
208
  withCoworker: boolean = false
192
- ): Promise<User> {
209
+ ): Promise<APIResponse<User>> {
193
210
  const url = `${USERS_URL}${id}`;
194
211
  const userResponse = await callLimeApi<User>(nodeContext, {
195
212
  method: 'GET',
@@ -199,13 +216,21 @@ export async function fetchSingleUserById(
199
216
  },
200
217
  });
201
218
 
202
- if (!withCoworker) return userResponse;
203
- const coworker = await findCoworker(nodeContext);
204
- const coworkerResponse = await getCoworker(nodeContext, coworker, id);
219
+ if (!userResponse.success || !withCoworker) return userResponse;
220
+ const coworkerLimetypeResponse = await findCoworker(nodeContext);
221
+ if (!coworkerLimetypeResponse.success) return coworkerLimetypeResponse;
222
+
223
+ const coworkerResponse = await getCoworker(
224
+ nodeContext,
225
+ coworkerLimetypeResponse.data,
226
+ id
227
+ );
228
+ if (!coworkerResponse.success) return coworkerResponse;
205
229
 
206
230
  return {
207
231
  ...userResponse,
208
- [coworker.name]: coworkerResponse.objects[0] || null,
232
+ [coworkerLimetypeResponse.data.name]:
233
+ coworkerResponse.data.objects[0] || null,
209
234
  };
210
235
  }
211
236
 
@@ -228,25 +253,33 @@ export async function fetchSingleUserByLimeobjectId(
228
253
  nodeContext: IAllExecuteFunctions,
229
254
  id: string,
230
255
  withCoworker: boolean = false
231
- ): Promise<User> {
232
- const coworker = await findCoworker(nodeContext);
256
+ ): Promise<APIResponse<User>> {
257
+ const coworkerLimetypeResponse = await findCoworker(nodeContext);
258
+ if (!coworkerLimetypeResponse.success) return coworkerLimetypeResponse;
259
+
260
+ const coworkerLimetype = coworkerLimetypeResponse.data;
261
+
233
262
  const coworkerResponse = await getLimeobject(
234
263
  nodeContext,
235
- coworker.name,
264
+ coworkerLimetype.name,
236
265
  id
237
266
  );
267
+ if (!coworkerResponse.success) return coworkerResponse;
238
268
 
239
- const userProperty = coworker.properties.find(
269
+ const userProperty = coworkerLimetype.properties.find(
240
270
  (prop) => prop.type === 'user'
241
271
  );
242
272
  if (!userProperty) {
243
- throw new NodeOperationError(
244
- nodeContext.getNode(),
245
- `No property of type 'user' found in ${coworker.name} limetype`
273
+ return handleWorkflowError(
274
+ nodeContext,
275
+ {
276
+ message: `No property of type 'user' found in ${coworkerLimetype.name} limetype`,
277
+ },
278
+ true
246
279
  );
247
280
  }
248
281
 
249
- const url = `${USERS_URL}${coworkerResponse[userProperty.name]}`;
282
+ const url = `${USERS_URL}${coworkerResponse.data[userProperty.name]}`;
250
283
  const userResponse = await callLimeApi<User>(nodeContext, {
251
284
  method: 'GET',
252
285
  url: url,
@@ -255,10 +288,13 @@ export async function fetchSingleUserByLimeobjectId(
255
288
  },
256
289
  });
257
290
 
258
- if (!withCoworker) return userResponse;
291
+ if (!userResponse.success || !withCoworker) return userResponse;
259
292
 
260
293
  return {
261
- ...userResponse,
262
- [coworker.name]: coworkerResponse || null,
294
+ success: true,
295
+ data: {
296
+ ...userResponse.data,
297
+ [coworkerLimetype.name]: coworkerResponse.data || null,
298
+ },
263
299
  };
264
300
  }
@@ -1,6 +1,7 @@
1
1
  import { callLimeApi } from '.';
2
2
  import { IAllExecuteFunctions } from 'n8n-workflow';
3
3
  import { CreateWebhook, Webhook } from '../models';
4
+ import { APIResponse } from '../../response';
4
5
 
5
6
  /**
6
7
  * Endpoint path for Lime CRM Subscription API.
@@ -44,7 +45,7 @@ export interface ApiResponseWebhook {
44
45
  export async function getSubscription(
45
46
  nodeContext: IAllExecuteFunctions,
46
47
  webhook: Webhook
47
- ): Promise<ApiResponseWebhook> {
48
+ ): Promise<APIResponse<ApiResponseWebhook>> {
48
49
  return await callLimeApi(nodeContext, {
49
50
  method: 'GET',
50
51
  url: `${SUBSCRIPTION_URL}${webhook.data.webhookId}`,
@@ -65,7 +66,7 @@ export async function getSubscription(
65
66
  export async function listSubscriptionsWithExistingData(
66
67
  nodeContext: IAllExecuteFunctions,
67
68
  webhook: Webhook
68
- ): Promise<ApiResponseWebhook[]> {
69
+ ): Promise<APIResponse<ApiResponseWebhook[]>> {
69
70
  return await callLimeApi(nodeContext, {
70
71
  method: 'GET',
71
72
  url: SUBSCRIPTION_URL,
@@ -93,7 +94,7 @@ export async function listSubscriptionsWithExistingData(
93
94
  export async function createSubscription(
94
95
  nodeContext: IAllExecuteFunctions,
95
96
  webhook: CreateWebhook
96
- ): Promise<ApiResponseWebhook> {
97
+ ): Promise<APIResponse<ApiResponseWebhook>> {
97
98
  return await callLimeApi(nodeContext, {
98
99
  method: 'POST',
99
100
  url: SUBSCRIPTION_URL,
@@ -122,7 +123,7 @@ export async function createSubscription(
122
123
  export async function deleteSubscription(
123
124
  nodeContext: IAllExecuteFunctions,
124
125
  webhook: Webhook
125
- ): Promise<void> {
126
+ ): Promise<APIResponse<void>> {
126
127
  return await callLimeApi(nodeContext, {
127
128
  method: 'DELETE',
128
129
  url: `${SUBSCRIPTION_URL}${webhook.data.webhookId}/`,