@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/src/lib/config.js CHANGED
@@ -1,29 +1,239 @@
1
1
  const Conf = require('conf');
2
- const path = require('path');
2
+
3
+ // Default config values for a domain
4
+ const DEFAULT_DOMAIN_CONFIG = {
5
+ AUTO_DISCOVER: true,
6
+ API_BASE_URL: 'http://localhost:4201',
7
+ API_VERSION: 'v1',
8
+ DB_HOST: 'localhost',
9
+ DB_PORT: 5432,
10
+ DB_NAME: 'vNext_WorkflowDb',
11
+ DB_USER: 'postgres',
12
+ DB_PASSWORD: 'postgres',
13
+ USE_DOCKER: false,
14
+ DOCKER_POSTGRES_CONTAINER: 'vnext-postgres',
15
+ DEBUG_MODE: false
16
+ };
17
+
18
+ const DOMAIN_CONFIG_KEYS = Object.keys(DEFAULT_DOMAIN_CONFIG);
3
19
 
4
20
  const config = new Conf({
5
- projectName: 'vnext-workflow-cli',
6
- defaults: {
21
+ projectName: 'vnext-workflow-cli'
22
+ });
23
+
24
+ /**
25
+ * Migrates old flat config to new domain-aware format.
26
+ * Old: { API_BASE_URL: "...", DB_NAME: "..." }
27
+ * New: { ACTIVE_DOMAIN: "default", DOMAINS: [{ DOMAIN_NAME: "default", ... }] }
28
+ */
29
+ function migrateConfig() {
30
+ const store = config.store;
31
+
32
+ // Already in new format - skip
33
+ if (store.ACTIVE_DOMAIN !== undefined && Array.isArray(store.DOMAINS)) {
34
+ return;
35
+ }
36
+
37
+ // Collect existing values from old flat config
38
+ const existingValues = {};
39
+ for (const key of DOMAIN_CONFIG_KEYS) {
40
+ if (store[key] !== undefined) {
41
+ existingValues[key] = store[key];
42
+ }
43
+ }
44
+
45
+ // Create default domain: defaults + any existing overrides
46
+ const defaultDomain = {
47
+ DOMAIN_NAME: 'default',
48
+ ...DEFAULT_DOMAIN_CONFIG,
49
+ ...existingValues
50
+ };
51
+
52
+ // Clear old keys and set new format via conf API
53
+ for (const key of DOMAIN_CONFIG_KEYS) {
54
+ config.delete(key);
55
+ }
56
+ config.set('ACTIVE_DOMAIN', 'default');
57
+ config.set('DOMAINS', [defaultDomain]);
58
+ }
59
+
60
+ // Run migration on module load
61
+ migrateConfig();
62
+
63
+ /**
64
+ * Returns the active domain config object.
65
+ * @returns {Object} Active domain config
66
+ */
67
+ function getActiveDomainConfig() {
68
+ const activeDomain = config.get('ACTIVE_DOMAIN');
69
+ const domains = config.get('DOMAINS') || [];
70
+ const domain = domains.find(d => d.DOMAIN_NAME === activeDomain);
71
+
72
+ if (!domain) {
73
+ throw new Error(`Active domain "${activeDomain}" not found in config.`);
74
+ }
75
+ return domain;
76
+ }
77
+
78
+ /**
79
+ * Gets a config value from the active domain.
80
+ * PROJECT_ROOT always returns process.cwd().
81
+ * @param {string} key - Config key
82
+ * @returns {any} Config value
83
+ */
84
+ function get(key) {
85
+ if (key === 'PROJECT_ROOT') {
86
+ return process.cwd();
87
+ }
88
+ if (key === 'ACTIVE_DOMAIN') {
89
+ return config.get('ACTIVE_DOMAIN');
90
+ }
91
+ const domainConfig = getActiveDomainConfig();
92
+ return domainConfig[key];
93
+ }
94
+
95
+ /**
96
+ * Sets a config value on the active domain.
97
+ * PROJECT_ROOT cannot be set (always uses cwd).
98
+ * @param {string} key - Config key
99
+ * @param {any} value - Config value
100
+ */
101
+ function set(key, value) {
102
+ const RESERVED_KEYS = {
103
+ PROJECT_ROOT: 'PROJECT_ROOT is always the current working directory and cannot be changed.',
104
+ DOMAIN_NAME: 'DOMAIN_NAME cannot be changed directly. Use "wf domain add/remove" instead.',
105
+ ACTIVE_DOMAIN: 'ACTIVE_DOMAIN cannot be changed directly. Use "wf domain use <name>" instead.'
106
+ };
107
+
108
+ if (RESERVED_KEYS[key]) {
109
+ throw new Error(RESERVED_KEYS[key]);
110
+ }
111
+
112
+ const activeDomainName = config.get('ACTIVE_DOMAIN');
113
+ const domains = config.get('DOMAINS') || [];
114
+ const idx = domains.findIndex(d => d.DOMAIN_NAME === activeDomainName);
115
+
116
+ if (idx === -1) {
117
+ throw new Error(`Active domain "${activeDomainName}" not found.`);
118
+ }
119
+
120
+ domains[idx][key] = value;
121
+ config.set('DOMAINS', domains);
122
+ }
123
+
124
+ /**
125
+ * Gets all config values from the active domain.
126
+ * @returns {Object} All config values including PROJECT_ROOT and ACTIVE_DOMAIN
127
+ */
128
+ function getAll() {
129
+ const domainConfig = getActiveDomainConfig();
130
+ return {
7
131
  PROJECT_ROOT: process.cwd(),
8
- AUTO_DISCOVER: true,
9
- API_BASE_URL: 'http://localhost:4201',
10
- API_VERSION: 'v1',
11
- DB_HOST: 'localhost',
12
- DB_PORT: 5432,
13
- DB_NAME: 'vNext_WorkflowDb',
14
- DB_USER: 'postgres',
15
- DB_PASSWORD: 'postgres',
16
- USE_DOCKER: false,
17
- DOCKER_POSTGRES_CONTAINER: 'vnext-postgres',
18
- DEBUG_MODE: false
132
+ ACTIVE_DOMAIN: config.get('ACTIVE_DOMAIN'),
133
+ ...domainConfig
134
+ };
135
+ }
136
+
137
+ /**
138
+ * Resets config to default state.
139
+ */
140
+ function clear() {
141
+ config.clear();
142
+ config.set('ACTIVE_DOMAIN', 'default');
143
+ config.set('DOMAINS', [{
144
+ DOMAIN_NAME: 'default',
145
+ ...DEFAULT_DOMAIN_CONFIG
146
+ }]);
147
+ }
148
+
149
+ /**
150
+ * Adds a new domain. Missing values are inherited from the default domain.
151
+ * @param {string} name - Domain name
152
+ * @param {Object} options - Domain config overrides
153
+ * @returns {Object} Created domain config
154
+ */
155
+ function addDomain(name, options) {
156
+ const domains = config.get('DOMAINS') || [];
157
+
158
+ if (domains.find(d => d.DOMAIN_NAME === name)) {
159
+ throw new Error(`Domain "${name}" already exists.`);
19
160
  }
20
- });
161
+
162
+ // Use default domain as base, fall back to DEFAULT_DOMAIN_CONFIG
163
+ const defaultDomain = domains.find(d => d.DOMAIN_NAME === 'default');
164
+ const base = defaultDomain
165
+ ? { ...defaultDomain }
166
+ : { ...DEFAULT_DOMAIN_CONFIG };
167
+ delete base.DOMAIN_NAME;
168
+
169
+ const newDomain = {
170
+ DOMAIN_NAME: name,
171
+ ...base,
172
+ ...options
173
+ };
174
+
175
+ domains.push(newDomain);
176
+ config.set('DOMAINS', domains);
177
+ return newDomain;
178
+ }
179
+
180
+ /**
181
+ * Switches the active domain.
182
+ * @param {string} name - Domain name to activate
183
+ */
184
+ function useDomain(name) {
185
+ const domains = config.get('DOMAINS') || [];
186
+ if (!domains.find(d => d.DOMAIN_NAME === name)) {
187
+ throw new Error(`Domain "${name}" not found.`);
188
+ }
189
+ config.set('ACTIVE_DOMAIN', name);
190
+ }
191
+
192
+ /**
193
+ * Lists all domains with active domain info.
194
+ * @returns {Object} { activeDomain, domains }
195
+ */
196
+ function listDomains() {
197
+ return {
198
+ activeDomain: config.get('ACTIVE_DOMAIN'),
199
+ domains: config.get('DOMAINS') || []
200
+ };
201
+ }
202
+
203
+ /**
204
+ * Removes a domain. Cannot remove the default domain.
205
+ * If the removed domain was active, switches to default.
206
+ * @param {string} name - Domain name to remove
207
+ */
208
+ function removeDomain(name) {
209
+ if (name === 'default') {
210
+ throw new Error('Cannot remove the default domain.');
211
+ }
212
+
213
+ const domains = config.get('DOMAINS') || [];
214
+ const filtered = domains.filter(d => d.DOMAIN_NAME !== name);
215
+
216
+ if (filtered.length === domains.length) {
217
+ throw new Error(`Domain "${name}" not found.`);
218
+ }
219
+
220
+ config.set('DOMAINS', filtered);
221
+
222
+ if (config.get('ACTIVE_DOMAIN') === name) {
223
+ config.set('ACTIVE_DOMAIN', 'default');
224
+ }
225
+ }
21
226
 
22
227
  module.exports = {
23
- get: (key) => config.get(key),
24
- set: (key, value) => config.set(key, value),
25
- getAll: () => config.store,
26
- clear: () => config.clear(),
27
- path: config.path
228
+ get,
229
+ set,
230
+ getAll,
231
+ clear,
232
+ path: config.path,
233
+ addDomain,
234
+ useDomain,
235
+ listDomains,
236
+ removeDomain,
237
+ getActiveDomainConfig,
238
+ DEFAULT_DOMAIN_CONFIG
28
239
  };
29
-
package/src/lib/csx.js CHANGED
@@ -1,9 +1,12 @@
1
1
  const fs = require('fs').promises;
2
2
  const path = require('path');
3
3
  const { glob } = require('glob');
4
+ const { discoverComponents, findAllJsonFiles } = require('./discover');
4
5
 
5
6
  /**
6
- * CSX dosyasını Base64'e çevirir
7
+ * Encodes CSX file to Base64
8
+ * @param {string} csxPath - CSX file path
9
+ * @returns {Promise<string>} Base64 encoded content
7
10
  */
8
11
  async function encodeToBase64(csxPath) {
9
12
  const content = await fs.readFile(csxPath, 'utf8');
@@ -11,28 +14,32 @@ async function encodeToBase64(csxPath) {
11
14
  }
12
15
 
13
16
  /**
14
- * CSX dosyası için ilgili JSON dosyalarını bulur
17
+ * Finds JSON files that reference the CSX file
18
+ * Only searches in paths defined in vnext.config.json
19
+ * @param {string} csxPath - CSX file path
20
+ * @param {string} projectRoot - Project root folder
21
+ * @returns {Promise<string[]>} Matching JSON file paths
15
22
  */
16
23
  async function findJsonFilesForCsx(csxPath, projectRoot) {
17
24
  const csxBaseName = path.basename(csxPath);
18
25
 
19
- // Tüm JSON dosyalarını bul
20
- const pattern = path.join(projectRoot, '**', '*.json');
21
- const jsonFiles = await glob(pattern, {
22
- ignore: ['**/node_modules/**', '**/dist/**', '**/package*.json', '**/*config*.json']
23
- });
26
+ // Get discovered components (only paths defined in vnext.config.json)
27
+ const discovered = await discoverComponents(projectRoot);
24
28
 
25
- // CSX referansı olan JSON'ları filtrele
29
+ // Get all JSON files from discovered components only
30
+ const jsonFileInfos = await findAllJsonFiles(discovered);
31
+
32
+ // Filter JSONs that reference the CSX
26
33
  const matchingJsons = [];
27
34
 
28
- for (const jsonFile of jsonFiles) {
35
+ for (const jsonInfo of jsonFileInfos) {
29
36
  try {
30
- const content = await fs.readFile(jsonFile, 'utf8');
37
+ const content = await fs.readFile(jsonInfo.path, 'utf8');
31
38
  if (content.includes(csxBaseName)) {
32
- matchingJsons.push(jsonFile);
39
+ matchingJsons.push(jsonInfo.path);
33
40
  }
34
41
  } catch (error) {
35
- // Ignore
42
+ // Skip unreadable files
36
43
  }
37
44
  }
38
45
 
@@ -40,11 +47,14 @@ async function findJsonFilesForCsx(csxPath, projectRoot) {
40
47
  }
41
48
 
42
49
  /**
43
- * CSX location path'ini hesaplar
50
+ * Calculates CSX location path
51
+ * @param {string} csxPath - CSX file path
52
+ * @param {string} projectRoot - Project root folder
53
+ * @returns {string} Location path
44
54
  */
45
- function getCsxLocation(csxPath) {
46
- // ./src/Rules/MyRule.csx formatına çevir
47
- const parts = csxPath.split('/');
55
+ function getCsxLocation(csxPath, projectRoot) {
56
+ // Convert to ./src/Rules/MyRule.csx format
57
+ const parts = csxPath.split(path.sep);
48
58
  const srcIndex = parts.lastIndexOf('src');
49
59
 
50
60
  if (srcIndex !== -1) {
@@ -56,91 +66,154 @@ function getCsxLocation(csxPath) {
56
66
  }
57
67
 
58
68
  /**
59
- * JSON dosyasında CSX code'unu günceller
69
+ * Updates ALL CSX codes in a JSON file
70
+ * Updates all references with the same location
71
+ * Supports encoding types: NAT (native/plain text), B64 (Base64, default)
72
+ * @param {string} jsonPath - JSON file path
73
+ * @param {string} csxLocation - CSX location path
74
+ * @param {string} base64Code - Base64 encoded CSX content
75
+ * @param {string} nativeCode - Native (plain text) CSX content
76
+ * @returns {Promise<number>} Number of updated references
60
77
  */
61
- async function updateCodeInJson(jsonPath, csxLocation, base64Code) {
78
+ async function updateCodeInJson(jsonPath, csxLocation, base64Code, nativeCode) {
62
79
  const content = await fs.readFile(jsonPath, 'utf8');
63
80
  const data = JSON.parse(content);
64
81
 
65
- // Recursive olarak location'ı bul ve güncelle
82
+ let updateCount = 0;
83
+
84
+ // Recursively find and update ALL location matches
66
85
  function updateRecursive(obj) {
67
- if (typeof obj !== 'object' || obj === null) return false;
86
+ if (typeof obj !== 'object' || obj === null) return;
87
+
88
+ // Skip if location is missing
89
+ if (!obj.location) {
90
+ // Continue scanning children
91
+ for (const key in obj) {
92
+ if (typeof obj[key] === 'object' && obj[key] !== null) {
93
+ updateRecursive(obj[key]);
94
+ }
95
+ }
96
+ return;
97
+ }
68
98
 
69
99
  if (obj.location === csxLocation && 'code' in obj) {
70
- obj.code = base64Code;
71
- return true;
100
+ // Check encoding type: NAT = Native (plain text), B64 or empty = Base64 (default)
101
+ const encoding = obj.encoding ? obj.encoding.toUpperCase() : 'B64';
102
+
103
+ if (encoding === 'NAT') {
104
+ // Native encoding - write plain text content
105
+ obj.code = nativeCode;
106
+ } else {
107
+ // B64 or default - write Base64 encoded content
108
+ obj.code = base64Code;
109
+ }
110
+ updateCount++;
72
111
  }
73
112
 
113
+ // Scan all elements in array or object
74
114
  for (const key in obj) {
75
- if (updateRecursive(obj[key])) {
76
- return true;
115
+ if (typeof obj[key] === 'object' && obj[key] !== null) {
116
+ updateRecursive(obj[key]);
77
117
  }
78
118
  }
79
-
80
- return false;
81
119
  }
82
120
 
83
- const updated = updateRecursive(data);
121
+ updateRecursive(data);
84
122
 
85
- if (updated) {
123
+ if (updateCount > 0) {
86
124
  await fs.writeFile(jsonPath, JSON.stringify(data, null, 2), 'utf8');
87
- return true;
88
125
  }
89
126
 
90
- return false;
127
+ return updateCount;
91
128
  }
92
129
 
93
130
  /**
94
- * Tek bir CSX dosyasını işler
131
+ * Reads CSX file content as plain text (native)
132
+ * @param {string} csxPath - CSX file path
133
+ * @returns {Promise<string>} Plain text content
134
+ */
135
+ async function readNativeContent(csxPath) {
136
+ return await fs.readFile(csxPath, 'utf8');
137
+ }
138
+
139
+ /**
140
+ * Processes a single CSX file
141
+ * Updates ALL referencing JSON files
142
+ * Supports both NAT (native) and B64 (Base64) encoding
143
+ * @param {string} csxPath - CSX file path
144
+ * @param {string} projectRoot - Project root folder
145
+ * @returns {Promise<Object>} Process result
95
146
  */
96
147
  async function processCsxFile(csxPath, projectRoot) {
97
- // Base64'e çevir
98
- const base64Code = await encodeToBase64(csxPath);
148
+ // Read native content
149
+ const nativeCode = await readNativeContent(csxPath);
99
150
 
100
- // İlgili JSON'ları bul
151
+ // Convert to Base64
152
+ const base64Code = Buffer.from(nativeCode).toString('base64');
153
+
154
+ // Find ALL related JSONs (only in paths defined in vnext.config.json)
101
155
  const jsonFiles = await findJsonFilesForCsx(csxPath, projectRoot);
102
156
 
103
157
  if (jsonFiles.length === 0) {
104
- return { success: false, message: 'İlgili JSON bulunamadı' };
158
+ return {
159
+ success: false,
160
+ message: 'No related JSON found',
161
+ updatedJsonCount: 0,
162
+ totalUpdates: 0,
163
+ jsonFiles: []
164
+ };
105
165
  }
106
166
 
107
- // CSX location'ı hesapla
108
- const csxLocation = getCsxLocation(csxPath);
167
+ // Calculate CSX location
168
+ const csxLocation = getCsxLocation(csxPath, projectRoot);
169
+
170
+ // Update each JSON
171
+ let updatedJsonCount = 0;
172
+ let totalUpdates = 0;
173
+ const updatedFiles = [];
109
174
 
110
- // Her JSON'u güncelle
111
- let updatedCount = 0;
112
175
  for (const jsonFile of jsonFiles) {
113
176
  try {
114
- const updated = await updateCodeInJson(jsonFile, csxLocation, base64Code);
115
- if (updated) {
116
- updatedCount++;
177
+ const updates = await updateCodeInJson(jsonFile, csxLocation, base64Code, nativeCode);
178
+ if (updates > 0) {
179
+ updatedJsonCount++;
180
+ totalUpdates += updates;
181
+ updatedFiles.push({
182
+ file: path.basename(jsonFile),
183
+ updates: updates
184
+ });
117
185
  }
118
186
  } catch (error) {
119
- // Continue with next file
187
+ // Continue with next file on error
120
188
  }
121
189
  }
122
190
 
123
191
  return {
124
- success: updatedCount > 0,
125
- updatedCount,
126
- jsonFiles: jsonFiles.map(f => path.basename(f))
192
+ success: updatedJsonCount > 0,
193
+ message: updatedJsonCount > 0 ? 'Updated' : 'No references to update',
194
+ updatedJsonCount,
195
+ totalUpdates,
196
+ jsonFiles: updatedFiles
127
197
  };
128
198
  }
129
199
 
130
200
  /**
131
- * Git'te değişen CSX dosyalarını bulur
201
+ * Finds changed CSX files in Git
202
+ * @param {string} projectRoot - Project root folder
203
+ * @returns {Promise<string[]>} Changed CSX file paths
132
204
  */
133
205
  async function getGitChangedCsx(projectRoot) {
134
206
  const { exec } = require('child_process');
135
207
  const util = require('util');
136
208
  const execPromise = util.promisify(exec);
209
+ const fsSync = require('fs');
137
210
 
138
211
  try {
139
- // Git root'u bul
212
+ // Find git root
140
213
  const { stdout: gitRoot } = await execPromise('git rev-parse --show-toplevel', { cwd: projectRoot });
141
214
  const gitRootDir = gitRoot.trim();
142
215
 
143
- // Git status'u git root'tan çalıştır
216
+ // Run git status from git root
144
217
  const { stdout } = await execPromise('git status --porcelain', { cwd: gitRootDir });
145
218
  const lines = stdout.split('\n').filter(Boolean);
146
219
 
@@ -158,7 +231,7 @@ async function getGitChangedCsx(projectRoot) {
158
231
  .filter(file => {
159
232
  // Only .csx files that exist and are in our project
160
233
  return file.endsWith('.csx') &&
161
- require('fs').existsSync(file) &&
234
+ fsSync.existsSync(file) &&
162
235
  file.startsWith(path.normalize(projectRoot));
163
236
  });
164
237
 
@@ -169,18 +242,19 @@ async function getGitChangedCsx(projectRoot) {
169
242
  }
170
243
 
171
244
  /**
172
- * Tüm CSX dosyalarını bulur
245
+ * Finds all CSX files in discovered components ONLY
246
+ * Does NOT scan folders outside of paths definition
247
+ * @param {string} projectRoot - Project root folder
248
+ * @returns {Promise<string[]>} CSX file paths
173
249
  */
174
250
  async function findAllCsx(projectRoot) {
175
- const pattern = path.join(projectRoot, '**', 'src', '**', '*.csx');
176
- const files = await glob(pattern, {
177
- ignore: ['**/node_modules/**', '**/dist/**']
178
- });
179
- return files;
251
+ const { findAllCsxInComponents } = require('./discover');
252
+ return findAllCsxInComponents(projectRoot);
180
253
  }
181
254
 
182
255
  module.exports = {
183
256
  encodeToBase64,
257
+ readNativeContent,
184
258
  findJsonFilesForCsx,
185
259
  getCsxLocation,
186
260
  updateCodeInJson,
@@ -188,4 +262,3 @@ module.exports = {
188
262
  getGitChangedCsx,
189
263
  findAllCsx
190
264
  };
191
-
package/src/lib/db.js CHANGED
@@ -5,11 +5,11 @@ const util = require('util');
5
5
  const execPromise = util.promisify(exec);
6
6
 
7
7
  /**
8
- * DB bağlantısını test eder
8
+ * Tests the DB connection
9
9
  */
10
10
  async function testDbConnection(dbConfig) {
11
11
  if (dbConfig.useDocker) {
12
- // Docker üzerinden test
12
+ // Test via Docker
13
13
  try {
14
14
  const cmd = `docker exec ${dbConfig.dockerContainer} psql -U ${dbConfig.user} -d ${dbConfig.database} -c "SELECT 1;"`;
15
15
  await execPromise(cmd);
@@ -18,7 +18,7 @@ async function testDbConnection(dbConfig) {
18
18
  return false;
19
19
  }
20
20
  } else {
21
- // Direkt bağlantı
21
+ // Direct connection
22
22
  const client = new Client({
23
23
  host: dbConfig.host,
24
24
  port: dbConfig.port,
@@ -39,15 +39,15 @@ async function testDbConnection(dbConfig) {
39
39
  }
40
40
 
41
41
  /**
42
- * Workflow'un DB'deki ID'sini bulur
43
- * NOT: Version kontrolü yapmıyoruz, sadece Key'e bakıyoruz (bash script gibi)
42
+ * Finds the workflow's ID in the DB
43
+ * NOTE: We don't check version, only the Key (like the bash script)
44
44
  */
45
45
  async function getInstanceId(dbConfig, schema, key, version) {
46
46
  const dbSchema = schema.replace(/-/g, '_');
47
47
  const query = `SELECT "Id" FROM "${dbSchema}"."Instances" WHERE "Key" = $1 ORDER BY "CreatedAt" DESC LIMIT 1`;
48
48
 
49
49
  if (dbConfig.useDocker) {
50
- // Docker üzerinden - SQL içindeki double quote'ları backslash ile escape et
50
+ // Via Docker - escape double quotes in SQL with backslash
51
51
  const cmd = `docker exec ${dbConfig.dockerContainer} psql -U ${dbConfig.user} -d ${dbConfig.database} -t -c "SELECT \\"Id\\" FROM \\"${dbSchema}\\".\\"Instances\\" WHERE \\"Key\\" = '${key}' ORDER BY \\"CreatedAt\\" DESC LIMIT 1"`;
52
52
  try {
53
53
  const { stdout } = await execPromise(cmd);
@@ -57,7 +57,7 @@ async function getInstanceId(dbConfig, schema, key, version) {
57
57
  return null;
58
58
  }
59
59
  } else {
60
- // Direkt bağlantı
60
+ // Direct connection
61
61
  const client = new Client({
62
62
  host: dbConfig.host,
63
63
  port: dbConfig.port,
@@ -78,13 +78,13 @@ async function getInstanceId(dbConfig, schema, key, version) {
78
78
  }
79
79
 
80
80
  /**
81
- * Workflow'u DB'den siler
81
+ * Deletes a workflow from the DB
82
82
  */
83
83
  async function deleteWorkflow(dbConfig, schema, instanceId) {
84
84
  const dbSchema = schema.replace(/-/g, '_');
85
85
 
86
86
  if (dbConfig.useDocker) {
87
- // Docker üzerinden - Double quote'ları escape et
87
+ // Via Docker - escape double quotes
88
88
  const cmd = `docker exec ${dbConfig.dockerContainer} psql -U ${dbConfig.user} -d ${dbConfig.database} -c "DELETE FROM \\"${dbSchema}\\".\\"Instances\\" WHERE \\"Id\\" = '${instanceId}'"`;
89
89
  try {
90
90
  await execPromise(cmd);
@@ -93,7 +93,7 @@ async function deleteWorkflow(dbConfig, schema, instanceId) {
93
93
  return false;
94
94
  }
95
95
  } else {
96
- // Direkt bağlantı
96
+ // Direct connection
97
97
  const query = `DELETE FROM "${dbSchema}"."Instances" WHERE "Id" = $1`;
98
98
  const client = new Client({
99
99
  host: dbConfig.host,