Flowfile 0.3.9__py3-none-any.whl → 0.5.1__py3-none-any.whl

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 (201) hide show
  1. flowfile/__init__.py +8 -1
  2. flowfile/api.py +1 -3
  3. flowfile/web/static/assets/{CloudConnectionManager-c97c25f8.js → CloudConnectionManager-0dfba9f2.js} +2 -2
  4. flowfile/web/static/assets/{CloudStorageReader-f1ff509e.js → CloudStorageReader-d5b1b6c9.js} +11 -78
  5. flowfile/web/static/assets/{CloudStorageWriter-034f8b78.js → CloudStorageWriter-00d87aad.js} +12 -79
  6. flowfile/web/static/assets/{CloudStorageWriter-49c9a4b2.css → CloudStorageWriter-b0ee067f.css} +24 -24
  7. flowfile/web/static/assets/ColumnSelector-4685e75d.js +83 -0
  8. flowfile/web/static/assets/ColumnSelector-47996a16.css +10 -0
  9. flowfile/web/static/assets/ContextMenu-23e909da.js +41 -0
  10. flowfile/web/static/assets/{SettingsSection-9c836ecc.css → ContextMenu-4c74eef1.css} +0 -21
  11. flowfile/web/static/assets/ContextMenu-63cfa99b.css +26 -0
  12. flowfile/web/static/assets/ContextMenu-70ae0c79.js +41 -0
  13. flowfile/web/static/assets/ContextMenu-c13f91d0.css +26 -0
  14. flowfile/web/static/assets/ContextMenu-f149cf7c.js +41 -0
  15. flowfile/web/static/assets/{CrossJoin-41efa4cb.css → CrossJoin-1119d18e.css} +18 -18
  16. flowfile/web/static/assets/{CrossJoin-9e156ebe.js → CrossJoin-702a3edd.js} +14 -84
  17. flowfile/web/static/assets/CustomNode-74a37f74.css +32 -0
  18. flowfile/web/static/assets/CustomNode-b1519993.js +211 -0
  19. flowfile/web/static/assets/{DatabaseConnectionSettings-d5c625b3.js → DatabaseConnectionSettings-6f3e4ea5.js} +3 -3
  20. flowfile/web/static/assets/{DatabaseManager-265adc5e.js → DatabaseManager-cf5ef661.js} +2 -2
  21. flowfile/web/static/assets/{DatabaseReader-f50c6558.css → DatabaseReader-ae61773c.css} +0 -27
  22. flowfile/web/static/assets/{DatabaseReader-0b10551e.js → DatabaseReader-d38c7295.js} +14 -114
  23. flowfile/web/static/assets/{DatabaseWriter-c17c6916.js → DatabaseWriter-b04ef46a.js} +13 -74
  24. flowfile/web/static/assets/{ExploreData-5bdae813.css → ExploreData-2d0cf4db.css} +8 -14
  25. flowfile/web/static/assets/ExploreData-5fa10ed8.js +192 -0
  26. flowfile/web/static/assets/{ExternalSource-3a66556c.js → ExternalSource-d39af878.js} +8 -79
  27. flowfile/web/static/assets/{Filter-91ad87e7.js → Filter-9b6d08db.js} +12 -85
  28. flowfile/web/static/assets/{Filter-a9d08ba1.css → Filter-f62091b3.css} +3 -3
  29. flowfile/web/static/assets/{Formula-3c395ab1.js → Formula-6b04fb1d.js} +20 -87
  30. flowfile/web/static/assets/{Formula-29f19d21.css → Formula-bb96803d.css} +4 -4
  31. flowfile/web/static/assets/{FuzzyMatch-6857de82.css → FuzzyMatch-1010f966.css} +42 -42
  32. flowfile/web/static/assets/{FuzzyMatch-2df0d230.js → FuzzyMatch-999521f4.js} +16 -87
  33. flowfile/web/static/assets/{GraphSolver-d285877f.js → GraphSolver-17dd2198.js} +13 -159
  34. flowfile/web/static/assets/GraphSolver-f0cb7bfb.css +22 -0
  35. flowfile/web/static/assets/{GroupBy-0bd1cc6b.js → GroupBy-6b039e18.js} +12 -75
  36. flowfile/web/static/assets/{Unique-b5615727.css → GroupBy-b9505323.css} +8 -8
  37. flowfile/web/static/assets/{Join-5a78a203.js → Join-24d0f113.js} +15 -85
  38. flowfile/web/static/assets/{Join-f45eff22.css → Join-fd79b451.css} +20 -20
  39. flowfile/web/static/assets/{ManualInput-a71b52c6.css → ManualInput-3246a08d.css} +20 -20
  40. flowfile/web/static/assets/{ManualInput-93aef9d6.js → ManualInput-34639209.js} +11 -82
  41. flowfile/web/static/assets/MultiSelect-0e8724a3.js +5 -0
  42. flowfile/web/static/assets/MultiSelect.vue_vue_type_script_setup_true_lang-b0e538c2.js +63 -0
  43. flowfile/web/static/assets/NumericInput-3d63a470.js +5 -0
  44. flowfile/web/static/assets/NumericInput.vue_vue_type_script_setup_true_lang-e0edeccc.js +35 -0
  45. flowfile/web/static/assets/Output-283fe388.css +37 -0
  46. flowfile/web/static/assets/{Output-411ecaee.js → Output-edea9802.js} +62 -273
  47. flowfile/web/static/assets/{Pivot-89db4b04.js → Pivot-61d19301.js} +14 -138
  48. flowfile/web/static/assets/Pivot-cf333e3d.css +22 -0
  49. flowfile/web/static/assets/PivotValidation-891ddfb0.css +13 -0
  50. flowfile/web/static/assets/PivotValidation-c46cd420.css +13 -0
  51. flowfile/web/static/assets/PivotValidation-de9f43fe.js +61 -0
  52. flowfile/web/static/assets/PivotValidation-f97fec5b.js +61 -0
  53. flowfile/web/static/assets/{PolarsCode-a9f974f8.js → PolarsCode-bc3c9984.js} +13 -80
  54. flowfile/web/static/assets/Read-64a3f259.js +218 -0
  55. flowfile/web/static/assets/Read-e808b239.css +62 -0
  56. flowfile/web/static/assets/RecordCount-3d5039be.js +53 -0
  57. flowfile/web/static/assets/{RecordId-55ae7d36.js → RecordId-597510e0.js} +8 -80
  58. flowfile/web/static/assets/SQLQueryComponent-36cef432.css +27 -0
  59. flowfile/web/static/assets/SQLQueryComponent-df51adbe.js +38 -0
  60. flowfile/web/static/assets/{Sample-b4a18476.js → Sample-4be0a507.js} +8 -77
  61. flowfile/web/static/assets/{SecretManager-b066d13a.js → SecretManager-4839be57.js} +2 -2
  62. flowfile/web/static/assets/{Select-727688dc.js → Select-9b72f201.js} +11 -85
  63. flowfile/web/static/assets/SettingsSection-2e4d03c4.css +21 -0
  64. flowfile/web/static/assets/SettingsSection-5c696bee.css +20 -0
  65. flowfile/web/static/assets/SettingsSection-71e6b7e3.css +21 -0
  66. flowfile/web/static/assets/SettingsSection-7ded385d.js +45 -0
  67. flowfile/web/static/assets/{SettingsSection-695ac487.js → SettingsSection-e1e9c953.js} +2 -40
  68. flowfile/web/static/assets/SettingsSection-f0f75a42.js +53 -0
  69. flowfile/web/static/assets/SingleSelect-6c777aac.js +5 -0
  70. flowfile/web/static/assets/SingleSelect.vue_vue_type_script_setup_true_lang-33e3ff9b.js +62 -0
  71. flowfile/web/static/assets/SliderInput-7cb93e62.js +40 -0
  72. flowfile/web/static/assets/SliderInput-b8fb6a8c.css +4 -0
  73. flowfile/web/static/assets/{GroupBy-ab1ea74b.css → Sort-3643d625.css} +8 -8
  74. flowfile/web/static/assets/{Sort-be3339a8.js → Sort-6cbde21a.js} +12 -97
  75. flowfile/web/static/assets/TextInput-d9a40c11.js +5 -0
  76. flowfile/web/static/assets/TextInput.vue_vue_type_script_setup_true_lang-5896c375.js +32 -0
  77. flowfile/web/static/assets/{TextToRows-c92d1ec2.css → TextToRows-5d2c1190.css} +9 -9
  78. flowfile/web/static/assets/{TextToRows-7b8998da.js → TextToRows-c4fcbf4d.js} +14 -83
  79. flowfile/web/static/assets/ToggleSwitch-4ef91d19.js +5 -0
  80. flowfile/web/static/assets/ToggleSwitch.vue_vue_type_script_setup_true_lang-38478c20.js +31 -0
  81. flowfile/web/static/assets/{UnavailableFields-8b0cb48e.js → UnavailableFields-a03f512c.js} +2 -2
  82. flowfile/web/static/assets/{Union-8d9ac7f9.css → Union-af6c3d9b.css} +6 -6
  83. flowfile/web/static/assets/Union-bfe9b996.js +77 -0
  84. flowfile/web/static/assets/{Unique-af5a80b4.js → Unique-5d023a27.js} +23 -104
  85. flowfile/web/static/assets/{Sort-7ccfa0fe.css → Unique-f9fb0809.css} +8 -8
  86. flowfile/web/static/assets/Unpivot-1e422df3.css +30 -0
  87. flowfile/web/static/assets/{Unpivot-5195d411.js → Unpivot-91cc5354.js} +12 -166
  88. flowfile/web/static/assets/UnpivotValidation-0d240eeb.css +13 -0
  89. flowfile/web/static/assets/UnpivotValidation-7ee2de44.js +51 -0
  90. flowfile/web/static/assets/{ExploreData-18a4fe52.js → VueGraphicWalker-e51b9924.js} +4 -264
  91. flowfile/web/static/assets/VueGraphicWalker-ed5ab88b.css +6 -0
  92. flowfile/web/static/assets/{api-cb00cce6.js → api-c1bad5ca.js} +1 -1
  93. flowfile/web/static/assets/{api-023d1733.js → api-cf1221f0.js} +1 -1
  94. flowfile/web/static/assets/{designer-2197d782.css → designer-8da3ba3a.css} +859 -201
  95. flowfile/web/static/assets/{designer-6c322d8e.js → designer-9633482a.js} +2297 -733
  96. flowfile/web/static/assets/{documentation-4d1fafe1.js → documentation-ca400224.js} +1 -1
  97. flowfile/web/static/assets/{dropDown-0b46dd77.js → dropDown-614b998d.js} +1 -1
  98. flowfile/web/static/assets/{fullEditor-ec4e4f95.js → fullEditor-f7971590.js} +2 -2
  99. flowfile/web/static/assets/{genericNodeSettings-def5879b.js → genericNodeSettings-4fe5f36b.js} +3 -3
  100. flowfile/web/static/assets/{index-681a3ed0.css → index-50508d4d.css} +8 -0
  101. flowfile/web/static/assets/{index-683fc198.js → index-5429bbf8.js} +208 -31
  102. flowfile/web/static/assets/nodeInput-5d0d6b79.js +41 -0
  103. flowfile/web/static/assets/outputCsv-076b85ab.js +86 -0
  104. flowfile/web/static/assets/{Output-48f81019.css → outputCsv-9cc59e0b.css} +0 -143
  105. flowfile/web/static/assets/outputExcel-0fd17dbe.js +56 -0
  106. flowfile/web/static/assets/outputExcel-b41305c0.css +102 -0
  107. flowfile/web/static/assets/outputParquet-b61e0847.js +31 -0
  108. flowfile/web/static/assets/outputParquet-cf8cf3f2.css +4 -0
  109. flowfile/web/static/assets/readCsv-a8bb8b61.js +179 -0
  110. flowfile/web/static/assets/readCsv-c767cb37.css +52 -0
  111. flowfile/web/static/assets/readExcel-67b4aee0.js +201 -0
  112. flowfile/web/static/assets/readExcel-806d2826.css +64 -0
  113. flowfile/web/static/assets/readParquet-48c81530.css +19 -0
  114. flowfile/web/static/assets/readParquet-92ce1dbc.js +23 -0
  115. flowfile/web/static/assets/{secretApi-baceb6f9.js → secretApi-68435402.js} +1 -1
  116. flowfile/web/static/assets/{selectDynamic-de91449a.js → selectDynamic-92e25ee3.js} +7 -7
  117. flowfile/web/static/assets/{selectDynamic-b062bc9b.css → selectDynamic-aa913ff4.css} +16 -16
  118. flowfile/web/static/assets/user-defined-icon-0ae16c90.png +0 -0
  119. flowfile/web/static/assets/{vue-codemirror.esm-dc5e3348.js → vue-codemirror.esm-41b0e0d7.js} +65 -36
  120. flowfile/web/static/assets/{vue-content-loader.es-ba94b82f.js → vue-content-loader.es-2c8e608f.js} +1 -1
  121. flowfile/web/static/index.html +2 -2
  122. {flowfile-0.3.9.dist-info → flowfile-0.5.1.dist-info}/METADATA +5 -3
  123. {flowfile-0.3.9.dist-info → flowfile-0.5.1.dist-info}/RECORD +191 -121
  124. {flowfile-0.3.9.dist-info → flowfile-0.5.1.dist-info}/WHEEL +1 -1
  125. {flowfile-0.3.9.dist-info → flowfile-0.5.1.dist-info}/entry_points.txt +1 -0
  126. flowfile_core/__init__.py +3 -0
  127. flowfile_core/configs/flow_logger.py +5 -13
  128. flowfile_core/configs/node_store/__init__.py +30 -0
  129. flowfile_core/configs/node_store/nodes.py +383 -99
  130. flowfile_core/configs/node_store/user_defined_node_registry.py +193 -0
  131. flowfile_core/configs/settings.py +2 -1
  132. flowfile_core/database/connection.py +5 -21
  133. flowfile_core/fileExplorer/funcs.py +239 -121
  134. flowfile_core/flowfile/analytics/analytics_processor.py +1 -0
  135. flowfile_core/flowfile/code_generator/code_generator.py +62 -64
  136. flowfile_core/flowfile/flow_data_engine/create/funcs.py +73 -56
  137. flowfile_core/flowfile/flow_data_engine/flow_data_engine.py +77 -86
  138. flowfile_core/flowfile/flow_data_engine/flow_file_column/interface.py +4 -0
  139. flowfile_core/flowfile/flow_data_engine/flow_file_column/main.py +19 -34
  140. flowfile_core/flowfile/flow_data_engine/flow_file_column/type_registry.py +36 -0
  141. flowfile_core/flowfile/flow_data_engine/fuzzy_matching/prepare_for_fuzzy_match.py +23 -23
  142. flowfile_core/flowfile/flow_data_engine/join/utils.py +1 -1
  143. flowfile_core/flowfile/flow_data_engine/join/verify_integrity.py +9 -4
  144. flowfile_core/flowfile/flow_data_engine/subprocess_operations/subprocess_operations.py +212 -86
  145. flowfile_core/flowfile/flow_data_engine/utils.py +2 -0
  146. flowfile_core/flowfile/flow_graph.py +240 -54
  147. flowfile_core/flowfile/flow_node/flow_node.py +48 -13
  148. flowfile_core/flowfile/flow_node/models.py +2 -1
  149. flowfile_core/flowfile/handler.py +24 -5
  150. flowfile_core/flowfile/manage/compatibility_enhancements.py +404 -41
  151. flowfile_core/flowfile/manage/io_flowfile.py +394 -0
  152. flowfile_core/flowfile/node_designer/__init__.py +47 -0
  153. flowfile_core/flowfile/node_designer/_type_registry.py +197 -0
  154. flowfile_core/flowfile/node_designer/custom_node.py +371 -0
  155. flowfile_core/flowfile/node_designer/ui_components.py +277 -0
  156. flowfile_core/flowfile/schema_callbacks.py +17 -10
  157. flowfile_core/flowfile/setting_generator/settings.py +15 -10
  158. flowfile_core/main.py +5 -1
  159. flowfile_core/routes/routes.py +73 -30
  160. flowfile_core/routes/user_defined_components.py +55 -0
  161. flowfile_core/schemas/cloud_storage_schemas.py +0 -2
  162. flowfile_core/schemas/input_schema.py +228 -65
  163. flowfile_core/schemas/output_model.py +5 -2
  164. flowfile_core/schemas/schemas.py +153 -35
  165. flowfile_core/schemas/transform_schema.py +1083 -412
  166. flowfile_core/schemas/yaml_types.py +103 -0
  167. flowfile_core/types.py +156 -0
  168. flowfile_core/utils/validate_setup.py +3 -1
  169. flowfile_frame/__init__.py +3 -1
  170. flowfile_frame/flow_frame.py +31 -24
  171. flowfile_frame/flow_frame_methods.py +12 -9
  172. flowfile_worker/__init__.py +9 -35
  173. flowfile_worker/create/__init__.py +3 -21
  174. flowfile_worker/create/funcs.py +68 -56
  175. flowfile_worker/create/models.py +130 -62
  176. flowfile_worker/main.py +5 -2
  177. flowfile_worker/routes.py +52 -13
  178. shared/__init__.py +15 -0
  179. shared/storage_config.py +258 -0
  180. tools/migrate/README.md +56 -0
  181. tools/migrate/__init__.py +12 -0
  182. tools/migrate/__main__.py +131 -0
  183. tools/migrate/legacy_schemas.py +621 -0
  184. tools/migrate/migrate.py +598 -0
  185. tools/migrate/tests/__init__.py +0 -0
  186. tools/migrate/tests/conftest.py +23 -0
  187. tools/migrate/tests/test_migrate.py +627 -0
  188. tools/migrate/tests/test_migration_e2e.py +1010 -0
  189. tools/migrate/tests/test_node_migrations.py +813 -0
  190. flowfile/web/static/assets/GraphSolver-17fd26db.css +0 -68
  191. flowfile/web/static/assets/Pivot-f415e85f.css +0 -35
  192. flowfile/web/static/assets/Read-80dc1675.css +0 -197
  193. flowfile/web/static/assets/Read-c3b1929c.js +0 -701
  194. flowfile/web/static/assets/RecordCount-4e95f98e.js +0 -122
  195. flowfile/web/static/assets/Union-89fd73dc.js +0 -146
  196. flowfile/web/static/assets/Unpivot-246e9bbd.css +0 -77
  197. flowfile/web/static/assets/nodeTitle-a16db7c3.js +0 -227
  198. flowfile/web/static/assets/nodeTitle-f4b12bcb.css +0 -134
  199. flowfile_core/flowfile/manage/open_flowfile.py +0 -135
  200. {flowfile-0.3.9.dist-info → flowfile-0.5.1.dist-info/licenses}/LICENSE +0 -0
  201. /flowfile_core/flowfile/manage/manage_flowfile.py → /tools/__init__.py +0 -0
@@ -0,0 +1,193 @@
1
+ import sys
2
+ import importlib.util
3
+ import inspect
4
+ from pathlib import Path
5
+ from typing import Dict, Type, List
6
+ import logging
7
+
8
+ from flowfile_core.flowfile.node_designer.custom_node import CustomNodeBase, NodeSettings
9
+ from shared import storage
10
+
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ def get_all_custom_nodes() -> Dict[str, Type[CustomNodeBase]]:
16
+ """
17
+ Scan the user-defined nodes directory and import all CustomNodeBase subclasses.
18
+
19
+ Returns:
20
+ Dictionary mapping node names to node classes
21
+ """
22
+ custom_nodes = {}
23
+
24
+ # Get the directory path where user-defined nodes are stored
25
+ nodes_directory = storage.user_defined_nodes_icons
26
+
27
+ # Convert to Path object for easier handling
28
+ nodes_path = Path(nodes_directory)
29
+
30
+ if not nodes_path.exists() or not nodes_path.is_dir():
31
+ print(f"Warning: Nodes directory {nodes_path} does not exist or is not a directory")
32
+ return custom_nodes
33
+
34
+ # Scan all Python files in the directory
35
+ for file_path in nodes_path.glob("*.py"):
36
+ # Skip __init__.py and other special files
37
+ if file_path.name.startswith("__"):
38
+ continue
39
+
40
+ try:
41
+ # Load the module dynamically
42
+ module_name = file_path.stem # filename without extension
43
+ spec = importlib.util.spec_from_file_location(module_name, file_path)
44
+
45
+ if spec and spec.loader:
46
+ module = importlib.util.module_from_spec(spec)
47
+
48
+ # Add to sys.modules to handle imports within the module
49
+ sys.modules[module_name] = module
50
+
51
+ # Execute the module
52
+ spec.loader.exec_module(module)
53
+
54
+ # Inspect the module for CustomNodeBase subclasses
55
+ for name, obj in inspect.getmembers(module):
56
+ # Check if it's a class and a subclass of CustomNodeBase
57
+ # but not CustomNodeBase itself
58
+ if (inspect.isclass(obj) and
59
+ issubclass(obj, CustomNodeBase) and
60
+ obj is not CustomNodeBase):
61
+
62
+ # Use the node_name attribute if it exists, otherwise use class name
63
+ node_name = getattr(obj, 'node_name', name)
64
+ custom_nodes[node_name] = obj
65
+ print(f"Loaded custom node: {node_name} from {file_path.name}")
66
+
67
+ except Exception as e:
68
+ print(f"Error loading module from {file_path}: {e}")
69
+ # Continue with other files even if one fails
70
+ continue
71
+
72
+ return custom_nodes
73
+
74
+
75
+ def get_all_custom_nodes_with_validation() -> Dict[str, Type[CustomNodeBase]]:
76
+ """
77
+ Enhanced version that validates the nodes before adding them.
78
+ """
79
+
80
+ custom_nodes = {}
81
+ nodes_path = storage.user_defined_nodes_directory
82
+
83
+ if not nodes_path.exists():
84
+ return custom_nodes
85
+
86
+ for file_path in nodes_path.glob("*.py"):
87
+ if file_path.name.startswith("__"):
88
+ continue
89
+
90
+ try:
91
+ module_name = file_path.stem
92
+ spec = importlib.util.spec_from_file_location(module_name, file_path)
93
+
94
+ if spec and spec.loader:
95
+ module = importlib.util.module_from_spec(spec)
96
+ sys.modules[module_name] = module
97
+ spec.loader.exec_module(module)
98
+
99
+ for name, obj in inspect.getmembers(module):
100
+ if (inspect.isclass(obj) and
101
+ issubclass(obj, CustomNodeBase) and
102
+ obj is not CustomNodeBase):
103
+
104
+ try:
105
+ _obj = obj()
106
+ # Validate that the node has required attributes
107
+ if not hasattr(_obj, 'node_name'):
108
+ logger.error(f"Warning: {name} missing node_name attribute")
109
+ raise ValueError(f"Node {name} must implement a node_name attribute")
110
+
111
+ if not hasattr(_obj, 'settings_schema'):
112
+ logger.error(f"Warning: {name} missing settings_schema attribute")
113
+ raise ValueError(f"Node {name} must implement a settings_schema attribute")
114
+
115
+ if not hasattr(_obj, 'process'):
116
+ logger.error(f"Warning: {name} missing process method")
117
+ raise ValueError(f"Node {name} must implement a process method")
118
+ if not (storage.user_defined_nodes_icons / _obj.node_icon).exists():
119
+ logger.warning(
120
+ f"Warning: Icon file does not exist for node {_obj.node_name} at {_obj.node_icon} "
121
+ "Falling back to default icon."
122
+ )
123
+
124
+ node_name = _obj.to_node_template().item
125
+ custom_nodes[node_name] = obj
126
+ print(f"✓ Loaded: {node_name} from {file_path.name}")
127
+ except Exception as e:
128
+ print(f"Error validating node {name} in {file_path}: {e}")
129
+ continue
130
+ except SyntaxError as e:
131
+ print(f"Syntax error in {file_path}: {e}")
132
+ except ImportError as e:
133
+ print(f"Import error in {file_path}: {e}")
134
+ except Exception as e:
135
+ print(f"Unexpected error loading {file_path}: {e}")
136
+
137
+ return custom_nodes
138
+
139
+
140
+ def get_custom_nodes_lazy() -> List[Type[CustomNodeBase]]:
141
+ """
142
+ Returns a list of custom node classes without instantiating them.
143
+ Useful for registration or catalog purposes.
144
+ """
145
+ nodes = []
146
+ nodes_path = Path(storage.user_defined_nodes_directory)
147
+
148
+ if not nodes_path.exists():
149
+ return nodes
150
+
151
+ for file_path in nodes_path.glob("*.py"):
152
+ if file_path.name.startswith("__"):
153
+ continue
154
+
155
+ try:
156
+ # Create a unique module name to avoid conflicts
157
+ module_name = f"custom_node_{file_path.stem}_{id(file_path)}"
158
+ spec = importlib.util.spec_from_file_location(module_name, file_path)
159
+
160
+ if spec and spec.loader:
161
+ module = importlib.util.module_from_spec(spec)
162
+ spec.loader.exec_module(module)
163
+
164
+ for name, obj in inspect.getmembers(module):
165
+ if (inspect.isclass(obj) and
166
+ issubclass(obj, CustomNodeBase) and
167
+ obj is not CustomNodeBase and
168
+ obj.__module__ == module.__name__): # Only get classes defined in this module
169
+ nodes.append(obj)
170
+
171
+ except Exception as e:
172
+ print(f"Error processing {file_path}: {e}")
173
+ continue
174
+
175
+ return nodes
176
+
177
+
178
+ # Example usage function that matches your original pattern
179
+ def add_custom_node(node_class: Type[CustomNodeBase], registry: Dict[str, Type[CustomNodeBase]]):
180
+ """Add a single custom node to the registry."""
181
+ if hasattr(node_class, 'node_name'):
182
+ registry[node_class.node_name] = node_class
183
+ else:
184
+ registry[node_class.__name__] = node_class
185
+
186
+
187
+ def get_all_nodes_from_standard_location() -> Dict[str, Type[CustomNodeBase]]:
188
+ """
189
+ Main function to get all custom nodes from the standard location.
190
+ This matches your original function signature.
191
+ """
192
+
193
+ return get_all_custom_nodes_with_validation()
@@ -7,6 +7,7 @@ import argparse
7
7
 
8
8
  from passlib.context import CryptContext
9
9
  from starlette.config import Config
10
+ from shared.storage_config import storage
10
11
 
11
12
  from flowfile_core.configs.utils import MutableBool
12
13
 
@@ -93,7 +94,7 @@ FILE_LOCATION = config("FILE_LOCATION", cast=str, default=".\\files\\")
93
94
  AVAILABLE_RAM = config("AVAILABLE_RAM", cast=int, default=8)
94
95
  WORKER_URL = config("FLOWFILE_WORKER_URL", cast=str, default=get_default_worker_url(WORKER_PORT))
95
96
  IS_RUNNING_IN_DOCKER = os.getenv('RUNNING_IN_DOCKER', 'false').lower() == 'true'
96
- TEMP_DIR = get_temp_dir()
97
+ TEMP_DIR = storage.temp_directory
97
98
 
98
99
  ALGORITHM = "HS256"
99
100
  ACCESS_TOKEN_EXPIRE_MINUTES = 120
@@ -5,37 +5,21 @@ import os
5
5
  import sys
6
6
  from pathlib import Path
7
7
  from flowfile_core.configs import logger
8
+ from shared.storage_config import storage
8
9
 
9
10
 
10
11
  def get_app_data_dir() -> Path:
11
12
  """Get the appropriate application data directory for the current platform."""
12
- app_name = "Flowfile"
13
13
 
14
- if sys.platform == "win32":
15
- # Windows: C:\Users\{username}\AppData\Local\flowfile
16
- base_dir = os.environ.get("LOCALAPPDATA")
17
- if not base_dir:
18
- base_dir = os.path.join(os.path.expanduser("~"), "AppData", "Local")
19
- elif sys.platform == "darwin":
20
- # macOS: ~/Library/Application Support/flowfile
21
- base_dir = os.path.join(os.path.expanduser("~"), "Library", "Application Support")
22
- else:
23
- # Linux: ~/.local/share/flowfile or use XDG_DATA_HOME
24
- base_dir = os.environ.get("XDG_DATA_HOME")
25
- if not base_dir:
26
- base_dir = os.path.join(os.path.expanduser("~"), ".local", "share")
27
-
28
- app_dir = Path(base_dir) / app_name
29
- app_dir.mkdir(parents=True, exist_ok=True)
30
-
31
- return app_dir
14
+ return storage.database_directory
32
15
 
33
16
 
34
17
  def get_database_url():
35
18
  """Get the database URL based on the current environment."""
36
19
  if os.environ.get("TESTING") == "True":
37
20
  # Use a temporary test database
38
- test_db_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../test_flowfile.db")
21
+ test_db_path = storage.temp_directory / "test_flowfile.db"
22
+ logger.debug(f"Using TESTING database URL: sqlite:///{test_db_path}")
39
23
  return f"sqlite:///{test_db_path}"
40
24
 
41
25
  custom_db_path = os.environ.get("FLOWFILE_DB_PATH")
@@ -94,4 +78,4 @@ def get_database_info():
94
78
  "path": str(get_database_path()) if get_database_path() else None,
95
79
  "app_data_dir": str(get_app_data_dir()),
96
80
  "platform": sys.platform
97
- }
81
+ }