@limetech/n8n-nodes-lime 0.3.8 → 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 (85) hide show
  1. package/.prettierignore +3 -1
  2. package/CHANGELOG.md +100 -0
  3. package/README.md +1 -8
  4. package/credentials/LimeCrmApi.credentials.ts +6 -6
  5. package/dist/nodes/lime-crm/LimeCrmNode.node.js +13 -0
  6. package/dist/nodes/lime-crm/LimeCrmNode.node.js.map +1 -1
  7. package/dist/nodes/lime-crm/commons/constants.d.ts +1 -0
  8. package/dist/nodes/lime-crm/commons/constants.js +2 -1
  9. package/dist/nodes/lime-crm/commons/constants.js.map +1 -1
  10. package/dist/nodes/lime-crm/commons/index.d.ts +1 -1
  11. package/dist/nodes/lime-crm/commons/index.js +2 -1
  12. package/dist/nodes/lime-crm/commons/index.js.map +1 -1
  13. package/dist/nodes/lime-crm/resources/limeQuery/index.d.ts +6 -0
  14. package/dist/nodes/lime-crm/resources/limeQuery/index.js +66 -0
  15. package/dist/nodes/lime-crm/resources/limeQuery/index.js.map +1 -0
  16. package/dist/nodes/lime-crm/resources/limeQuery/operations/query.operation.d.ts +9 -0
  17. package/dist/nodes/lime-crm/resources/limeQuery/operations/query.operation.js +191 -0
  18. package/dist/nodes/lime-crm/resources/limeQuery/operations/query.operation.js.map +1 -0
  19. package/dist/nodes/lime-crm/resources/limeType/index.d.ts +3 -3
  20. package/dist/nodes/lime-crm/transport/index.d.ts +1 -0
  21. package/dist/nodes/lime-crm/transport/index.js +3 -1
  22. package/dist/nodes/lime-crm/transport/index.js.map +1 -1
  23. package/dist/nodes/lime-crm/transport/limeQuery.d.ts +10 -0
  24. package/dist/nodes/lime-crm/transport/limeQuery.js +15 -0
  25. package/dist/nodes/lime-crm/transport/limeQuery.js.map +1 -0
  26. package/dist/package.json +1 -1
  27. package/dist/tsconfig.tsbuildinfo +1 -1
  28. package/docker-compose.yml +9 -3
  29. package/nodes/fortnox/Fortnox.node.ts +3 -3
  30. package/nodes/fortnox/FortnoxTrigger.node.ts +2 -2
  31. package/nodes/lime-crm/LimeCrmNode.node.ts +54 -53
  32. package/nodes/lime-crm/LimeCrmTrigger.node.ts +17 -24
  33. package/nodes/lime-crm/commons/constants.ts +2 -2
  34. package/nodes/lime-crm/commons/files.ts +162 -0
  35. package/nodes/lime-crm/commons/index.ts +4 -3
  36. package/nodes/lime-crm/commons/webhook.ts +15 -3
  37. package/nodes/lime-crm/methods/getLimetypeProperties.ts +67 -0
  38. package/nodes/lime-crm/methods/getLimetypes.ts +21 -0
  39. package/nodes/lime-crm/methods/index.ts +6 -2
  40. package/nodes/lime-crm/model.ts +22 -0
  41. package/nodes/lime-crm/resources/data/index.ts +80 -0
  42. package/nodes/lime-crm/resources/{limeObject/operations/create.operation.ts → data/operations/createSingleObject.ts} +53 -30
  43. package/nodes/lime-crm/resources/{limeObject/operations/delete.operation.ts → data/operations/deleteSingleObject.ts} +15 -15
  44. package/nodes/lime-crm/resources/data/operations/getManyObjects.ts +356 -0
  45. package/nodes/lime-crm/resources/data/operations/getSingleFile.ts +138 -0
  46. package/nodes/lime-crm/resources/data/operations/getSingleObject.ts +83 -0
  47. package/nodes/lime-crm/resources/{limeObject/operations/update.operation.ts → data/operations/updateSingleObject.operation.ts} +51 -23
  48. package/nodes/lime-crm/resources/erpConnector/index.ts +3 -3
  49. package/nodes/lime-crm/resources/erpConnector/operations/transform.operation.ts +14 -14
  50. package/nodes/lime-crm/resources/erpConnector/transform.ts +3 -3
  51. package/nodes/lime-crm/resources/erpConnector/transformers/baseTransformer.ts +2 -2
  52. package/nodes/lime-crm/resources/erpConnector/transformers/fortnox.ts +8 -8
  53. package/nodes/lime-crm/resources/metadata/index.ts +57 -0
  54. package/nodes/lime-crm/resources/metadata/operations/getAllLimetypes.operation.ts +18 -0
  55. package/nodes/lime-crm/resources/metadata/operations/getSingleFileMetadata.ts +130 -0
  56. package/nodes/lime-crm/resources/metadata/operations/getSingleLimetype.ts +36 -0
  57. package/nodes/lime-crm/transport/commons.ts +14 -2
  58. package/nodes/lime-crm/transport/files.ts +155 -0
  59. package/nodes/lime-crm/transport/index.ts +14 -6
  60. package/nodes/lime-crm/transport/limeQuery.ts +26 -0
  61. package/nodes/lime-crm/transport/limeobjects.ts +79 -44
  62. package/nodes/lime-crm/transport/limetypes.ts +80 -24
  63. package/package.json +4 -3
  64. package/restore_script/README +42 -0
  65. package/restore_script/api_key_download.txt +0 -0
  66. package/restore_script/api_key_upload.txt +0 -0
  67. package/restore_script/cli.py +73 -0
  68. package/restore_script/download.py +73 -0
  69. package/restore_script/main.py +19 -0
  70. package/restore_script/poetry.lock +162 -0
  71. package/restore_script/pyproject.toml +15 -0
  72. package/restore_script/transfer.py +41 -0
  73. package/restore_script/upload.py +66 -0
  74. package/restore_script/utils.py +42 -0
  75. package/tests/transform.spec.ts +6 -6
  76. package/nodes/lime-crm/commons/limetype.ts +0 -11
  77. package/nodes/lime-crm/methods/getLimeTypeProperties.ts +0 -27
  78. package/nodes/lime-crm/methods/getLimeTypes.ts +0 -23
  79. package/nodes/lime-crm/resources/limeObject/index.ts +0 -64
  80. package/nodes/lime-crm/resources/limeObject/operations/fetchMany.operation.ts +0 -112
  81. package/nodes/lime-crm/resources/limeObject/operations/get.operation.ts +0 -54
  82. package/nodes/lime-crm/resources/limeType/index.ts +0 -58
  83. package/nodes/lime-crm/resources/limeType/operations/getProperties.operation.ts +0 -42
  84. package/nodes/lime-crm/resources/limeType/operations/getType.operation.ts +0 -36
  85. package/nodes/lime-crm/resources/limeType/operations/listTypes.operation.ts +0 -18
@@ -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.3.8",
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
@@ -0,0 +1,73 @@
1
+ import argparse
2
+ import os
3
+ import sys
4
+
5
+
6
+ from download import create_workflows_endpoint, fetch_workflows, save_workflows
7
+ from upload import upload_workflows
8
+
9
+
10
+ def _get_api_key(parser_args):
11
+ api_key = parser_args.api_key or os.getenv("N8N_API_KEY")
12
+ if not api_key:
13
+ print("Error: No api_key provided. Use --api_key argument or set N8N_API_KEY environment variable.",
14
+ file=sys.stderr)
15
+ sys.exit(1)
16
+
17
+ return api_key
18
+
19
+
20
+ def download(instance_url, folder_path, parser_args):
21
+ api_key = _get_api_key(parser_args)
22
+ url = create_workflows_endpoint(instance_url, active=False, pinned_data=True)
23
+
24
+ if workflows:= fetch_workflows(url, api_key):
25
+ os.makedirs(os.path.normpath(folder_path), exist_ok=True)
26
+ save_workflows(folder_path, workflows)
27
+
28
+
29
+ def upload(instance_url, folder_path, parser_args):
30
+ api_key = _get_api_key(parser_args)
31
+ url = f"{instance_url}/api/v1/workflows"
32
+
33
+ upload_workflows(
34
+ url=url, api_key=api_key, folder_path=os.path.normpath(folder_path))
35
+
36
+
37
+ def download_cmd(subparsers):
38
+ download_parser = subparsers.add_parser("download", help="Download workflows from an n8n instance")
39
+ download_parser.add_argument("--instance_url", required=True,
40
+ help="n8n instance URL (e.g., https://n8n.example.com)")
41
+ download_parser.add_argument("--folder_path", required=True,
42
+ help="Path to save downloaded workflows")
43
+ download_parser.add_argument("--api_key",
44
+ help="Your n8n API key the default is read from N8N_API_KEY env variable")
45
+
46
+
47
+ def upload_cmd(subparsers):
48
+ upload_parser = subparsers.add_parser("upload", help="Upload workflows to an n8n instance")
49
+ upload_parser.add_argument("--instance_url", required=True,
50
+ help="n8n instance URL (e.g., https://n8n.example.com)")
51
+ upload_parser.add_argument("--folder_path", required=True,
52
+ help="Path to the folder containing workflows to upload")
53
+ upload_parser.add_argument("--api_key",
54
+ help="Your n8n API key the default is read from N8N_API_KEY env variable")
55
+
56
+
57
+ def main():
58
+ parser = argparse.ArgumentParser(description="A simple CLI tool for n8n workflows restore.")
59
+ subparsers = parser.add_subparsers(dest="command", required=True)
60
+
61
+ download_cmd(subparsers)
62
+ upload_cmd(subparsers)
63
+
64
+ args = parser.parse_args()
65
+
66
+ if args.command == "download":
67
+ download(parser_args=args, instance_url=args.instance_url, folder_path=args.folder_path)
68
+ elif args.command == "upload":
69
+ upload(parser_args=args, instance_url=args.instance_url, folder_path=args.folder_path)
70
+
71
+
72
+ if __name__ == "__main__":
73
+ main()
@@ -0,0 +1,73 @@
1
+ import datetime
2
+ import os
3
+
4
+ import requests
5
+ import json
6
+
7
+ from utils import get_api_key, create_headers
8
+
9
+
10
+ def main():
11
+ print("n8n Workflow Downloader")
12
+ instance_url = input("Enter n8n instance URL (e.g., https://n8n.example.com): ").strip().rstrip("/")
13
+ api_key = input("Enter your n8n API key: ").strip() or get_api_key("api_key_download.txt")
14
+ active = input("Do you want to download only active workflows? (y/n, default n): ").strip().lower() == 'y'
15
+ pinned_data = input("Do you want to download pinned data also? (y/n, default n): ").strip().lower() == 'y'
16
+
17
+ url = create_workflows_endpoint(instance_url, active, pinned_data)
18
+ if workflows:= fetch_workflows(url, api_key):
19
+ folder_path = create_folder(folder_path="./workflows/", instance_url=instance_url)
20
+ save_workflows(folder_path, workflows)
21
+
22
+
23
+ def create_workflows_endpoint(instance_url: str, active: bool, pinned_data: bool):
24
+ base_url = f"{instance_url}/api/v1/workflows"
25
+ active = "true" if active else "false"
26
+ pinned_data = "true" if not pinned_data else "false"
27
+
28
+ return f"{base_url}?active={active}&excludePinnedData={pinned_data}"
29
+
30
+
31
+ def fetch_workflows(url, api_key):
32
+ headers = create_headers(api_key)
33
+ workflows = []
34
+ next_cursor = None
35
+ while True:
36
+ full_url = f"{url}&limit=100" + (f"&cursor={next_cursor}" if next_cursor else "")
37
+ try:
38
+ resp = requests.get(full_url, headers=headers)
39
+ resp.raise_for_status()
40
+ except requests.RequestException as e:
41
+ print(f"Error: {e}")
42
+ return []
43
+
44
+ data = resp.json()
45
+ workflows.extend(data.get("data", []))
46
+ next_cursor = data.get("nextCursor")
47
+ if not next_cursor:
48
+ break
49
+
50
+ return workflows
51
+
52
+
53
+ def create_folder(folder_path, instance_url):
54
+ name = (f"{datetime.datetime.now().strftime('%Y_%m_%d-%H_%M')}-"
55
+ f"{instance_url.replace('https://', '').replace('http://', '').replace('/', '_')}"
56
+ )
57
+ path = os.path.join(folder_path, name)
58
+ os.makedirs(path, exist_ok=True)
59
+
60
+ return path
61
+
62
+
63
+ def save_workflows(folder_path, workflows):
64
+ for workflow in workflows:
65
+ filename = f"{workflow['name']}.json"
66
+ with open(f"{folder_path}/{filename}", "w") as f:
67
+ json.dump(workflow, f, indent=2)
68
+ print(f"{filename} - saved")
69
+ print(f"All workflows has been saved to {folder_path}")
70
+
71
+
72
+ if __name__ == "__main__":
73
+ main()
@@ -0,0 +1,19 @@
1
+ from utils import select_option
2
+
3
+
4
+ def main():
5
+ options = ["Download", "Upload", "Transfer"]
6
+ selected = select_option(options)
7
+ match selected:
8
+ case "Download":
9
+ from download import main
10
+ case "Upload":
11
+ from upload import main
12
+ case "Transfer":
13
+ from transfer import main
14
+
15
+ main()
16
+
17
+
18
+ if __name__ == "__main__":
19
+ main()
@@ -0,0 +1,162 @@
1
+ # This file is automatically @generated by Poetry and should not be changed by hand.
2
+
3
+ [[package]]
4
+ name = "certifi"
5
+ version = "2025.10.5"
6
+ description = "Python package for providing Mozilla's CA Bundle."
7
+ category = "main"
8
+ optional = false
9
+ python-versions = ">=3.7"
10
+ files = [
11
+ {file = "certifi-2025.10.5-py3-none-any.whl", hash = "sha256:0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de"},
12
+ {file = "certifi-2025.10.5.tar.gz", hash = "sha256:47c09d31ccf2acf0be3f701ea53595ee7e0b8fa08801c6624be771df09ae7b43"},
13
+ ]
14
+
15
+ [[package]]
16
+ name = "charset-normalizer"
17
+ version = "3.4.3"
18
+ description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
19
+ category = "main"
20
+ optional = false
21
+ python-versions = ">=3.7"
22
+ files = [
23
+ {file = "charset_normalizer-3.4.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fb7f67a1bfa6e40b438170ebdc8158b78dc465a5a67b6dde178a46987b244a72"},
24
+ {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc9370a2da1ac13f0153780040f465839e6cccb4a1e44810124b4e22483c93fe"},
25
+ {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:07a0eae9e2787b586e129fdcbe1af6997f8d0e5abaa0bc98c0e20e124d67e601"},
26
+ {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:74d77e25adda8581ffc1c720f1c81ca082921329452eba58b16233ab1842141c"},
27
+ {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d0e909868420b7049dafd3a31d45125b31143eec59235311fc4c57ea26a4acd2"},
28
+ {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c6f162aabe9a91a309510d74eeb6507fab5fff92337a15acbe77753d88d9dcf0"},
29
+ {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4ca4c094de7771a98d7fbd67d9e5dbf1eb73efa4f744a730437d8a3a5cf994f0"},
30
+ {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:02425242e96bcf29a49711b0ca9f37e451da7c70562bc10e8ed992a5a7a25cc0"},
31
+ {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:78deba4d8f9590fe4dae384aeff04082510a709957e968753ff3c48399f6f92a"},
32
+ {file = "charset_normalizer-3.4.3-cp310-cp310-win32.whl", hash = "sha256:d79c198e27580c8e958906f803e63cddb77653731be08851c7df0b1a14a8fc0f"},
33
+ {file = "charset_normalizer-3.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:c6e490913a46fa054e03699c70019ab869e990270597018cef1d8562132c2669"},
34
+ {file = "charset_normalizer-3.4.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b256ee2e749283ef3ddcff51a675ff43798d92d746d1a6e4631bf8c707d22d0b"},
35
+ {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13faeacfe61784e2559e690fc53fa4c5ae97c6fcedb8eb6fb8d0a15b475d2c64"},
36
+ {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:00237675befef519d9af72169d8604a067d92755e84fe76492fef5441db05b91"},
37
+ {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:585f3b2a80fbd26b048a0be90c5aae8f06605d3c92615911c3a2b03a8a3b796f"},
38
+ {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e78314bdc32fa80696f72fa16dc61168fda4d6a0c014e0380f9d02f0e5d8a07"},
39
+ {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:96b2b3d1a83ad55310de8c7b4a2d04d9277d5591f40761274856635acc5fcb30"},
40
+ {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:939578d9d8fd4299220161fdd76e86c6a251987476f5243e8864a7844476ba14"},
41
+ {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fd10de089bcdcd1be95a2f73dbe6254798ec1bda9f450d5828c96f93e2536b9c"},
42
+ {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1e8ac75d72fa3775e0b7cb7e4629cec13b7514d928d15ef8ea06bca03ef01cae"},
43
+ {file = "charset_normalizer-3.4.3-cp311-cp311-win32.whl", hash = "sha256:6cf8fd4c04756b6b60146d98cd8a77d0cdae0e1ca20329da2ac85eed779b6849"},
44
+ {file = "charset_normalizer-3.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:31a9a6f775f9bcd865d88ee350f0ffb0e25936a7f930ca98995c05abf1faf21c"},
45
+ {file = "charset_normalizer-3.4.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1"},
46
+ {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884"},
47
+ {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018"},
48
+ {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392"},
49
+ {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f"},
50
+ {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154"},
51
+ {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491"},
52
+ {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93"},
53
+ {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f"},
54
+ {file = "charset_normalizer-3.4.3-cp312-cp312-win32.whl", hash = "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37"},
55
+ {file = "charset_normalizer-3.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc"},
56
+ {file = "charset_normalizer-3.4.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe"},
57
+ {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8"},
58
+ {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9"},
59
+ {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31"},
60
+ {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f"},
61
+ {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927"},
62
+ {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9"},
63
+ {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5"},
64
+ {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc"},
65
+ {file = "charset_normalizer-3.4.3-cp313-cp313-win32.whl", hash = "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce"},
66
+ {file = "charset_normalizer-3.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef"},
67
+ {file = "charset_normalizer-3.4.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15"},
68
+ {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db"},
69
+ {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d"},
70
+ {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096"},
71
+ {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa"},
72
+ {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049"},
73
+ {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0"},
74
+ {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92"},
75
+ {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16"},
76
+ {file = "charset_normalizer-3.4.3-cp314-cp314-win32.whl", hash = "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce"},
77
+ {file = "charset_normalizer-3.4.3-cp314-cp314-win_amd64.whl", hash = "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c"},
78
+ {file = "charset_normalizer-3.4.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0f2be7e0cf7754b9a30eb01f4295cc3d4358a479843b31f328afd210e2c7598c"},
79
+ {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c60e092517a73c632ec38e290eba714e9627abe9d301c8c8a12ec32c314a2a4b"},
80
+ {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:252098c8c7a873e17dd696ed98bbe91dbacd571da4b87df3736768efa7a792e4"},
81
+ {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3653fad4fe3ed447a596ae8638b437f827234f01a8cd801842e43f3d0a6b281b"},
82
+ {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8999f965f922ae054125286faf9f11bc6932184b93011d138925a1773830bbe9"},
83
+ {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d95bfb53c211b57198bb91c46dd5a2d8018b3af446583aab40074bf7988401cb"},
84
+ {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:5b413b0b1bfd94dbf4023ad6945889f374cd24e3f62de58d6bb102c4d9ae534a"},
85
+ {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:b5e3b2d152e74e100a9e9573837aba24aab611d39428ded46f4e4022ea7d1942"},
86
+ {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a2d08ac246bb48479170408d6c19f6385fa743e7157d716e144cad849b2dd94b"},
87
+ {file = "charset_normalizer-3.4.3-cp38-cp38-win32.whl", hash = "sha256:ec557499516fc90fd374bf2e32349a2887a876fbf162c160e3c01b6849eaf557"},
88
+ {file = "charset_normalizer-3.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:5d8d01eac18c423815ed4f4a2ec3b439d654e55ee4ad610e153cf02faf67ea40"},
89
+ {file = "charset_normalizer-3.4.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:70bfc5f2c318afece2f5838ea5e4c3febada0be750fcf4775641052bbba14d05"},
90
+ {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:23b6b24d74478dc833444cbd927c338349d6ae852ba53a0d02a2de1fce45b96e"},
91
+ {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:34a7f768e3f985abdb42841e20e17b330ad3aaf4bb7e7aeeb73db2e70f077b99"},
92
+ {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fb731e5deb0c7ef82d698b0f4c5bb724633ee2a489401594c5c88b02e6cb15f7"},
93
+ {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:257f26fed7d7ff59921b78244f3cd93ed2af1800ff048c33f624c87475819dd7"},
94
+ {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1ef99f0456d3d46a50945c98de1774da86f8e992ab5c77865ea8b8195341fc19"},
95
+ {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:2c322db9c8c89009a990ef07c3bcc9f011a3269bc06782f916cd3d9eed7c9312"},
96
+ {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:511729f456829ef86ac41ca78c63a5cb55240ed23b4b737faca0eb1abb1c41bc"},
97
+ {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:88ab34806dea0671532d3f82d82b85e8fc23d7b2dd12fa837978dad9bb392a34"},
98
+ {file = "charset_normalizer-3.4.3-cp39-cp39-win32.whl", hash = "sha256:16a8770207946ac75703458e2c743631c79c59c5890c80011d536248f8eaa432"},
99
+ {file = "charset_normalizer-3.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:d22dbedd33326a4a5190dd4fe9e9e693ef12160c77382d9e87919bce54f3d4ca"},
100
+ {file = "charset_normalizer-3.4.3-py3-none-any.whl", hash = "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a"},
101
+ {file = "charset_normalizer-3.4.3.tar.gz", hash = "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14"},
102
+ ]
103
+
104
+ [[package]]
105
+ name = "idna"
106
+ version = "3.11"
107
+ description = "Internationalized Domain Names in Applications (IDNA)"
108
+ category = "main"
109
+ optional = false
110
+ python-versions = ">=3.8"
111
+ files = [
112
+ {file = "idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea"},
113
+ {file = "idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902"},
114
+ ]
115
+
116
+ [package.extras]
117
+ all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"]
118
+
119
+ [[package]]
120
+ name = "requests"
121
+ version = "2.32.5"
122
+ description = "Python HTTP for Humans."
123
+ category = "main"
124
+ optional = false
125
+ python-versions = ">=3.9"
126
+ files = [
127
+ {file = "requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6"},
128
+ {file = "requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf"},
129
+ ]
130
+
131
+ [package.dependencies]
132
+ certifi = ">=2017.4.17"
133
+ charset_normalizer = ">=2,<4"
134
+ idna = ">=2.5,<4"
135
+ urllib3 = ">=1.21.1,<3"
136
+
137
+ [package.extras]
138
+ socks = ["PySocks (>=1.5.6,!=1.5.7)"]
139
+ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
140
+
141
+ [[package]]
142
+ name = "urllib3"
143
+ version = "2.5.0"
144
+ description = "HTTP library with thread-safe connection pooling, file post, and more."
145
+ category = "main"
146
+ optional = false
147
+ python-versions = ">=3.9"
148
+ files = [
149
+ {file = "urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc"},
150
+ {file = "urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760"},
151
+ ]
152
+
153
+ [package.extras]
154
+ brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
155
+ h2 = ["h2 (>=4,<5)"]
156
+ socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
157
+ zstd = ["zstandard (>=0.18.0)"]
158
+
159
+ [metadata]
160
+ lock-version = "2.0"
161
+ python-versions = "^3.11"
162
+ content-hash = "f40c18dabbaa3889f633dd67739f0501e4752091d81200dbc7f42d2cdb09545c"
@@ -0,0 +1,15 @@
1
+ [tool.poetry]
2
+ name = "n8n-scripts"
3
+ version = "0.1.0"
4
+ description = ""
5
+ authors = ["jakub-piatkowski <jakub.piatkowski@lime.tech>"]
6
+ readme = "README.md"
7
+ packages = [{include = "n8n_scripts"}]
8
+
9
+ [tool.poetry.dependencies]
10
+ python = "^3.11"
11
+ requests = "^2.32.5"
12
+
13
+ [build-system]
14
+ requires = ["poetry-core"]
15
+ build-backend = "poetry.core.masonry.api"
@@ -0,0 +1,41 @@
1
+ import requests
2
+
3
+ from download import fetch_workflows, create_workflows_endpoint
4
+ from upload import clean_workflow, post_workflow
5
+ from utils import get_api_key, create_headers
6
+
7
+
8
+ def main():
9
+ print("n8n Workflow Transfer")
10
+ download_instance_url = (input("DOWNLOAD FROM - Enter n8n instance URL (e.g., https://n8n.example.com): ")
11
+ .strip().rstrip("/"))
12
+ api_key_download = input("Enter your n8n API key: ").strip() or get_api_key("api_key_download.txt")
13
+ active = input("Do you want to transfer only active workflows? (y/n, default n): ").strip().lower() == 'y'
14
+
15
+ upload_instance_url = (input("UPLOAD TO - Enter n8n instance URL (e.g., https://n8n.example.com): ")
16
+ .strip().rstrip("/"))
17
+ api_key_upload = input("Enter your n8n API key: ").strip() or get_api_key("api_key_upload.txt")
18
+
19
+ download_endpoint = create_workflows_endpoint(instance_url=download_instance_url, active=active, pinned_data=False)
20
+ upload_endpoint = f"{upload_instance_url}/api/v1/workflows"
21
+
22
+ print("Starting workflow transfer...")
23
+ for workflow in fetch_workflows(url=download_endpoint, api_key=api_key_download):
24
+ clean_workflow(workflow)
25
+ try:
26
+ post_workflow(
27
+ url=upload_endpoint,
28
+ headers=create_headers(api_key_upload),
29
+ body=workflow
30
+ )
31
+ except requests.exceptions.RequestException as e:
32
+ print(f"Error: {e}")
33
+ return
34
+ print(f"{workflow['name']} - uploaded")
35
+ print("Workflow transfer completed.")
36
+
37
+
38
+
39
+
40
+ if __name__ == "__main__":
41
+ main()