@limetech/n8n-nodes-lime 0.4.0 → 0.5.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 (64) hide show
  1. package/.prettierignore +3 -1
  2. package/CHANGELOG.md +93 -0
  3. package/README.md +1 -8
  4. package/credentials/LimeCrmApi.credentials.ts +6 -6
  5. package/docker-compose.yml +9 -3
  6. package/nodes/fortnox/Fortnox.node.ts +3 -3
  7. package/nodes/fortnox/FortnoxTrigger.node.ts +2 -2
  8. package/nodes/lime-crm/LimeCrmNode.node.ts +54 -67
  9. package/nodes/lime-crm/LimeCrmTrigger.node.ts +17 -24
  10. package/nodes/lime-crm/commons/constants.ts +2 -3
  11. package/nodes/lime-crm/commons/files.ts +162 -0
  12. package/nodes/lime-crm/commons/index.ts +4 -4
  13. package/nodes/lime-crm/commons/webhook.ts +15 -3
  14. package/nodes/lime-crm/methods/getLimetypeProperties.ts +67 -0
  15. package/nodes/lime-crm/methods/getLimetypes.ts +21 -0
  16. package/nodes/lime-crm/methods/index.ts +6 -2
  17. package/nodes/lime-crm/model.ts +22 -0
  18. package/nodes/lime-crm/resources/data/index.ts +80 -0
  19. package/nodes/lime-crm/resources/{limeObject/operations/create.operation.ts → data/operations/createSingleObject.ts} +53 -30
  20. package/nodes/lime-crm/resources/{limeObject/operations/delete.operation.ts → data/operations/deleteSingleObject.ts} +15 -15
  21. package/nodes/lime-crm/resources/data/operations/getManyObjects.ts +356 -0
  22. package/nodes/lime-crm/resources/data/operations/getSingleFile.ts +138 -0
  23. package/nodes/lime-crm/resources/data/operations/getSingleObject.ts +83 -0
  24. package/nodes/lime-crm/resources/{limeObject/operations/update.operation.ts → data/operations/updateSingleObject.operation.ts} +51 -23
  25. package/nodes/lime-crm/resources/erpConnector/index.ts +3 -3
  26. package/nodes/lime-crm/resources/erpConnector/operations/transform.operation.ts +14 -14
  27. package/nodes/lime-crm/resources/erpConnector/transform.ts +3 -3
  28. package/nodes/lime-crm/resources/erpConnector/transformers/baseTransformer.ts +2 -2
  29. package/nodes/lime-crm/resources/erpConnector/transformers/fortnox.ts +8 -8
  30. package/nodes/lime-crm/resources/metadata/index.ts +57 -0
  31. package/nodes/lime-crm/resources/metadata/operations/getAllLimetypes.operation.ts +18 -0
  32. package/nodes/lime-crm/resources/metadata/operations/getSingleFileMetadata.ts +130 -0
  33. package/nodes/lime-crm/resources/metadata/operations/getSingleLimetype.ts +36 -0
  34. package/nodes/lime-crm/transport/commons.ts +14 -2
  35. package/nodes/lime-crm/transport/files.ts +155 -0
  36. package/nodes/lime-crm/transport/index.ts +14 -7
  37. package/nodes/lime-crm/transport/limeQuery.ts +2 -4
  38. package/nodes/lime-crm/transport/limeobjects.ts +79 -44
  39. package/nodes/lime-crm/transport/limetypes.ts +80 -24
  40. package/package.json +4 -3
  41. package/restore_script/README +42 -0
  42. package/restore_script/api_key_download.txt +0 -0
  43. package/restore_script/api_key_upload.txt +0 -0
  44. package/restore_script/cli.py +73 -0
  45. package/restore_script/download.py +73 -0
  46. package/restore_script/main.py +19 -0
  47. package/restore_script/poetry.lock +162 -0
  48. package/restore_script/pyproject.toml +15 -0
  49. package/restore_script/transfer.py +41 -0
  50. package/restore_script/upload.py +66 -0
  51. package/restore_script/utils.py +42 -0
  52. package/tests/transform.spec.ts +6 -6
  53. package/nodes/lime-crm/commons/limetype.ts +0 -11
  54. package/nodes/lime-crm/methods/getLimeTypeProperties.ts +0 -27
  55. package/nodes/lime-crm/methods/getLimeTypes.ts +0 -23
  56. package/nodes/lime-crm/resources/limeObject/index.ts +0 -64
  57. package/nodes/lime-crm/resources/limeObject/operations/fetchMany.operation.ts +0 -112
  58. package/nodes/lime-crm/resources/limeObject/operations/get.operation.ts +0 -54
  59. package/nodes/lime-crm/resources/limeQuery/index.ts +0 -40
  60. package/nodes/lime-crm/resources/limeQuery/operations/query.operation.ts +0 -222
  61. package/nodes/lime-crm/resources/limeType/index.ts +0 -58
  62. package/nodes/lime-crm/resources/limeType/operations/getProperties.operation.ts +0 -42
  63. package/nodes/lime-crm/resources/limeType/operations/getType.operation.ts +0 -36
  64. package/nodes/lime-crm/resources/limeType/operations/listTypes.operation.ts +0 -18
@@ -0,0 +1,155 @@
1
+ import { callLimeApi, getLimeobject } from '.';
2
+ import { IExecuteFunctions, IBinaryData, BINARY_ENCODING } from 'n8n-workflow';
3
+ import { NodeResponse } from '../../nodeResponse';
4
+ import { removeKeys } from './commons';
5
+ import { getFilenameFromHeader, setFilename } from '../commons';
6
+
7
+ const LIME_FILE_URL = '/api/v1/file/';
8
+
9
+ interface FileApiResponse {
10
+ headers: Record<string, string | string[] | undefined>;
11
+ body: Buffer;
12
+ }
13
+
14
+ interface FileMetadata {
15
+ filename: string;
16
+ id: number;
17
+ size: number;
18
+ content_type: string;
19
+ extension: string;
20
+ created_by: number;
21
+ locked_by: number;
22
+ last_modified: string;
23
+ _links?: { [key: string]: { href: string } };
24
+ }
25
+
26
+ export async function getFileMetadata(
27
+ nodeContext: IExecuteFunctions,
28
+ id: string | number
29
+ ): Promise<NodeResponse<FileMetadata>> {
30
+ const url = `${LIME_FILE_URL}${id}/`;
31
+ const response = await callLimeApi<FileMetadata>(nodeContext, 'GET', url);
32
+ if (!response.success) {
33
+ return response;
34
+ }
35
+
36
+ return {
37
+ success: true,
38
+ data: removeKeys(response.data, ['_links']),
39
+ };
40
+ }
41
+
42
+ export async function getFileMetadataByLimeobject(
43
+ nodeContext: IExecuteFunctions,
44
+ limetype: string,
45
+ id: string,
46
+ fileTypeProperty: string
47
+ ): Promise<NodeResponse<FileMetadata>> {
48
+ const objectResponse = await getLimeobject(nodeContext, limetype, id);
49
+ if (!objectResponse.success) {
50
+ return objectResponse;
51
+ }
52
+ const fileId = objectResponse.data[fileTypeProperty] as string | undefined;
53
+
54
+ if (!fileId) {
55
+ return {
56
+ success: false,
57
+ error: 'The specified Limeobject does not have an associated file.',
58
+ };
59
+ }
60
+
61
+ const metadataResponse = await getFileMetadata(nodeContext, fileId);
62
+ if (!metadataResponse.success) {
63
+ return metadataResponse;
64
+ }
65
+
66
+ return {
67
+ success: true,
68
+ data: removeKeys(metadataResponse.data, ['_links']),
69
+ };
70
+ }
71
+
72
+ export async function getFileContent(
73
+ nodeContext: IExecuteFunctions,
74
+ id: string | number
75
+ ): Promise<NodeResponse<IBinaryData>> {
76
+ const url = `${LIME_FILE_URL}${id}/contents/`;
77
+
78
+ const response = await callLimeApi<FileApiResponse>(
79
+ nodeContext,
80
+ 'GET',
81
+ url,
82
+ {
83
+ encoding: null,
84
+ responseType: 'stream',
85
+ resolveWithFullResponse: true,
86
+ },
87
+ false
88
+ );
89
+ if (!response.success) {
90
+ return response;
91
+ }
92
+
93
+ const fileName =
94
+ getFilenameFromHeader(response.data.headers) || `file_${id}`;
95
+ const binaryData = await nodeContext.helpers.prepareBinaryData(
96
+ response.data.body
97
+ );
98
+ binaryData.fileName = setFilename(binaryData, fileName);
99
+
100
+ return {
101
+ success: true,
102
+ data: binaryData,
103
+ };
104
+ }
105
+
106
+ export async function getFileContentByLimetype(
107
+ nodeContext: IExecuteFunctions,
108
+ limetype: string,
109
+ id: string,
110
+ fileTypeProperty: string
111
+ ): Promise<NodeResponse<IBinaryData>> {
112
+ const objectResponse = await getLimeobject(nodeContext, limetype, id);
113
+ if (!objectResponse.success) {
114
+ return objectResponse;
115
+ }
116
+ const fileId = objectResponse.data[fileTypeProperty] as string | undefined;
117
+
118
+ if (!fileId) {
119
+ return {
120
+ success: false,
121
+ error: 'The specified Limeobject does not have an associated file.',
122
+ };
123
+ }
124
+
125
+ return await getFileContent(nodeContext, fileId);
126
+ }
127
+
128
+ export async function createFile(
129
+ nodeContext: IExecuteFunctions,
130
+ binary: IBinaryData,
131
+ fallbackFileName: string
132
+ ): Promise<NodeResponse<FileMetadata>> {
133
+ const response = await callLimeApi<FileMetadata>(
134
+ nodeContext,
135
+ 'POST',
136
+ LIME_FILE_URL,
137
+ {
138
+ body: Buffer.from(binary.data, BINARY_ENCODING),
139
+ headers: {
140
+ 'Content-Disposition': `;filename*="UTF-8''${encodeURIComponent(binary.fileName || fallbackFileName)}"`,
141
+ 'Content-Type': binary.mimeType,
142
+ },
143
+ }
144
+ );
145
+
146
+ // Remove metadata from the response to reduce its overall size
147
+ if (!response.success) {
148
+ return { success: false, error: response.error };
149
+ }
150
+
151
+ return {
152
+ success: true,
153
+ data: removeKeys(response.data, ['_links']),
154
+ };
155
+ }
@@ -4,15 +4,22 @@ export {
4
4
  createSubscription,
5
5
  listSubscriptionsWithExistingData,
6
6
  } from './webhooks';
7
- export { getLimeTypesFromApi, getProperties } from './limetypes';
7
+ export { getLimetypesFromApi, getProperties } from './limetypes';
8
8
 
9
9
  export {
10
- createLimeObject,
11
- deleteLimeObject,
12
- updateLimeObject,
13
- getLimeObject,
14
- fetchManyLimeObjects,
10
+ createLimeobject,
11
+ deleteLimeobject,
12
+ updateLimeobject,
13
+ getLimeobject,
14
+ fetchManyLimeobjects,
15
15
  } from './limeobjects';
16
16
  export { startCreateOrUpdateObjectsTask } from './erpConnector';
17
- export { queryLimeObjects } from './limeQuery';
17
+ export { queryLimeobjects } from './limeQuery';
18
+ export {
19
+ createFile,
20
+ getFileContent,
21
+ getFileContentByLimetype,
22
+ getFileMetadata,
23
+ getFileMetadataByLimeobject,
24
+ } from './files';
18
25
  export { callLimeApi } from './commons';
@@ -12,14 +12,12 @@ export interface QueryResponse {
12
12
  objects: IncludedProperties[];
13
13
  }
14
14
 
15
- export async function queryLimeObjects(
15
+ export async function queryLimeobjects(
16
16
  nodeContext: IAllExecuteFunctions,
17
- q: string,
18
- activeObject: string
17
+ q: string
19
18
  ): Promise<NodeResponse<QueryResponse>> {
20
19
  const queryParameters = {
21
20
  q: q,
22
- activeObject: activeObject,
23
21
  };
24
22
 
25
23
  return await callLimeApi(nodeContext, 'GET', LIME_QUERY_URL, {
@@ -1,41 +1,56 @@
1
- import { callLimeApi } from './commons';
1
+ import { callLimeApi, removeKeys } from './commons';
2
2
  import { IAllExecuteFunctions, IDataObject } from 'n8n-workflow';
3
3
  import { NodeResponse } from '../../nodeResponse';
4
+ import { Limeobject } from '../model';
4
5
 
5
6
  const LIMEOBJECT_URL = '/api/v1/limeobject/';
6
7
 
7
- interface FetchManyLimeObjectsApiResponse {
8
+ interface LimeobjectCrmApiResponse {
9
+ id_: number;
10
+ _links: object;
11
+ }
12
+
13
+ interface FetchManyLimeobjectsApiResponse {
8
14
  _embedded: {
9
- limeobjects: Array<object>;
15
+ limeobjects: LimeobjectCrmApiResponse[];
10
16
  };
11
17
  }
12
18
 
13
- export async function createLimeObject(
19
+ export async function createLimeobject(
14
20
  nodeContext: IAllExecuteFunctions,
15
- limeType: string,
21
+ limetype: string,
16
22
  data: object
17
- ): Promise<NodeResponse<unknown>> {
18
- const url = `${LIMEOBJECT_URL}${limeType}/`;
19
- const response = await callLimeApi(nodeContext, 'POST', url, {
20
- body: data,
21
- });
22
- if (response.success) return response;
23
+ ): Promise<NodeResponse<Limeobject>> {
24
+ const url = `${LIMEOBJECT_URL}${limetype}/`;
25
+ const response = await callLimeApi<LimeobjectCrmApiResponse>(
26
+ nodeContext,
27
+ 'POST',
28
+ url,
29
+ {
30
+ body: data,
31
+ }
32
+ );
33
+ if (response.success)
34
+ return {
35
+ success: true,
36
+ data: removeKeys(response.data, ['_links']),
37
+ };
23
38
 
24
39
  return {
25
40
  ...response,
26
41
  metadata: {
27
42
  ...response.metadata,
28
- limeType: limeType,
43
+ limetype: limetype,
29
44
  },
30
45
  };
31
46
  }
32
47
 
33
- export async function deleteLimeObject(
48
+ export async function deleteLimeobject(
34
49
  nodeContext: IAllExecuteFunctions,
35
- limeType: string,
50
+ limetype: string,
36
51
  id: string
37
52
  ): Promise<NodeResponse<void>> {
38
- const url = `${LIMEOBJECT_URL}${limeType}/${id}/`;
53
+ const url = `${LIMEOBJECT_URL}${limetype}/${id}/`;
39
54
  const response: NodeResponse<void> = await callLimeApi(
40
55
  nodeContext,
41
56
  'DELETE',
@@ -48,63 +63,80 @@ export async function deleteLimeObject(
48
63
  ...response,
49
64
  metadata: {
50
65
  ...response.metadata,
51
- limeType: limeType,
66
+ limetype: limetype,
52
67
  id: id,
53
68
  },
54
69
  };
55
70
  }
56
71
 
57
- export async function getLimeObject(
72
+ export async function getLimeobject(
58
73
  nodeContext: IAllExecuteFunctions,
59
- limeType: string,
74
+ limetype: string,
60
75
  id: string
61
- ): Promise<NodeResponse<unknown>> {
62
- const url = `${LIMEOBJECT_URL}${limeType}/${id}/`;
63
- const response = await callLimeApi(nodeContext, 'GET', url);
76
+ ): Promise<NodeResponse<Limeobject>> {
77
+ const url = `${LIMEOBJECT_URL}${limetype}/${id}/`;
78
+ const response = await callLimeApi<LimeobjectCrmApiResponse>(
79
+ nodeContext,
80
+ 'GET',
81
+ url
82
+ );
64
83
 
65
- if (response.success) return response;
84
+ if (response.success)
85
+ return {
86
+ success: true,
87
+ data: removeKeys(response.data, ['_links']),
88
+ };
66
89
 
67
90
  return {
68
91
  ...response,
69
92
  metadata: {
70
93
  ...response.metadata,
71
- limeType: limeType,
94
+ limetype: limetype,
72
95
  id: id,
73
96
  },
74
97
  };
75
98
  }
76
99
 
77
- export async function updateLimeObject(
100
+ export async function updateLimeobject(
78
101
  nodeContext: IAllExecuteFunctions,
79
- limeType: string,
102
+ limetype: string,
80
103
  id: string,
81
104
  data: object
82
- ): Promise<NodeResponse<unknown>> {
83
- const url = `${LIMEOBJECT_URL}${limeType}/${id}/`;
84
- const response = await callLimeApi(nodeContext, 'PUT', url, {
85
- body: data,
86
- });
105
+ ): Promise<NodeResponse<Limeobject>> {
106
+ const url = `${LIMEOBJECT_URL}${limetype}/${id}/`;
107
+ const response = await callLimeApi<LimeobjectCrmApiResponse>(
108
+ nodeContext,
109
+ 'PUT',
110
+ url,
111
+ {
112
+ body: data,
113
+ }
114
+ );
87
115
 
88
- if (response.success) return response;
116
+ if (response.success)
117
+ return {
118
+ success: true,
119
+ data: removeKeys(response.data, ['_links']),
120
+ };
89
121
 
90
122
  return {
91
123
  ...response,
92
124
  metadata: {
93
125
  ...response.metadata,
94
- limeType: limeType,
126
+ limetype: limetype,
95
127
  id: id,
96
128
  },
97
129
  };
98
130
  }
99
131
 
100
- async function _searchLimeObjectWithLimit(
132
+ async function _searchLimeobjectWithLimit(
101
133
  nodeContext: IAllExecuteFunctions,
102
134
  url: string,
103
135
  limit: number,
104
136
  offset: number,
105
137
  qs: IDataObject
106
- ): Promise<NodeResponse<FetchManyLimeObjectsApiResponse>> {
107
- const returnData = [];
138
+ ): Promise<NodeResponse<FetchManyLimeobjectsApiResponse>> {
139
+ const returnData: LimeobjectCrmApiResponse[] = [];
108
140
  let hasMoreData = true;
109
141
  let currentOffset = Math.max(0, offset);
110
142
  const pageLimit = 50;
@@ -113,7 +145,7 @@ async function _searchLimeObjectWithLimit(
113
145
  qs._limit = Math.min(limit, pageLimit);
114
146
  qs._offset = currentOffset;
115
147
 
116
- const response = await callLimeApi<FetchManyLimeObjectsApiResponse>(
148
+ const response = await callLimeApi<FetchManyLimeobjectsApiResponse>(
117
149
  nodeContext,
118
150
  'GET',
119
151
  url,
@@ -143,16 +175,16 @@ async function _searchLimeObjectWithLimit(
143
175
  };
144
176
  }
145
177
 
146
- export async function fetchManyLimeObjects(
178
+ export async function fetchManyLimeobjects(
147
179
  nodeContext: IAllExecuteFunctions,
148
- limeType: string,
180
+ limetype: string,
149
181
  searchField: string,
150
182
  searchTerm: string,
151
183
  limit: number,
152
184
  offset: number,
153
185
  sortField: string | null
154
- ): Promise<NodeResponse<Array<object>>> {
155
- const url = `${LIMEOBJECT_URL}${limeType}/`;
186
+ ): Promise<NodeResponse<Limeobject[]>> {
187
+ const url = `${LIMEOBJECT_URL}${limetype}/`;
156
188
  const qs: IDataObject = {
157
189
  ...(searchField && searchTerm && { [searchField]: searchTerm }),
158
190
  ...(offset != null && offset > 0 && { _offset: offset }),
@@ -161,7 +193,7 @@ export async function fetchManyLimeObjects(
161
193
 
162
194
  let response;
163
195
  if (limit) {
164
- response = await _searchLimeObjectWithLimit(
196
+ response = await _searchLimeobjectWithLimit(
165
197
  nodeContext,
166
198
  url,
167
199
  limit,
@@ -169,7 +201,7 @@ export async function fetchManyLimeObjects(
169
201
  qs
170
202
  );
171
203
  } else {
172
- response = await callLimeApi<FetchManyLimeObjectsApiResponse>(
204
+ response = await callLimeApi<FetchManyLimeobjectsApiResponse>(
173
205
  nodeContext,
174
206
  'GET',
175
207
  url,
@@ -182,7 +214,10 @@ export async function fetchManyLimeObjects(
182
214
  if (response.success) {
183
215
  return {
184
216
  success: true,
185
- data: response.data?._embedded.limeobjects ?? [],
217
+ data:
218
+ response.data?._embedded.limeobjects.map((limeobject) =>
219
+ removeKeys(limeobject, ['_links'])
220
+ ) ?? [],
186
221
  };
187
222
  }
188
223
  return {
@@ -191,7 +226,7 @@ export async function fetchManyLimeObjects(
191
226
  status: response.status,
192
227
  metadata: {
193
228
  ...response.metadata,
194
- limeType: limeType,
229
+ limetype: limetype,
195
230
  },
196
231
  };
197
232
  }
@@ -1,63 +1,112 @@
1
1
  import { callLimeApi } from '.';
2
2
  import { IAllExecuteFunctions } from 'n8n-workflow';
3
- import { LimeType, LimeTypeProperty } from '../commons';
3
+ import { Limetype, LimetypeProperty } from '../model';
4
4
  import { NodeResponse } from '../../nodeResponse';
5
+ import { removeKeys } from './commons';
5
6
 
6
7
  const LIMETYPE_URL = '/api/v1/limetype/';
7
8
 
8
- interface LimeTypesApiResponse {
9
- _links: {
10
- limetypes: LimeType[];
9
+ interface LimetypePropertyApiResponse {
10
+ name: string;
11
+ _links?: object;
12
+ _embedded?: object;
13
+ }
14
+
15
+ interface LimetypeCrmApiResponse {
16
+ name: string;
17
+ localname?: {
18
+ singular?: string;
19
+ plural?: string;
20
+ };
21
+ _embedded: {
22
+ properties: LimetypePropertyApiResponse[];
23
+ };
24
+ _links: object;
25
+ }
26
+
27
+ interface LimetypesCrmApiResponse {
28
+ _embedded: {
29
+ limetypes: LimetypeCrmApiResponse[];
30
+ _links: object;
11
31
  };
12
32
  }
13
33
 
14
- interface LimeTypePropertiesApiResponse {
34
+ interface LimetypePropertiesApiResponse {
15
35
  _embedded: {
16
- properties: LimeTypeProperty[];
36
+ properties: LimetypeCrmApiResponse[];
17
37
  };
18
38
  }
19
39
 
20
- export async function getLimeTypesFromApi(
40
+ function deserializeLimetype(limetype: LimetypeCrmApiResponse): Limetype {
41
+ return {
42
+ ...removeKeys(limetype, ['_links', '_embedded']),
43
+ properties: limetype._embedded.properties.map((property) =>
44
+ removeKeys(property, ['_links'])
45
+ ),
46
+ } as Limetype;
47
+ }
48
+
49
+ export async function getLimetypesFromApi(
21
50
  nodeContext: IAllExecuteFunctions
22
- ): Promise<NodeResponse<LimeType[]>> {
23
- const response = await callLimeApi<LimeTypesApiResponse>(
51
+ ): Promise<NodeResponse<Limetype[]>> {
52
+ const response = await callLimeApi<LimetypesCrmApiResponse>(
24
53
  nodeContext,
25
54
  'GET',
26
- LIMETYPE_URL
55
+ LIMETYPE_URL,
56
+ {
57
+ qs: {
58
+ _embed: 'limetypes.properties',
59
+ },
60
+ }
27
61
  );
28
62
  if (response.success) {
29
63
  return {
30
64
  success: true,
31
- data: response.data?._links.limetypes ?? [],
65
+ data:
66
+ response.data._embedded?.limetypes.map(deserializeLimetype) ||
67
+ [],
32
68
  };
33
69
  }
34
70
  return response;
35
71
  }
36
72
 
37
- export async function getLimeType(
73
+ export async function getLimetype(
38
74
  nodeContext: IAllExecuteFunctions,
39
- limeType: string
40
- ): Promise<NodeResponse<LimeType>> {
41
- const url = `${LIMETYPE_URL}${limeType}/`;
42
- const response = await callLimeApi<LimeType>(nodeContext, 'GET', url);
75
+ limetype: string
76
+ ): Promise<NodeResponse<Limetype>> {
77
+ const url = `${LIMETYPE_URL}${limetype}/`;
78
+ const response = await callLimeApi<LimetypeCrmApiResponse>(
79
+ nodeContext,
80
+ 'GET',
81
+ url,
82
+ {
83
+ qs: {
84
+ _embed: 'properties',
85
+ },
86
+ }
87
+ );
43
88
 
44
- if (response.success) return response;
89
+ if (response.success)
90
+ return {
91
+ success: true,
92
+ data: deserializeLimetype(response.data),
93
+ };
45
94
 
46
95
  return {
47
96
  ...response,
48
97
  metadata: {
49
98
  ...response.metadata,
50
- limetype: limeType,
99
+ limetype: limetype,
51
100
  },
52
101
  };
53
102
  }
54
103
 
55
104
  export async function getProperties(
56
105
  nodeContext: IAllExecuteFunctions,
57
- limeType: string
58
- ): Promise<NodeResponse<LimeTypeProperty[]>> {
59
- const url = `${LIMETYPE_URL}${limeType}/`;
60
- const response = await callLimeApi<LimeTypePropertiesApiResponse>(
106
+ limetype: string
107
+ ): Promise<NodeResponse<LimetypeProperty[]>> {
108
+ const url = `${LIMETYPE_URL}${limetype}/`;
109
+ const response = await callLimeApi<LimetypePropertiesApiResponse>(
61
110
  nodeContext,
62
111
  'GET',
63
112
  url,
@@ -71,7 +120,14 @@ export async function getProperties(
71
120
  if (response.success) {
72
121
  return {
73
122
  success: true,
74
- data: response.data?._embedded.properties ?? [],
123
+ data:
124
+ response.data?._embedded.properties.map(
125
+ (property) =>
126
+ removeKeys(property, [
127
+ '_links',
128
+ '_embedded',
129
+ ]) as LimetypeProperty
130
+ ) || [],
75
131
  };
76
132
  }
77
133
 
@@ -79,7 +135,7 @@ export async function getProperties(
79
135
  ...response,
80
136
  metadata: {
81
137
  ...response.metadata,
82
- limetype: limeType,
138
+ limetype: limetype,
83
139
  },
84
140
  };
85
141
  }
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@limetech/n8n-nodes-lime",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "n8n node to connect to Lime CRM",
5
5
  "license": "MIT",
6
6
  "main": "index.js",
7
7
  "scripts": {
8
- "build": "tsc && mkdir -p dist/nodes/lime-crm/assets && find nodes -name '*.svg' -exec cp {} dist/{} \\;",
8
+ "build": "tsc && copyfiles \"nodes/**/*.svg\" dist",
9
9
  "dev": "tsc --watch",
10
10
  "dev:reload": "nodemon --watch dist --exec 'cp -R dist/* ~/.n8n/custom/dist/'",
11
11
  "watch": "concurrently \"npm run dev\" \"npm run dev:reload\"",
@@ -48,6 +48,7 @@
48
48
  "@typescript-eslint/eslint-plugin": "^8.38.0",
49
49
  "@typescript-eslint/parser": "^8.38.0",
50
50
  "concurrently": "^7.0.0",
51
+ "copyfiles": "^2.4.1",
51
52
  "eslint": "^9.32.0",
52
53
  "eslint-config-prettier": "^10.1.8",
53
54
  "eslint-plugin-n8n-nodes-base": "^1.16.1",
@@ -70,6 +71,6 @@
70
71
  "ws": "^8.18.3"
71
72
  },
72
73
  "peerDependencies": {
73
- "n8n-workflow": "*"
74
+ "n8n-workflow": "^1.109.0"
74
75
  }
75
76
  }
@@ -0,0 +1,42 @@
1
+ ### n8n Scripts
2
+
3
+ Utility scripts to batch upload, download and transfer workflows as JSON data to and from an n8n instance via
4
+ its REST API.
5
+
6
+ =========================================================================================
7
+ ### Features
8
+ - download: Fetch items workflows from n8n and store locally.
9
+ - upload: Push local workflows to n8n.
10
+ - transfer: Combine download then upload for migrating between two instances without local storage
11
+ - cli: Unified command line entrypoint wrapping the download and upload operations.
12
+
13
+ =========================================================================================
14
+ ### Installation
15
+ ```bash
16
+ poetry install
17
+ ```
18
+
19
+ =========================================================================================
20
+ ### Usage
21
+
22
+ #### Interactive Mode
23
+ ```bash
24
+ poetry run python ./main.py
25
+ ```
26
+
27
+ The api_key can also be provided in files [root directory]:
28
+ - `api_key_download.txt` for download operations
29
+ - `api_key_upload.txt` for upload operations
30
+
31
+ #### CLI Mode
32
+ Download
33
+ ```bash
34
+ poetry run python ./cli.py download --instance_url <INSTANCE_URL> --api_key <API_KEY> --folder_path <FOLDER_PATH>
35
+ ```
36
+
37
+ Upload
38
+ ```bash
39
+ poetry run python ./cli.py upload --instance_url <INSTANCE_URL> --api_key <API_KEY> --folder_path <FOLDER_PATH>
40
+ ```
41
+
42
+ The api_key can also be provided via the N8N_API_KEY environment variable.
File without changes
File without changes