@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 ADDED
@@ -0,0 +1,3 @@
1
+ CLI mit diversen Funktionen für die Arbeit in der Inteco und mit dem WEGAS
2
+
3
+ Weitere Informationen: https://inteco.atlassian.net/wiki/x/BYBuAw
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
+ }