@rudsys/n8n-nodes-sqlite3 0.1.9 → 0.1.10
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.
package/package.json
CHANGED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SqliteSsh = void 0;
|
|
4
|
-
class SqliteSsh {
|
|
5
|
-
constructor() {
|
|
6
|
-
this.name = 'sqliteSsh';
|
|
7
|
-
this.displayName = 'SQLite SSH Credentials';
|
|
8
|
-
this.documentationUrl = 'https://github.com/rudsys/n8n-nodes-sqlite3';
|
|
9
|
-
this.properties = [
|
|
10
|
-
{
|
|
11
|
-
displayName: 'Host',
|
|
12
|
-
name: 'host',
|
|
13
|
-
type: 'string',
|
|
14
|
-
default: '',
|
|
15
|
-
required: true,
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
displayName: 'Port',
|
|
19
|
-
name: 'port',
|
|
20
|
-
type: 'number',
|
|
21
|
-
default: 22,
|
|
22
|
-
required: true,
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
displayName: 'Username',
|
|
26
|
-
name: 'username',
|
|
27
|
-
type: 'string',
|
|
28
|
-
default: '',
|
|
29
|
-
required: true,
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
displayName: 'Authentication Method',
|
|
33
|
-
name: 'authMethod',
|
|
34
|
-
type: 'options',
|
|
35
|
-
options: [
|
|
36
|
-
{
|
|
37
|
-
name: 'Password',
|
|
38
|
-
value: 'password',
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
name: 'Private Key',
|
|
42
|
-
value: 'privateKey',
|
|
43
|
-
},
|
|
44
|
-
],
|
|
45
|
-
default: 'password',
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
displayName: 'Password',
|
|
49
|
-
name: 'password',
|
|
50
|
-
type: 'string',
|
|
51
|
-
typeOptions: {
|
|
52
|
-
password: true,
|
|
53
|
-
},
|
|
54
|
-
displayOptions: {
|
|
55
|
-
show: {
|
|
56
|
-
authMethod: ['password'],
|
|
57
|
-
},
|
|
58
|
-
},
|
|
59
|
-
default: '',
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
displayName: 'Private Key',
|
|
63
|
-
name: 'privateKey',
|
|
64
|
-
type: 'string',
|
|
65
|
-
typeOptions: {
|
|
66
|
-
password: true,
|
|
67
|
-
rows: 4,
|
|
68
|
-
},
|
|
69
|
-
displayOptions: {
|
|
70
|
-
show: {
|
|
71
|
-
authMethod: ['privateKey'],
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
default: '',
|
|
75
|
-
description: 'The private key content (PEM format)',
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
displayName: 'Passphrase',
|
|
79
|
-
name: 'passphrase',
|
|
80
|
-
type: 'string',
|
|
81
|
-
typeOptions: {
|
|
82
|
-
password: true,
|
|
83
|
-
},
|
|
84
|
-
displayOptions: {
|
|
85
|
-
show: {
|
|
86
|
-
authMethod: ['privateKey'],
|
|
87
|
-
},
|
|
88
|
-
},
|
|
89
|
-
default: '',
|
|
90
|
-
description: 'Passphrase for the private key',
|
|
91
|
-
},
|
|
92
|
-
];
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
exports.SqliteSsh = SqliteSsh;
|
|
@@ -1,572 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SqliteSsh = void 0;
|
|
4
|
-
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
|
-
const node_ssh_1 = require("node-ssh");
|
|
6
|
-
class SqliteSsh {
|
|
7
|
-
constructor() {
|
|
8
|
-
this.description = {
|
|
9
|
-
displayName: 'SQLite SSH',
|
|
10
|
-
name: 'sqliteSsh',
|
|
11
|
-
icon: 'fa:database',
|
|
12
|
-
group: ['transform'],
|
|
13
|
-
version: 2,
|
|
14
|
-
description: 'Execute SQLite operations on a remote server via SSH',
|
|
15
|
-
defaults: {
|
|
16
|
-
name: 'SQLite SSH',
|
|
17
|
-
},
|
|
18
|
-
inputs: ['main'],
|
|
19
|
-
outputs: ['main'],
|
|
20
|
-
credentials: [
|
|
21
|
-
{
|
|
22
|
-
name: 'sqliteSsh',
|
|
23
|
-
required: true,
|
|
24
|
-
},
|
|
25
|
-
],
|
|
26
|
-
properties: [
|
|
27
|
-
{
|
|
28
|
-
displayName: 'Database Path',
|
|
29
|
-
name: 'databasePath',
|
|
30
|
-
type: 'string',
|
|
31
|
-
default: '',
|
|
32
|
-
placeholder: '/var/www/html/data/database.db',
|
|
33
|
-
required: true,
|
|
34
|
-
description: 'Absolute path to the SQLite database file on the remote server',
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
displayName: 'SQLite Binary Path',
|
|
38
|
-
name: 'binaryPath',
|
|
39
|
-
type: 'string',
|
|
40
|
-
default: 'sqlite3',
|
|
41
|
-
placeholder: '/usr/bin/sqlite3',
|
|
42
|
-
description: 'Path to the sqlite3 binary on the remote server',
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
displayName: 'Operation',
|
|
46
|
-
name: 'operation',
|
|
47
|
-
type: 'options',
|
|
48
|
-
noDataExpression: true,
|
|
49
|
-
options: [
|
|
50
|
-
{ name: 'Execute Query', value: 'executeQuery', description: 'Execute a raw SQL query' },
|
|
51
|
-
{ name: 'Insert', value: 'insert', description: 'Insert data from input items' },
|
|
52
|
-
{ name: 'Select', value: 'select', description: 'Select data from a table' },
|
|
53
|
-
{ name: 'Update', value: 'update', description: 'Update data in a table' },
|
|
54
|
-
{ name: 'Delete', value: 'delete', description: 'Delete data from a table' },
|
|
55
|
-
{ name: 'Table Operations', value: 'manageTables', description: 'Create, rename, drop, or list tables' },
|
|
56
|
-
{ name: 'Column Operations', value: 'manageColumns', description: 'Add, rename, drop, or list columns' },
|
|
57
|
-
{ name: 'Vacuum', value: 'vacuum', description: 'Rebuild the database file' },
|
|
58
|
-
],
|
|
59
|
-
default: 'executeQuery',
|
|
60
|
-
},
|
|
61
|
-
// ------------------ Table Operations ------------------
|
|
62
|
-
{
|
|
63
|
-
displayName: 'Action',
|
|
64
|
-
name: 'tableAction',
|
|
65
|
-
type: 'options',
|
|
66
|
-
displayOptions: { show: { operation: ['manageTables'] } },
|
|
67
|
-
options: [
|
|
68
|
-
{ name: 'List Tables', value: 'list' },
|
|
69
|
-
{ name: 'Create Table', value: 'create' },
|
|
70
|
-
{ name: 'Rename Table', value: 'rename' },
|
|
71
|
-
{ name: 'Drop Table', value: 'drop' },
|
|
72
|
-
],
|
|
73
|
-
default: 'list',
|
|
74
|
-
description: 'Action to perform on tables',
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
displayName: 'New Table Name',
|
|
78
|
-
name: 'newTableName',
|
|
79
|
-
type: 'string',
|
|
80
|
-
displayOptions: {
|
|
81
|
-
show: {
|
|
82
|
-
operation: ['manageTables'],
|
|
83
|
-
tableAction: ['rename'],
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
default: '',
|
|
87
|
-
placeholder: 'my_renamed_table',
|
|
88
|
-
required: true,
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
displayName: 'Columns',
|
|
92
|
-
name: 'columnsUi',
|
|
93
|
-
type: 'fixedCollection',
|
|
94
|
-
typeOptions: {
|
|
95
|
-
multipleValues: true,
|
|
96
|
-
},
|
|
97
|
-
displayOptions: {
|
|
98
|
-
show: {
|
|
99
|
-
operation: ['manageTables'],
|
|
100
|
-
tableAction: ['create'],
|
|
101
|
-
},
|
|
102
|
-
},
|
|
103
|
-
default: {},
|
|
104
|
-
placeholder: 'Add Column',
|
|
105
|
-
options: [
|
|
106
|
-
{
|
|
107
|
-
name: 'column',
|
|
108
|
-
displayName: 'Column',
|
|
109
|
-
values: [
|
|
110
|
-
{
|
|
111
|
-
displayName: 'Name',
|
|
112
|
-
name: 'name',
|
|
113
|
-
type: 'string',
|
|
114
|
-
default: '',
|
|
115
|
-
required: true,
|
|
116
|
-
description: 'Name of the column',
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
displayName: 'Type',
|
|
120
|
-
name: 'type',
|
|
121
|
-
type: 'options',
|
|
122
|
-
options: [
|
|
123
|
-
{ name: 'INTEGER', value: 'INTEGER' },
|
|
124
|
-
{ name: 'TEXT', value: 'TEXT' },
|
|
125
|
-
{ name: 'REAL', value: 'REAL' },
|
|
126
|
-
{ name: 'BLOB', value: 'BLOB' },
|
|
127
|
-
{ name: 'NUMERIC', value: 'NUMERIC' },
|
|
128
|
-
],
|
|
129
|
-
default: 'TEXT',
|
|
130
|
-
description: 'Data type of the column',
|
|
131
|
-
},
|
|
132
|
-
{
|
|
133
|
-
displayName: 'Primary Key',
|
|
134
|
-
name: 'primaryKey',
|
|
135
|
-
type: 'boolean',
|
|
136
|
-
default: false,
|
|
137
|
-
description: 'Whether this column is a primary key',
|
|
138
|
-
},
|
|
139
|
-
{
|
|
140
|
-
displayName: 'Auto Increment',
|
|
141
|
-
name: 'autoIncrement',
|
|
142
|
-
type: 'boolean',
|
|
143
|
-
default: false,
|
|
144
|
-
displayOptions: {
|
|
145
|
-
show: {
|
|
146
|
-
primaryKey: [true],
|
|
147
|
-
type: ['INTEGER'],
|
|
148
|
-
},
|
|
149
|
-
},
|
|
150
|
-
description: 'Whether this column should auto increment (only for INTEGER PRIMARY KEY)',
|
|
151
|
-
},
|
|
152
|
-
{
|
|
153
|
-
displayName: 'Not Null',
|
|
154
|
-
name: 'notNull',
|
|
155
|
-
type: 'boolean',
|
|
156
|
-
default: false,
|
|
157
|
-
description: 'Whether this column cannot be null',
|
|
158
|
-
},
|
|
159
|
-
{
|
|
160
|
-
displayName: 'Unique',
|
|
161
|
-
name: 'unique',
|
|
162
|
-
type: 'boolean',
|
|
163
|
-
default: false,
|
|
164
|
-
description: 'Whether values in this column must be unique',
|
|
165
|
-
},
|
|
166
|
-
],
|
|
167
|
-
},
|
|
168
|
-
],
|
|
169
|
-
},
|
|
170
|
-
// ------------------ Column Operations ------------------
|
|
171
|
-
{
|
|
172
|
-
displayName: 'Action',
|
|
173
|
-
name: 'columnAction',
|
|
174
|
-
type: 'options',
|
|
175
|
-
displayOptions: { show: { operation: ['manageColumns'] } },
|
|
176
|
-
options: [
|
|
177
|
-
{ name: 'List Columns', value: 'list' },
|
|
178
|
-
{ name: 'Add Column', value: 'add' },
|
|
179
|
-
{ name: 'Rename Column', value: 'rename' },
|
|
180
|
-
{ name: 'Drop Column', value: 'drop' },
|
|
181
|
-
],
|
|
182
|
-
default: 'list',
|
|
183
|
-
description: 'Action to perform on the table columns',
|
|
184
|
-
},
|
|
185
|
-
{
|
|
186
|
-
displayName: 'Column Name',
|
|
187
|
-
name: 'columnName',
|
|
188
|
-
type: 'string',
|
|
189
|
-
displayOptions: {
|
|
190
|
-
show: {
|
|
191
|
-
operation: ['manageColumns'],
|
|
192
|
-
columnAction: ['add', 'rename', 'drop'],
|
|
193
|
-
},
|
|
194
|
-
},
|
|
195
|
-
default: '',
|
|
196
|
-
placeholder: 'my_new_column',
|
|
197
|
-
required: true,
|
|
198
|
-
},
|
|
199
|
-
{
|
|
200
|
-
displayName: 'New Column Name',
|
|
201
|
-
name: 'newColumnName',
|
|
202
|
-
type: 'string',
|
|
203
|
-
displayOptions: {
|
|
204
|
-
show: {
|
|
205
|
-
operation: ['manageColumns'],
|
|
206
|
-
columnAction: ['rename'],
|
|
207
|
-
},
|
|
208
|
-
},
|
|
209
|
-
default: '',
|
|
210
|
-
placeholder: 'my_renamed_column',
|
|
211
|
-
required: true,
|
|
212
|
-
},
|
|
213
|
-
{
|
|
214
|
-
displayName: 'Column Definition',
|
|
215
|
-
name: 'columnDefinition',
|
|
216
|
-
type: 'string',
|
|
217
|
-
displayOptions: {
|
|
218
|
-
show: {
|
|
219
|
-
operation: ['manageColumns'],
|
|
220
|
-
columnAction: ['add'],
|
|
221
|
-
},
|
|
222
|
-
},
|
|
223
|
-
default: 'TEXT',
|
|
224
|
-
placeholder: 'TEXT NOT NULL DEFAULT ""',
|
|
225
|
-
description: 'Type and constraints (e.g., INTEGER PRIMARY KEY, TEXT DEFAULT "active")',
|
|
226
|
-
},
|
|
227
|
-
// ------------------ Execute Query ------------------
|
|
228
|
-
{
|
|
229
|
-
displayName: 'Query',
|
|
230
|
-
name: 'query',
|
|
231
|
-
type: 'string',
|
|
232
|
-
typeOptions: { rows: 5 },
|
|
233
|
-
displayOptions: { show: { operation: ['executeQuery'] } },
|
|
234
|
-
default: '',
|
|
235
|
-
placeholder: 'SELECT * FROM users;',
|
|
236
|
-
required: true,
|
|
237
|
-
},
|
|
238
|
-
// ------------------ Table Field ------------------
|
|
239
|
-
{
|
|
240
|
-
displayName: 'Table',
|
|
241
|
-
name: 'table',
|
|
242
|
-
type: 'string',
|
|
243
|
-
displayOptions: {
|
|
244
|
-
show: {
|
|
245
|
-
operation: [
|
|
246
|
-
'insert',
|
|
247
|
-
'select',
|
|
248
|
-
'update',
|
|
249
|
-
'delete',
|
|
250
|
-
'manageTables',
|
|
251
|
-
'manageColumns',
|
|
252
|
-
],
|
|
253
|
-
},
|
|
254
|
-
hide: {
|
|
255
|
-
operation: ['manageTables'],
|
|
256
|
-
tableAction: ['list'],
|
|
257
|
-
},
|
|
258
|
-
},
|
|
259
|
-
default: '',
|
|
260
|
-
required: true,
|
|
261
|
-
description: 'Name of the table',
|
|
262
|
-
},
|
|
263
|
-
// ------------------ Insert Options ------------------
|
|
264
|
-
{
|
|
265
|
-
displayName: 'Conflict Mode',
|
|
266
|
-
name: 'conflictMode',
|
|
267
|
-
type: 'options',
|
|
268
|
-
displayOptions: { show: { operation: ['insert'] } },
|
|
269
|
-
options: [
|
|
270
|
-
{ name: 'Abort (Fail)', value: 'abort' },
|
|
271
|
-
{ name: 'Ignore', value: 'ignore' },
|
|
272
|
-
{ name: 'Replace', value: 'replace' },
|
|
273
|
-
],
|
|
274
|
-
default: 'abort',
|
|
275
|
-
},
|
|
276
|
-
{
|
|
277
|
-
displayName: 'Data Processing Mode',
|
|
278
|
-
name: 'dataMode',
|
|
279
|
-
type: 'options',
|
|
280
|
-
options: [
|
|
281
|
-
{ name: 'Auto-Map Input Data to Columns', value: 'autoMap', description: 'Use all input items fields as column names' },
|
|
282
|
-
{ name: 'Map Specific Columns', value: 'define', description: 'Only use specific fields from input items' },
|
|
283
|
-
],
|
|
284
|
-
displayOptions: { show: { operation: ['insert', 'update'] } },
|
|
285
|
-
default: 'autoMap',
|
|
286
|
-
description: 'Choose whether to map all input fields to columns or select specific ones',
|
|
287
|
-
},
|
|
288
|
-
{
|
|
289
|
-
displayName: 'Columns to Map',
|
|
290
|
-
name: 'specificColumns',
|
|
291
|
-
type: 'string',
|
|
292
|
-
displayOptions: {
|
|
293
|
-
show: {
|
|
294
|
-
operation: ['insert', 'update'],
|
|
295
|
-
dataMode: ['define'],
|
|
296
|
-
},
|
|
297
|
-
},
|
|
298
|
-
default: '',
|
|
299
|
-
placeholder: 'id, name, email',
|
|
300
|
-
description: 'Comma-separated list of column names to map from input',
|
|
301
|
-
},
|
|
302
|
-
// ------------------ Select Options ------------------
|
|
303
|
-
{
|
|
304
|
-
displayName: 'Columns',
|
|
305
|
-
name: 'columns',
|
|
306
|
-
type: 'string',
|
|
307
|
-
displayOptions: { show: { operation: ['select'] } },
|
|
308
|
-
default: '*',
|
|
309
|
-
description: 'Comma-separated list of columns',
|
|
310
|
-
},
|
|
311
|
-
// ------------------ Filters ------------------
|
|
312
|
-
{
|
|
313
|
-
displayName: 'Filters',
|
|
314
|
-
name: 'filters',
|
|
315
|
-
type: 'fixedCollection',
|
|
316
|
-
typeOptions: { multipleValues: true },
|
|
317
|
-
displayOptions: {
|
|
318
|
-
show: { operation: ['select', 'update', 'delete'] },
|
|
319
|
-
},
|
|
320
|
-
default: {},
|
|
321
|
-
options: [
|
|
322
|
-
{
|
|
323
|
-
name: 'filter',
|
|
324
|
-
displayName: 'Filter',
|
|
325
|
-
values: [
|
|
326
|
-
{ displayName: 'Column', name: 'column', type: 'string', default: '' },
|
|
327
|
-
{
|
|
328
|
-
displayName: 'Operator',
|
|
329
|
-
name: 'operator',
|
|
330
|
-
type: 'options',
|
|
331
|
-
options: [
|
|
332
|
-
{ name: 'Equal (=)', value: 'equal' },
|
|
333
|
-
{ name: 'Not Equal (!=)', value: 'notEqual' },
|
|
334
|
-
{ name: 'Like', value: 'like' },
|
|
335
|
-
{ name: 'Greater Than (>)', value: 'greater' },
|
|
336
|
-
{ name: 'Less Than (<)', value: 'less' },
|
|
337
|
-
{ name: 'Is Null', value: 'isNull' },
|
|
338
|
-
{ name: 'Is Not Null', value: 'isNotNull' },
|
|
339
|
-
],
|
|
340
|
-
default: 'equal',
|
|
341
|
-
},
|
|
342
|
-
{
|
|
343
|
-
displayName: 'Value',
|
|
344
|
-
name: 'value',
|
|
345
|
-
type: 'string',
|
|
346
|
-
default: '',
|
|
347
|
-
displayOptions: { hide: { operator: ['isNull', 'isNotNull'] } },
|
|
348
|
-
},
|
|
349
|
-
],
|
|
350
|
-
},
|
|
351
|
-
],
|
|
352
|
-
},
|
|
353
|
-
],
|
|
354
|
-
};
|
|
355
|
-
}
|
|
356
|
-
async execute() {
|
|
357
|
-
const items = this.getInputData();
|
|
358
|
-
const returnData = [];
|
|
359
|
-
const credentials = await this.getCredentials('sqliteSsh');
|
|
360
|
-
const operation = this.getNodeParameter('operation', 0);
|
|
361
|
-
const databasePath = this.getNodeParameter('databasePath', 0);
|
|
362
|
-
const binaryPath = this.getNodeParameter('binaryPath', 0, 'sqlite3');
|
|
363
|
-
const ssh = new node_ssh_1.NodeSSH();
|
|
364
|
-
// Helpers for SQL Escaping
|
|
365
|
-
const escapeIdentifier = (id) => `"${id.replace(/"/g, '""')}"`;
|
|
366
|
-
const escapeValue = (v) => {
|
|
367
|
-
if (v === null || v === undefined)
|
|
368
|
-
return 'NULL';
|
|
369
|
-
if (typeof v === 'number')
|
|
370
|
-
return String(v);
|
|
371
|
-
if (typeof v === 'boolean')
|
|
372
|
-
return v ? '1' : '0';
|
|
373
|
-
return `'${String(v).replace(/'/g, "''")}'`;
|
|
374
|
-
};
|
|
375
|
-
const buildWhereClause = (i) => {
|
|
376
|
-
const filters = this.getNodeParameter('filters', i, {});
|
|
377
|
-
if (!filters.filter || filters.filter.length === 0)
|
|
378
|
-
return '';
|
|
379
|
-
const clauses = filters.filter.map((f) => {
|
|
380
|
-
const col = escapeIdentifier(f.column);
|
|
381
|
-
switch (f.operator) {
|
|
382
|
-
case 'equal': return `${col} = ${escapeValue(f.value)}`;
|
|
383
|
-
case 'notEqual': return `${col} != ${escapeValue(f.value)}`;
|
|
384
|
-
case 'like': return `${col} LIKE ${escapeValue(f.value)}`;
|
|
385
|
-
case 'greater': return `${col} > ${escapeValue(f.value)}`;
|
|
386
|
-
case 'less': return `${col} < ${escapeValue(f.value)}`;
|
|
387
|
-
case 'isNull': return `${col} IS NULL`;
|
|
388
|
-
case 'isNotNull': return `${col} IS NOT NULL`;
|
|
389
|
-
default: return '';
|
|
390
|
-
}
|
|
391
|
-
});
|
|
392
|
-
return ` WHERE ${clauses.join(' AND ')}`;
|
|
393
|
-
};
|
|
394
|
-
try {
|
|
395
|
-
// 1. Establish SSH Connection
|
|
396
|
-
await ssh.connect({
|
|
397
|
-
host: credentials.host,
|
|
398
|
-
port: credentials.port,
|
|
399
|
-
username: credentials.username,
|
|
400
|
-
password: credentials.password,
|
|
401
|
-
privateKey: credentials.privateKey,
|
|
402
|
-
passphrase: credentials.passphrase,
|
|
403
|
-
readyTimeout: 20000,
|
|
404
|
-
});
|
|
405
|
-
// 2. Handle Operations
|
|
406
|
-
if (operation === 'insert') {
|
|
407
|
-
// BULK INSERT (Efficiency)
|
|
408
|
-
const table = escapeIdentifier(this.getNodeParameter('table', 0));
|
|
409
|
-
const conflictMode = this.getNodeParameter('conflictMode', 0, 'abort');
|
|
410
|
-
const verb = conflictMode === 'replace' ? 'INSERT OR REPLACE' : (conflictMode === 'ignore' ? 'INSERT OR IGNORE' : 'INSERT');
|
|
411
|
-
if (items.length > 0) {
|
|
412
|
-
const dataMode = this.getNodeParameter('dataMode', 0, 'autoMap');
|
|
413
|
-
let columnsList = Object.keys(items[0].json);
|
|
414
|
-
if (dataMode === 'define') {
|
|
415
|
-
const specificColumns = this.getNodeParameter('specificColumns', 0, '')
|
|
416
|
-
.split(',')
|
|
417
|
-
.map(c => c.trim())
|
|
418
|
-
.filter(c => c);
|
|
419
|
-
if (specificColumns.length > 0) {
|
|
420
|
-
columnsList = specificColumns;
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
const columnsSql = columnsList.map(escapeIdentifier).join(', ');
|
|
424
|
-
const valuesSql = items.map(item => {
|
|
425
|
-
return `(${columnsList.map(k => escapeValue(item.json[k])).join(', ')})`;
|
|
426
|
-
}).join(', ');
|
|
427
|
-
const sql = `${verb} INTO ${table} (${columnsSql}) VALUES ${valuesSql};`;
|
|
428
|
-
const result = await ssh.execCommand(`${binaryPath} -json "${databasePath}" '${sql.replace(/'/g, "'\\''")}'`);
|
|
429
|
-
if (result.code !== 0)
|
|
430
|
-
throw new Error(result.stderr || 'SQLite Execution Error');
|
|
431
|
-
items.forEach((_, i) => returnData.push({ json: { success: true }, pairedItem: { item: i } }));
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
else {
|
|
435
|
-
// ITERATIVE OPERATIONS (Select, Update, Delete, Raw Query)
|
|
436
|
-
for (let i = 0; i < items.length; i++) {
|
|
437
|
-
let sql = '';
|
|
438
|
-
const table = this.getNodeParameter('table', i, '') ? escapeIdentifier(this.getNodeParameter('table', i, '')) : '';
|
|
439
|
-
if (operation === 'select') {
|
|
440
|
-
const columns = this.getNodeParameter('columns', i, '*');
|
|
441
|
-
const where = buildWhereClause(i);
|
|
442
|
-
sql = `SELECT ${columns} FROM ${table}${where};`;
|
|
443
|
-
}
|
|
444
|
-
else if (operation === 'update') {
|
|
445
|
-
const where = buildWhereClause(i);
|
|
446
|
-
const dataMode = this.getNodeParameter('dataMode', i, 'autoMap');
|
|
447
|
-
let updateEntries = Object.entries(items[i].json);
|
|
448
|
-
if (dataMode === 'define') {
|
|
449
|
-
const specificColumns = this.getNodeParameter('specificColumns', i, '')
|
|
450
|
-
.split(',')
|
|
451
|
-
.map(c => c.trim())
|
|
452
|
-
.filter(c => c);
|
|
453
|
-
if (specificColumns.length > 0) {
|
|
454
|
-
updateEntries = updateEntries.filter(([k]) => specificColumns.includes(k));
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
const updateFields = updateEntries
|
|
458
|
-
.map(([k, v]) => `${escapeIdentifier(k)} = ${escapeValue(v)}`)
|
|
459
|
-
.join(', ');
|
|
460
|
-
sql = `UPDATE ${table} SET ${updateFields}${where};`;
|
|
461
|
-
}
|
|
462
|
-
else if (operation === 'delete') {
|
|
463
|
-
const where = buildWhereClause(i);
|
|
464
|
-
sql = `DELETE FROM ${table}${where};`;
|
|
465
|
-
}
|
|
466
|
-
else if (operation === 'executeQuery') {
|
|
467
|
-
sql = this.getNodeParameter('query', i);
|
|
468
|
-
}
|
|
469
|
-
else if (operation === 'manageTables') {
|
|
470
|
-
const action = this.getNodeParameter('tableAction', i);
|
|
471
|
-
if (action === 'list') {
|
|
472
|
-
sql = "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%';";
|
|
473
|
-
}
|
|
474
|
-
else {
|
|
475
|
-
if (!table) {
|
|
476
|
-
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Table name is required', { itemIndex: i });
|
|
477
|
-
}
|
|
478
|
-
if (action === 'create') {
|
|
479
|
-
const columnsUi = this.getNodeParameter('columnsUi', i);
|
|
480
|
-
const columns = (columnsUi === null || columnsUi === void 0 ? void 0 : columnsUi.column) || [];
|
|
481
|
-
if (!columns.length) {
|
|
482
|
-
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'At least one column is required to create a table', { itemIndex: i });
|
|
483
|
-
}
|
|
484
|
-
const columnDefs = columns.map((col) => {
|
|
485
|
-
let def = `${escapeIdentifier(col.name)} ${col.type}`;
|
|
486
|
-
if (col.primaryKey) {
|
|
487
|
-
def += ' PRIMARY KEY';
|
|
488
|
-
if (col.autoIncrement && col.type === 'INTEGER')
|
|
489
|
-
def += ' AUTOINCREMENT';
|
|
490
|
-
}
|
|
491
|
-
if (col.notNull)
|
|
492
|
-
def += ' NOT NULL';
|
|
493
|
-
if (col.unique)
|
|
494
|
-
def += ' UNIQUE';
|
|
495
|
-
return def;
|
|
496
|
-
});
|
|
497
|
-
sql = `CREATE TABLE ${table} (${columnDefs.join(', ')});`;
|
|
498
|
-
}
|
|
499
|
-
else if (action === 'rename') {
|
|
500
|
-
const newName = escapeIdentifier(this.getNodeParameter('newTableName', i));
|
|
501
|
-
sql = `ALTER TABLE ${table} RENAME TO ${newName};`;
|
|
502
|
-
}
|
|
503
|
-
else if (action === 'drop') {
|
|
504
|
-
sql = `DROP TABLE ${table};`;
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
else if (operation === 'manageColumns') {
|
|
509
|
-
const action = this.getNodeParameter('columnAction', i);
|
|
510
|
-
if (action === 'list') {
|
|
511
|
-
// PRAGMA table_info returns list of columns
|
|
512
|
-
sql = `PRAGMA table_info(${table});`;
|
|
513
|
-
}
|
|
514
|
-
else {
|
|
515
|
-
const colName = escapeIdentifier(this.getNodeParameter('columnName', i));
|
|
516
|
-
if (action === 'add') {
|
|
517
|
-
let colDef = this.getNodeParameter('columnDefinition', i);
|
|
518
|
-
colDef = colDef.trim();
|
|
519
|
-
if (colDef.startsWith('(') && colDef.endsWith(')')) {
|
|
520
|
-
colDef = colDef.slice(1, -1);
|
|
521
|
-
}
|
|
522
|
-
sql = `ALTER TABLE ${table} ADD COLUMN ${colName} ${colDef};`;
|
|
523
|
-
}
|
|
524
|
-
else if (action === 'rename') {
|
|
525
|
-
const newColName = escapeIdentifier(this.getNodeParameter('newColumnName', i));
|
|
526
|
-
sql = `ALTER TABLE ${table} RENAME COLUMN ${colName} TO ${newColName};`;
|
|
527
|
-
}
|
|
528
|
-
else if (action === 'drop') {
|
|
529
|
-
sql = `ALTER TABLE ${table} DROP COLUMN ${colName};`;
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
else if (operation === 'vacuum') {
|
|
534
|
-
sql = 'VACUUM;';
|
|
535
|
-
}
|
|
536
|
-
const result = await ssh.execCommand(`${binaryPath} -json "${databasePath}" '${sql.replace(/'/g, "'\\''")}'`);
|
|
537
|
-
if (result.code !== 0) {
|
|
538
|
-
throw new n8n_workflow_1.NodeOperationError(this.getNode(), result.stderr || 'SQLite Error', {
|
|
539
|
-
itemIndex: i,
|
|
540
|
-
description: `Query: ${sql}`,
|
|
541
|
-
});
|
|
542
|
-
}
|
|
543
|
-
if (result.stdout) {
|
|
544
|
-
try {
|
|
545
|
-
const parsed = JSON.parse(result.stdout);
|
|
546
|
-
if (Array.isArray(parsed)) {
|
|
547
|
-
parsed.forEach(row => returnData.push({ json: row, pairedItem: { item: i } }));
|
|
548
|
-
}
|
|
549
|
-
else {
|
|
550
|
-
returnData.push({ json: parsed, pairedItem: { item: i } });
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
catch {
|
|
554
|
-
returnData.push({ json: { output: result.stdout }, pairedItem: { item: i } });
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
else {
|
|
558
|
-
returnData.push({ json: { success: true }, pairedItem: { item: i } });
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
catch (error) {
|
|
564
|
-
throw error;
|
|
565
|
-
}
|
|
566
|
-
finally {
|
|
567
|
-
ssh.dispose();
|
|
568
|
-
}
|
|
569
|
-
return [returnData];
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
exports.SqliteSsh = SqliteSsh;
|