tsoft-cli 1.2.3 → 1.4.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/CHANGELOG.md +20 -1
- package/README.md +79 -67
- package/bin/index.js +10 -10
- package/package.json +2 -1
- package/src/{tsoft.js → Tsoft.js} +8 -13
- package/src/commands/CreateCommand.js +100 -0
- package/src/commands/StartCommand.js +280 -0
- package/src/commands/SyncCommand.js +97 -0
- package/src/{client-credentials.js → core/ClientCredentials.js} +41 -46
- package/src/{constants.js → core/Constants.js} +5 -2
- package/src/{file-manager.js → core/FileManager.js} +5 -22
- package/src/core/Request.js +41 -0
- package/src/{theme-manager.js → core/ThemeManager.js} +3 -2
- package/src/{utils.js → core/Utils.js} +31 -11
- package/src/commands/create.js +0 -127
- package/src/commands/start.js +0 -265
- package/src/commands/sync.js +0 -80
- package/src/request.js +0 -37
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const chokidar = require('chokidar');
|
|
4
|
+
const readline = require('readline');
|
|
5
|
+
const { exec } = require('child_process');
|
|
6
|
+
const Tsoft = require('../Tsoft');
|
|
7
|
+
const Constants = require('../core/Constants');
|
|
8
|
+
const cliProgress = require('cli-progress');
|
|
9
|
+
const { Input } = require('enquirer');
|
|
10
|
+
const { displayAsciiArt, info, unzipFile } = require('../core/Utils');
|
|
11
|
+
|
|
12
|
+
class StartCommand {
|
|
13
|
+
static async showProgress(tsoft, theme) {
|
|
14
|
+
const themePath = path.join(process.cwd(), tsoft.site, theme);
|
|
15
|
+
const fileList = tsoft.fileManager.listFilesRecursive(themePath).filter(file => !file.includes('.env'));
|
|
16
|
+
const totalFiles = fileList.length;
|
|
17
|
+
|
|
18
|
+
const progressBar = new cliProgress.SingleBar({
|
|
19
|
+
format: 'İlerleme |{bar}| {percentage}% || {value}/{total} Dosya Yüklendi',
|
|
20
|
+
barCompleteChar: '\u2588',
|
|
21
|
+
barIncompleteChar: '\u2591',
|
|
22
|
+
hideCursor: true,
|
|
23
|
+
clearOnComplete: true
|
|
24
|
+
});
|
|
25
|
+
progressBar.start(totalFiles, 0);
|
|
26
|
+
|
|
27
|
+
for (let i = 0; i < totalFiles; i++) {
|
|
28
|
+
const file = fileList[i];
|
|
29
|
+
const fileName = tsoft.fileManager.getRelativePath(theme, file);
|
|
30
|
+
const content = tsoft.fileManager.readFile(file);
|
|
31
|
+
const env = tsoft.themeManager.getEnvironment(theme);
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
await tsoft.saveFile(theme, fileName, content, env.bearer);
|
|
35
|
+
} catch (error) {
|
|
36
|
+
console.error(`Dosya yükleme hatası ${fileName}:`, error);
|
|
37
|
+
}
|
|
38
|
+
progressBar.update(i + 1);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
progressBar.stop();
|
|
42
|
+
|
|
43
|
+
return 'Tüm dosyalar ilerleme ile başarıyla yüklendi';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
static async initializeAndAuthorize(tsoft, themeName) {
|
|
47
|
+
await tsoft.initialize(themeName);
|
|
48
|
+
|
|
49
|
+
const approvalPrompt = new Input({
|
|
50
|
+
name: 'approval',
|
|
51
|
+
message: 'Lütfen onay kodunu sağlayın:'
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const approval = await approvalPrompt.run();
|
|
55
|
+
|
|
56
|
+
if (approval) {
|
|
57
|
+
await Constants.APPROVAL.handler(tsoft.clientCredentials.setClientSecret(approval));
|
|
58
|
+
tsoft.buildEnvironment();
|
|
59
|
+
console.info('Ortam dosyası başarıyla oluşturuldu.');
|
|
60
|
+
return true;
|
|
61
|
+
} else {
|
|
62
|
+
console.error('Onay kodu gerekli.');
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
static async handleExistingEnvironment(tsoft, themeName, themeEnvPath) {
|
|
68
|
+
let envData = {};
|
|
69
|
+
if (fs.existsSync(themeEnvPath)) {
|
|
70
|
+
try {
|
|
71
|
+
envData = JSON.parse(fs.readFileSync(themeEnvPath, 'utf-8'));
|
|
72
|
+
} catch (error) {
|
|
73
|
+
console.warn(`${themeEnvPath} dosyasında geçersiz JSON formatı. Bu dosya silinecek ve yeniden yetkilendirmeniz gerekecek.`);
|
|
74
|
+
fs.unlinkSync(themeEnvPath);
|
|
75
|
+
console.info('Geçersiz ortam dosyası silindi. Başlatma işlemine devam ediliyor...');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (envData.bearer) {
|
|
79
|
+
const bearerTokenValid = await tsoft.isTokenValid(themeName);
|
|
80
|
+
|
|
81
|
+
if (bearerTokenValid) {
|
|
82
|
+
console.info('Geçerli bir taşıyıcı jetonuna sahip mevcut ortam dosyası bulundu. Mevcut yapılandırma ile devam ediliyor...');
|
|
83
|
+
return true;
|
|
84
|
+
} else {
|
|
85
|
+
console.warn('Mevcut taşıyıcı jetonu geçersiz. Yeniden yetkilendirmeniz gerekecek.');
|
|
86
|
+
fs.unlinkSync(themeEnvPath);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
static async startWatching(themePath, tsoft, theme) {
|
|
94
|
+
const watcher = chokidar.watch(themePath, {
|
|
95
|
+
ignored: /(^|[\/\\])(\.theme|(.*?)\.env)$/, // .theme ve .env dosyaları yoksayılır
|
|
96
|
+
persistent: true
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
watcher.on('change', async (filePath) => {
|
|
100
|
+
console.log(`Dosya değiştirildi ${filePath}`);
|
|
101
|
+
await StartCommand.handleFileChange(filePath, tsoft, theme);
|
|
102
|
+
}).on('unlink', async (filePath) => {
|
|
103
|
+
console.log(`Dosya silindi ${filePath}`);
|
|
104
|
+
await StartCommand.handleFileDeletion(filePath, tsoft, theme);
|
|
105
|
+
}).on('unlinkDir', async (dirPath) => {
|
|
106
|
+
console.log(`Dizin silindi ${dirPath}`);
|
|
107
|
+
await StartCommand.handleDirectoryDeletion(dirPath, tsoft, theme);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
console.log(`${themePath} dizinindeki dosya değişiklikleri izleniyor`);
|
|
111
|
+
|
|
112
|
+
const rl = readline.createInterface({
|
|
113
|
+
input: process.stdin,
|
|
114
|
+
output: process.stdout
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
info();
|
|
118
|
+
|
|
119
|
+
rl.on('line', async (input) => {
|
|
120
|
+
await StartCommand.handleUserInput(input, tsoft, theme, watcher, rl);
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
static async handleFileChange(filePath, tsoft, theme) {
|
|
125
|
+
const env = JSON.parse(fs.readFileSync(path.join(process.cwd(), tsoft.site, theme, `${theme}.env`), 'utf-8'));
|
|
126
|
+
const fileName = filePath.replace(`${path.join(process.cwd(), tsoft.site, theme)}/`, '');
|
|
127
|
+
const content = fs.readFileSync(filePath).toString();
|
|
128
|
+
|
|
129
|
+
try {
|
|
130
|
+
await tsoft.saveFile(theme, fileName, content, env.bearer);
|
|
131
|
+
console.log(`Dosya başarıyla yüklendi ${fileName}`);
|
|
132
|
+
} catch (error) {
|
|
133
|
+
console.error(`Dosya yükleme hatası ${fileName}:`, error);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
static async handleFileDeletion(filePath, tsoft, theme) {
|
|
138
|
+
const env = JSON.parse(fs.readFileSync(path.join(process.cwd(), tsoft.site, theme, `${theme}.env`), 'utf-8'));
|
|
139
|
+
const fileName = filePath.replace(`${path.join(process.cwd(), tsoft.site, theme)}/`, '');
|
|
140
|
+
|
|
141
|
+
try {
|
|
142
|
+
await tsoft.deleteFile(theme, fileName, env.bearer);
|
|
143
|
+
console.log(`Dosya başarıyla silindi ${fileName}`);
|
|
144
|
+
} catch (error) {
|
|
145
|
+
console.error(`Dosya silme hatası ${fileName}:`, error);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
static async handleDirectoryDeletion(dirPath, tsoft, theme) {
|
|
150
|
+
const env = JSON.parse(fs.readFileSync(path.join(process.cwd(), tsoft.site, theme, `${theme}.env`), 'utf-8'));
|
|
151
|
+
const dirName = dirPath.replace(`${path.join(process.cwd(), tsoft.site, theme)}/`, '');
|
|
152
|
+
|
|
153
|
+
try {
|
|
154
|
+
await tsoft.deleteDirectory(theme, dirName, env.bearer);
|
|
155
|
+
console.log(`Dizin başarıyla silindi ${dirName}`);
|
|
156
|
+
} catch (error) {
|
|
157
|
+
console.error(`Dizin silme hatası ${dirName}:`, error);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
static async handleUserInput(input, tsoft, theme, watcher, rl) {
|
|
162
|
+
info();
|
|
163
|
+
switch (input.trim()) {
|
|
164
|
+
case 'q':
|
|
165
|
+
console.log('Dosya izleme işlemi sonlandırılıyor...');
|
|
166
|
+
watcher.close();
|
|
167
|
+
rl.close();
|
|
168
|
+
process.exit(0);
|
|
169
|
+
break;
|
|
170
|
+
case 'u':
|
|
171
|
+
console.log('Tema güncelleniyor...');
|
|
172
|
+
try {
|
|
173
|
+
const result = await StartCommand.updateTheme(tsoft, theme);
|
|
174
|
+
console.log(result);
|
|
175
|
+
|
|
176
|
+
} catch (error) {
|
|
177
|
+
console.error(`Tema güncelleme hatası:`, error);
|
|
178
|
+
}
|
|
179
|
+
break;
|
|
180
|
+
case 's':
|
|
181
|
+
console.log('Tüm dosyalar ilerleme ile yüklenmeye başlanıyor...');
|
|
182
|
+
try {
|
|
183
|
+
const result = await StartCommand.showProgress(tsoft, theme);
|
|
184
|
+
console.log(result);
|
|
185
|
+
|
|
186
|
+
} catch (error) {
|
|
187
|
+
console.error(`İlerleme gösterim hatası:`, error);
|
|
188
|
+
}
|
|
189
|
+
break;
|
|
190
|
+
case 'e':
|
|
191
|
+
console.log('.theme dosyası düzenleniyor...');
|
|
192
|
+
try {
|
|
193
|
+
await StartCommand.editThemeFile(tsoft.themeManager, theme);
|
|
194
|
+
} catch (error) {
|
|
195
|
+
console.error(`.theme dosyası düzenleme hatası:`, error);
|
|
196
|
+
}
|
|
197
|
+
break;
|
|
198
|
+
case 'o':
|
|
199
|
+
console.log('Tema dizini açılıyor...');
|
|
200
|
+
const openCommand = process.platform === 'win32' ? 'start' :
|
|
201
|
+
process.platform === 'darwin' ? 'open' :
|
|
202
|
+
'xdg-open';
|
|
203
|
+
exec(`${openCommand} ${path.join(process.cwd(), tsoft.site, theme)}`, (err) => {
|
|
204
|
+
if (err) {
|
|
205
|
+
console.error('Tema dizini açılamadı:', err);
|
|
206
|
+
} else {
|
|
207
|
+
console.log('Tema dizini başarıyla açıldı.');
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
static async start(siteName, themeName, recentlyCreated = false) {
|
|
215
|
+
await displayAsciiArt();
|
|
216
|
+
console.log('Geliştirme ortamı aşağıdaki ayrıntılarla başlatılıyor:');
|
|
217
|
+
console.log(`Site Adı: ${siteName}`);
|
|
218
|
+
console.log(`Tema Adı: ${themeName}`);
|
|
219
|
+
|
|
220
|
+
const tsoft = new Tsoft(siteName);
|
|
221
|
+
const themeEnvPath = path.join(process.cwd(), siteName, themeName, `${themeName}.env`);
|
|
222
|
+
|
|
223
|
+
const existingEnvValid = await StartCommand.handleExistingEnvironment(tsoft, themeName, themeEnvPath);
|
|
224
|
+
if (existingEnvValid) {
|
|
225
|
+
await StartCommand.startWatching(path.join(process.cwd(), siteName, themeName), tsoft, themeName);
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const initializedAndAuthorized = await StartCommand.initializeAndAuthorize(tsoft, themeName);
|
|
230
|
+
if (initializedAndAuthorized) {
|
|
231
|
+
if(recentlyCreated) {
|
|
232
|
+
const defaultZipFile = path.join(process.cwd(), siteName, themeName, 'theme.zip');
|
|
233
|
+
console.log('Default tema dosyaları indirme işlemi başlatılıyor, lütfen bekleyin');
|
|
234
|
+
const themePath = path.join(process.cwd(), siteName, themeName);
|
|
235
|
+
await tsoft.fileManager.downloadAndSaveZip(
|
|
236
|
+
themePath, defaultZipFile,
|
|
237
|
+
tsoft.clientCredentials.bearer,
|
|
238
|
+
'default'
|
|
239
|
+
);
|
|
240
|
+
console.log('Default tema dosyaları indirildi. Çıkarma işlemi başlatılıyor');
|
|
241
|
+
await unzipFile(defaultZipFile, themePath);
|
|
242
|
+
console.log('Çıkarma işlemi tamamlandı.');
|
|
243
|
+
fs.unlinkSync(defaultZipFile);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
await StartCommand.startWatching(path.join(process.cwd(), siteName, themeName), tsoft, themeName);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
static async updateTheme(tsoft, theme) {
|
|
251
|
+
const directoryName = path.basename(path.join(process.cwd(), tsoft.site, theme));
|
|
252
|
+
const response = await tsoft.updateTheme(directoryName);
|
|
253
|
+
if (response.status === true) {
|
|
254
|
+
return 'Successfully updated';
|
|
255
|
+
} else {
|
|
256
|
+
throw new Error('Update failed');
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
static async editThemeFile(themeManager, directoryName) {
|
|
261
|
+
const themePath = path.join(process.cwd(), themeManager.site, directoryName, '.theme');
|
|
262
|
+
if (!fs.existsSync(themePath)) {
|
|
263
|
+
console.error('.theme file not found.');
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
console.log(`Opening .theme file: ${themePath}`);
|
|
267
|
+
const openCommand = process.platform === 'win32' ? 'start' :
|
|
268
|
+
process.platform === 'darwin' ? 'open' :
|
|
269
|
+
'xdg-open';
|
|
270
|
+
exec(`${openCommand} ${themePath}`, (err) => {
|
|
271
|
+
if (err) {
|
|
272
|
+
console.error('Failed to open .theme file:', err);
|
|
273
|
+
} else {
|
|
274
|
+
console.log('.theme file opened successfully.');
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
module.exports = StartCommand;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { Input } = require('enquirer');
|
|
4
|
+
const { clearScreen } = require('../core/Utils');
|
|
5
|
+
const { selectSite, createThemeDirectory } = require('./CreateCommand');
|
|
6
|
+
const StartCommand = require('./StartCommand');
|
|
7
|
+
const Tsoft = require("../Tsoft");
|
|
8
|
+
const { slugify, unzipFile } = require('../core/Utils');
|
|
9
|
+
|
|
10
|
+
class SyncCommand {
|
|
11
|
+
static async syncTheme() {
|
|
12
|
+
const cwd = process.cwd();
|
|
13
|
+
const sites = fs.readdirSync(cwd).filter(file => {
|
|
14
|
+
return file.charAt(0) !== '.' && !['node_modules', 'build', 'dist'].includes(file);
|
|
15
|
+
}).filter(file => fs.statSync(path.join(cwd, file)).isDirectory());
|
|
16
|
+
|
|
17
|
+
const selectedSite = await selectSite(sites);
|
|
18
|
+
|
|
19
|
+
const tsoft = new Tsoft(selectedSite);
|
|
20
|
+
|
|
21
|
+
let recoveryCode;
|
|
22
|
+
let recoveryData;
|
|
23
|
+
while (!recoveryData) {
|
|
24
|
+
const codePrompt = new Input({
|
|
25
|
+
name: 'code',
|
|
26
|
+
message: 'Lütfen kurtarma anahtarını girin:'
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
recoveryCode = await codePrompt.run();
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
recoveryData = await tsoft.startRecovery(recoveryCode);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
if (error.message.includes('Çok fazla deneme yapıldı')) {
|
|
35
|
+
console.error(`Hata: ${error.message}`);
|
|
36
|
+
return;
|
|
37
|
+
} else {
|
|
38
|
+
console.error(`Hata: ${error.message}`);
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (!recoveryData) {
|
|
44
|
+
console.error('Kurtarma işlemi başarısız oldu. Lütfen geçerli bir kurtarma anahtarı girin.');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const { secret, public_key } = recoveryData;
|
|
49
|
+
|
|
50
|
+
tsoft.clientCredentials.setClientSecret(secret).setClientId(public_key);
|
|
51
|
+
const authorizeResponse = await tsoft.clientCredentials.authorize(true);
|
|
52
|
+
const themeInformation = authorizeResponse.data.tokenable;
|
|
53
|
+
|
|
54
|
+
const themeName = themeInformation.name;
|
|
55
|
+
const themeNameSlug = slugify(themeName);
|
|
56
|
+
const themePath = await createThemeDirectory(selectedSite, themeNameSlug);
|
|
57
|
+
|
|
58
|
+
const themeData = {
|
|
59
|
+
site: selectedSite,
|
|
60
|
+
name: themeName,
|
|
61
|
+
author: themeInformation.author,
|
|
62
|
+
version: themeInformation.version
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
fs.writeFileSync(path.join(themePath, '.theme'), JSON.stringify(themeData, null, 2));
|
|
66
|
+
tsoft.themeManager.setTheme(themeNameSlug);
|
|
67
|
+
|
|
68
|
+
if (!fs.existsSync(themePath)) {
|
|
69
|
+
fs.mkdirSync(themePath, { recursive: true });
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
clearScreen();
|
|
73
|
+
|
|
74
|
+
const zipFilePath = path.join(themePath, 'theme.zip');
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
console.log('Zip dosyası indiriliyor...');
|
|
78
|
+
await tsoft.fileManager.downloadAndSaveZip(themePath, zipFilePath, tsoft.clientCredentials.bearer);
|
|
79
|
+
console.log('İndirme tamamlandı.');
|
|
80
|
+
|
|
81
|
+
console.log('Dosyalar çıkarılıyor...');
|
|
82
|
+
await unzipFile(zipFilePath, themePath);
|
|
83
|
+
console.log('Çıkarma işlemi tamamlandı.');
|
|
84
|
+
fs.unlinkSync(zipFilePath);
|
|
85
|
+
} catch (error) {
|
|
86
|
+
console.error(`Zip dosyası ile ilgili bir hata oluştu: ${error.message}`);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
tsoft.buildEnvironment();
|
|
91
|
+
|
|
92
|
+
// Geliştirme ortamını başlat
|
|
93
|
+
await StartCommand.start(selectedSite, themeNameSlug);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
module.exports = SyncCommand;
|
|
@@ -1,27 +1,16 @@
|
|
|
1
|
-
const {buildPostRequest} = require('./
|
|
1
|
+
const {buildPostRequest} = require('./Request');
|
|
2
2
|
|
|
3
3
|
class ClientCredentials {
|
|
4
|
-
site;
|
|
5
|
-
clientId;
|
|
6
|
-
clientSecret;
|
|
7
|
-
bearer;
|
|
8
|
-
|
|
9
4
|
constructor(site) {
|
|
10
5
|
this.site = site;
|
|
6
|
+
this.clientId = null;
|
|
7
|
+
this.clientSecret = null;
|
|
8
|
+
this.bearer = null;
|
|
11
9
|
}
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
return {
|
|
15
|
-
site: this.site, clientId: this.clientId, clientSecret: this.clientSecret, bearer: this.bearer
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
set clientId(clientId) {
|
|
11
|
+
setClientId(clientId) {
|
|
20
12
|
this.clientId = clientId;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
get clientId() {
|
|
24
|
-
return this.clientId;
|
|
13
|
+
return this;
|
|
25
14
|
}
|
|
26
15
|
|
|
27
16
|
setClientSecret(clientSecret) {
|
|
@@ -29,19 +18,25 @@ class ClientCredentials {
|
|
|
29
18
|
return this;
|
|
30
19
|
}
|
|
31
20
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
21
|
+
getEnvironment() {
|
|
22
|
+
return {
|
|
23
|
+
site: this.site,
|
|
24
|
+
clientId: this.clientId,
|
|
25
|
+
clientSecret: this.clientSecret,
|
|
26
|
+
bearer: this.bearer
|
|
27
|
+
};
|
|
35
28
|
}
|
|
36
29
|
|
|
37
30
|
async register(CLIENT_UUID, clientConfiguration = {}) {
|
|
38
|
-
|
|
39
31
|
const uri = "api/v3/admin/auth/auth-application";
|
|
40
|
-
const result = await this.
|
|
41
|
-
|
|
42
|
-
'Content-Type': 'application/json',
|
|
43
|
-
|
|
44
|
-
|
|
32
|
+
const result = await buildPostRequest(this.site, uri, {
|
|
33
|
+
headers: {
|
|
34
|
+
'Content-Type': 'application/json',
|
|
35
|
+
'Accept': 'application/json'
|
|
36
|
+
},
|
|
37
|
+
body: JSON.stringify({
|
|
38
|
+
uuid: CLIENT_UUID,
|
|
39
|
+
configuration: {
|
|
45
40
|
name: clientConfiguration.name,
|
|
46
41
|
author: clientConfiguration.author,
|
|
47
42
|
version: clientConfiguration.version
|
|
@@ -51,22 +46,26 @@ class ClientCredentials {
|
|
|
51
46
|
|
|
52
47
|
if (result.status === true) {
|
|
53
48
|
this.clientId = result.data.public_key;
|
|
49
|
+
return true;
|
|
54
50
|
} else {
|
|
55
51
|
return false;
|
|
56
52
|
}
|
|
57
|
-
|
|
58
|
-
return true;
|
|
59
53
|
}
|
|
60
54
|
|
|
61
55
|
async authorize() {
|
|
62
56
|
const uri = "api/v3/admin/auth/auth-application/authorize";
|
|
63
|
-
return await this.
|
|
57
|
+
return await buildPostRequest(this.site, uri, {
|
|
58
|
+
headers: {
|
|
59
|
+
'Content-Type': 'application/json',
|
|
60
|
+
'Accept': 'application/json'
|
|
61
|
+
},
|
|
64
62
|
body: JSON.stringify({
|
|
65
|
-
public_key: this.clientId,
|
|
63
|
+
public_key: this.clientId,
|
|
64
|
+
secret: this.clientSecret
|
|
66
65
|
})
|
|
67
66
|
}).then((result) => {
|
|
68
67
|
if (result.status === true) {
|
|
69
|
-
this.bearer = result.data.token.plainTextToken
|
|
68
|
+
this.bearer = result.data.token.plainTextToken;
|
|
70
69
|
return result;
|
|
71
70
|
}
|
|
72
71
|
return false;
|
|
@@ -74,39 +73,35 @@ class ClientCredentials {
|
|
|
74
73
|
console.error('Hata:', error.message);
|
|
75
74
|
return false;
|
|
76
75
|
});
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
async buildPostRequest(uri, options = {}) {
|
|
82
|
-
return buildPostRequest(this.site, uri, options);
|
|
83
76
|
}
|
|
84
77
|
|
|
85
78
|
async validateToken(token) {
|
|
86
79
|
const uri = 'api/v3/admin/auth/me';
|
|
87
80
|
const response = await buildPostRequest(this.site, uri, {
|
|
81
|
+
headers: {
|
|
82
|
+
Authorization: `Bearer ${token}`
|
|
83
|
+
},
|
|
88
84
|
body: JSON.stringify({
|
|
89
85
|
_method: 'GET'
|
|
90
|
-
})
|
|
91
|
-
Authorization: `Bearer ${token}`
|
|
92
|
-
}
|
|
86
|
+
})
|
|
93
87
|
});
|
|
94
88
|
return response.message === 'ok';
|
|
95
89
|
}
|
|
96
90
|
|
|
97
91
|
async recovery(token) {
|
|
98
|
-
const uri =
|
|
99
|
-
|
|
92
|
+
const uri = `api/v3/admin/auth/auth-application/recovery/${token}`;
|
|
100
93
|
const response = await buildPostRequest(this.site, uri);
|
|
101
|
-
|
|
102
94
|
if (response.status) {
|
|
103
95
|
return {
|
|
104
96
|
secret: response.data.secret,
|
|
105
97
|
public_key: response.data.public_key
|
|
106
|
-
}
|
|
98
|
+
};
|
|
99
|
+
} else if (response?.throttle) {
|
|
100
|
+
const {limit, retryAfter, resetDate} = response.throttle;
|
|
101
|
+
throw new Error(`Çok fazla deneme yapıldı. Lütfen ${retryAfter} saniye sonra tekrar deneyin. Limit: ${limit}, Reset Zamanı: ${resetDate}`);
|
|
107
102
|
}
|
|
108
|
-
|
|
103
|
+
return null;
|
|
109
104
|
}
|
|
110
105
|
}
|
|
111
106
|
|
|
112
|
-
module.exports = ClientCredentials;
|
|
107
|
+
module.exports = ClientCredentials;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
const handleAuthorization = async (credentialHandler) => {
|
|
2
2
|
await credentialHandler.authorize();
|
|
3
3
|
};
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
const Constants = Object.freeze({
|
|
5
6
|
INITIALIZE: {
|
|
6
7
|
type: 'input',
|
|
7
8
|
name: 'site',
|
|
@@ -13,4 +14,6 @@ module.exports = Object.freeze({
|
|
|
13
14
|
message: 'Parolanızı giriniz (Lütfen panelden onaylayınız):',
|
|
14
15
|
handler: handleAuthorization
|
|
15
16
|
}
|
|
16
|
-
});
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
module.exports = Constants;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
-
const
|
|
4
|
-
const {
|
|
5
|
-
const {buildDownloadZipRequest} = require('./request');
|
|
3
|
+
const Utils = require('./Utils');
|
|
4
|
+
const { buildDownloadZipRequest } = require('./Request');
|
|
6
5
|
|
|
7
6
|
class FileManager {
|
|
8
7
|
constructor(site) {
|
|
@@ -34,12 +33,11 @@ class FileManager {
|
|
|
34
33
|
|
|
35
34
|
isAllowedExtension(file) {
|
|
36
35
|
const ext = path.extname(file).substring(1);
|
|
37
|
-
return
|
|
36
|
+
return Utils.allowedExtensions.includes(ext);
|
|
38
37
|
}
|
|
39
38
|
|
|
40
|
-
async downloadAndSaveZip(saveToDir, zipFilePath, bearerToken) {
|
|
41
|
-
|
|
42
|
-
const response = await buildDownloadZipRequest(this.site, `api/v3/admin/online-store-2/theme/download-theme`, {
|
|
39
|
+
async downloadAndSaveZip(saveToDir, zipFilePath, bearerToken, type = 'none') {
|
|
40
|
+
const response = await buildDownloadZipRequest(this.site, `api/v3/admin/online-store-2/theme/download-theme?type=${type}`, {
|
|
43
41
|
headers: {
|
|
44
42
|
'Content-Type': 'application/zip',
|
|
45
43
|
'Accept': 'application/zip',
|
|
@@ -47,23 +45,8 @@ class FileManager {
|
|
|
47
45
|
}
|
|
48
46
|
});
|
|
49
47
|
|
|
50
|
-
|
|
51
48
|
fs.writeFileSync(zipFilePath, Buffer.from(response));
|
|
52
|
-
|
|
53
49
|
console.log(`Zip dosyası ${zipFilePath} konumuna kaydedildi.`);
|
|
54
|
-
|
|
55
|
-
// Open the directory in file explorer
|
|
56
|
-
const openCommand = process.platform === 'win32' ? 'start' :
|
|
57
|
-
process.platform === 'darwin' ? 'open' :
|
|
58
|
-
'xdg-open';
|
|
59
|
-
exec(`${openCommand} ${saveToDir}`, (err) => {
|
|
60
|
-
if (err) {
|
|
61
|
-
console.error('Dizin açılamadı:', err);
|
|
62
|
-
} else {
|
|
63
|
-
console.log(`Dizin açıldı: ${saveToDir}`);
|
|
64
|
-
console.log('Lütfen zip dosyasını bu dizine çıkartın.');
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
50
|
}
|
|
68
51
|
}
|
|
69
52
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
class Request {
|
|
2
|
+
static async buildPostRequest(site, uri, options = {}) {
|
|
3
|
+
const fetch = (await import('node-fetch')).default;
|
|
4
|
+
try {
|
|
5
|
+
const response = await fetch(`https://${site}/${uri}`, {
|
|
6
|
+
method: 'POST',
|
|
7
|
+
headers: {
|
|
8
|
+
'Content-Type': 'application/json',
|
|
9
|
+
'Accept': 'application/json',
|
|
10
|
+
...options.headers
|
|
11
|
+
},
|
|
12
|
+
body: options.body
|
|
13
|
+
});
|
|
14
|
+
return await response.json();
|
|
15
|
+
} catch (error) {
|
|
16
|
+
console.error(error);
|
|
17
|
+
throw new Error('Request failed');
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static async buildDownloadZipRequest(site, uri, options = {}) {
|
|
22
|
+
const fetch = (await import('node-fetch')).default;
|
|
23
|
+
try {
|
|
24
|
+
const response = await fetch(`https://${site}/${uri}`, {
|
|
25
|
+
method: 'POST',
|
|
26
|
+
headers: {
|
|
27
|
+
'Content-Type': 'application/zip',
|
|
28
|
+
'Accept': 'application/zip',
|
|
29
|
+
...options.headers
|
|
30
|
+
},
|
|
31
|
+
body: options.body
|
|
32
|
+
});
|
|
33
|
+
return await response.arrayBuffer();
|
|
34
|
+
} catch (error) {
|
|
35
|
+
console.error(error);
|
|
36
|
+
throw new Error('Request failed');
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports = Request;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
-
const {slugify} = require('./
|
|
3
|
+
const { slugify } = require('./Utils');
|
|
4
4
|
const http = require('http');
|
|
5
5
|
const https = require('https');
|
|
6
6
|
|
|
@@ -55,8 +55,9 @@ class ThemeManager {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
setTheme(theme) {
|
|
58
|
-
this.theme = slugify(theme)
|
|
58
|
+
this.theme = slugify(theme);
|
|
59
59
|
}
|
|
60
|
+
|
|
60
61
|
isRegistered() {
|
|
61
62
|
return this.registered;
|
|
62
63
|
}
|