@dartfx/n8n-nodes-qsv 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/README.md +8 -8
  2. package/package.json +4 -4
  3. package/dist/nodes/Qsv/actions/executeClean.d.ts +0 -2
  4. package/dist/nodes/Qsv/actions/executeClean.js +0 -147
  5. package/dist/nodes/Qsv/actions/executeClipboard.d.ts +0 -2
  6. package/dist/nodes/Qsv/actions/executeClipboard.js +0 -114
  7. package/dist/nodes/Qsv/actions/executeColor.d.ts +0 -2
  8. package/dist/nodes/Qsv/actions/executeColor.js +0 -126
  9. package/dist/nodes/Qsv/actions/executeLens.d.ts +0 -2
  10. package/dist/nodes/Qsv/actions/executeLens.js +0 -156
  11. package/dist/nodes/Qsv/actions/executeLog.d.ts +0 -2
  12. package/dist/nodes/Qsv/actions/executeLog.js +0 -111
  13. package/dist/nodes/Qsv/actions/executePrompt.d.ts +0 -2
  14. package/dist/nodes/Qsv/actions/executePrompt.js +0 -132
  15. package/dist/nodes/Qsv/descriptions/CleanDescription.d.ts +0 -2
  16. package/dist/nodes/Qsv/descriptions/CleanDescription.js +0 -140
  17. package/dist/nodes/Qsv/descriptions/ClipboardDescription.d.ts +0 -2
  18. package/dist/nodes/Qsv/descriptions/ClipboardDescription.js +0 -63
  19. package/dist/nodes/Qsv/descriptions/ColorDescription.d.ts +0 -2
  20. package/dist/nodes/Qsv/descriptions/ColorDescription.js +0 -91
  21. package/dist/nodes/Qsv/descriptions/LensDescription.d.ts +0 -2
  22. package/dist/nodes/Qsv/descriptions/LensDescription.js +0 -161
  23. package/dist/nodes/Qsv/descriptions/LogDescription.d.ts +0 -2
  24. package/dist/nodes/Qsv/descriptions/LogDescription.js +0 -55
  25. package/dist/nodes/Qsv/descriptions/PromptDescription.d.ts +0 -2
  26. package/dist/nodes/Qsv/descriptions/PromptDescription.js +0 -105
package/README.md CHANGED
@@ -1,15 +1,15 @@
1
1
  # n8n Community Node for datHere QSV (`@dartfx/n8n-nodes-qsv`)
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@dartfx/n8n-nodes-qsv.svg)](https://www.npmjs.com/package/@dartfx/n8n-nodes-qsv)
4
- [![CI](https://github.com/DataArtifex/dartfx-n8n/actions/workflows/ci.yml/badge.svg)](https://github.com/DataArtifex/dartfx-n8n/actions/workflows/ci.yml)
5
- [![Docs](https://github.com/DataArtifex/dartfx-n8n/actions/workflows/sphinx.yaml/badge.svg)](https://dataartifex.github.io/dartfx-n8n/)
6
- [![Ask DeepWiki](https://img.shields.io/badge/Ask-DeepWiki-6366f1.svg)](https://deepwiki.com/DataArtifex/dartfx-n8n)
4
+ [![CI](https://github.com/DataArtifex/dartfx-n8n-nodes-qsv/actions/workflows/ci.yml/badge.svg)](https://github.com/DataArtifex/dartfx-n8n-nodes-qsv/actions/workflows/ci.yml)
5
+ [![Docs](https://github.com/DataArtifex/dartfx-n8n-nodes-qsv/actions/workflows/sphinx.yaml/badge.svg)](https://dataartifex.github.io/dartfx-n8n-nodes-qsv/)
6
+ [![Ask DeepWiki](https://img.shields.io/badge/Ask-DeepWiki-6366f1.svg)](https://deepwiki.com/DataArtifex/dartfx-n8n-nodes-qsv)
7
7
  [![n8n Community Node](https://img.shields.io/badge/n8n-community--node-ea4b71.svg)](https://docs.n8n.io/integrations/community-nodes/)
8
8
  [![Powered by QSV](https://img.shields.io/badge/powered%20by-QSV-orange.svg)](https://github.com/dathere/qsv)
9
9
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
10
10
 
11
11
  > [!NOTE]
12
- > Node APIs, parameters, and operation interfaces in `@dartfx/n8n-nodes-qsv` are actively expanding. Please report any issues or feature requests on [GitHub Issues](https://github.com/DataArtifex/dartfx-n8n/issues).
12
+ > Node APIs, parameters, and operation interfaces in `@dartfx/n8n-nodes-qsv` are actively expanding. Please report any issues or feature requests on [GitHub Issues](https://github.com/DataArtifex/dartfx-n8n-nodes-qsv/issues).
13
13
 
14
14
  A custom [n8n](https://n8n.io/) community node for ultra-fast, zero-copy tabular data wrangling, transformation, validation, and analytics powered by [datHere QSV](https://github.com/dathere/qsv).
15
15
 
@@ -189,8 +189,8 @@ Node collections that wrap host binaries declare and verify their target CLI ver
189
189
 
190
190
  ```bash
191
191
  # Clone repository
192
- git clone https://github.com/DataArtifex/dartfx-n8n.git
193
- cd dartfx-n8n
192
+ git clone https://github.com/DataArtifex/dartfx-n8n-nodes-qsv.git
193
+ cd dartfx-n8n-nodes-qsv
194
194
 
195
195
  # Use supported Node LTS (20/22)
196
196
  nvm use
@@ -235,7 +235,7 @@ If running an older n8n v1 or v2 instance directly via Node / npm on your host m
235
235
  ```bash
236
236
  mkdir -p ~/.n8n/custom
237
237
  cd ~/.n8n/custom
238
- pnpm link /path/to/dartfx-n8n
238
+ pnpm link /path/to/dartfx-n8n-nodes-qsv
239
239
 
240
240
  # Start n8n
241
241
  n8n start
@@ -250,7 +250,7 @@ n8n start
250
250
 
251
251
  ```bash
252
252
  # Step 1: Register package globally
253
- cd /path/to/dartfx-n8n
253
+ cd /path/to/dartfx-n8n-nodes-qsv
254
254
  npm link
255
255
 
256
256
  # Step 2: Link into n8n custom directory
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dartfx/n8n-nodes-qsv",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "n8n community node for datHere QSV ultra-fast tabular data wrangling, stats, and transformations (requires 'qsv' CLI on host)",
5
5
  "keywords": [
6
6
  "n8n-community-node-package",
@@ -17,13 +17,13 @@
17
17
  "name": "Data Artifex",
18
18
  "url": "https://github.com/DataArtifex"
19
19
  },
20
- "homepage": "https://github.com/DataArtifex/dartfx-n8n",
20
+ "homepage": "https://github.com/DataArtifex/dartfx-n8n-nodes-qsv",
21
21
  "repository": {
22
22
  "type": "git",
23
- "url": "https://github.com/DataArtifex/dartfx-n8n.git"
23
+ "url": "https://github.com/DataArtifex/dartfx-n8n-nodes-qsv.git"
24
24
  },
25
25
  "bugs": {
26
- "url": "https://github.com/DataArtifex/dartfx-n8n/issues"
26
+ "url": "https://github.com/DataArtifex/dartfx-n8n-nodes-qsv/issues"
27
27
  },
28
28
  "main": "index.js",
29
29
  "engines": {
@@ -1,2 +0,0 @@
1
- import type { IExecuteFunctions, INodeExecutionData } from "n8n-workflow";
2
- export declare function executeClean(this: IExecuteFunctions, itemIndex: number): Promise<INodeExecutionData[]>;
@@ -1,147 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.executeClean = executeClean;
4
- const n8n_workflow_1 = require("n8n-workflow");
5
- const child_process_1 = require("child_process");
6
- const util_1 = require("util");
7
- const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
8
- async function executeClean(itemIndex) {
9
- const inputPath = this.getNodeParameter("inputPath", itemIndex);
10
- if (!inputPath || !inputPath.trim()) {
11
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), "Input CSV file path is required.", { itemIndex });
12
- }
13
- const outputPath = this.getNodeParameter("outputPath", itemIndex, "") || "";
14
- const additionalArgs = this.getNodeParameter("additionalArgs", itemIndex, "") || "";
15
- const options = this.getNodeParameter("options", itemIndex, {}) || {};
16
- const args = ["clean"];
17
- if (options.stale === true) {
18
- args.push("--stale");
19
- }
20
- if (options.recursive === true) {
21
- args.push("--recursive");
22
- }
23
- if (options.dryRun === true) {
24
- args.push("--dry-run");
25
- }
26
- if (options.force === true) {
27
- args.push("--force");
28
- }
29
- if (options.index === true) {
30
- args.push("--index");
31
- }
32
- if (options.stats === true) {
33
- args.push("--stats");
34
- }
35
- if (options.frequency === true) {
36
- args.push("--frequency");
37
- }
38
- if (options.schema === true) {
39
- args.push("--schema");
40
- }
41
- if (options.validate === true) {
42
- args.push("--validate");
43
- }
44
- if (options.moarstats === true) {
45
- args.push("--moarstats");
46
- }
47
- if (options.all === true) {
48
- args.push("--all");
49
- }
50
- if (options.quiet === true) {
51
- args.push("--quiet");
52
- }
53
- if (additionalArgs.trim()) {
54
- const rawMatches = additionalArgs.match(/[^\s"']+|"[^"]*"|'[^']*'/g) || [];
55
- const parsedArgs = rawMatches.map((arg) => {
56
- if ((arg.startsWith('"') && arg.endsWith('"')) ||
57
- (arg.startsWith("'") && arg.endsWith("'"))) {
58
- return arg.slice(1, -1);
59
- }
60
- return arg;
61
- });
62
- args.push(...parsedArgs);
63
- }
64
- if (outputPath.trim()) {
65
- args.push("--output", outputPath.trim());
66
- }
67
- args.push(inputPath);
68
- const qsvBin = process.env.DARTFX_QSV_BIN_PATH ||
69
- process.env.QSV_BIN_PATH ||
70
- process.env.QSV_PATH ||
71
- "qsv";
72
- try {
73
- const { stdout, stderr } = await execFileAsync(qsvBin, args, {
74
- maxBuffer: 50 * 1024 * 1024,
75
- encoding: "utf8",
76
- });
77
- let resultJson;
78
- try {
79
- resultJson = JSON.parse(stdout);
80
- }
81
- catch {
82
- resultJson = {
83
- command: "qsv clean",
84
- inputPath,
85
- rawOutput: stdout,
86
- };
87
- }
88
- const returnJson = {
89
- success: true,
90
- command: "clean",
91
- inputPath,
92
- result: resultJson,
93
- };
94
- if (outputPath.trim()) {
95
- returnJson.outputPath = outputPath.trim();
96
- }
97
- if (stderr && stderr.trim()) {
98
- returnJson.warnings = stderr.trim();
99
- }
100
- return [
101
- {
102
- json: returnJson,
103
- },
104
- ];
105
- }
106
- catch (error) {
107
- if (error.code === "ENOENT") {
108
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The QSV CLI binary ('${qsvBin}') was not found`, {
109
- itemIndex,
110
- description: `Please ensure 'qsv' is installed and available in the system PATH where n8n is running, or specify its absolute path via the DARTFX_QSV_BIN_PATH environment variable. (https://github.com/dathere/qsv)`,
111
- });
112
- }
113
- if (error.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER" ||
114
- (error.message && error.message.includes("maxBuffer"))) {
115
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `QSV execution exceeded maximum stdout buffer (50 MB)`, {
116
- itemIndex,
117
- description: `qsv clean returned more data than could fit into memory. Specify an 'Output File Path' to stream results directly to disk instead.`,
118
- });
119
- }
120
- const rawError = (error.stderr || error.message || "").trim();
121
- if (rawError.includes("is not a qsv command") ||
122
- rawError.includes("unrecognized subcommand") ||
123
- rawError.includes("not available in this")) {
124
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Operation 'clean' is not available in the installed QSV binary`, {
125
- itemIndex,
126
- description: `The installed QSV binary at '${qsvBin}' does not include the 'clean' feature. This feature may require a full feature build of QSV (e.g. qsv with all_features or a prebuilt binary with feature flags enabled). See https://github.com/dathere/qsv#feature-flags`,
127
- });
128
- }
129
- if (rawError.includes("No such file or directory") ||
130
- rawError.includes("os error 2")) {
131
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Input file not found: '${inputPath}'`, {
132
- itemIndex,
133
- description: `qsv clean could not find the file at '${inputPath}'. Check for typos, or if n8n is running in Docker, ensure the host directory is mounted into the container.`,
134
- });
135
- }
136
- if (rawError.includes("Operation not permitted") ||
137
- rawError.includes("os error 1") ||
138
- rawError.includes("Permission denied") ||
139
- rawError.includes("os error 13")) {
140
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Permission denied accessing file: '${inputPath}'`, {
141
- itemIndex,
142
- description: `qsv clean was denied read access to '${inputPath}'. On macOS, check Full Disk Access or Removable Volumes permissions for the application running n8n.`,
143
- });
144
- }
145
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed executing 'qsv clean': ${rawError}`, { itemIndex });
146
- }
147
- }
@@ -1,2 +0,0 @@
1
- import type { IExecuteFunctions, INodeExecutionData } from "n8n-workflow";
2
- export declare function executeClipboard(this: IExecuteFunctions, itemIndex: number): Promise<INodeExecutionData[]>;
@@ -1,114 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.executeClipboard = executeClipboard;
4
- const n8n_workflow_1 = require("n8n-workflow");
5
- const child_process_1 = require("child_process");
6
- const util_1 = require("util");
7
- const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
8
- async function executeClipboard(itemIndex) {
9
- const inputPath = this.getNodeParameter("inputPath", itemIndex);
10
- if (!inputPath || !inputPath.trim()) {
11
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), "Input CSV file path is required.", { itemIndex });
12
- }
13
- const outputPath = this.getNodeParameter("outputPath", itemIndex, "") || "";
14
- const additionalArgs = this.getNodeParameter("additionalArgs", itemIndex, "") || "";
15
- const options = this.getNodeParameter("options", itemIndex, {}) || {};
16
- const args = ["clipboard"];
17
- if (options.save === true) {
18
- args.push("--save");
19
- }
20
- if (additionalArgs.trim()) {
21
- const rawMatches = additionalArgs.match(/[^\s"']+|"[^"]*"|'[^']*'/g) || [];
22
- const parsedArgs = rawMatches.map((arg) => {
23
- if ((arg.startsWith('"') && arg.endsWith('"')) ||
24
- (arg.startsWith("'") && arg.endsWith("'"))) {
25
- return arg.slice(1, -1);
26
- }
27
- return arg;
28
- });
29
- args.push(...parsedArgs);
30
- }
31
- if (outputPath.trim()) {
32
- args.push("--output", outputPath.trim());
33
- }
34
- args.push(inputPath);
35
- const qsvBin = process.env.DARTFX_QSV_BIN_PATH ||
36
- process.env.QSV_BIN_PATH ||
37
- process.env.QSV_PATH ||
38
- "qsv";
39
- try {
40
- const { stdout, stderr } = await execFileAsync(qsvBin, args, {
41
- maxBuffer: 50 * 1024 * 1024,
42
- encoding: "utf8",
43
- });
44
- let resultJson;
45
- try {
46
- resultJson = JSON.parse(stdout);
47
- }
48
- catch {
49
- resultJson = {
50
- command: "qsv clipboard",
51
- inputPath,
52
- rawOutput: stdout,
53
- };
54
- }
55
- const returnJson = {
56
- success: true,
57
- command: "clipboard",
58
- inputPath,
59
- result: resultJson,
60
- };
61
- if (outputPath.trim()) {
62
- returnJson.outputPath = outputPath.trim();
63
- }
64
- if (stderr && stderr.trim()) {
65
- returnJson.warnings = stderr.trim();
66
- }
67
- return [
68
- {
69
- json: returnJson,
70
- },
71
- ];
72
- }
73
- catch (error) {
74
- if (error.code === "ENOENT") {
75
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The QSV CLI binary ('${qsvBin}') was not found`, {
76
- itemIndex,
77
- description: `Please ensure 'qsv' is installed and available in the system PATH where n8n is running, or specify its absolute path via the DARTFX_QSV_BIN_PATH environment variable. (https://github.com/dathere/qsv)`,
78
- });
79
- }
80
- if (error.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER" ||
81
- (error.message && error.message.includes("maxBuffer"))) {
82
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `QSV execution exceeded maximum stdout buffer (50 MB)`, {
83
- itemIndex,
84
- description: `qsv clipboard returned more data than could fit into memory. Specify an 'Output File Path' to stream results directly to disk instead.`,
85
- });
86
- }
87
- const rawError = (error.stderr || error.message || "").trim();
88
- if (rawError.includes("is not a qsv command") ||
89
- rawError.includes("unrecognized subcommand") ||
90
- rawError.includes("not available in this")) {
91
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Operation 'clipboard' is not available in the installed QSV binary`, {
92
- itemIndex,
93
- description: `The installed QSV binary at '${qsvBin}' does not include the 'clipboard' feature. This feature may require a full feature build of QSV (e.g. qsv with all_features or a prebuilt binary with feature flags enabled). See https://github.com/dathere/qsv#feature-flags`,
94
- });
95
- }
96
- if (rawError.includes("No such file or directory") ||
97
- rawError.includes("os error 2")) {
98
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Input file not found: '${inputPath}'`, {
99
- itemIndex,
100
- description: `qsv clipboard could not find the file at '${inputPath}'. Check for typos, or if n8n is running in Docker, ensure the host directory is mounted into the container.`,
101
- });
102
- }
103
- if (rawError.includes("Operation not permitted") ||
104
- rawError.includes("os error 1") ||
105
- rawError.includes("Permission denied") ||
106
- rawError.includes("os error 13")) {
107
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Permission denied accessing file: '${inputPath}'`, {
108
- itemIndex,
109
- description: `qsv clipboard was denied read access to '${inputPath}'. On macOS, check Full Disk Access or Removable Volumes permissions for the application running n8n.`,
110
- });
111
- }
112
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed executing 'qsv clipboard': ${rawError}`, { itemIndex });
113
- }
114
- }
@@ -1,2 +0,0 @@
1
- import type { IExecuteFunctions, INodeExecutionData } from "n8n-workflow";
2
- export declare function executeColor(this: IExecuteFunctions, itemIndex: number): Promise<INodeExecutionData[]>;
@@ -1,126 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.executeColor = executeColor;
4
- const n8n_workflow_1 = require("n8n-workflow");
5
- const child_process_1 = require("child_process");
6
- const util_1 = require("util");
7
- const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
8
- async function executeColor(itemIndex) {
9
- const inputPath = this.getNodeParameter("inputPath", itemIndex);
10
- if (!inputPath || !inputPath.trim()) {
11
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), "Input CSV file path is required.", { itemIndex });
12
- }
13
- const outputPath = this.getNodeParameter("outputPath", itemIndex, "") || "";
14
- const additionalArgs = this.getNodeParameter("additionalArgs", itemIndex, "") || "";
15
- const options = this.getNodeParameter("options", itemIndex, {}) || {};
16
- const args = ["color"];
17
- if (options.color === true) {
18
- args.push("--color");
19
- }
20
- if (options.rowNumbers === true) {
21
- args.push("--row-numbers");
22
- }
23
- if (options.title !== undefined && options.title !== "") {
24
- args.push("--title", String(options.title));
25
- }
26
- if (options.delimiter !== undefined && options.delimiter !== "") {
27
- args.push("--delimiter", String(options.delimiter));
28
- }
29
- if (options.memcheck === true) {
30
- args.push("--memcheck");
31
- }
32
- if (additionalArgs.trim()) {
33
- const rawMatches = additionalArgs.match(/[^\s"']+|"[^"]*"|'[^']*'/g) || [];
34
- const parsedArgs = rawMatches.map((arg) => {
35
- if ((arg.startsWith('"') && arg.endsWith('"')) ||
36
- (arg.startsWith("'") && arg.endsWith("'"))) {
37
- return arg.slice(1, -1);
38
- }
39
- return arg;
40
- });
41
- args.push(...parsedArgs);
42
- }
43
- if (outputPath.trim()) {
44
- args.push("--output", outputPath.trim());
45
- }
46
- args.push(inputPath);
47
- const qsvBin = process.env.DARTFX_QSV_BIN_PATH ||
48
- process.env.QSV_BIN_PATH ||
49
- process.env.QSV_PATH ||
50
- "qsv";
51
- try {
52
- const { stdout, stderr } = await execFileAsync(qsvBin, args, {
53
- maxBuffer: 50 * 1024 * 1024,
54
- encoding: "utf8",
55
- });
56
- let resultJson;
57
- try {
58
- resultJson = JSON.parse(stdout);
59
- }
60
- catch {
61
- resultJson = {
62
- command: "qsv color",
63
- inputPath,
64
- rawOutput: stdout,
65
- };
66
- }
67
- const returnJson = {
68
- success: true,
69
- command: "color",
70
- inputPath,
71
- result: resultJson,
72
- };
73
- if (outputPath.trim()) {
74
- returnJson.outputPath = outputPath.trim();
75
- }
76
- if (stderr && stderr.trim()) {
77
- returnJson.warnings = stderr.trim();
78
- }
79
- return [
80
- {
81
- json: returnJson,
82
- },
83
- ];
84
- }
85
- catch (error) {
86
- if (error.code === "ENOENT") {
87
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The QSV CLI binary ('${qsvBin}') was not found`, {
88
- itemIndex,
89
- description: `Please ensure 'qsv' is installed and available in the system PATH where n8n is running, or specify its absolute path via the DARTFX_QSV_BIN_PATH environment variable. (https://github.com/dathere/qsv)`,
90
- });
91
- }
92
- if (error.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER" ||
93
- (error.message && error.message.includes("maxBuffer"))) {
94
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `QSV execution exceeded maximum stdout buffer (50 MB)`, {
95
- itemIndex,
96
- description: `qsv color returned more data than could fit into memory. Specify an 'Output File Path' to stream results directly to disk instead.`,
97
- });
98
- }
99
- const rawError = (error.stderr || error.message || "").trim();
100
- if (rawError.includes("is not a qsv command") ||
101
- rawError.includes("unrecognized subcommand") ||
102
- rawError.includes("not available in this")) {
103
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Operation 'color' is not available in the installed QSV binary`, {
104
- itemIndex,
105
- description: `The installed QSV binary at '${qsvBin}' does not include the 'color' feature. This feature may require a full feature build of QSV (e.g. qsv with all_features or a prebuilt binary with feature flags enabled). See https://github.com/dathere/qsv#feature-flags`,
106
- });
107
- }
108
- if (rawError.includes("No such file or directory") ||
109
- rawError.includes("os error 2")) {
110
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Input file not found: '${inputPath}'`, {
111
- itemIndex,
112
- description: `qsv color could not find the file at '${inputPath}'. Check for typos, or if n8n is running in Docker, ensure the host directory is mounted into the container.`,
113
- });
114
- }
115
- if (rawError.includes("Operation not permitted") ||
116
- rawError.includes("os error 1") ||
117
- rawError.includes("Permission denied") ||
118
- rawError.includes("os error 13")) {
119
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Permission denied accessing file: '${inputPath}'`, {
120
- itemIndex,
121
- description: `qsv color was denied read access to '${inputPath}'. On macOS, check Full Disk Access or Removable Volumes permissions for the application running n8n.`,
122
- });
123
- }
124
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed executing 'qsv color': ${rawError}`, { itemIndex });
125
- }
126
- }
@@ -1,2 +0,0 @@
1
- import type { IExecuteFunctions, INodeExecutionData } from "n8n-workflow";
2
- export declare function executeLens(this: IExecuteFunctions, itemIndex: number): Promise<INodeExecutionData[]>;
@@ -1,156 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.executeLens = executeLens;
4
- const n8n_workflow_1 = require("n8n-workflow");
5
- const child_process_1 = require("child_process");
6
- const util_1 = require("util");
7
- const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
8
- async function executeLens(itemIndex) {
9
- const inputPath = this.getNodeParameter("inputPath", itemIndex);
10
- if (!inputPath || !inputPath.trim()) {
11
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), "Input CSV file path is required.", { itemIndex });
12
- }
13
- const outputPath = this.getNodeParameter("outputPath", itemIndex, "") || "";
14
- const additionalArgs = this.getNodeParameter("additionalArgs", itemIndex, "") || "";
15
- const options = this.getNodeParameter("options", itemIndex, {}) || {};
16
- const args = ["lens"];
17
- if (options.delimiter !== undefined && options.delimiter !== "") {
18
- args.push("--delimiter", String(options.delimiter));
19
- }
20
- if (options.tabSeparated === true) {
21
- args.push("--tab-separated");
22
- }
23
- if (options.noHeaders === true) {
24
- args.push("--no-headers");
25
- }
26
- if (options.columns !== undefined && options.columns !== "") {
27
- args.push("--columns", String(options.columns));
28
- }
29
- if (options.filter !== undefined && options.filter !== "") {
30
- args.push("--filter", String(options.filter));
31
- }
32
- if (options.find !== undefined && options.find !== "") {
33
- args.push("--find", String(options.find));
34
- }
35
- if (options.ignoreCase === true) {
36
- args.push("--ignore-case");
37
- }
38
- if (options.freezeColumns !== undefined && options.freezeColumns !== "") {
39
- args.push("--freeze-columns", String(options.freezeColumns));
40
- }
41
- if (options.monochrome === true) {
42
- args.push("--monochrome");
43
- }
44
- if (options.wrapMode !== undefined && options.wrapMode !== "") {
45
- args.push("--wrap-mode", String(options.wrapMode));
46
- }
47
- if (options.autoReload === true) {
48
- args.push("--auto-reload");
49
- }
50
- if (options.streamingStdin === true) {
51
- args.push("--streaming-stdin");
52
- }
53
- if (options.prompt !== undefined && options.prompt !== "") {
54
- args.push("--prompt", String(options.prompt));
55
- }
56
- if (options.echoColumn !== undefined && options.echoColumn !== "") {
57
- args.push("--echo-column", String(options.echoColumn));
58
- }
59
- if (options.debug === true) {
60
- args.push("--debug");
61
- }
62
- if (additionalArgs.trim()) {
63
- const rawMatches = additionalArgs.match(/[^\s"']+|"[^"]*"|'[^']*'/g) || [];
64
- const parsedArgs = rawMatches.map((arg) => {
65
- if ((arg.startsWith('"') && arg.endsWith('"')) ||
66
- (arg.startsWith("'") && arg.endsWith("'"))) {
67
- return arg.slice(1, -1);
68
- }
69
- return arg;
70
- });
71
- args.push(...parsedArgs);
72
- }
73
- if (outputPath.trim()) {
74
- args.push("--output", outputPath.trim());
75
- }
76
- args.push(inputPath);
77
- const qsvBin = process.env.DARTFX_QSV_BIN_PATH ||
78
- process.env.QSV_BIN_PATH ||
79
- process.env.QSV_PATH ||
80
- "qsv";
81
- try {
82
- const { stdout, stderr } = await execFileAsync(qsvBin, args, {
83
- maxBuffer: 50 * 1024 * 1024,
84
- encoding: "utf8",
85
- });
86
- let resultJson;
87
- try {
88
- resultJson = JSON.parse(stdout);
89
- }
90
- catch {
91
- resultJson = {
92
- command: "qsv lens",
93
- inputPath,
94
- rawOutput: stdout,
95
- };
96
- }
97
- const returnJson = {
98
- success: true,
99
- command: "lens",
100
- inputPath,
101
- result: resultJson,
102
- };
103
- if (outputPath.trim()) {
104
- returnJson.outputPath = outputPath.trim();
105
- }
106
- if (stderr && stderr.trim()) {
107
- returnJson.warnings = stderr.trim();
108
- }
109
- return [
110
- {
111
- json: returnJson,
112
- },
113
- ];
114
- }
115
- catch (error) {
116
- if (error.code === "ENOENT") {
117
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The QSV CLI binary ('${qsvBin}') was not found`, {
118
- itemIndex,
119
- description: `Please ensure 'qsv' is installed and available in the system PATH where n8n is running, or specify its absolute path via the DARTFX_QSV_BIN_PATH environment variable. (https://github.com/dathere/qsv)`,
120
- });
121
- }
122
- if (error.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER" ||
123
- (error.message && error.message.includes("maxBuffer"))) {
124
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `QSV execution exceeded maximum stdout buffer (50 MB)`, {
125
- itemIndex,
126
- description: `qsv lens returned more data than could fit into memory. Specify an 'Output File Path' to stream results directly to disk instead.`,
127
- });
128
- }
129
- const rawError = (error.stderr || error.message || "").trim();
130
- if (rawError.includes("is not a qsv command") ||
131
- rawError.includes("unrecognized subcommand") ||
132
- rawError.includes("not available in this")) {
133
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Operation 'lens' is not available in the installed QSV binary`, {
134
- itemIndex,
135
- description: `The installed QSV binary at '${qsvBin}' does not include the 'lens' feature. This feature may require a full feature build of QSV (e.g. qsv with all_features or a prebuilt binary with feature flags enabled). See https://github.com/dathere/qsv#feature-flags`,
136
- });
137
- }
138
- if (rawError.includes("No such file or directory") ||
139
- rawError.includes("os error 2")) {
140
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Input file not found: '${inputPath}'`, {
141
- itemIndex,
142
- description: `qsv lens could not find the file at '${inputPath}'. Check for typos, or if n8n is running in Docker, ensure the host directory is mounted into the container.`,
143
- });
144
- }
145
- if (rawError.includes("Operation not permitted") ||
146
- rawError.includes("os error 1") ||
147
- rawError.includes("Permission denied") ||
148
- rawError.includes("os error 13")) {
149
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Permission denied accessing file: '${inputPath}'`, {
150
- itemIndex,
151
- description: `qsv lens was denied read access to '${inputPath}'. On macOS, check Full Disk Access or Removable Volumes permissions for the application running n8n.`,
152
- });
153
- }
154
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed executing 'qsv lens': ${rawError}`, { itemIndex });
155
- }
156
- }
@@ -1,2 +0,0 @@
1
- import type { IExecuteFunctions, INodeExecutionData } from "n8n-workflow";
2
- export declare function executeLog(this: IExecuteFunctions, itemIndex: number): Promise<INodeExecutionData[]>;