@intecoag/inteco-cli 0.5.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.
- package/README.md +3 -0
- package/package.json +35 -0
- package/src/index.js +85 -0
- package/src/modules/adbBridge.js +52 -0
- package/src/modules/adbIntentSender.js +82 -0
- package/src/modules/bundleProduct.js +161 -0
- package/src/modules/csvMerger.js +118 -0
- package/src/modules/deleteDB.js +84 -0
- package/src/modules/dumpDB.js +216 -0
- package/src/modules/dumpTableToCSV.js +154 -0
- package/src/modules/extdSearch.js +226 -0
- package/src/modules/graphqlSchemaExport.js +61 -0
- package/src/modules/importDB.js +121 -0
- package/src/modules/rewriteConfig.js +79 -0
- package/src/modules/setCLIConfig.js +33 -0
- package/src/modules/syncConfig.js +264 -0
- package/src/modules/t003Rewrite.js +64 -0
- package/src/ressources/cmds.json +47 -0
- package/src/ressources/wegas_p.ico +0 -0
- package/src/utils/config/config.js +70 -0
- package/src/utils/config/default.json +9 -0
- package/src/utils/db/DB.js +54 -0
- package/src/utils/fs/FS.js +88 -0
package/README.md
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@intecoag/inteco-cli",
|
|
3
|
+
"version": "0.5.1",
|
|
4
|
+
"description": "CLI-Tools for Inteco",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"start": "node src/index.js"
|
|
9
|
+
},
|
|
10
|
+
"author": "ah1",
|
|
11
|
+
"license": "ISC",
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"7zip-bin": "^5.2.0",
|
|
14
|
+
"adb-ts": "^2.1.2",
|
|
15
|
+
"application-config": "^2.0.0",
|
|
16
|
+
"chalk": "^5.0.1",
|
|
17
|
+
"cli-meow-help": "^3.1.0",
|
|
18
|
+
"cli-table3": "^0.6.5",
|
|
19
|
+
"csv-parser": "^3.0.0",
|
|
20
|
+
"fuzzysort": "^3.1.0",
|
|
21
|
+
"graphql": "^16.6.0",
|
|
22
|
+
"meow": "^10.1.5",
|
|
23
|
+
"mysql-await": "^2.1.8",
|
|
24
|
+
"n-readlines": "^1.0.1",
|
|
25
|
+
"node-7z": "^3.0.0",
|
|
26
|
+
"ora": "^6.1.0",
|
|
27
|
+
"prompts": "^2.4.2",
|
|
28
|
+
"properties-parser": "^0.3.1",
|
|
29
|
+
"readline": "^1.3.0",
|
|
30
|
+
"yaml": "^1.10.2"
|
|
31
|
+
},
|
|
32
|
+
"bin": {
|
|
33
|
+
"inteco": "src/index.js"
|
|
34
|
+
}
|
|
35
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import cliMeowHelp from 'cli-meow-help';
|
|
3
|
+
import meow from 'meow';
|
|
4
|
+
import adb_bridge from './modules/adbBridge.js';
|
|
5
|
+
import adb_intent from './modules/adbIntentSender.js';
|
|
6
|
+
import dumpTableToCSV from './modules/dumpTableToCSV.js';
|
|
7
|
+
import importDB from './modules/importDB.js';
|
|
8
|
+
import rewrite from './modules/rewriteConfig.js';
|
|
9
|
+
import writeCLIConfig from './modules/setCLIConfig.js';
|
|
10
|
+
import t003Rewrite from './modules/t003Rewrite.js';
|
|
11
|
+
import graphqlSchemaExport from './modules/graphqlSchemaExport.js';
|
|
12
|
+
import csvMerge from './modules/csvMerger.js';
|
|
13
|
+
import {dumpDBMand, dumpDB } from './modules/dumpDB.js';
|
|
14
|
+
import deleteDBMand from './modules/deleteDB.js';
|
|
15
|
+
|
|
16
|
+
import commands from "./ressources/cmds.json" with {type: 'json'};
|
|
17
|
+
import packageJson from "../package.json" with {type: 'json'}
|
|
18
|
+
import extdSearch from './modules/extdSearch.js';
|
|
19
|
+
import syncConfig from './modules/syncConfig.js';
|
|
20
|
+
import bundleProduct from './modules/bundleProduct.js';
|
|
21
|
+
|
|
22
|
+
const helpText = cliMeowHelp({
|
|
23
|
+
name: `inteco`,
|
|
24
|
+
desc: "Version: "+packageJson.version,
|
|
25
|
+
commands
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const cli = meow(helpText, {
|
|
29
|
+
importMeta: import.meta,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
switch (cli.input[0]) {
|
|
33
|
+
case "config_rewrite":
|
|
34
|
+
rewrite(cli)
|
|
35
|
+
break;
|
|
36
|
+
case "import_db":
|
|
37
|
+
importDB(cli)
|
|
38
|
+
break;
|
|
39
|
+
case "download_db":
|
|
40
|
+
downloadDB(cli)
|
|
41
|
+
break;
|
|
42
|
+
case "t003_rewrite":
|
|
43
|
+
t003Rewrite(cli)
|
|
44
|
+
break;
|
|
45
|
+
case "adb_bridge":
|
|
46
|
+
adb_bridge()
|
|
47
|
+
break;
|
|
48
|
+
case "adb_intent":
|
|
49
|
+
adb_intent()
|
|
50
|
+
break;
|
|
51
|
+
case "set_cli_config":
|
|
52
|
+
writeCLIConfig()
|
|
53
|
+
break;
|
|
54
|
+
case "dump_table_to_csv":
|
|
55
|
+
dumpTableToCSV()
|
|
56
|
+
break;
|
|
57
|
+
case "csv_merge":
|
|
58
|
+
csvMerge();
|
|
59
|
+
break;
|
|
60
|
+
case "graphql_schema_export":
|
|
61
|
+
graphqlSchemaExport();
|
|
62
|
+
break;
|
|
63
|
+
case "dump_db_mand":
|
|
64
|
+
dumpDBMand(cli);
|
|
65
|
+
break;
|
|
66
|
+
case "dump_db":
|
|
67
|
+
dumpDB(cli);
|
|
68
|
+
break;
|
|
69
|
+
case "delete_db_mand":
|
|
70
|
+
deleteDBMand();
|
|
71
|
+
break;
|
|
72
|
+
case "extd_search":
|
|
73
|
+
extdSearch();
|
|
74
|
+
break;
|
|
75
|
+
case "sync_config":
|
|
76
|
+
syncConfig();
|
|
77
|
+
break;
|
|
78
|
+
case "bundle_product":
|
|
79
|
+
bundleProduct(cli);
|
|
80
|
+
break;
|
|
81
|
+
default:
|
|
82
|
+
cli.showHelp()
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import adb from "adb-ts";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import prompts from "prompts";
|
|
4
|
+
import { Config } from "../utils/config/config.js";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
export default async function adb_bridge(cli){
|
|
8
|
+
|
|
9
|
+
console.log()
|
|
10
|
+
|
|
11
|
+
const config = await Config.getConfig();
|
|
12
|
+
|
|
13
|
+
const adbClient = new adb.AdbClient({host: "127.0.0.1"})
|
|
14
|
+
|
|
15
|
+
adbClient.listDevices()
|
|
16
|
+
.then(async (devices) => {
|
|
17
|
+
let success = true;
|
|
18
|
+
const result = await prompts([
|
|
19
|
+
{
|
|
20
|
+
// Ordnerauswahl von vorhandenen Ordner in configIndividual
|
|
21
|
+
type: 'autocomplete',
|
|
22
|
+
name: 'device',
|
|
23
|
+
message: 'Device?',
|
|
24
|
+
choices: devices.map(dev => {return {title: dev.id+" ("+dev.model+")", value:dev}})
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
// Ordnerauswahl von vorhandenen Ordner in configIndividual
|
|
28
|
+
type: 'number',
|
|
29
|
+
name: 'port',
|
|
30
|
+
initial: "3000",
|
|
31
|
+
message: 'Port?'
|
|
32
|
+
}
|
|
33
|
+
],{
|
|
34
|
+
onCancel: () => {
|
|
35
|
+
console.log()
|
|
36
|
+
console.log(chalk.red("Cancelled ADB Bridge!"))
|
|
37
|
+
console.log()
|
|
38
|
+
success = false
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
if(success){
|
|
43
|
+
await adbClient.reverse(result.device.id, "tcp:"+result.port, "tcp:"+result.port)
|
|
44
|
+
console.log()
|
|
45
|
+
console.log(chalk.green("ADB bridged!"))
|
|
46
|
+
console.log()
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import adb from "adb-ts";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import prompts from "prompts";
|
|
4
|
+
import { Config } from "../utils/config/config.js";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
export default async function adb_intent(cli){
|
|
8
|
+
|
|
9
|
+
console.log()
|
|
10
|
+
|
|
11
|
+
const config = await Config.getConfig();
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
const adbClient = new adb.AdbClient({host: "127.0.0.1"})
|
|
16
|
+
|
|
17
|
+
adbClient.listDevices()
|
|
18
|
+
.then(async (devices) => {
|
|
19
|
+
let success = true;
|
|
20
|
+
const result = await prompts([
|
|
21
|
+
{
|
|
22
|
+
// Ordnerauswahl von vorhandenen Ordner in configIndividual
|
|
23
|
+
type: 'autocomplete',
|
|
24
|
+
name: 'device',
|
|
25
|
+
message: 'Device?',
|
|
26
|
+
choices: devices.map(dev => {return {title: dev.id+" ("+dev.model+")", value:dev}})
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
// Ordnerauswahl von vorhandenen Ordner in configIndividual
|
|
30
|
+
type: 'autocomplete',
|
|
31
|
+
name: 'action',
|
|
32
|
+
message: 'Action?',
|
|
33
|
+
choices: [
|
|
34
|
+
{
|
|
35
|
+
"title":"BARCODE_DATA",
|
|
36
|
+
"value": "ch.inteco.orderprep.action.BARCODE_DATA"
|
|
37
|
+
},
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
// Ordnerauswahl von vorhandenen Ordner in configIndividual
|
|
42
|
+
type: 'text',
|
|
43
|
+
name: 'data',
|
|
44
|
+
message: 'Data?',
|
|
45
|
+
initial:"1"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
// Ordnerauswahl von vorhandenen Ordner in configIndividual
|
|
49
|
+
type: 'autocomplete',
|
|
50
|
+
name: 'codeId',
|
|
51
|
+
message: 'Code-Typ?',
|
|
52
|
+
choices: [
|
|
53
|
+
{
|
|
54
|
+
"title":"QR-Code",
|
|
55
|
+
"value": "s"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"title":"EAN13",
|
|
59
|
+
"value": "d"
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
],{
|
|
64
|
+
onCancel: () => {
|
|
65
|
+
console.log()
|
|
66
|
+
console.log(chalk.red("Cancelled ADB Intent!"))
|
|
67
|
+
console.log()
|
|
68
|
+
success = false
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
if(success){
|
|
73
|
+
await adbClient.shell(result.device.id, "am broadcast -a "+result.action+" --ei version 1 --es codeId "+result.codeId+" --es data "+result.data)
|
|
74
|
+
console.log()
|
|
75
|
+
console.log(chalk.green("Intent sent!"))
|
|
76
|
+
console.log()
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { existsSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "fs";
|
|
2
|
+
import Seven from 'node-7z'
|
|
3
|
+
import sevenBin from '7zip-bin'
|
|
4
|
+
import { Config } from "../utils/config/config.js";
|
|
5
|
+
import prompts from "prompts";
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
import { dirname } from 'path';
|
|
9
|
+
import path from "path";
|
|
10
|
+
import ora from "ora";
|
|
11
|
+
import { cp } from "fs/promises";
|
|
12
|
+
|
|
13
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
+
const __dirname = dirname(__filename);
|
|
15
|
+
|
|
16
|
+
export default async function bundleProduct(cli) {
|
|
17
|
+
console.log()
|
|
18
|
+
|
|
19
|
+
const config = await Config.getConfig();
|
|
20
|
+
|
|
21
|
+
let success = true;
|
|
22
|
+
|
|
23
|
+
const folders = readdirSync(process.cwd(), { withFileTypes: true }).filter(dirent => !dirent.isFile()).map(dirent => { return { title: dirent.name } })
|
|
24
|
+
|
|
25
|
+
const configDirectories = readdirSync(config.configIndividualPathEclipse, { withFileTypes: true }).filter(dirent => dirent.isDirectory()).map(dirent => { return { title: dirent.name } })
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
const results = await prompts([
|
|
29
|
+
{
|
|
30
|
+
// Ordnerauswahl von vorhandenen Ordner in configIndividual
|
|
31
|
+
type: 'autocomplete',
|
|
32
|
+
name: 'folder',
|
|
33
|
+
message: 'Product-Folder?',
|
|
34
|
+
choices: folders,
|
|
35
|
+
initial: "eclipse"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
// Ordnerauswahl von vorhandenen Ordner in configIndividual
|
|
39
|
+
type: 'autocomplete',
|
|
40
|
+
name: 'configIndividual',
|
|
41
|
+
message: 'Customer-Config (from Eclipse-Repository)?',
|
|
42
|
+
choices: configDirectories
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
// Ordnerauswahl von vorhandenen Ordner in configIndividual
|
|
46
|
+
type: 'text',
|
|
47
|
+
name: 'ram',
|
|
48
|
+
message: 'Xmx-Value (Max. RAM) in GB?',
|
|
49
|
+
initial: "8",
|
|
50
|
+
validate: input => {
|
|
51
|
+
if (isNaN(input)) {
|
|
52
|
+
return "Enter a Number"
|
|
53
|
+
}
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
// Ordnerauswahl von vorhandenen Ordner in configIndividual
|
|
59
|
+
type: 'text',
|
|
60
|
+
name: 'folderName',
|
|
61
|
+
message: 'Product-Name?',
|
|
62
|
+
initial: "eclipse"
|
|
63
|
+
},
|
|
64
|
+
], {
|
|
65
|
+
onCancel: () => {
|
|
66
|
+
console.log()
|
|
67
|
+
console.log(chalk.red("Cancelled Import!"))
|
|
68
|
+
console.log()
|
|
69
|
+
success = false
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
if (success) {
|
|
74
|
+
console.log()
|
|
75
|
+
|
|
76
|
+
const spinnerRemoveOld = ora("Removing old configs")
|
|
77
|
+
const configPath = path.resolve(".", results.folder, "config");
|
|
78
|
+
const configIndividualPath = path.resolve(".", results.folder, "configIndividual");
|
|
79
|
+
|
|
80
|
+
if (existsSync(configPath)) {
|
|
81
|
+
rmSync(configPath, { recursive: true, force: true });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (existsSync(configIndividualPath)) {
|
|
85
|
+
rmSync(configIndividualPath, { recursive: true, force: true });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
spinnerRemoveOld.succeed("Removed old configs")
|
|
89
|
+
|
|
90
|
+
const spinnerConfig = ora('Copying config').start();
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
const sourceConfig = path.resolve(config.configIndividualPathEclipse, '..', "config");
|
|
94
|
+
const destConfig = path.resolve(".", results.folder, "config")
|
|
95
|
+
|
|
96
|
+
await cp(sourceConfig, destConfig, { recursive: true })
|
|
97
|
+
|
|
98
|
+
spinnerConfig.succeed("Config copied")
|
|
99
|
+
|
|
100
|
+
const spinnerConfigIndividual = ora('Copying configIndividual: ' + results.configIndividual).start();
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
const sourceConfigIndividual = path.resolve(config.configIndividualPathEclipse, results.configIndividual);
|
|
104
|
+
const destConfigIndividual = path.resolve(".", results.folder, "configIndividual", results.configIndividual)
|
|
105
|
+
|
|
106
|
+
await cp(sourceConfigIndividual, destConfigIndividual, { recursive: true })
|
|
107
|
+
|
|
108
|
+
spinnerConfigIndividual.succeed("ConfigIndividual copied: " + results.configIndividual)
|
|
109
|
+
|
|
110
|
+
const spinnerIcon = ora('Copying icon').start();
|
|
111
|
+
|
|
112
|
+
const sourceIcon = path.resolve(__dirname, "..", "ressources", "wegas_p.ico");
|
|
113
|
+
const destIcon = path.resolve(".", results.folder, "wegas_p.ico")
|
|
114
|
+
|
|
115
|
+
await cp(sourceIcon, destIcon, { recursive: true })
|
|
116
|
+
|
|
117
|
+
spinnerIcon.succeed("Icon copied")
|
|
118
|
+
|
|
119
|
+
const spinnerIniRewrite = ora('Rewriting wegas.ini: -Xmx' + results.ram + "g").start();
|
|
120
|
+
|
|
121
|
+
const iniPath = path.resolve(".", results.folder, "wegas.ini")
|
|
122
|
+
|
|
123
|
+
let iniContent = readFileSync(iniPath, 'utf-8');
|
|
124
|
+
const updatedContent = iniContent.replace(/-Xmx\d+[mgMG]?/, `-Xmx${results.ram}g`);
|
|
125
|
+
writeFileSync(iniPath, updatedContent);
|
|
126
|
+
|
|
127
|
+
spinnerIniRewrite.succeed("wegas.ini rewritten: -Xmx" + results.ram + "g")
|
|
128
|
+
|
|
129
|
+
const spinnerRename = ora("Renaming folder: " + results.folder + " -> " + results.folderName).start();
|
|
130
|
+
renameSync(path.resolve(".", results.folder), path.resolve(".", results.folderName))
|
|
131
|
+
spinnerRename.succeed("Folder renamed: " + results.folder + " -> " + results.folderName)
|
|
132
|
+
|
|
133
|
+
const spinnerZIP = ora('Zipping: ' + results.folderName + ".zip").start();
|
|
134
|
+
|
|
135
|
+
const zipPath = path.resolve(".", results.folderName + ".zip")
|
|
136
|
+
const addPath = path.resolve(".", results.folderName)
|
|
137
|
+
const add = Seven.add(zipPath, addPath, {
|
|
138
|
+
$bin: sevenBin.path7za
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
await getPromiseFromEvent(add, "end")
|
|
142
|
+
|
|
143
|
+
spinnerZIP.succeed('Zipped: ' + results.folderName + ".zip")
|
|
144
|
+
|
|
145
|
+
const spinnerRenameRevert = ora("Renaming folder: " + results.folderName + " -> " + results.folder).start();
|
|
146
|
+
renameSync(path.resolve(".", results.folderName), path.resolve(".", results.folder))
|
|
147
|
+
spinnerRenameRevert.succeed("Folder renamed: " + results.folderName + " -> " + results.folder)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
console.log()
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function getPromiseFromEvent(item, event) {
|
|
155
|
+
return new Promise((resolve) => {
|
|
156
|
+
const listener = (data) => {
|
|
157
|
+
resolve(data);
|
|
158
|
+
}
|
|
159
|
+
item.on(event, listener);
|
|
160
|
+
})
|
|
161
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import csv from 'csv-parser';
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
import prompts from "prompts";
|
|
5
|
+
|
|
6
|
+
export default async function csvMerge() {
|
|
7
|
+
console.log()
|
|
8
|
+
|
|
9
|
+
let success = true;
|
|
10
|
+
|
|
11
|
+
const promptResults = await prompts([
|
|
12
|
+
{
|
|
13
|
+
// Output-File
|
|
14
|
+
type: 'text',
|
|
15
|
+
name: 'output',
|
|
16
|
+
message: 'Output-File?',
|
|
17
|
+
initial: "results.csv"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
// Filterverwendung
|
|
21
|
+
type: 'toggle',
|
|
22
|
+
name: 'useFilter',
|
|
23
|
+
message: 'Use Filter?',
|
|
24
|
+
initial: false,
|
|
25
|
+
active: 'yes',
|
|
26
|
+
inactive: 'no'
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
type: prev => prev == true ? "select" : null,
|
|
30
|
+
name: 'filtertype',
|
|
31
|
+
message: 'Filter type?',
|
|
32
|
+
choices: [
|
|
33
|
+
{ title: 'Equal', value: 'eq' },
|
|
34
|
+
{ title: 'Non-Equal', value: 'neq' }
|
|
35
|
+
]
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
type: prev => prev != "" ? "text" : null,
|
|
39
|
+
name: 'filterfield',
|
|
40
|
+
message: 'Filter field?'
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
type: prev => prev != "" ? "text" : null,
|
|
44
|
+
name: 'filtervalue',
|
|
45
|
+
message: 'Filter value?'
|
|
46
|
+
},
|
|
47
|
+
], {
|
|
48
|
+
onCancel: () => {
|
|
49
|
+
console.log()
|
|
50
|
+
console.log(chalk.red("Cancelled CSV-Merge!"))
|
|
51
|
+
console.log()
|
|
52
|
+
success = false
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
if (success) {
|
|
58
|
+
console.log()
|
|
59
|
+
|
|
60
|
+
let files = fs.readdirSync(process.cwd(), { withFileTypes: true }).filter(file => file.isFile && file.name.endsWith(".csv") && file.name != promptResults.output);
|
|
61
|
+
|
|
62
|
+
let finalResult = [];
|
|
63
|
+
let counter = 0;
|
|
64
|
+
|
|
65
|
+
files.forEach(file => {
|
|
66
|
+
const results = [];
|
|
67
|
+
|
|
68
|
+
fs.createReadStream(process.cwd() + "/" + file.name)
|
|
69
|
+
.pipe(csv({ separator: ";", quote: "'" }))
|
|
70
|
+
.on('data', (data) => results.push(data))
|
|
71
|
+
.on('end', () => {
|
|
72
|
+
const filteredResults = results.map(row => {
|
|
73
|
+
const newRow = {}
|
|
74
|
+
Object.entries(row).forEach(entry => {
|
|
75
|
+
newRow[entry[0].replaceAll("'", "").replaceAll("`", "")] = entry[1]
|
|
76
|
+
})
|
|
77
|
+
newRow.file = file.name
|
|
78
|
+
return newRow
|
|
79
|
+
}).filter(row => {
|
|
80
|
+
if (promptResults.useFilter) {
|
|
81
|
+
switch (promptResults.filtertype){
|
|
82
|
+
case "neq":
|
|
83
|
+
if(row[promptResults.filterfield] != promptResults.filtervalue){
|
|
84
|
+
return true
|
|
85
|
+
}
|
|
86
|
+
return false;
|
|
87
|
+
case "eq":
|
|
88
|
+
if(row[promptResults.filterfield] == promptResults.filtervalue){
|
|
89
|
+
return true
|
|
90
|
+
}
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
return true;
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
finalResult = finalResult.concat(filteredResults)
|
|
99
|
+
counter = counter + filteredResults.length
|
|
100
|
+
|
|
101
|
+
let firstLine = true;
|
|
102
|
+
fs.writeFileSync(process.cwd() + "/" + promptResults.output, finalResult.map(row => {
|
|
103
|
+
let prev = ""
|
|
104
|
+
if (firstLine) {
|
|
105
|
+
prev = Object.keys(row).map(entry => { return "\"" + entry + "\"" }).join(";") + "\n";
|
|
106
|
+
firstLine = false;
|
|
107
|
+
}
|
|
108
|
+
return prev + Object.values(row).map(entry => { return "\"" + entry + "\"" }).join(";");
|
|
109
|
+
}).join("\n"))
|
|
110
|
+
console.log(chalk.green(file.name + " merged."))
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
})
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import prompts from "prompts"
|
|
2
|
+
import { rmSync } from "fs";
|
|
3
|
+
import ora from "ora";
|
|
4
|
+
import { DB } from "../utils/db/DB.js";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
import path from "path";
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
export default async function deleteDBMand(cli){
|
|
10
|
+
console.log()
|
|
11
|
+
|
|
12
|
+
const databaseNames = await DB.getDatabaseNames();
|
|
13
|
+
|
|
14
|
+
let success = true;
|
|
15
|
+
|
|
16
|
+
const results = await prompts([
|
|
17
|
+
{
|
|
18
|
+
// DB-Auswahl von DB
|
|
19
|
+
type: 'autocomplete',
|
|
20
|
+
name: 'dbName',
|
|
21
|
+
message: 'DB-Name?',
|
|
22
|
+
choices: databaseNames.map(name => { return { title: name.name } })
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
type: 'number',
|
|
26
|
+
name: 'mnr',
|
|
27
|
+
message: 'Mandant?',
|
|
28
|
+
initial: '1'
|
|
29
|
+
}
|
|
30
|
+
],{
|
|
31
|
+
onCancel: () => {
|
|
32
|
+
console.log()
|
|
33
|
+
console.log(chalk.red("Cancelled Import!"))
|
|
34
|
+
console.log()
|
|
35
|
+
success = false
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
if(success){
|
|
40
|
+
console.log()
|
|
41
|
+
|
|
42
|
+
const spinner = ora('Deleting in DB').start();
|
|
43
|
+
|
|
44
|
+
// Load table names
|
|
45
|
+
let tables = await DB.executeQueryOnDB("SHOW TABLES;", results.dbName);
|
|
46
|
+
const tableKey = Object.keys(tables[0])[0];
|
|
47
|
+
tables = tables.map(row => row[tableKey])
|
|
48
|
+
|
|
49
|
+
if(tables == null || tables.length == 0){
|
|
50
|
+
spinner.fail("Database has no tables: "+results.dbName)
|
|
51
|
+
}else{
|
|
52
|
+
// Remove previous dump
|
|
53
|
+
rmSync("."+path.sep+results.dumpName, {recursive:true, force:true})
|
|
54
|
+
for(const table of tables){
|
|
55
|
+
// Check if Mand-Column exists
|
|
56
|
+
const tableSpinner = ora("Deleting data: "+table).start();
|
|
57
|
+
const tableCol = table+"_mnr"
|
|
58
|
+
const columnExists = await DB.executeQueryOnDB("SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = '"+results.dbName+"' AND table_name = '"+table+"' AND column_name = '"+tableCol+"';")
|
|
59
|
+
|
|
60
|
+
if(columnExists [0]['COUNT(*)'] != 0){
|
|
61
|
+
// Check if Mand-Data is present
|
|
62
|
+
const dataExists = await DB.executeQueryOnDB("SELECT COUNT(*) FROM "+table+" WHERE "+tableCol+" = '"+results.mnr+"';", results.dbName);
|
|
63
|
+
|
|
64
|
+
if(dataExists[0]['COUNT(*)'] != 0){
|
|
65
|
+
await DB.executeQueryOnDB("DELETE FROM "+table+" WHERE "+tableCol+" = '"+results.mnr+"';", results.dbName)
|
|
66
|
+
tableSpinner.succeed("Data deleted: "+table);
|
|
67
|
+
}else{
|
|
68
|
+
tableSpinner.info("No data present, Skipping table: "+table)
|
|
69
|
+
}
|
|
70
|
+
}else{
|
|
71
|
+
tableSpinner.info("Column "+tableCol+" not found, Skipping table: "+table)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Dump mand-table (special field name)
|
|
75
|
+
const tableSpinner = ora("Deleting mand (custom logic)")
|
|
76
|
+
await DB.executeQueryOnDB("DELETE FROM mand WHERE mand_mandant = '"+results.mnr+"';", results.dbName)
|
|
77
|
+
tableSpinner.succeed("Data deleted: mand")
|
|
78
|
+
spinner.succeed("Mand deleted: "+results.mnr);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
console.log();
|
|
83
|
+
}
|
|
84
|
+
}
|