@burgan-tech/vnext-workflow-cli 1.0.0
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/.github/workflows/build-and-publish.yml +702 -0
- package/.github/workflows/check-sonar.yml +69 -0
- package/README.md +382 -0
- package/bin/workflow.js +70 -0
- package/package.json +44 -0
- package/src/commands/check.js +74 -0
- package/src/commands/config.js +31 -0
- package/src/commands/csx.js +85 -0
- package/src/commands/reset.js +161 -0
- package/src/commands/sync.js +189 -0
- package/src/commands/update.js +203 -0
- package/src/lib/api.js +72 -0
- package/src/lib/config.js +29 -0
- package/src/lib/csx.js +191 -0
- package/src/lib/db.js +122 -0
- package/src/lib/discover.js +65 -0
- package/src/lib/workflow.js +162 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const ora = require('ora');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const config = require('../lib/config');
|
|
5
|
+
const {
|
|
6
|
+
processCsxFile,
|
|
7
|
+
getGitChangedCsx,
|
|
8
|
+
findAllCsx
|
|
9
|
+
} = require('../lib/csx');
|
|
10
|
+
|
|
11
|
+
async function csxCommand(options) {
|
|
12
|
+
console.log(chalk.cyan.bold('\n🔄 CSX Güncelleme\n'));
|
|
13
|
+
|
|
14
|
+
const projectRoot = config.get('PROJECT_ROOT');
|
|
15
|
+
let csxFiles = [];
|
|
16
|
+
|
|
17
|
+
// Hangi CSX dosyalarını işleyeceğiz?
|
|
18
|
+
if (options.file) {
|
|
19
|
+
// Belirli dosya
|
|
20
|
+
const filePath = path.isAbsolute(options.file)
|
|
21
|
+
? options.file
|
|
22
|
+
: path.join(projectRoot, options.file);
|
|
23
|
+
csxFiles = [filePath];
|
|
24
|
+
console.log(chalk.blue(`Dosya: ${path.basename(filePath)}\n`));
|
|
25
|
+
} 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`));
|
|
30
|
+
} 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'));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
spinner.succeed(chalk.green(`${csxFiles.length} değişen CSX dosyası bulundu`));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Her CSX dosyasını işle
|
|
45
|
+
let successCount = 0;
|
|
46
|
+
let failCount = 0;
|
|
47
|
+
|
|
48
|
+
console.log();
|
|
49
|
+
for (const csxFile of csxFiles) {
|
|
50
|
+
const fileName = path.basename(csxFile);
|
|
51
|
+
const spinner = ora(`İşleniyor: ${fileName}`).start();
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
const result = await processCsxFile(csxFile, projectRoot);
|
|
55
|
+
|
|
56
|
+
if (result.success) {
|
|
57
|
+
spinner.succeed(chalk.green(`✓ ${fileName} → ${result.updatedCount} JSON güncellendi`));
|
|
58
|
+
successCount++;
|
|
59
|
+
} else {
|
|
60
|
+
spinner.fail(chalk.red(`✗ ${fileName} → ${result.message}`));
|
|
61
|
+
failCount++;
|
|
62
|
+
}
|
|
63
|
+
} catch (error) {
|
|
64
|
+
spinner.fail(chalk.red(`✗ ${fileName} → Hata: ${error.message}`));
|
|
65
|
+
failCount++;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
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}`));
|
|
76
|
+
}
|
|
77
|
+
console.log(chalk.cyan('─'.repeat(50)));
|
|
78
|
+
console.log();
|
|
79
|
+
|
|
80
|
+
if (successCount > 0) {
|
|
81
|
+
console.log(chalk.green.bold('✓ CSX güncelleme tamamlandı\n'));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
module.exports = csxCommand;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const ora = require('ora');
|
|
3
|
+
const inquirer = require('inquirer');
|
|
4
|
+
const config = require('../lib/config');
|
|
5
|
+
const { discoverComponents } = require('../lib/discover');
|
|
6
|
+
const { processWorkflow, findAllJson } = require('../lib/workflow');
|
|
7
|
+
const { reinitializeSystem } = require('../lib/api');
|
|
8
|
+
|
|
9
|
+
async function resetCommand(options) {
|
|
10
|
+
console.log(chalk.cyan.bold('\n🔄 Workflow Reset (Force Update)\n'));
|
|
11
|
+
|
|
12
|
+
const projectRoot = config.get('PROJECT_ROOT');
|
|
13
|
+
const autoDiscover = config.get('AUTO_DISCOVER');
|
|
14
|
+
|
|
15
|
+
// DB Config
|
|
16
|
+
const dbConfig = {
|
|
17
|
+
host: config.get('DB_HOST'),
|
|
18
|
+
port: config.get('DB_PORT'),
|
|
19
|
+
database: config.get('DB_NAME'),
|
|
20
|
+
user: config.get('DB_USER'),
|
|
21
|
+
password: config.get('DB_PASSWORD'),
|
|
22
|
+
useDocker: config.get('USE_DOCKER'),
|
|
23
|
+
dockerContainer: config.get('DOCKER_POSTGRES_CONTAINER')
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// API Config
|
|
27
|
+
const apiConfig = {
|
|
28
|
+
baseUrl: config.get('API_BASE_URL'),
|
|
29
|
+
version: config.get('API_VERSION')
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// Klasörleri keşfet
|
|
33
|
+
const spinner = ora('Klasörler taranıyor...').start();
|
|
34
|
+
const discovered = await discoverComponents(projectRoot);
|
|
35
|
+
spinner.succeed(chalk.green('Klasörler bulundu'));
|
|
36
|
+
|
|
37
|
+
// Seçenekler
|
|
38
|
+
const choices = [
|
|
39
|
+
{ name: '🔵 Workflows (sys-flows)', value: 'Workflows' },
|
|
40
|
+
{ name: '📋 Tasks (sys-tasks)', value: 'Tasks' },
|
|
41
|
+
{ name: '📊 Schemas (sys-schemas)', value: 'Schemas' },
|
|
42
|
+
{ name: '👁️ Views (sys-views)', value: 'Views' },
|
|
43
|
+
{ name: '⚙️ Functions (sys-functions)', value: 'Functions' },
|
|
44
|
+
{ name: '🔌 Extensions (sys-extensions)', value: 'Extensions' },
|
|
45
|
+
new inquirer.Separator(),
|
|
46
|
+
{ name: '🔴 TÜMÜ (Tüm klasörler)', value: 'ALL' }
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
// Kullanıcıdan seç
|
|
50
|
+
const { selected } = await inquirer.prompt([{
|
|
51
|
+
type: 'list',
|
|
52
|
+
name: 'selected',
|
|
53
|
+
message: 'Hangi klasör resetlensin?',
|
|
54
|
+
choices: choices
|
|
55
|
+
}]);
|
|
56
|
+
|
|
57
|
+
// Dosyaları bul
|
|
58
|
+
let jsonFiles = [];
|
|
59
|
+
|
|
60
|
+
if (selected === 'ALL') {
|
|
61
|
+
jsonFiles = await findAllJson(discovered);
|
|
62
|
+
} else {
|
|
63
|
+
const dir = discovered[selected];
|
|
64
|
+
if (!dir) {
|
|
65
|
+
console.log(chalk.red(`\n✗ ${selected} klasörü bulunamadı\n`));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Sadece bu klasördeki JSON'ları bul
|
|
70
|
+
const fs = require('fs').promises;
|
|
71
|
+
const path = require('path');
|
|
72
|
+
const { glob } = require('glob');
|
|
73
|
+
|
|
74
|
+
const pattern = path.join(dir, '**/*.json');
|
|
75
|
+
jsonFiles = await glob(pattern);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (jsonFiles.length === 0) {
|
|
79
|
+
console.log(chalk.yellow('\n⚠ JSON dosyası bulunamadı\n'));
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Son onay
|
|
84
|
+
console.log(chalk.yellow(`\n⚠️ ${jsonFiles.length} workflow resetlenecek (DB'den silinip tekrar eklenecek)!\n`));
|
|
85
|
+
|
|
86
|
+
const { confirm } = await inquirer.prompt([{
|
|
87
|
+
type: 'confirm',
|
|
88
|
+
name: 'confirm',
|
|
89
|
+
message: 'Devam edilsin mi?',
|
|
90
|
+
default: false
|
|
91
|
+
}]);
|
|
92
|
+
|
|
93
|
+
if (!confirm) {
|
|
94
|
+
console.log(chalk.yellow('\nİşlem iptal edildi.\n'));
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// İşle
|
|
99
|
+
let successCount = 0;
|
|
100
|
+
let failCount = 0;
|
|
101
|
+
|
|
102
|
+
console.log();
|
|
103
|
+
for (const jsonFile of jsonFiles) {
|
|
104
|
+
const fileName = require('path').basename(jsonFile);
|
|
105
|
+
const spinner = ora(`İşleniyor: ${fileName}`).start();
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
const result = await processWorkflow(jsonFile, dbConfig, apiConfig);
|
|
109
|
+
|
|
110
|
+
const status = result.wasDeleted ? 'resetlendi' : 'oluşturuldu';
|
|
111
|
+
spinner.succeed(chalk.green(`✓ ${fileName} → ${status}`));
|
|
112
|
+
successCount++;
|
|
113
|
+
} catch (error) {
|
|
114
|
+
let errorMsg = error.message;
|
|
115
|
+
if (error.response?.data) {
|
|
116
|
+
if (typeof error.response.data === 'string') {
|
|
117
|
+
errorMsg = error.response.data;
|
|
118
|
+
} else if (error.response.data.error?.message) {
|
|
119
|
+
errorMsg = error.response.data.error.message;
|
|
120
|
+
} else if (error.response.data.message) {
|
|
121
|
+
errorMsg = error.response.data.message;
|
|
122
|
+
} else {
|
|
123
|
+
errorMsg = JSON.stringify(error.response.data);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
spinner.fail(chalk.red(`✗ ${fileName} → ${errorMsg}`));
|
|
127
|
+
failCount++;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Re-initialize
|
|
132
|
+
if (successCount > 0) {
|
|
133
|
+
console.log();
|
|
134
|
+
const reinitSpinner = ora('Sistem yeniden başlatılıyor...').start();
|
|
135
|
+
const reinitSuccess = await reinitializeSystem(apiConfig.baseUrl, apiConfig.version);
|
|
136
|
+
|
|
137
|
+
if (reinitSuccess) {
|
|
138
|
+
reinitSpinner.succeed(chalk.green('✓ Sistem yenilendi'));
|
|
139
|
+
} else {
|
|
140
|
+
reinitSpinner.warn(chalk.yellow('⚠ Sistem yenilenemedi (devam edildi)'));
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Özet
|
|
145
|
+
console.log();
|
|
146
|
+
console.log(chalk.cyan('═'.repeat(50)));
|
|
147
|
+
console.log(chalk.white(`Toplam: ${jsonFiles.length} dosya`));
|
|
148
|
+
console.log(chalk.green(`✓ Başarılı: ${successCount}`));
|
|
149
|
+
if (failCount > 0) {
|
|
150
|
+
console.log(chalk.red(`✗ Başarısız: ${failCount}`));
|
|
151
|
+
}
|
|
152
|
+
console.log(chalk.cyan('═'.repeat(50)));
|
|
153
|
+
console.log();
|
|
154
|
+
|
|
155
|
+
if (successCount > 0) {
|
|
156
|
+
console.log(chalk.green.bold('✓ Reset tamamlandı\n'));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
module.exports = resetCommand;
|
|
161
|
+
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const ora = require('ora');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const config = require('../lib/config');
|
|
5
|
+
const { discoverComponents } = require('../lib/discover');
|
|
6
|
+
const { getInstanceId } = require('../lib/db');
|
|
7
|
+
const { postWorkflow, activateWorkflow, reinitializeSystem } = require('../lib/api');
|
|
8
|
+
const {
|
|
9
|
+
getJsonMetadata,
|
|
10
|
+
detectFlowFromPath,
|
|
11
|
+
findAllJson
|
|
12
|
+
} = require('../lib/workflow');
|
|
13
|
+
const {
|
|
14
|
+
processCsxFile,
|
|
15
|
+
getGitChangedCsx,
|
|
16
|
+
findAllCsx
|
|
17
|
+
} = require('../lib/csx');
|
|
18
|
+
|
|
19
|
+
async function syncCommand() {
|
|
20
|
+
console.log(chalk.cyan.bold('\n🔄 Sistem Sync - Eksik Olanları Ekle\n'));
|
|
21
|
+
|
|
22
|
+
const projectRoot = config.get('PROJECT_ROOT');
|
|
23
|
+
const autoDiscover = config.get('AUTO_DISCOVER');
|
|
24
|
+
|
|
25
|
+
if (!autoDiscover) {
|
|
26
|
+
console.log(chalk.yellow('⚠️ AUTO_DISCOVER kapalı. Açmak için:'));
|
|
27
|
+
console.log(chalk.dim(' workflow config set AUTO_DISCOVER true\n'));
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// DB Config
|
|
32
|
+
const dbConfig = {
|
|
33
|
+
host: config.get('DB_HOST'),
|
|
34
|
+
port: config.get('DB_PORT'),
|
|
35
|
+
database: config.get('DB_NAME'),
|
|
36
|
+
user: config.get('DB_USER'),
|
|
37
|
+
password: config.get('DB_PASSWORD'),
|
|
38
|
+
useDocker: config.get('USE_DOCKER'),
|
|
39
|
+
dockerContainer: config.get('DOCKER_POSTGRES_CONTAINER')
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// API Config
|
|
43
|
+
const apiConfig = {
|
|
44
|
+
baseUrl: config.get('API_BASE_URL'),
|
|
45
|
+
version: config.get('API_VERSION')
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// Klasörleri bul
|
|
49
|
+
const discoverSpinner = ora('Klasörler taranıyor...').start();
|
|
50
|
+
const discovered = await discoverComponents(projectRoot);
|
|
51
|
+
discoverSpinner.succeed(chalk.green('Klasörler bulundu'));
|
|
52
|
+
|
|
53
|
+
// ÖNCELİKLE: Tüm CSX dosyalarını güncelle
|
|
54
|
+
const csxSpinner = ora('Tüm CSX dosyaları bulunuyor...').start();
|
|
55
|
+
const csxFiles = await findAllCsx(projectRoot);
|
|
56
|
+
csxSpinner.succeed(chalk.green(`${csxFiles.length} CSX dosyası bulundu`));
|
|
57
|
+
|
|
58
|
+
// CSX dosyalarını güncelle
|
|
59
|
+
if (csxFiles.length > 0) {
|
|
60
|
+
console.log(chalk.blue('\n📝 CSX dosyaları JSON\'lara yazılıyor...\n'));
|
|
61
|
+
|
|
62
|
+
let csxSuccessCount = 0;
|
|
63
|
+
for (const csxFile of csxFiles) {
|
|
64
|
+
const fileName = path.basename(csxFile);
|
|
65
|
+
const csxFileSpinner = ora(`Base64 encode: ${fileName}`).start();
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
const result = await processCsxFile(csxFile, projectRoot);
|
|
69
|
+
|
|
70
|
+
if (result.success) {
|
|
71
|
+
csxFileSpinner.succeed(chalk.green(`✓ ${fileName} → ${result.updatedCount} JSON`));
|
|
72
|
+
csxSuccessCount++;
|
|
73
|
+
} else {
|
|
74
|
+
csxFileSpinner.warn(chalk.yellow(`○ ${fileName} → ${result.message}`));
|
|
75
|
+
}
|
|
76
|
+
} catch (error) {
|
|
77
|
+
csxFileSpinner.fail(chalk.red(`✗ ${fileName} → ${error.message}`));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (csxSuccessCount > 0) {
|
|
82
|
+
console.log(chalk.green(`\n✓ ${csxSuccessCount} CSX dosyası güncellendi\n`));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Tüm JSON dosyalarını bul
|
|
87
|
+
const findSpinner = ora('JSON dosyaları bulunuyor...').start();
|
|
88
|
+
const allJsons = await findAllJson(discovered);
|
|
89
|
+
findSpinner.succeed(chalk.green(`${allJsons.length} JSON dosyası bulundu`));
|
|
90
|
+
|
|
91
|
+
// Her dosyayı kontrol et
|
|
92
|
+
let addedCount = 0;
|
|
93
|
+
let skippedCount = 0;
|
|
94
|
+
let failedCount = 0;
|
|
95
|
+
|
|
96
|
+
console.log();
|
|
97
|
+
for (const jsonFile of allJsons) {
|
|
98
|
+
const fileName = require('path').basename(jsonFile);
|
|
99
|
+
const spinner = ora(`Kontrol ediliyor: ${fileName}`).start();
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
const metadata = await getJsonMetadata(jsonFile);
|
|
103
|
+
|
|
104
|
+
if (!metadata.key || !metadata.version) {
|
|
105
|
+
spinner.warn(chalk.yellow(`○ ${fileName} → key/version yok`));
|
|
106
|
+
skippedCount++;
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const flow = metadata.flow || detectFlowFromPath(jsonFile);
|
|
111
|
+
|
|
112
|
+
// DB'de var mı?
|
|
113
|
+
const existingId = await getInstanceId(dbConfig, flow, metadata.key, metadata.version);
|
|
114
|
+
|
|
115
|
+
if (existingId) {
|
|
116
|
+
spinner.info(chalk.dim(`○ ${fileName} → zaten var`));
|
|
117
|
+
skippedCount++;
|
|
118
|
+
} else {
|
|
119
|
+
// Yok, ekle
|
|
120
|
+
const postResult = await postWorkflow(
|
|
121
|
+
apiConfig.baseUrl,
|
|
122
|
+
apiConfig.version,
|
|
123
|
+
flow,
|
|
124
|
+
metadata.data
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
const newId = postResult.id || postResult.Id;
|
|
128
|
+
|
|
129
|
+
// Aktif et
|
|
130
|
+
await activateWorkflow(
|
|
131
|
+
apiConfig.baseUrl,
|
|
132
|
+
apiConfig.version,
|
|
133
|
+
flow,
|
|
134
|
+
newId,
|
|
135
|
+
metadata.version
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
spinner.succeed(chalk.green(`✓ ${fileName} → eklendi`));
|
|
139
|
+
addedCount++;
|
|
140
|
+
}
|
|
141
|
+
} catch (error) {
|
|
142
|
+
let errorMsg = error.message;
|
|
143
|
+
if (error.response?.data) {
|
|
144
|
+
if (typeof error.response.data === 'string') {
|
|
145
|
+
errorMsg = error.response.data;
|
|
146
|
+
} else if (error.response.data.message) {
|
|
147
|
+
errorMsg = error.response.data.message;
|
|
148
|
+
} else {
|
|
149
|
+
errorMsg = JSON.stringify(error.response.data);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
spinner.fail(chalk.red(`✗ ${fileName} → ${errorMsg}`));
|
|
153
|
+
failedCount++;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Re-initialize
|
|
158
|
+
if (addedCount > 0) {
|
|
159
|
+
console.log();
|
|
160
|
+
const reinitSpinner = ora('Sistem yeniden başlatılıyor...').start();
|
|
161
|
+
const reinitSuccess = await reinitializeSystem(apiConfig.baseUrl, apiConfig.version);
|
|
162
|
+
|
|
163
|
+
if (reinitSuccess) {
|
|
164
|
+
reinitSpinner.succeed(chalk.green('✓ Sistem yenilendi'));
|
|
165
|
+
} else {
|
|
166
|
+
reinitSpinner.warn(chalk.yellow('⚠ Sistem yenilenemedi'));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Özet
|
|
171
|
+
console.log();
|
|
172
|
+
console.log(chalk.cyan('═'.repeat(50)));
|
|
173
|
+
console.log(chalk.white(`Toplam: ${allJsons.length} dosya`));
|
|
174
|
+
console.log(chalk.green(`✓ Eklendi: ${addedCount}`));
|
|
175
|
+
console.log(chalk.dim(`○ Zaten var: ${skippedCount}`));
|
|
176
|
+
if (failedCount > 0) {
|
|
177
|
+
console.log(chalk.red(`✗ Başarısız: ${failedCount}`));
|
|
178
|
+
}
|
|
179
|
+
console.log(chalk.cyan('═'.repeat(50)));
|
|
180
|
+
console.log();
|
|
181
|
+
|
|
182
|
+
if (addedCount === 0 && failedCount === 0) {
|
|
183
|
+
console.log(chalk.green.bold('✓ Sistem güncel - Tüm kayıtlar mevcut\n'));
|
|
184
|
+
} else if (addedCount > 0) {
|
|
185
|
+
console.log(chalk.green.bold('✓ Sync tamamlandı\n'));
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
module.exports = syncCommand;
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const ora = require('ora');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const inquirer = require('inquirer');
|
|
5
|
+
const config = require('../lib/config');
|
|
6
|
+
const { discoverComponents } = require('../lib/discover');
|
|
7
|
+
const { reinitializeSystem } = require('../lib/api');
|
|
8
|
+
const {
|
|
9
|
+
processWorkflow,
|
|
10
|
+
getGitChangedJson,
|
|
11
|
+
findAllJson
|
|
12
|
+
} = require('../lib/workflow');
|
|
13
|
+
const {
|
|
14
|
+
processCsxFile,
|
|
15
|
+
getGitChangedCsx,
|
|
16
|
+
findAllCsx
|
|
17
|
+
} = require('../lib/csx');
|
|
18
|
+
|
|
19
|
+
async function updateCommand(options) {
|
|
20
|
+
console.log(chalk.cyan.bold('\n🔄 Workflow Güncelleme\n'));
|
|
21
|
+
|
|
22
|
+
const projectRoot = config.get('PROJECT_ROOT');
|
|
23
|
+
const autoDiscover = config.get('AUTO_DISCOVER');
|
|
24
|
+
|
|
25
|
+
// DB Config
|
|
26
|
+
const dbConfig = {
|
|
27
|
+
host: config.get('DB_HOST'),
|
|
28
|
+
port: config.get('DB_PORT'),
|
|
29
|
+
database: config.get('DB_NAME'),
|
|
30
|
+
user: config.get('DB_USER'),
|
|
31
|
+
password: config.get('DB_PASSWORD'),
|
|
32
|
+
useDocker: config.get('USE_DOCKER'),
|
|
33
|
+
dockerContainer: config.get('DOCKER_POSTGRES_CONTAINER')
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// API Config
|
|
37
|
+
const apiConfig = {
|
|
38
|
+
baseUrl: config.get('API_BASE_URL'),
|
|
39
|
+
version: config.get('API_VERSION')
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// ÖNCELİKLE: Değişen CSX dosyalarını güncelle
|
|
43
|
+
let csxFiles = [];
|
|
44
|
+
|
|
45
|
+
if (options.all) {
|
|
46
|
+
// Tüm CSX'leri bul
|
|
47
|
+
const csxSpinner = ora('Tüm CSX dosyaları bulunuyor...').start();
|
|
48
|
+
csxFiles = await findAllCsx(projectRoot);
|
|
49
|
+
csxSpinner.succeed(chalk.green(`${csxFiles.length} CSX dosyası bulundu`));
|
|
50
|
+
} else {
|
|
51
|
+
// Git'te değişen CSX'leri bul
|
|
52
|
+
const csxSpinner = ora('Git\'te değişen CSX dosyaları aranıyor...').start();
|
|
53
|
+
csxFiles = await getGitChangedCsx(projectRoot);
|
|
54
|
+
|
|
55
|
+
if (csxFiles.length > 0) {
|
|
56
|
+
csxSpinner.succeed(chalk.green(`${csxFiles.length} değişen CSX dosyası bulundu`));
|
|
57
|
+
} else {
|
|
58
|
+
csxSpinner.info(chalk.dim('Değişen CSX dosyası yok'));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// CSX dosyalarını güncelle
|
|
63
|
+
if (csxFiles.length > 0) {
|
|
64
|
+
console.log(chalk.blue('\n📝 CSX dosyaları JSON\'lara yazılıyor...\n'));
|
|
65
|
+
|
|
66
|
+
let csxSuccessCount = 0;
|
|
67
|
+
for (const csxFile of csxFiles) {
|
|
68
|
+
const fileName = path.basename(csxFile);
|
|
69
|
+
const csxSpinner = ora(`Base64 encode: ${fileName}`).start();
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
const result = await processCsxFile(csxFile, projectRoot);
|
|
73
|
+
|
|
74
|
+
if (result.success) {
|
|
75
|
+
csxSpinner.succeed(chalk.green(`✓ ${fileName} → ${result.updatedCount} JSON`));
|
|
76
|
+
csxSuccessCount++;
|
|
77
|
+
} else {
|
|
78
|
+
csxSpinner.warn(chalk.yellow(`○ ${fileName} → ${result.message}`));
|
|
79
|
+
}
|
|
80
|
+
} catch (error) {
|
|
81
|
+
csxSpinner.fail(chalk.red(`✗ ${fileName} → ${error.message}`));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (csxSuccessCount > 0) {
|
|
86
|
+
console.log(chalk.green(`\n✓ ${csxSuccessCount} CSX dosyası güncellendi\n`));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
let jsonFiles = [];
|
|
91
|
+
|
|
92
|
+
// Hangi JSON dosyalarını işleyeceğiz?
|
|
93
|
+
if (options.file) {
|
|
94
|
+
// Belirli dosya
|
|
95
|
+
const filePath = path.isAbsolute(options.file)
|
|
96
|
+
? options.file
|
|
97
|
+
: path.join(projectRoot, options.file);
|
|
98
|
+
jsonFiles = [filePath];
|
|
99
|
+
console.log(chalk.blue(`Dosya: ${path.basename(filePath)}\n`));
|
|
100
|
+
} else if (options.all) {
|
|
101
|
+
// Tüm JSON dosyaları
|
|
102
|
+
console.log(chalk.yellow('⚠️ TÜM workflow\'lar güncellenecek!\n'));
|
|
103
|
+
|
|
104
|
+
const { confirm } = await inquirer.prompt([{
|
|
105
|
+
type: 'confirm',
|
|
106
|
+
name: 'confirm',
|
|
107
|
+
message: 'Devam edilsin mi?',
|
|
108
|
+
default: false
|
|
109
|
+
}]);
|
|
110
|
+
|
|
111
|
+
if (!confirm) {
|
|
112
|
+
console.log(chalk.yellow('\nİşlem iptal edildi.\n'));
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const spinner = ora('Tüm JSON dosyaları bulunuyor...').start();
|
|
117
|
+
|
|
118
|
+
if (autoDiscover) {
|
|
119
|
+
const discovered = await discoverComponents(projectRoot);
|
|
120
|
+
jsonFiles = await findAllJson(discovered);
|
|
121
|
+
} else {
|
|
122
|
+
// Fallback
|
|
123
|
+
jsonFiles = [];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
spinner.succeed(chalk.green(`${jsonFiles.length} JSON dosyası bulundu`));
|
|
127
|
+
} else {
|
|
128
|
+
// Git'te değişenler (default)
|
|
129
|
+
const spinner = ora('Git\'te değişen JSON dosyaları aranıyor...').start();
|
|
130
|
+
jsonFiles = await getGitChangedJson(projectRoot);
|
|
131
|
+
|
|
132
|
+
if (jsonFiles.length === 0) {
|
|
133
|
+
spinner.info(chalk.yellow('Git\'te değişen JSON dosyası bulunamadı'));
|
|
134
|
+
console.log(chalk.green('\n✓ Tüm workflow\'lar güncel\n'));
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
spinner.succeed(chalk.green(`${jsonFiles.length} değişen JSON dosyası bulundu`));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Her JSON dosyasını işle
|
|
142
|
+
let successCount = 0;
|
|
143
|
+
let failCount = 0;
|
|
144
|
+
|
|
145
|
+
console.log();
|
|
146
|
+
for (const jsonFile of jsonFiles) {
|
|
147
|
+
const fileName = path.basename(jsonFile);
|
|
148
|
+
const spinner = ora(`İşleniyor: ${fileName}`).start();
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
const result = await processWorkflow(jsonFile, dbConfig, apiConfig);
|
|
152
|
+
|
|
153
|
+
const status = result.wasDeleted ? 'güncellendi' : 'oluşturuldu';
|
|
154
|
+
spinner.succeed(chalk.green(`✓ ${fileName} → ${status}`));
|
|
155
|
+
successCount++;
|
|
156
|
+
} catch (error) {
|
|
157
|
+
let errorMsg = error.message;
|
|
158
|
+
if (error.response?.data) {
|
|
159
|
+
if (typeof error.response.data === 'string') {
|
|
160
|
+
errorMsg = error.response.data;
|
|
161
|
+
} else if (error.response.data.error?.message) {
|
|
162
|
+
errorMsg = error.response.data.error.message;
|
|
163
|
+
} else if (error.response.data.message) {
|
|
164
|
+
errorMsg = error.response.data.message;
|
|
165
|
+
} else {
|
|
166
|
+
errorMsg = JSON.stringify(error.response.data);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
spinner.fail(chalk.red(`✗ ${fileName} → ${errorMsg}`));
|
|
170
|
+
failCount++;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Re-initialize
|
|
175
|
+
if (successCount > 0) {
|
|
176
|
+
console.log();
|
|
177
|
+
const reinitSpinner = ora('Sistem yeniden başlatılıyor...').start();
|
|
178
|
+
const reinitSuccess = await reinitializeSystem(apiConfig.baseUrl, apiConfig.version);
|
|
179
|
+
|
|
180
|
+
if (reinitSuccess) {
|
|
181
|
+
reinitSpinner.succeed(chalk.green('✓ Sistem yenilendi'));
|
|
182
|
+
} else {
|
|
183
|
+
reinitSpinner.warn(chalk.yellow('⚠ Sistem yenilenemedi (devam edildi)'));
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Özet
|
|
188
|
+
console.log();
|
|
189
|
+
console.log(chalk.cyan('═'.repeat(50)));
|
|
190
|
+
console.log(chalk.white(`Toplam: ${jsonFiles.length} dosya`));
|
|
191
|
+
console.log(chalk.green(`✓ Başarılı: ${successCount}`));
|
|
192
|
+
if (failCount > 0) {
|
|
193
|
+
console.log(chalk.red(`✗ Başarısız: ${failCount}`));
|
|
194
|
+
}
|
|
195
|
+
console.log(chalk.cyan('═'.repeat(50)));
|
|
196
|
+
console.log();
|
|
197
|
+
|
|
198
|
+
if (successCount > 0) {
|
|
199
|
+
console.log(chalk.green.bold('✓ Workflow güncelleme tamamlandı\n'));
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
module.exports = updateCommand;
|
package/src/lib/api.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* API bağlantısını test eder
|
|
5
|
+
*/
|
|
6
|
+
async function testApiConnection(baseUrl) {
|
|
7
|
+
try {
|
|
8
|
+
const response = await axios.get(`${baseUrl}/health`, {
|
|
9
|
+
timeout: 5000
|
|
10
|
+
});
|
|
11
|
+
return response.status === 200;
|
|
12
|
+
} catch (error) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Workflow'u API'ye post eder
|
|
19
|
+
*/
|
|
20
|
+
async function postWorkflow(baseUrl, version, flow, data) {
|
|
21
|
+
const domain = 'core'; // API_DOMAIN
|
|
22
|
+
const workflowVersion = data.version || '1.0.0';
|
|
23
|
+
const syncMode = 'true';
|
|
24
|
+
|
|
25
|
+
const url = `${baseUrl}/api/${version}/${domain}/workflows/${flow}/instances/start?version=${workflowVersion}&sync=${syncMode}`;
|
|
26
|
+
|
|
27
|
+
const response = await axios.post(url, data, {
|
|
28
|
+
headers: {
|
|
29
|
+
'accept': '*/*',
|
|
30
|
+
'Content-Type': 'application/json'
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
return response.data;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Workflow'u aktif eder
|
|
38
|
+
*/
|
|
39
|
+
async function activateWorkflow(baseUrl, version, flow, instanceId, workflowVersion) {
|
|
40
|
+
const domain = 'core'; // API_DOMAIN
|
|
41
|
+
const syncMode = 'true';
|
|
42
|
+
|
|
43
|
+
const url = `${baseUrl}/api/${version}/${domain}/workflows/${flow}/instances/${instanceId}/transitions/activate?version=${workflowVersion}&sync=${syncMode}`;
|
|
44
|
+
|
|
45
|
+
const response = await axios.patch(url, null, {
|
|
46
|
+
headers: {
|
|
47
|
+
'accept': '*/*'
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
return response.data;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Sistemi yeniden başlatır
|
|
55
|
+
*/
|
|
56
|
+
async function reinitializeSystem(baseUrl, version) {
|
|
57
|
+
const url = `${baseUrl}/api/${version}/admin/re-initialize`;
|
|
58
|
+
try {
|
|
59
|
+
await axios.get(url, { timeout: 10000 });
|
|
60
|
+
return true;
|
|
61
|
+
} catch (error) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
module.exports = {
|
|
67
|
+
testApiConnection,
|
|
68
|
+
postWorkflow,
|
|
69
|
+
activateWorkflow,
|
|
70
|
+
reinitializeSystem
|
|
71
|
+
};
|
|
72
|
+
|