@burgan-tech/vnext-workflow-cli 1.0.1 → 1.0.3

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/bin/workflow.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- const { program } = require('commander');
3
+ const { program, Argument } = require('commander');
4
4
  const chalk = require('chalk');
5
5
  const pkg = require('../package.json');
6
6
 
@@ -11,6 +11,7 @@ const updateCommand = require('../src/commands/update');
11
11
  const syncCommand = require('../src/commands/sync');
12
12
  const resetCommand = require('../src/commands/reset');
13
13
  const configCommand = require('../src/commands/config');
14
+ const domainCommand = require('../src/commands/domain');
14
15
 
15
16
  program
16
17
  .name('workflow')
@@ -20,46 +21,80 @@ program
20
21
  // Check command
21
22
  program
22
23
  .command('check')
23
- .description('Sistem kontrolü (API, DB, klasörler)')
24
+ .description('System check (API, DB, directories)')
24
25
  .action(checkCommand);
25
26
 
26
27
  // CSX command
27
28
  program
28
29
  .command('csx')
29
- .description('CSX dosyalarını güncelle')
30
- .option('-a, --all', 'Tüm CSX dosyalarını güncelle')
31
- .option('-f, --file <path>', 'Belirli bir CSX dosyasını güncelle')
30
+ .description('Update CSX files')
31
+ .option('-a, --all', 'Update all CSX files')
32
+ .option('-f, --file <path>', 'Update a specific CSX file')
32
33
  .action(csxCommand);
33
34
 
34
35
  // Update command
35
36
  program
36
37
  .command('update')
37
- .description('Workflow\'ları güncelle')
38
- .option('-a, --all', 'Tüm workflow\'ları güncelle')
39
- .option('-f, --file <path>', 'Belirli bir workflow\'u güncelle')
38
+ .description('Update workflows')
39
+ .option('-a, --all', 'Update all workflows')
40
+ .option('-f, --file <path>', 'Update a specific workflow')
40
41
  .action(updateCommand);
41
42
 
42
43
  // Sync command
43
44
  program
44
45
  .command('sync')
45
- .description('DB\'de eksik olanları ekle')
46
+ .description('Add missing entries to DB')
46
47
  .action(syncCommand);
47
48
 
48
49
  // Reset command
49
50
  program
50
51
  .command('reset')
51
- .description('Workflow\'ları resetle (force update)')
52
+ .description('Reset workflows (force update)')
52
53
  .action(resetCommand);
53
54
 
54
55
  // Config command
55
56
  program
56
57
  .command('config')
57
- .description('Konfigürasyon yönetimi')
58
- .argument('<action>', 'set veya get')
58
+ .description('Configuration management')
59
+ .argument('<action>', 'set or get')
59
60
  .argument('[key]', 'Config key')
60
61
  .argument('[value]', 'Config value')
61
62
  .action(configCommand);
62
63
 
64
+ // Domain command
65
+ program
66
+ .command('domain')
67
+ .description('Domain management (multidomain support)')
68
+ .addArgument(new Argument('[action]', 'Action to perform').choices(['active', 'add', 'use', 'list', 'remove']))
69
+ .argument('[name]', 'Domain name')
70
+ .option('-l, --list', 'List domains')
71
+ .option('--API_BASE_URL <url>', 'API base URL')
72
+ .option('--API_VERSION <version>', 'API version')
73
+ .option('--DB_HOST <host>', 'Database host')
74
+ .option('--DB_PORT <port>', 'Database port')
75
+ .option('--DB_NAME <dbname>', 'Database name')
76
+ .option('--DB_USER <user>', 'Database username')
77
+ .option('--DB_PASSWORD <password>', 'Database password')
78
+ .option('--AUTO_DISCOVER <value>', 'Auto discover (true/false)')
79
+ .option('--USE_DOCKER <value>', 'Use Docker (true/false)')
80
+ .option('--DOCKER_POSTGRES_CONTAINER <container>', 'Docker PostgreSQL container name')
81
+ .option('--DEBUG_MODE <value>', 'Debug mode (true/false)')
82
+ .addHelpText('after', `
83
+ Examples:
84
+ wf domain active Show active domain name
85
+ wf domain list List domains
86
+ wf domain --list List domains
87
+ wf domain add domain-a --API_BASE_URL http://localhost:4201 --DB_NAME myDb Add a new domain
88
+ wf domain use domain-a Switch active domain
89
+ wf domain remove domain-a Remove a domain
90
+
91
+ Notes:
92
+ - When adding a domain, unspecified settings are inherited from the default domain.
93
+ - The default domain cannot be deleted.
94
+ - If the active domain is deleted, it automatically switches back to default.
95
+ `)
96
+ .action(domainCommand);
97
+
63
98
  // Parse arguments
64
99
  program.parse(process.argv);
65
100
 
@@ -67,4 +102,3 @@ program.parse(process.argv);
67
102
  if (!process.argv.slice(2).length) {
68
103
  program.outputHelp();
69
104
  }
70
-
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burgan-tech/vnext-workflow-cli",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "vNext Workflow Manager - CLI tool for managing workflows, tasks, schemas and more",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -32,13 +32,13 @@
32
32
  "node": ">=14.0.0"
33
33
  },
34
34
  "dependencies": {
35
- "commander": "^11.1.0",
36
- "chalk": "^4.1.2",
37
35
  "axios": "^1.6.2",
38
- "pg": "^8.11.3",
36
+ "chalk": "^4.1.2",
37
+ "commander": "^11.1.0",
38
+ "conf": "^10.2.0",
39
39
  "glob": "^10.3.10",
40
40
  "inquirer": "^8.2.6",
41
41
  "ora": "^5.4.1",
42
- "conf": "^10.2.0"
42
+ "pg": "^8.11.3"
43
43
  }
44
44
  }
@@ -2,73 +2,113 @@ const chalk = require('chalk');
2
2
  const ora = require('ora');
3
3
  const config = require('../lib/config');
4
4
  const { discoverComponents, listDiscovered } = require('../lib/discover');
5
+ const { getDomain, getComponentTypes, getComponentsRoot } = require('../lib/vnextConfig');
5
6
  const { testApiConnection } = require('../lib/api');
6
7
  const { testDbConnection } = require('../lib/db');
7
8
 
9
+ // Logging helpers
10
+ const LOG = {
11
+ separator: () => console.log(chalk.cyan('═'.repeat(60))),
12
+ subSeparator: () => console.log(chalk.cyan('─'.repeat(60))),
13
+ header: (text) => {
14
+ console.log();
15
+ LOG.separator();
16
+ console.log(chalk.cyan.bold(` ${text}`));
17
+ LOG.separator();
18
+ },
19
+ success: (text) => console.log(chalk.green(` ✓ ${text}`)),
20
+ error: (text) => console.log(chalk.red(` ✗ ${text}`)),
21
+ warning: (text) => console.log(chalk.yellow(` ⚠ ${text}`)),
22
+ info: (text) => console.log(chalk.dim(` ○ ${text}`))
23
+ };
24
+
8
25
  async function checkCommand() {
9
- console.log(chalk.cyan.bold('\n🔄 Workflow Yönetim Sistemi - Sistem Kontrolü\n'));
26
+ LOG.header('SYSTEM CHECK');
10
27
 
11
28
  const projectRoot = config.get('PROJECT_ROOT');
12
29
  const autoDiscover = config.get('AUTO_DISCOVER');
13
30
 
14
- // API kontrolü
15
- let apiSpinner = ora('API kontrolü...').start();
31
+ // vnext.config.json check
32
+ console.log(chalk.white.bold('\n Configuration:\n'));
33
+
34
+ let domain, componentTypes, componentsRoot;
35
+ try {
36
+ domain = getDomain(projectRoot);
37
+ componentTypes = getComponentTypes(projectRoot);
38
+ componentsRoot = getComponentsRoot(projectRoot);
39
+
40
+ LOG.success(`vnext.config.json found`);
41
+ console.log(chalk.dim(` Domain: ${domain}`));
42
+ console.log(chalk.dim(` Components Root: ${componentsRoot}`));
43
+ } catch (error) {
44
+ LOG.error(`vnext.config.json: ${error.message}`);
45
+ componentTypes = {};
46
+ }
47
+
48
+ // API check
49
+ console.log(chalk.white.bold('\n Connection Status:\n'));
50
+
51
+ let apiSpinner = ora(' Checking API...').start();
16
52
  try {
17
53
  const apiUrl = config.get('API_BASE_URL');
18
54
  const isApiOk = await testApiConnection(apiUrl);
19
55
  if (isApiOk) {
20
- apiSpinner.succeed(chalk.green('API: Erişilebilir'));
56
+ apiSpinner.succeed(chalk.green(` API: Accessible (${apiUrl})`));
21
57
  } else {
22
- apiSpinner.fail(chalk.red('API: Erişilemiyor'));
58
+ apiSpinner.fail(chalk.red(` API: Not accessible (${apiUrl})`));
23
59
  }
24
60
  } catch (error) {
25
- apiSpinner.fail(chalk.red(`API: Hata - ${error.message}`));
61
+ apiSpinner.fail(chalk.red(` API: Error - ${error.message}`));
26
62
  }
27
63
 
28
- // DB kontrolü
29
- let dbSpinner = ora('Veritabanı kontrolü...').start();
64
+ // DB check
65
+ let dbSpinner = ora(' Checking database...').start();
30
66
  try {
67
+ const useDockerValue = config.get('USE_DOCKER');
31
68
  const isDbOk = await testDbConnection({
32
69
  host: config.get('DB_HOST'),
33
70
  port: config.get('DB_PORT'),
34
71
  database: config.get('DB_NAME'),
35
72
  user: config.get('DB_USER'),
36
73
  password: config.get('DB_PASSWORD'),
37
- useDocker: config.get('USE_DOCKER'),
74
+ useDocker: useDockerValue === true || useDockerValue === 'true',
38
75
  dockerContainer: config.get('DOCKER_POSTGRES_CONTAINER')
39
76
  });
40
77
  if (isDbOk) {
41
- dbSpinner.succeed(chalk.green('DB: Bağlı'));
78
+ dbSpinner.succeed(chalk.green(` DB: Connected (${config.get('DB_HOST')}:${config.get('DB_PORT')})`));
42
79
  } else {
43
- dbSpinner.fail(chalk.red('DB: Bağlanamıyor'));
80
+ dbSpinner.fail(chalk.red(' DB: Cannot connect'));
44
81
  }
45
82
  } catch (error) {
46
- dbSpinner.fail(chalk.red(`DB: Hata - ${error.message}`));
83
+ dbSpinner.fail(chalk.red(` DB: Error - ${error.message}`));
47
84
  }
48
85
 
49
- // Klasör tarama
50
- if (autoDiscover) {
51
- console.log(chalk.cyan('\n📁 Bulunan Klasörler:\n'));
52
- let discoverSpinner = ora('Klasörler taranıyor...').start();
86
+ // Folder scan
87
+ if (autoDiscover && Object.keys(componentTypes).length > 0) {
88
+ console.log(chalk.white.bold('\n Component Folders:\n'));
89
+
90
+ let discoverSpinner = ora(' Scanning folders...').start();
53
91
  try {
54
92
  const discovered = await discoverComponents(projectRoot);
55
93
  discoverSpinner.stop();
56
94
 
57
- const list = listDiscovered(discovered);
95
+ const list = listDiscovered(discovered, componentTypes);
58
96
  for (const item of list) {
59
97
  if (item.found) {
60
- console.log(chalk.green(` ✓ ${item.name}`));
98
+ console.log(chalk.green(` ✓ ${item.name.padEnd(12)} → ${item.folderName}/`));
61
99
  } else {
62
- console.log(chalk.yellow(` ○ ${item.name} ${chalk.dim('(bulunamadı)')}`));
100
+ console.log(chalk.yellow(` ○ ${item.name.padEnd(12)} ${chalk.dim('(not found)')}`));
63
101
  }
64
102
  }
65
103
  } catch (error) {
66
- discoverSpinner.fail(chalk.red(`Klasör tarama hatası: ${error.message}`));
104
+ discoverSpinner.fail(chalk.red(` Folder scan error: ${error.message}`));
67
105
  }
106
+ } else if (!autoDiscover) {
107
+ console.log(chalk.yellow('\n ⚠ AUTO_DISCOVER is disabled'));
68
108
  }
69
109
 
70
- console.log(chalk.green.bold('\n✓ Kontrol tamamlandı\n'));
110
+ LOG.separator();
111
+ console.log(chalk.green.bold('\n ✓ Check completed\n'));
71
112
  }
72
113
 
73
114
  module.exports = checkCommand;
74
-
@@ -7,25 +7,31 @@ async function configCommand(action, key, value) {
7
7
  const val = config.get(key);
8
8
  console.log(chalk.cyan(`${key}:`), val);
9
9
  } else {
10
- // Tüm config'i göster
11
- console.log(chalk.cyan.bold('\n📝 Mevcut Konfigürasyon:\n'));
10
+ // Show all config with active domain info
12
11
  const all = config.getAll();
12
+ console.log(chalk.cyan.bold('\n📝 Current Configuration:\n'));
13
+ console.log(chalk.yellow(` Active Domain: ${all.ACTIVE_DOMAIN}\n`));
13
14
  for (const [k, v] of Object.entries(all)) {
14
- console.log(chalk.cyan(`${k}:`), chalk.white(v));
15
+ if (k === 'ACTIVE_DOMAIN' || k === 'DOMAIN_NAME') continue;
16
+ console.log(chalk.cyan(` ${k}:`), chalk.white(v));
15
17
  }
16
- console.log(chalk.dim(`\nKonfig dosyası: ${config.path}\n`));
18
+ console.log(chalk.dim(`\n Config file: ${config.path}`));
19
+ console.log(chalk.dim(` Tip: Use "wf domain list" to see all domains.\n`));
17
20
  }
18
21
  } else if (action === 'set') {
19
22
  if (!key || value === undefined) {
20
- console.log(chalk.red('Kullanım: workflow config set <key> <value>'));
23
+ console.log(chalk.red('Usage: workflow config set <key> <value>'));
21
24
  return;
22
25
  }
23
- config.set(key, value);
24
- console.log(chalk.green(`✓ ${key} = ${value}`));
26
+ try {
27
+ config.set(key, value);
28
+ console.log(chalk.green(`✓ ${key} = ${value}`));
29
+ } catch (error) {
30
+ console.log(chalk.red(`✗ ${error.message}`));
31
+ }
25
32
  } else {
26
- console.log(chalk.red('Geçersiz action. Kullanın: get veya set'));
33
+ console.log(chalk.red('Invalid action. Use: get or set'));
27
34
  }
28
35
  }
29
36
 
30
37
  module.exports = configCommand;
31
-
@@ -2,83 +2,164 @@ const chalk = require('chalk');
2
2
  const ora = require('ora');
3
3
  const path = require('path');
4
4
  const config = require('../lib/config');
5
- const {
6
- processCsxFile,
7
- getGitChangedCsx,
8
- findAllCsx
9
- } = require('../lib/csx');
5
+ const { getDomain } = require('../lib/vnextConfig');
6
+ const { processCsxFile, getGitChangedCsx, findAllCsx } = require('../lib/csx');
7
+
8
+ // Logging helpers
9
+ const LOG = {
10
+ separator: () => console.log(chalk.cyan('═'.repeat(60))),
11
+ subSeparator: () => console.log(chalk.cyan('─'.repeat(60))),
12
+ header: (text) => {
13
+ console.log();
14
+ LOG.separator();
15
+ console.log(chalk.cyan.bold(` ${text}`));
16
+ LOG.separator();
17
+ },
18
+ success: (text) => console.log(chalk.green(` ✓ ${text}`)),
19
+ error: (text) => console.log(chalk.red(` ✗ ${text}`)),
20
+ warning: (text) => console.log(chalk.yellow(` ⚠ ${text}`)),
21
+ info: (text) => console.log(chalk.dim(` ○ ${text}`)),
22
+ component: (type, name, status, detail = '') => {
23
+ const typeLabel = chalk.cyan(`[${type}]`);
24
+ const nameLabel = chalk.white(name);
25
+ if (status === 'success') {
26
+ console.log(` ${typeLabel} ${chalk.green('✓')} ${nameLabel} ${chalk.dim(detail)}`);
27
+ } else if (status === 'error') {
28
+ console.log(` ${typeLabel} ${chalk.red('✗')} ${nameLabel}`);
29
+ if (detail) console.log(chalk.red(` └─ ${detail}`));
30
+ } else if (status === 'skip') {
31
+ console.log(` ${typeLabel} ${chalk.dim('○')} ${nameLabel} ${chalk.dim(detail)}`);
32
+ }
33
+ }
34
+ };
10
35
 
11
36
  async function csxCommand(options) {
12
- console.log(chalk.cyan.bold('\n🔄 CSX Güncelleme\n'));
37
+ LOG.header('CSX UPDATE');
13
38
 
14
39
  const projectRoot = config.get('PROJECT_ROOT');
40
+
41
+ // Check domain
42
+ try {
43
+ const domain = getDomain(projectRoot);
44
+ console.log(chalk.dim(` Domain: ${domain}`));
45
+ console.log();
46
+ } catch (error) {
47
+ LOG.error(`Failed to read vnext.config.json: ${error.message}`);
48
+ return;
49
+ }
50
+
15
51
  let csxFiles = [];
16
52
 
17
- // Hangi CSX dosyalarını işleyeceğiz?
53
+ // Which CSX files to process?
18
54
  if (options.file) {
19
- // Belirli dosya
55
+ // Specific file
20
56
  const filePath = path.isAbsolute(options.file)
21
57
  ? options.file
22
58
  : path.join(projectRoot, options.file);
23
59
  csxFiles = [filePath];
24
- console.log(chalk.blue(`Dosya: ${path.basename(filePath)}\n`));
60
+ console.log(chalk.blue(` File: ${path.basename(filePath)}\n`));
25
61
  } else if (options.all) {
26
- // Tüm CSX dosyaları
27
- const spinner = ora('Tüm CSX dosyaları bulunuyor...').start();
28
- csxFiles = await findAllCsx(projectRoot);
29
- spinner.succeed(chalk.green(`${csxFiles.length} CSX dosyası bulundu`));
62
+ // All CSX files
63
+ const spinner = ora(' Finding all CSX files...').start();
64
+ try {
65
+ csxFiles = await findAllCsx(projectRoot);
66
+ spinner.succeed(chalk.green(` ${csxFiles.length} CSX files found`));
67
+ } catch (error) {
68
+ spinner.fail(chalk.red(` CSX scan error: ${error.message}`));
69
+ return;
70
+ }
30
71
  } else {
31
- // Git'te değişenler (default)
32
- const spinner = ora('Git\'te değişen CSX dosyaları aranıyor...').start();
33
- csxFiles = await getGitChangedCsx(projectRoot);
34
-
35
- if (csxFiles.length === 0) {
36
- spinner.info(chalk.yellow('Git\'te değişen CSX dosyası bulunamadı'));
37
- console.log(chalk.green('\n✓ Tüm CSX dosyaları güncel\n'));
72
+ // Changed files in Git (default)
73
+ const spinner = ora(' Finding changed CSX files in Git...').start();
74
+ try {
75
+ csxFiles = await getGitChangedCsx(projectRoot);
76
+
77
+ if (csxFiles.length === 0) {
78
+ spinner.info(chalk.yellow(' No changed CSX files in Git'));
79
+ console.log(chalk.green('\n ✓ All CSX files up to date\n'));
80
+ return;
81
+ }
82
+
83
+ spinner.succeed(chalk.green(` ${csxFiles.length} changed CSX files found`));
84
+ } catch (error) {
85
+ spinner.fail(chalk.red(` CSX scan error: ${error.message}`));
38
86
  return;
39
87
  }
40
-
41
- spinner.succeed(chalk.green(`${csxFiles.length} değişen CSX dosyası bulundu`));
42
88
  }
43
89
 
44
- // Her CSX dosyasını işle
45
- let successCount = 0;
46
- let failCount = 0;
90
+ // Process each CSX file
91
+ const results = { success: 0, failed: 0, errors: [] };
92
+ const updatedFiles = [];
93
+
94
+ console.log(chalk.blue('\n Writing CSX files to JSONs...\n'));
47
95
 
48
- console.log();
49
96
  for (const csxFile of csxFiles) {
50
97
  const fileName = path.basename(csxFile);
51
- const spinner = ora(`İşleniyor: ${fileName}`).start();
52
98
 
53
99
  try {
54
100
  const result = await processCsxFile(csxFile, projectRoot);
55
101
 
56
102
  if (result.success) {
57
- spinner.succeed(chalk.green(`✓ ${fileName} ${result.updatedCount} JSON güncellendi`));
58
- successCount++;
103
+ LOG.component('CSX', fileName, 'success', `→ ${result.updatedJsonCount} JSON, ${result.totalUpdates} refs`);
104
+ results.success++;
105
+ updatedFiles.push({
106
+ file: fileName,
107
+ jsonCount: result.updatedJsonCount,
108
+ totalUpdates: result.totalUpdates,
109
+ jsonFiles: result.jsonFiles
110
+ });
59
111
  } else {
60
- spinner.fail(chalk.red(`✗ ${fileName} ${result.message}`));
61
- failCount++;
112
+ LOG.component('CSX', fileName, 'skip', result.message);
62
113
  }
63
114
  } catch (error) {
64
- spinner.fail(chalk.red(`✗ ${fileName} Hata: ${error.message}`));
65
- failCount++;
115
+ LOG.component('CSX', fileName, 'error', error.message);
116
+ results.failed++;
117
+ results.errors.push({ file: fileName, error: error.message });
118
+ }
119
+ }
120
+
121
+ // SUMMARY REPORT
122
+ LOG.header('CSX UPDATE SUMMARY');
123
+
124
+ // Results
125
+ console.log(chalk.white.bold('\n Results:\n'));
126
+
127
+ const successLabel = results.success > 0 ? chalk.green(`${results.success} success`) : chalk.dim('0 success');
128
+ const failedLabel = results.failed > 0 ? chalk.red(`, ${results.failed} failed`) : '';
129
+ console.log(` ${chalk.cyan('CSX Files'.padEnd(16))} : ${successLabel}${failedLabel}`);
130
+
131
+ // Updated JSON details
132
+ if (updatedFiles.length > 0) {
133
+ console.log();
134
+ LOG.subSeparator();
135
+ console.log(chalk.white.bold('\n Updated JSON Files:\n'));
136
+
137
+ for (const item of updatedFiles) {
138
+ console.log(chalk.green(` ${item.file}:`));
139
+ for (const json of item.jsonFiles) {
140
+ console.log(chalk.dim(` └─ ${json.file} (${json.updates} refs)`));
141
+ }
66
142
  }
67
143
  }
68
144
 
69
- // Özet
70
- console.log();
71
- console.log(chalk.cyan('─'.repeat(50)));
72
- console.log(chalk.white(`Toplam: ${csxFiles.length} dosya`));
73
- console.log(chalk.green(`✓ Başarılı: ${successCount}`));
74
- if (failCount > 0) {
75
- console.log(chalk.red(`✗ Başarısız: ${failCount}`));
145
+ // Errors
146
+ if (results.errors.length > 0) {
147
+ console.log();
148
+ LOG.subSeparator();
149
+ console.log(chalk.red.bold('\n ERRORS:\n'));
150
+
151
+ for (const err of results.errors) {
152
+ console.log(chalk.red(` [CSX] ${err.file}`));
153
+ console.log(chalk.dim(` └─ ${err.error}`));
154
+ }
76
155
  }
77
- console.log(chalk.cyan('─'.repeat(50)));
78
- console.log();
79
156
 
80
- if (successCount > 0) {
81
- console.log(chalk.green.bold('✓ CSX güncelleme tamamlandı\n'));
157
+ LOG.separator();
158
+
159
+ if (results.success > 0 && results.failed === 0) {
160
+ console.log(chalk.green.bold('\n ✓ CSX update completed\n'));
161
+ } else if (results.failed > 0) {
162
+ console.log(chalk.yellow.bold(`\n ⚠ CSX update completed (${results.failed} errors)\n`));
82
163
  }
83
164
  }
84
165