tsoft-cli 1.3.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,22 +1,27 @@
1
1
  const figlet = require("figlet");
2
- const packageJson = require('../package.json');
2
+ const packageJson = require('../../package.json');
3
3
  const fs = require("fs");
4
4
  const unzipper = require("unzipper");
5
5
 
6
- module.exports = {
7
- slugify: function (text) {
6
+ class Utils {
7
+ static slugify(text) {
8
8
  return text.toString().toLowerCase()
9
9
  .replace(/\s+/g, '-')
10
10
  .replace(/[^\w\-]+/g, '')
11
11
  .replace(/\-\-+/g, '-')
12
12
  .replace(/^-+/, '')
13
13
  .replace(/-+$/, '');
14
- },
15
- allowedExtensions: ['theme', 'twig', 'css', 'js', 'md', 'json', 'svg', 'jpeg', 'jpg', 'png', 'gif', 'webp'],
16
- clearScreen: function () {
14
+ }
15
+
16
+ static get allowedExtensions() {
17
+ return ['theme', 'twig', 'css', 'js', 'md', 'json', 'svg', 'jpeg', 'jpg', 'png', 'gif', 'webp'];
18
+ }
19
+
20
+ static clearScreen() {
17
21
  process.stdout.write('\x1B[2J\x1B[0f');
18
- },
19
- displayAsciiArt: async function () {
22
+ }
23
+
24
+ static displayAsciiArt() {
20
25
  return new Promise((resolve, reject) => {
21
26
  figlet('T-SOFT CLI', {
22
27
  font: 'Standard',
@@ -33,8 +38,11 @@ module.exports = {
33
38
  }).then(() => {
34
39
  console.log('Versiyon: ' + packageJson.version);
35
40
  });
36
- },
37
- info: function () {
41
+ }
42
+
43
+ static info(tsoft, theme) {
44
+ Utils.clearScreen()
45
+
38
46
  console.log('\n' +
39
47
  '********************************************************\n' +
40
48
  '* *\n' +
@@ -43,17 +51,41 @@ module.exports = {
43
51
  '* Temayı kaydetmek için "s" tuşuna basın, *\n' +
44
52
  '* .theme dosyasını düzenlemek için "e" tuşuna basın, *\n' +
45
53
  '* Tema dizinini açmak için "o" tuşuna basın. *\n' +
54
+ '* URL\'yi tarayıcıda açmak için "p" tuşuna basın. *\n' +
46
55
  '* *\n' +
47
56
  '********************************************************\n'
48
57
  );
49
- },
50
- unzipFile: function (zipFilePath, extractToDir) {
58
+ const {clientId, clientSecret} = tsoft.themeManager.getEnvironment(theme);
59
+
60
+ const url = 'https://' + tsoft.site + '?tsoft-cli=' + clientId + '&tsoft-cli-secret=' + clientSecret;
61
+ console.log('İzlenen tema: ' + theme);
62
+ console.log('Önizleme: \n')
63
+ console.log(url+ '\n');
64
+
65
+ process.stdin.setRawMode(true);
66
+ process.stdin.resume();
67
+ process.stdin.on('data', async (key) => {
68
+ if (key.toString() === 'p') {
69
+ console.log('URL tarayıcıda açılıyor...');
70
+ const open = (await import('open')).default;
71
+ await open(url);
72
+ } else if (key.toString() === 'q') {
73
+ console.log('Programdan çıkılıyor. Hoşça kalın!');
74
+ process.exit(0);
75
+ }
76
+ // Other keypress handlers can go here
77
+ });
78
+
79
+ }
80
+
81
+ static unzipFile(zipFilePath, extractToDir) {
51
82
  return new Promise((resolve, reject) => {
52
83
  fs.createReadStream(zipFilePath)
53
- .pipe(unzipper.Extract({path: extractToDir}))
84
+ .pipe(unzipper.Extract({ path: extractToDir }))
54
85
  .on('close', resolve)
55
86
  .on('error', reject);
56
87
  });
57
88
  }
89
+ }
58
90
 
59
- }
91
+ module.exports = Utils;
@@ -1,127 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const {Select, Input} = require('enquirer');
4
- const {slugify, clearScreen} = require('../utils');
5
- const {start} = require('./start');
6
- const ThemeManager = require('../theme-manager');
7
-
8
- async function getSites() {
9
- const cwd = process.cwd();
10
- return fs.readdirSync(cwd).filter(file => {
11
- return file.charAt(0) !== '.' && !['node_modules', 'build', 'dist'].includes(file);
12
- }).filter(file => fs.statSync(path.join(cwd, file)).isDirectory());
13
- }
14
-
15
- async function selectSite(sites) {
16
- const siteChoices = [...sites, 'Yeni bir site oluştur'];
17
-
18
- const sitePrompt = new Select({
19
- name: 'site',
20
- message: 'Çalışmak istediğiniz sitenin adı:',
21
- choices: siteChoices
22
- });
23
-
24
- const selectedSite = await sitePrompt.run();
25
-
26
- if (selectedSite === 'Yeni bir site oluştur') {
27
- return await createNewSite();
28
- } else {
29
- return selectedSite;
30
- }
31
- }
32
-
33
- async function createNewSite() {
34
- const newSitePrompt = new Input({
35
- name: 'newSite',
36
- message: 'Yeni site adı:'
37
- });
38
- const siteName = await newSitePrompt.run();
39
-
40
- const themeManager = new ThemeManager(siteName);
41
- const isValid = await validateSiteName(themeManager, siteName);
42
- if (!isValid) return null;
43
-
44
- return siteName;
45
- }
46
-
47
- async function validateSiteName(themeManager, siteName) {
48
- try {
49
- const isValid = await themeManager.checkSiteValidity(siteName);
50
- if (!isValid) {
51
- console.error('Geçersiz site adı. Lütfen geçerli bir site adı girin.');
52
- return false;
53
- }
54
- return true;
55
- } catch (error) {
56
- console.error('Site doğrulaması sırasında hata oluştu:', error.message);
57
- return false;
58
- }
59
- }
60
-
61
- async function getThemeDetails() {
62
- const themeNamePrompt = new Input({
63
- name: 'themeName',
64
- message: 'Tema adı:'
65
- });
66
-
67
- const authorPrompt = new Input({
68
- name: 'author',
69
- message: 'Author (isteğe bağlı):'
70
- });
71
-
72
- const versionPrompt = new Input({
73
- name: 'version',
74
- message: 'Version (isteğe bağlı, varsayılan 1.0.0):',
75
- initial: '1.0.0'
76
- });
77
-
78
- const themeName = await themeNamePrompt.run();
79
- const author = await authorPrompt.run();
80
- const version = await versionPrompt.run();
81
-
82
- return {themeName, author, version};
83
- }
84
-
85
- async function createThemeDirectory(siteName, themeNameSlug) {
86
- const cwd = process.cwd();
87
- const themePath = path.join(cwd, siteName, themeNameSlug);
88
-
89
- if (!fs.existsSync(themePath)) {
90
- fs.mkdirSync(themePath, {recursive: true});
91
- }
92
-
93
- return themePath;
94
- }
95
-
96
- async function saveThemeData(themePath, themeData) {
97
- fs.writeFileSync(path.join(themePath, '.theme'), JSON.stringify(themeData, null, 2));
98
- }
99
-
100
- async function createTheme() {
101
- const sites = await getSites();
102
- const siteName = await selectSite(sites);
103
-
104
- if (!siteName) return;
105
-
106
- const {themeName, author, version} = await getThemeDetails();
107
- const themeNameSlug = slugify(themeName);
108
- const themePath = await createThemeDirectory(siteName, themeNameSlug);
109
-
110
- const themeData = {
111
- site: siteName,
112
- name: themeName,
113
- author: author,
114
- version: version
115
- };
116
-
117
- await saveThemeData(themePath, themeData);
118
-
119
- clearScreen();
120
- console.log(`Tema "${themeName}" başarıyla oluşturuldu.`);
121
-
122
- await start(siteName, themeNameSlug, true);
123
- }
124
-
125
- module.exports = {
126
- createTheme, createThemeDirectory, selectSite
127
- };
@@ -1,280 +0,0 @@
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('../constants');
8
- const cliProgress = require('cli-progress');
9
- const { Input } = require('enquirer');
10
- const { displayAsciiArt, clearScreen, info, unzipFile } = require('../utils');
11
-
12
- async function showProgress(tsoft, theme) {
13
- const themePath = path.join(process.cwd(), tsoft.site, theme);
14
- const fileList = tsoft.fileManager.listFilesRecursive(themePath).filter(file => !file.includes('.env'));
15
- const totalFiles = fileList.length;
16
-
17
- const progressBar = new cliProgress.SingleBar({
18
- format: 'İlerleme |{bar}| {percentage}% || {value}/{total} Dosya Yüklendi',
19
- barCompleteChar: '\u2588',
20
- barIncompleteChar: '\u2591',
21
- hideCursor: true,
22
- clearOnComplete: true
23
- });
24
- progressBar.start(totalFiles, 0);
25
-
26
- for (let i = 0; i < totalFiles; i++) {
27
- const file = fileList[i];
28
- const fileName = tsoft.fileManager.getRelativePath(theme, file);
29
- const content = tsoft.fileManager.readFile(file);
30
- const env = tsoft.themeManager.getEnvironment(theme);
31
-
32
- try {
33
- await tsoft.saveFile(theme, fileName, content, env.bearer);
34
- } catch (error) {
35
- console.error(`Dosya yükleme hatası ${fileName}:`, error);
36
- }
37
- progressBar.update(i + 1);
38
- }
39
-
40
- progressBar.stop();
41
-
42
- return 'Tüm dosyalar ilerleme ile başarıyla yüklendi';
43
- }
44
-
45
- async function initializeAndAuthorize(tsoft, themeName) {
46
- await tsoft.initialize(themeName);
47
-
48
- const approvalPrompt = new Input({
49
- name: 'approval',
50
- message: 'Lütfen onay kodunu sağlayın:'
51
- });
52
-
53
- const approval = await approvalPrompt.run();
54
-
55
- if (approval) {
56
- await constants.APPROVAL.handler(tsoft.clientCredentials.setClientSecret(approval));
57
- tsoft.buildEnvironment();
58
- console.info('Ortam dosyası başarıyla oluşturuldu.');
59
- return true;
60
- } else {
61
- console.error('Onay kodu gerekli.');
62
- return false;
63
- }
64
- }
65
-
66
- async function handleExistingEnvironment(tsoft, themeName, themeEnvPath) {
67
- let envData = {};
68
- if (fs.existsSync(themeEnvPath)) {
69
- try {
70
- envData = JSON.parse(fs.readFileSync(themeEnvPath, 'utf-8'));
71
- } catch (error) {
72
- console.warn(`${themeEnvPath} dosyasında geçersiz JSON formatı. Bu dosya silinecek ve yeniden yetkilendirmeniz gerekecek.`);
73
- fs.unlinkSync(themeEnvPath);
74
- console.info('Geçersiz ortam dosyası silindi. Başlatma işlemine devam ediliyor...');
75
- }
76
-
77
- if (envData.bearer) {
78
- const bearerTokenValid = await tsoft.isTokenValid(themeName);
79
-
80
- if (bearerTokenValid) {
81
- console.info('Geçerli bir taşıyıcı jetonuna sahip mevcut ortam dosyası bulundu. Mevcut yapılandırma ile devam ediliyor...');
82
- return true;
83
- } else {
84
- console.warn('Mevcut taşıyıcı jetonu geçersiz. Yeniden yetkilendirmeniz gerekecek.');
85
- fs.unlinkSync(themeEnvPath);
86
- }
87
- }
88
- }
89
- return false;
90
- }
91
-
92
- async function startWatching(themePath, tsoft, theme) {
93
- const watcher = chokidar.watch(themePath, {
94
- ignored: /(^|[\/\\])(\.theme|(.*?)\.env)$/, // .theme ve .env dosyaları yoksayılır
95
- persistent: true
96
- });
97
-
98
- watcher.on('change', async (filePath) => {
99
- console.log(`Dosya değiştirildi ${filePath}`);
100
- await handleFileChange(filePath, tsoft, theme);
101
- }).on('unlink', async (filePath) => {
102
- console.log(`Dosya silindi ${filePath}`);
103
- await handleFileDeletion(filePath, tsoft, theme);
104
- }).on('unlinkDir', async (dirPath) => {
105
- console.log(`Dizin silindi ${dirPath}`);
106
- await handleDirectoryDeletion(dirPath, tsoft, theme);
107
- });
108
-
109
- console.log(`${themePath} dizinindeki dosya değişiklikleri izleniyor`);
110
-
111
- const rl = readline.createInterface({
112
- input: process.stdin,
113
- output: process.stdout
114
- });
115
-
116
- info();
117
-
118
- rl.on('line', async (input) => {
119
- await handleUserInput(input, tsoft, theme, watcher, rl);
120
- });
121
- }
122
-
123
- async function handleFileChange(filePath, tsoft, theme) {
124
- const env = JSON.parse(fs.readFileSync(path.join(process.cwd(), tsoft.site, theme, `${theme}.env`), 'utf-8'));
125
- const fileName = filePath.replace(`${path.join(process.cwd(), tsoft.site, theme)}/`, '');
126
- const content = fs.readFileSync(filePath).toString();
127
-
128
- try {
129
- await tsoft.saveFile(theme, fileName, content, env.bearer);
130
- console.log(`Dosya başarıyla yüklendi ${fileName}`);
131
- } catch (error) {
132
- console.error(`Dosya yükleme hatası ${fileName}:`, error);
133
- }
134
- }
135
-
136
- async function handleFileDeletion(filePath, tsoft, theme) {
137
- const env = JSON.parse(fs.readFileSync(path.join(process.cwd(), tsoft.site, theme, `${theme}.env`), 'utf-8'));
138
- const fileName = filePath.replace(`${path.join(process.cwd(), tsoft.site, theme)}/`, '');
139
-
140
- try {
141
- await tsoft.deleteFile(theme, fileName, env.bearer);
142
- console.log(`Dosya başarıyla silindi ${fileName}`);
143
- } catch (error) {
144
- console.error(`Dosya silme hatası ${fileName}:`, error);
145
- }
146
- }
147
-
148
- async function handleDirectoryDeletion(dirPath, tsoft, theme) {
149
- const env = JSON.parse(fs.readFileSync(path.join(process.cwd(), tsoft.site, theme, `${theme}.env`), 'utf-8'));
150
- const dirName = dirPath.replace(`${path.join(process.cwd(), tsoft.site, theme)}/`, '');
151
-
152
- try {
153
- await tsoft.deleteDirectory(theme, dirName, env.bearer);
154
- console.log(`Dizin başarıyla silindi ${dirName}`);
155
- } catch (error) {
156
- console.error(`Dizin silme hatası ${dirName}:`, error);
157
- }
158
- }
159
-
160
- async function handleUserInput(input, tsoft, theme, watcher, rl) {
161
- switch (input.trim()) {
162
- case 'q':
163
- console.log('Dosya izleme işlemi sonlandırılıyor...');
164
- watcher.close();
165
- rl.close();
166
- process.exit(0);
167
- break;
168
- case 'u':
169
- console.log('Tema güncelleniyor...');
170
- try {
171
- const result = await updateTheme(tsoft, theme);
172
- console.log(result);
173
- info();
174
- } catch (error) {
175
- console.error(`Tema güncelleme hatası:`, error);
176
- }
177
- break;
178
- case 's':
179
- clearScreen();
180
- console.log('Tüm dosyalar ilerleme ile yüklenmeye başlanıyor...');
181
- try {
182
- const result = await showProgress(tsoft, theme);
183
- console.log(result);
184
- info();
185
- } catch (error) {
186
- console.error(`İlerleme gösterim hatası:`, error);
187
- }
188
- break;
189
- case 'e':
190
- console.log('.theme dosyası düzenleniyor...');
191
- try {
192
- await editThemeFile(tsoft.themeManager, theme);
193
- } catch (error) {
194
- console.error(`.theme dosyası düzenleme hatası:`, error);
195
- }
196
- break;
197
- case 'o':
198
- console.log('Tema dizini açılıyor...');
199
- const openCommand = process.platform === 'win32' ? 'start' :
200
- process.platform === 'darwin' ? 'open' :
201
- 'xdg-open';
202
- exec(`${openCommand} ${path.join(process.cwd(), tsoft.site, theme)}`, (err) => {
203
- if (err) {
204
- console.error('Tema dizini açılamadı:', err);
205
- } else {
206
- console.log('Tema dizini başarıyla açıldı.');
207
- }
208
- });
209
- break;
210
- }
211
- }
212
-
213
- async function start(siteName, themeName, recentlyCreated = false) {
214
- await displayAsciiArt();
215
- console.log('Geliştirme ortamı aşağıdaki ayrıntılarla başlatılıyor:');
216
- console.log(`Site Adı: ${siteName}`);
217
- console.log(`Tema Adı: ${themeName}`);
218
-
219
- const tsoft = new Tsoft(siteName);
220
- const themeEnvPath = path.join(process.cwd(), siteName, themeName, `${themeName}.env`);
221
-
222
- const existingEnvValid = await handleExistingEnvironment(tsoft, themeName, themeEnvPath);
223
- if (existingEnvValid) {
224
- await startWatching(path.join(process.cwd(), siteName, themeName), tsoft, themeName);
225
- return;
226
- }
227
-
228
- const initializedAndAuthorized = await initializeAndAuthorize(tsoft, themeName);
229
- if (initializedAndAuthorized) {
230
- if(recentlyCreated) {
231
- const defaultZipFile = path.join(process.cwd(), siteName, themeName, 'theme.zip');
232
- console.log('Default tema dosyaları indirme işlemi başlatılıyor, lütfen bekleyin');
233
- const themePath = path.join(process.cwd(), siteName, themeName)
234
- await tsoft.fileManager.downloadAndSaveZip(
235
- themePath, defaultZipFile,
236
- tsoft.clientCredentials.bearer,
237
- 'default'
238
- );
239
- console.log('Default tema dosyaları indirildi. Çıkarma işlemi başlatılıyor');
240
- await unzipFile(defaultZipFile, themePath);
241
- console.log('Çıkarma işlemi tamamlandı.');
242
- fs.unlinkSync(defaultZipFile);
243
- }
244
-
245
- await startWatching(path.join(process.cwd(), siteName, themeName), tsoft, themeName);
246
- }
247
- }
248
-
249
- async function updateTheme(tsoft, theme) {
250
- const directoryName = path.basename(path.join(process.cwd(), tsoft.site, theme));
251
- const response = await tsoft.updateTheme(directoryName);
252
- if (response.status === true) {
253
- return 'Successfully updated';
254
- } else {
255
- throw new Error('Update failed');
256
- }
257
- }
258
- async function editThemeFile(themeManager, directoryName) {
259
- const themePath = path.join(process.cwd(), themeManager.site, directoryName, '.theme');
260
-
261
- if (!fs.existsSync(themePath)) {
262
- console.error('.theme file not found.');
263
- return;
264
- }
265
-
266
- console.log(`Opening .theme file: ${themePath}`);
267
- const openCommand = process.platform === 'win32' ? 'start' :
268
- process.platform === 'darwin' ? 'open' :
269
- 'xdg-open';
270
-
271
- exec(`${openCommand} ${themePath}`, (err) => {
272
- if (err) {
273
- console.error('Failed to open .theme file:', err);
274
- } else {
275
- console.log('.theme file opened successfully.');
276
- }
277
- });
278
- }
279
-
280
- module.exports = { start };
@@ -1,73 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const {Input} = require('enquirer');
4
- const {clearScreen} = require('../utils');
5
- const {selectSite, createThemeDirectory} = require('./create');
6
- const Tsoft = require("../tsoft");
7
- const {slugify, unzipFile} = require('../utils');
8
-
9
-
10
-
11
-
12
- async function syncTheme() {
13
- const cwd = process.cwd();
14
- const sites = fs.readdirSync(cwd).filter(file => {
15
- return file.charAt(0) !== '.' && !['node_modules', 'build', 'dist'].includes(file);
16
- }).filter(file => fs.statSync(path.join(cwd, file)).isDirectory());
17
-
18
- const selectedSite = await selectSite(sites);
19
-
20
- const tsoft = new Tsoft(selectedSite);
21
-
22
- const codePrompt = new Input({
23
- name: 'code',
24
- message: 'Lütfen kurtarma anahtarını girin:'
25
- });
26
-
27
- const recoveryCode = await codePrompt.run();
28
-
29
-
30
- const {secret, public_key} = await tsoft.startRecovery(recoveryCode);
31
-
32
- tsoft.clientCredentials.setClientSecret(secret).setClientId(public_key)
33
- const authorizeResponse = await tsoft.clientCredentials.authorize(true)
34
- const themeInformation = authorizeResponse.data.tokenable;
35
-
36
- const themeName = themeInformation.name;
37
- const themeNameSlug = slugify(themeName);
38
- const themePath = await createThemeDirectory(selectedSite, themeNameSlug);
39
-
40
- const themeData = {
41
- site: selectedSite,
42
- name: themeName,
43
- author: themeInformation.author,
44
- version: themeInformation.version
45
- };
46
-
47
- fs.writeFileSync(path.join(themePath, '.theme'), JSON.stringify(themeData, null, 2));
48
- tsoft.themeManager.setTheme(themeNameSlug)
49
-
50
-
51
- if (!fs.existsSync(themePath)) {
52
- fs.mkdirSync(themePath, {recursive: true});
53
- }
54
-
55
- clearScreen();
56
-
57
- const zipFilePath = path.join(themePath, 'theme.zip');
58
-
59
- console.log('Zip dosyası indiriliyor...');
60
- await tsoft.fileManager.downloadAndSaveZip(themePath, zipFilePath, tsoft.clientCredentials.bearer);
61
- console.log('İndirme tamamlandı.');
62
-
63
- console.log('Dosyalar çıkarılıyor...');
64
- await unzipFile(zipFilePath, themePath);
65
- console.log('Çıkarma işlemi tamamlandı.');
66
- fs.unlinkSync(zipFilePath);
67
-
68
- tsoft.buildEnvironment();
69
- }
70
-
71
- module.exports = {
72
- syncTheme
73
- };
package/src/request.js DELETED
@@ -1,37 +0,0 @@
1
- buildPostRequest = (site, uri, options = {}) => {
2
- return fetch("https://" + site + '/' + uri, {
3
- method: 'POST',
4
- headers: {
5
- 'Content-Type': 'application/json',
6
- 'Accept': 'application/json',
7
- ...options.headers ?? {}
8
- },
9
- body: options.body
10
- })
11
- .then((response) => response.json())
12
- .then((result) => {
13
- return result
14
- })
15
- .catch((error) => console.error(error));
16
- }
17
- buildDownloadZipRequest = (site, uri, options = {}) => {
18
- return fetch("https://" + site + '/' + uri, {
19
- method: 'POST',
20
- headers: {
21
- 'Content-Type': 'application/zip',
22
- 'Accept': 'application/zip',
23
- ...options.headers ?? {}
24
- },
25
- body: options.body
26
- })
27
- .then((response) => response.arrayBuffer())
28
- .then((result) => {
29
- return result
30
- })
31
- .catch((error) => console.error(error));
32
- }
33
-
34
- module.exports = {
35
- buildPostRequest,
36
- buildDownloadZipRequest
37
- }