node-red-contrib-prib-functions 0.23.2 → 0.26.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 (58) hide show
  1. package/.github/copilot-instructions.md +36 -0
  2. package/README.md +153 -140
  3. package/columnar/columnar.html +258 -0
  4. package/columnar/columnar.js +1055 -0
  5. package/columnar/icons/columnar.svg +38 -0
  6. package/fileSystem/filesystem.html +299 -0
  7. package/fileSystem/filesystem.js +170 -0
  8. package/gitlab/gitlab.html +191 -0
  9. package/gitlab/gitlab.js +248 -0
  10. package/gitlab/icons/gitlab.svg +17 -0
  11. package/lib/AlphaBeta.js +32 -0
  12. package/lib/GraphDB.js +40 -9
  13. package/lib/MinMax.js +17 -0
  14. package/lib/Tree.js +64 -0
  15. package/lib/objectExtensions.js +28 -5
  16. package/lib/timeDimension.js +36 -0
  17. package/lib/typedInput.js +18 -2
  18. package/logisticRegression/icons/logisticregression.svg +22 -0
  19. package/logisticRegression/logisticRegression.html +136 -0
  20. package/logisticRegression/logisticRegression.js +83 -0
  21. package/package.json +21 -9
  22. package/test/02-graphdb.js +46 -0
  23. package/test/columnar.js +509 -0
  24. package/test/data/.config.nodes.json +114 -70
  25. package/test/data/.config.nodes.json.backup +104 -71
  26. package/test/data/.config.runtime.json +2 -1
  27. package/test/data/.config.runtime.json.backup +2 -1
  28. package/test/data/.config.users.json +3 -2
  29. package/test/data/.config.users.json.backup +3 -2
  30. package/test/data/.flow.json.backup +1545 -369
  31. package/test/data/flow.json +1457 -270
  32. package/test/data/package-lock.json +11 -11
  33. package/test/data/shares/.config.nodes.json +611 -0
  34. package/test/data/shares/.config.nodes.json.backup +589 -0
  35. package/test/data/shares/.config.runtime.json +5 -0
  36. package/test/data/shares/.config.runtime.json.backup +4 -0
  37. package/test/data/shares/.config.users.json +33 -0
  38. package/test/data/shares/.config.users.json.backup +33 -0
  39. package/test/data/shares/.flow.json.backup +230 -0
  40. package/test/data/shares/.flow_cred.json.backup +3 -0
  41. package/test/data/shares/flow.json +267 -0
  42. package/test/data/shares/flow_cred.json +3 -0
  43. package/test/data/shares/package.json +6 -0
  44. package/test/data/shares/settings.js +544 -0
  45. package/test/dataAnalysisExtensions.js +93 -93
  46. package/test/logisticRegression.js +379 -0
  47. package/test/transform.js +11 -11
  48. package/test/transformConfluence.js +4 -2
  49. package/test/transformNumPy.js +3 -1
  50. package/test/transformXLSX.js +4 -2
  51. package/test/transformXML.js +4 -2
  52. package/test-runner.js +400 -0
  53. package/test.parq +0 -0
  54. package/test_select.js +37 -0
  55. package/testing/test.js +8 -7
  56. package/transform/transform.html +23 -2
  57. package/transform/transform.js +239 -283
  58. package/transform/xlsx2.js +74 -0
@@ -0,0 +1,258 @@
1
+ <script type="text/javascript">
2
+ RED.nodes.registerType('columnar', {
3
+ category: 'storage',
4
+ color: '#8BC34A',
5
+ defaults: {
6
+ name: {value:"", required:false},
7
+ action: {value:"readFile", required:true},
8
+ filePath: {value:"", required:false},
9
+ sqlQuery: {value:"", required:false},
10
+ outputProperty: {value:"result", required:false},
11
+ parameterMappings: {value:[], required:false}
12
+ },
13
+ inputs: 1,
14
+ inputLabels: "in",
15
+ outputs:1,
16
+ outputLabels: function() { return [this.outputProperty || "result"]; },
17
+ paletteLabel: "Columnar Store",
18
+ icon: "columnar.svg",
19
+ label: function() {
20
+ const actionLabels = {
21
+ readFile: "Read",
22
+ writeFile: "Write",
23
+ appendFile: "Append",
24
+ queryFile: "Query",
25
+ sqlQuery: "SQL Query",
26
+ getSchema: "Get Schema",
27
+ getMetadata: "Get Metadata"
28
+ };
29
+ const actionLabel = actionLabels[this.action] || this.action;
30
+
31
+ if (this.name) {
32
+ return this.name;
33
+ }
34
+
35
+ if (this.action === 'sqlQuery' && this.sqlQuery) {
36
+ // Show truncated SQL query in label
37
+ const sqlPreview = this.sqlQuery.length > 30 ?
38
+ this.sqlQuery.substring(0, 27) + '...' :
39
+ this.sqlQuery;
40
+ return sqlPreview;
41
+ }
42
+
43
+ return actionLabel + " Columnar Store";
44
+ },
45
+ labelStyle: function() {
46
+ return "node_label_italic";
47
+ },
48
+ oneditprepare: function() {
49
+ // Show/hide SQL query field based on action
50
+ function updateSqlField() {
51
+ const action = $('#node-input-action').val();
52
+ if (action === 'sqlQuery') {
53
+ $('#sql-query-row').show();
54
+ } else {
55
+ $('#sql-query-row').hide();
56
+ }
57
+ }
58
+
59
+ $('#node-input-action').change(updateSqlField);
60
+ updateSqlField(); // Initial check
61
+
62
+ },
63
+ oneditsave: function() {
64
+ // No parameter mappings needed; explicit :msg., :flow., :global. markers only
65
+ }
66
+ });
67
+ </script>
68
+
69
+ <script type="text/x-red" data-template-name="columnar">
70
+ <div class="form-row">
71
+ <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
72
+ <input type="text" id="node-input-name" placeholder="Name">
73
+ </div>
74
+ <div class="form-row">
75
+ <label for="node-input-action"><i class="fa fa-cogs"></i> Action</label>
76
+ <select type="text" id="node-input-action">
77
+ <option value="readFile">Read File</option>
78
+ <option value="writeFile">Write File</option>
79
+ <option value="appendFile">Append File</option>
80
+ <option value="queryFile">Query File</option>
81
+ <option value="sqlQuery">SQL Query</option>
82
+ <option value="getSchema">Get Schema</option>
83
+ <option value="getMetadata">Get Metadata</option>
84
+ </select>
85
+ </div>
86
+ <div class="form-row">
87
+ <label for="node-input-filePath">File Path</label>
88
+ <input type="text" id="node-input-filePath" placeholder="/path/to/file.columnar">
89
+ </div>
90
+ <div class="form-row">
91
+ <label for="node-input-outputProperty"><i class="fa fa-sign-out"></i> Output Property</label>
92
+ <input type="text" id="node-input-outputProperty" placeholder="result">
93
+ </div>
94
+ <div class="form-row" id="sql-query-row" style="display:none;">
95
+ <label for="node-input-sqlQuery"><i class="fa fa-code"></i> SQL Query</label>
96
+ <textarea type="text" id="node-input-sqlQuery" placeholder="SELECT * FROM ? WHERE ..." rows="3" style="width:100%; resize:vertical;"></textarea>
97
+ </div>
98
+ </script>
99
+
100
+ <script type="text/x-red" data-help-name="columnar">
101
+ <p>Columnar Store node for reading and writing columnar data files. This implementation is based on <a href="https://github.com/apache/parquet-format/" target="_blank">Apache Parquet specification</a> concepts including columnar storage, metadata structures, and compression principles, but provides a simplified JavaScript implementation for basic use cases.</p>
102
+
103
+ <h3>Actions</h3>
104
+ <ul>
105
+ <li><b>Read File:</b> Reads all records from a Columnar Store file</li>
106
+ <li><b>Write File:</b> Writes records to a Columnar Store file (overwrites existing file)</li>
107
+ <li><b>Append File:</b> Appends records to an existing Columnar Store file (creates file if it doesn't exist)</li>
108
+ <li><b>Query File:</b> Reads and filters records from a Columnar Store file</li>
109
+ <li><b>SQL Query:</b> Execute SQL queries with aggregates, grouping, sorting, JOINs, and filtering</li>
110
+ <li><b>Get Schema:</b> Retrieves the schema information from a Columnar Store file</li>
111
+ <li><b>Get Metadata:</b> Retrieves metadata information from a Columnar Store file</li>
112
+ </ul>
113
+
114
+ <h3>Configuration</h3>
115
+ <ul>
116
+ <li><b>File Path:</b> Path to the Columnar file (.columnar extension). Can be overridden in msg.payload.filePath</li>
117
+ <li><b>Output Property:</b> Property name on msg object where results will be stored (default: "result")</li>
118
+ <li><b>SQL Query:</b> (SQL Query action only) Hardcoded SQL query to execute. Can be overridden by msg.payload.sql. Hardcoded queries are parsed once and cached for better performance.</li>
119
+ <li><b>Parameters:</b> <b>Only</b> <code>:msg.path</code>, <code>:flow.path</code>, or <code>:global.path</code> markers are allowed in SQL. Example: <code>WHERE a.name = :msg.payload.name AND a.age > :flow.minAge</code>. No other parameter markers are supported.</li>
120
+ </ul>
121
+
122
+ <h3>Input/Output Formats</h3>
123
+
124
+ <h4>Read File</h4>
125
+ <p><b>Input:</b> Optional filePath in msg.payload</p>
126
+ <p><b>Output:</b></p>
127
+ <pre>{
128
+ "result": {
129
+ "records": [...],
130
+ "count": 100,
131
+ "schema": {...},
132
+ "filePath": "/path/to/file.columnar"
133
+ }
134
+ }</pre>
135
+
136
+ <h4>Write File</h4>
137
+ <p><b>Input:</b></p>
138
+ <pre>{
139
+ "records": [
140
+ {"name": "John", "age": 30, "city": "NYC"},
141
+ {"name": "Jane", "age": 25, "city": "LA"}
142
+ ],
143
+ "filePath": "/path/to/output.columnar",
144
+ "schema": {...} // optional, auto-inferred if not provided
145
+ }</pre>
146
+ <p><b>Output:</b></p>
147
+ <pre>{
148
+ "result": {
149
+ "filePath": "/path/to/output.columnar",
150
+ "recordsWritten": 2,
151
+ "schema": {...}
152
+ }
153
+ }</pre>
154
+
155
+ <h4>Query File</h4>
156
+ <p><b>Input:</b></p>
157
+ <pre>{
158
+ "filePath": "/path/to/file.columnar",
159
+ "limit": 100, // optional
160
+ // either provide a javascript filter function or a ridMap to perform
161
+ // a column‑based intersection. The columnar layout stores each field
162
+ // as its own buffer along with a list of row‑ids (rids). A ridMap is an
163
+ // object whose keys are column names and whose values are arrays or
164
+ // Sets of rids; only rows present in *every* set will be returned.
165
+ // Example using a filter function:
166
+ "filter": "function(record) { return record.age > 25; }" // optional
167
+ // Example using a ridMap (select rows 1 and 2 from the 'age' column):
168
+ // "ridMap": {"age": [1,2]}
169
+ }</pre>
170
+ <p><b>Output:</b></p>
171
+ <pre>{
172
+ "result": {
173
+ "records": [...],
174
+ "count": 50,
175
+ "totalScanned": 100,
176
+ "schema": {...},
177
+ "filtered": true
178
+ }
179
+ }</pre>
180
+
181
+ <h4>SQL Query</h4>
182
+ <p><b>Input:</b> SQL query can be configured in the node or provided in msg.payload.sql (msg.payload.sql takes precedence)</p>
183
+ <pre>{
184
+ "filePath": "/path/to/file.columnar",
185
+ "sql": "SELECT * FROM ? WHERE a.name = :msg.payload.name AND a.age > :flow.minAge"
186
+ }</pre>
187
+ <p><b>Parameters:</b> Use <code>:msg.path</code>, <code>:flow.path</code>, or <code>:global.path</code> in your SQL to reference values from <code>msg</code>, <code>flow</code>, or <code>global</code> context. <b>Other parameter markers are not supported and will cause an error.</b></p>
188
+ <p><b>Supported Features:</b></p>
189
+ <ul>
190
+ <li><b>SELECT:</b> Column names, <code>*</code>, or aggregates (COUNT, SUM, AVG, MIN, MAX, COUNT DISTINCT)</li>
191
+ <li><b>FROM/JOIN:</b> Main table (<code>?</code>) with optional INNER/LEFT/RIGHT/FULL OUTER JOIN on other .columnar files</li>
192
+ <li><b>WHERE:</b> Filter records using JavaScript expressions</li>
193
+ <li><b>GROUP BY:</b> Group results by one or more columns with aggregate functions</li>
194
+ <li><b>HAVING:</b> Filter grouped results</li>
195
+ <li><b>ORDER BY:</b> Sort by column(s) with ASC/DESC</li>
196
+ <li><b>LIMIT:</b> Restrict result count</li>
197
+ <li><b>Parameters:</b> Use <code>:msg.path</code>, <code>:flow.path</code>, or <code>:global.path</code> in queries. No other parameter markers are allowed.</li>
198
+ </ul>
199
+ <p><b>JOIN Syntax:</b></p>
200
+ <pre>[INNER|LEFT|RIGHT|FULL OUTER] JOIN 'filepath.columnar' ON table1.col = table2.col</pre>
201
+ <p><b>Output:</b></p>
202
+ <pre>{
203
+ "result": [ /* array of result rows */ ]
204
+ }</pre>
205
+
206
+ <h4>Get Schema</h4>
207
+ <p><b>Input:</b> Optional filePath in msg.payload</p>
208
+ <p><b>Output:</b></p>
209
+ <pre>{
210
+ "result": {
211
+ "schema": {...},
212
+ "fields": ["name", "age", "city"],
213
+ "filePath": "/path/to/file.columnar"
214
+ }
215
+ }</pre>
216
+
217
+ <h4>Get Metadata</h4>
218
+ <p><b>Input:</b> Optional filePath in msg.payload</p>
219
+ <p><b>Output:</b></p>
220
+ <pre>{
221
+ "result": {
222
+ "metadata": {...},
223
+ "filePath": "/path/to/file.columnar",
224
+ "numRows": 1000,
225
+ "numRowGroups": 5
226
+ }
227
+ }</pre>
228
+
229
+ <h3>Data Types</h3>
230
+ <p>Columnar supports various data types. The node automatically infers types when writing:</p>
231
+ <ul>
232
+ <li>String → UTF8</li>
233
+ <li>Number → DOUBLE</li>
234
+ <li>Boolean → BOOLEAN</li>
235
+ <li>Date → TIMESTAMP</li>
236
+ </ul>
237
+
238
+ <h3>Implementation Notes</h3>
239
+ <ul>
240
+ <li>Based on <a href="https://github.com/apache/parquet-format/" target="_blank">Apache Parquet specification</a> concepts</li>
241
+ <li>Implements columnar storage for efficient data organization</li>
242
+ <li>Uses metadata structures inspired by Parquet format specification</li>
243
+ <li>Applies compression principles from the Parquet specification</li>
244
+ <li>Custom JavaScript implementation, not a full Apache Parquet compatible format</li>
245
+ <li>Best suited for basic tabular data storage and retrieval</li>
246
+ <li>Supports filtering via row‑id (rid) maps; query operations on
247
+ multiple columns efficiently intersect the provided rid sets</li>
248
+ </ul>
249
+
250
+ <h3>Error Handling</h3>
251
+ <p>Errors are reported in msg.error. Common issues:</p>
252
+ <ul>
253
+ <li>File not found</li>
254
+ <li>Invalid Columnar format</li>
255
+ <li>Schema mismatches</li>
256
+ <li>Permission issues</li>
257
+ </ul>
258
+ </script>