tsoft-cli 1.1.1 → 1.2.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 +15 -0
- package/README.md +10 -0
- package/bin/index.js +64 -18
- package/jest.config.js +3 -0
- package/package.json +7 -3
- package/src/client-credentials.js +13 -12
- package/src/commands/create.js +51 -19
- package/src/commands/start.js +84 -145
- package/src/file-manager.js +7 -1
- package/src/theme-manager.js +42 -7
- package/src/tsoft.js +41 -13
- package/src/utils.js +45 -0
- package/tests/FileManager.test.js +90 -0
- package/src/commands/save.js +0 -17
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [1.2.0] - 2024-06-12
|
|
4
|
+
### Added
|
|
5
|
+
- Yeni site ismi girildiğinde geçerli olup olmadığını kontrol eden özellik eklendi.
|
|
6
|
+
- Kullanıcı komut satırı etkileşimleri için `enquirer` kütüphanesi kullanımı güncellendi.
|
|
7
|
+
- Dosya izleme ve tema güncelleme özellikleri geliştirildi.
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
- `ThemeManager` sınıfı geliştirildi ve yeni yöntemler eklendi.
|
|
11
|
+
- `start.js` dosyasında önemli iyileştirmeler yapıldı.
|
|
12
|
+
- `create.js` dosyasında kullanıcı girişleri doğrulandı ve daha kullanıcı dostu hale getirildi.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
- Birkaç hata düzeltildi ve genel kod kalitesi iyileştirildi.
|
package/README.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# T-Soft CLI
|
|
2
|
+
|
|
3
|
+
## Özet
|
|
4
|
+
T-Soft CLI, T-Soft tarafından geliştirilen bir komut satırı aracıdır. Bu araç ile T-Soft ön yüz geliştirme süreçlerinde kullanılan bazı işlemler otomatize edilmiştir. Bu sayede geliştirme süreçleri hızlandırılmış ve daha verimli hale getirilmiştir.
|
|
5
|
+
|
|
6
|
+
## Kurulum
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g tsoft-cli
|
|
9
|
+
```
|
|
10
|
+
|
package/bin/index.js
CHANGED
|
@@ -1,29 +1,75 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
const {
|
|
3
|
+
const { Select, Input } = require('enquirer');
|
|
4
4
|
const { start } = require('../src/commands/start');
|
|
5
|
-
const { save } = require('../src/commands/save');
|
|
6
5
|
const { createTheme } = require('../src/commands/create');
|
|
6
|
+
const { clearScreen, displayAsciiArt } = require('../src/utils');
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
async function selectSiteAndTheme() {
|
|
11
|
+
const cwd = process.cwd();
|
|
12
|
+
const sites = fs.readdirSync(cwd).filter(file => {
|
|
13
|
+
return file.charAt(0) !== '.' && !['node_modules', 'build', 'dist'].includes(file);
|
|
14
|
+
}).filter(file => fs.statSync(path.join(cwd, file)).isDirectory());
|
|
15
|
+
|
|
16
|
+
if (sites.length === 0) {
|
|
17
|
+
console.error('Mevcut dizinde site bulunamadı.');
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const sitePrompt = new Select({
|
|
22
|
+
name: 'site',
|
|
23
|
+
message: 'Bir site seçin:',
|
|
24
|
+
choices: sites
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const selectedSite = await sitePrompt.run();
|
|
28
|
+
|
|
29
|
+
const themes = fs.readdirSync(path.join(cwd, selectedSite)).filter(file => {
|
|
30
|
+
return fs.statSync(path.join(cwd, selectedSite, file)).isDirectory();
|
|
13
31
|
});
|
|
14
32
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
33
|
+
if (themes.length === 0) {
|
|
34
|
+
console.error('Seçilen site dizininde tema bulunamadı.');
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const themePrompt = new Select({
|
|
39
|
+
name: 'theme',
|
|
40
|
+
message: 'Bir tema seçin:',
|
|
41
|
+
choices: themes
|
|
20
42
|
});
|
|
21
43
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
44
|
+
const selectedTheme = await themePrompt.run();
|
|
45
|
+
|
|
46
|
+
return { siteName: selectedSite, themeName: selectedTheme };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function showMainMenu() {
|
|
50
|
+
clearScreen();
|
|
51
|
+
|
|
52
|
+
await displayAsciiArt();
|
|
53
|
+
|
|
54
|
+
const prompt = new Select({
|
|
55
|
+
name: 'command',
|
|
56
|
+
message: 'Bir komut seçin',
|
|
57
|
+
choices: ['Yeni bir tema oluştur', 'Geliştirme ortamını başlat', 'Çıkış']
|
|
27
58
|
});
|
|
28
59
|
|
|
29
|
-
|
|
60
|
+
const answer = await prompt.run();
|
|
61
|
+
|
|
62
|
+
if (answer === 'Yeni bir tema oluştur') {
|
|
63
|
+
await createTheme();
|
|
64
|
+
} else if (answer === 'Geliştirme ortamını başlat') {
|
|
65
|
+
const selection = await selectSiteAndTheme();
|
|
66
|
+
if (selection) {
|
|
67
|
+
await start(selection.siteName, selection.themeName);
|
|
68
|
+
}
|
|
69
|
+
} else {
|
|
70
|
+
console.log('Programdan çıkılıyor. Hoşça kalın!');
|
|
71
|
+
process.exit(0);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
showMainMenu();
|
package/jest.config.js
ADDED
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tsoft-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "A theme development cli for developers who want to create themes for T-Soft.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"test": "
|
|
7
|
+
"test": "jest"
|
|
8
8
|
},
|
|
9
9
|
"keywords": [],
|
|
10
10
|
"author": "",
|
|
@@ -20,5 +20,9 @@
|
|
|
20
20
|
"figlet": "^1.7.0",
|
|
21
21
|
"fs": "^0.0.1-security"
|
|
22
22
|
},
|
|
23
|
-
"type": "commonjs"
|
|
23
|
+
"type": "commonjs",
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"jest": "^29.7.0",
|
|
26
|
+
"mock-fs": "^5.2.0"
|
|
27
|
+
}
|
|
24
28
|
}
|
|
@@ -12,10 +12,7 @@ class ClientCredentials {
|
|
|
12
12
|
|
|
13
13
|
getEnvironment() {
|
|
14
14
|
return {
|
|
15
|
-
site: this.site,
|
|
16
|
-
clientId: this.clientId,
|
|
17
|
-
clientSecret: this.clientSecret,
|
|
18
|
-
bearer: this.bearer
|
|
15
|
+
site: this.site, clientId: this.clientId, clientSecret: this.clientSecret, bearer: this.bearer
|
|
19
16
|
}
|
|
20
17
|
}
|
|
21
18
|
|
|
@@ -32,12 +29,18 @@ class ClientCredentials {
|
|
|
32
29
|
return this;
|
|
33
30
|
}
|
|
34
31
|
|
|
35
|
-
async register(CLIENT_UUID) {
|
|
32
|
+
async register(CLIENT_UUID, clientConfiguration = {}) {
|
|
36
33
|
|
|
37
34
|
const uri = "api/v3/admin/auth/auth-application";
|
|
38
35
|
const result = await this.buildPostRequest(uri, {
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
header: {
|
|
37
|
+
'Content-Type': 'application/json', 'Accept': 'application/json',
|
|
38
|
+
}, body: JSON.stringify({
|
|
39
|
+
uuid: CLIENT_UUID, configuration: {
|
|
40
|
+
theme: clientConfiguration.theme,
|
|
41
|
+
author: clientConfiguration.author,
|
|
42
|
+
version: clientConfiguration.version
|
|
43
|
+
}
|
|
41
44
|
})
|
|
42
45
|
});
|
|
43
46
|
|
|
@@ -54,8 +57,7 @@ class ClientCredentials {
|
|
|
54
57
|
const uri = "api/v3/admin/auth/auth-application/authorize";
|
|
55
58
|
await this.buildPostRequest(uri, {
|
|
56
59
|
body: JSON.stringify({
|
|
57
|
-
public_key: this.clientId,
|
|
58
|
-
secret: this.clientSecret
|
|
60
|
+
public_key: this.clientId, secret: this.clientSecret
|
|
59
61
|
})
|
|
60
62
|
}).then((result) => {
|
|
61
63
|
if (result.status === true) {
|
|
@@ -75,12 +77,11 @@ class ClientCredentials {
|
|
|
75
77
|
const response = await buildPostRequest(this.site, uri, {
|
|
76
78
|
body: JSON.stringify({
|
|
77
79
|
_method: 'GET'
|
|
78
|
-
}),
|
|
79
|
-
headers: {
|
|
80
|
+
}), headers: {
|
|
80
81
|
Authorization: `Bearer ${token}`
|
|
81
82
|
}
|
|
82
83
|
});
|
|
83
|
-
return response.message === 'ok';
|
|
84
|
+
return response.message === 'ok';
|
|
84
85
|
}
|
|
85
86
|
}
|
|
86
87
|
|
package/src/commands/create.js
CHANGED
|
@@ -1,24 +1,55 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
-
const { Input } = require('enquirer');
|
|
3
|
+
const { Select, Input } = require('enquirer');
|
|
4
|
+
const {slugify} = require('../utils');
|
|
5
|
+
const { start } = require('./start');
|
|
6
|
+
const ThemeManager = require('../theme-manager');
|
|
4
7
|
|
|
5
8
|
async function createTheme() {
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
const cwd = process.cwd();
|
|
10
|
+
const sites = 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
|
+
const siteChoices = [...sites, 'Yeni bir site oluştur'];
|
|
15
|
+
|
|
16
|
+
const sitePrompt = new Select({
|
|
17
|
+
name: 'site',
|
|
18
|
+
message: 'Çalışmak istediğiniz sitenin adı:',
|
|
19
|
+
choices: siteChoices
|
|
9
20
|
});
|
|
10
21
|
|
|
22
|
+
const selectedSite = await sitePrompt.run();
|
|
23
|
+
|
|
24
|
+
let siteName;
|
|
25
|
+
if (selectedSite === 'Yeni bir site oluştur') {
|
|
26
|
+
const newSitePrompt = new Input({
|
|
27
|
+
name: 'newSite',
|
|
28
|
+
message: 'Yeni site adı:'
|
|
29
|
+
});
|
|
30
|
+
siteName = await newSitePrompt.run();
|
|
31
|
+
|
|
32
|
+
const themeManager = new ThemeManager(siteName);
|
|
33
|
+
try {
|
|
34
|
+
const isValid = await themeManager.checkSiteValidity(siteName);
|
|
35
|
+
if (!isValid) {
|
|
36
|
+
console.error('Geçersiz site adı. Lütfen geçerli bir site adı girin.');
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
} catch (error) {
|
|
40
|
+
console.error('Site doğrulaması sırasında hata oluştu:', error.message);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
} else {
|
|
45
|
+
siteName = selectedSite;
|
|
46
|
+
}
|
|
47
|
+
|
|
11
48
|
const themeNamePrompt = new Input({
|
|
12
49
|
name: 'themeName',
|
|
13
50
|
message: 'Tema adı:'
|
|
14
51
|
});
|
|
15
52
|
|
|
16
|
-
const directoryNamePrompt = new Input({
|
|
17
|
-
name: 'directoryName',
|
|
18
|
-
message: 'Tema dizin ismi (a-z yalnızca İngilizce karakterler):',
|
|
19
|
-
validate: input => /^[a-z]+$/.test(input) ? true : 'Yalnızca küçük İngilizce harfler kullanabilirsiniz.'
|
|
20
|
-
});
|
|
21
|
-
|
|
22
53
|
const authorPrompt = new Input({
|
|
23
54
|
name: 'author',
|
|
24
55
|
message: 'Author (isteğe bağlı):'
|
|
@@ -30,30 +61,31 @@ async function createTheme() {
|
|
|
30
61
|
initial: '1.0.0'
|
|
31
62
|
});
|
|
32
63
|
|
|
33
|
-
const siteName = await sitePrompt.run();
|
|
34
64
|
const themeName = await themeNamePrompt.run();
|
|
35
|
-
const directoryName = await directoryNamePrompt.run();
|
|
36
65
|
const author = await authorPrompt.run();
|
|
37
66
|
const version = await versionPrompt.run();
|
|
38
67
|
|
|
39
|
-
const
|
|
40
|
-
|
|
68
|
+
const themeNameSlug = slugify(themeName);
|
|
69
|
+
|
|
70
|
+
const themePath = path.join(cwd, siteName, themeNameSlug);
|
|
41
71
|
|
|
42
72
|
if (!fs.existsSync(themePath)) {
|
|
43
73
|
fs.mkdirSync(themePath, { recursive: true });
|
|
44
74
|
}
|
|
45
75
|
|
|
46
76
|
const themeData = {
|
|
47
|
-
siteName,
|
|
48
|
-
themeName,
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
version
|
|
77
|
+
site: siteName,
|
|
78
|
+
theme: themeName,
|
|
79
|
+
author: author,
|
|
80
|
+
version: version
|
|
52
81
|
};
|
|
53
82
|
|
|
54
83
|
fs.writeFileSync(path.join(themePath, '.theme'), JSON.stringify(themeData, null, 2));
|
|
55
84
|
|
|
56
85
|
console.log(`Tema "${themeName}" başarıyla oluşturuldu.`);
|
|
86
|
+
|
|
87
|
+
// Doğrudan start fonksiyonuna geçiş yap
|
|
88
|
+
await start(siteName, themeNameSlug);
|
|
57
89
|
}
|
|
58
90
|
|
|
59
91
|
module.exports = {
|
package/src/commands/start.js
CHANGED
|
@@ -1,43 +1,26 @@
|
|
|
1
|
-
const Tsoft = require('../tsoft');
|
|
2
|
-
const constants = require('../constants');
|
|
3
1
|
const fs = require('fs');
|
|
4
2
|
const path = require('path');
|
|
5
|
-
const {Input, Select, Confirm, prompt} = require('enquirer');
|
|
6
3
|
const chokidar = require('chokidar');
|
|
7
|
-
const figlet = require('figlet');
|
|
8
4
|
const readline = require('readline');
|
|
5
|
+
const { exec } = require('child_process');
|
|
6
|
+
const Tsoft = require('../tsoft');
|
|
7
|
+
const constants = require('../constants');
|
|
9
8
|
const cliProgress = require('cli-progress');
|
|
10
|
-
const {
|
|
11
|
-
|
|
12
|
-
async function displayAsciiArt() {
|
|
13
|
-
return new Promise((resolve, reject) => {
|
|
14
|
-
figlet('T-SOFT', {
|
|
15
|
-
font: 'Standard',
|
|
16
|
-
}, (err, data) => {
|
|
17
|
-
if (err) {
|
|
18
|
-
console.log('Something went wrong...');
|
|
19
|
-
console.dir(err);
|
|
20
|
-
reject(err);
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
console.log(data);
|
|
24
|
-
resolve();
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
}
|
|
9
|
+
const { Input } = require('enquirer');
|
|
10
|
+
const { displayAsciiArt, clearScreen, info, slugify } = require('../utils');
|
|
28
11
|
|
|
29
12
|
async function showProgress(tsoft, theme) {
|
|
30
13
|
const themePath = path.join(process.cwd(), tsoft.site, theme);
|
|
31
14
|
const fileList = tsoft.fileManager.listFilesRecursive(themePath).filter(file => !file.includes('.env'));
|
|
32
15
|
const totalFiles = fileList.length;
|
|
33
16
|
|
|
34
|
-
//
|
|
17
|
+
// Yeni bir ilerleme çubuğu oluşturun ve shades_classic temasını kullanın
|
|
35
18
|
const progressBar = new cliProgress.SingleBar({
|
|
36
|
-
format: '
|
|
19
|
+
format: 'İlerleme |{bar}| {percentage}% || {value}/{total} Dosya Yüklendi',
|
|
37
20
|
barCompleteChar: '\u2588',
|
|
38
21
|
barIncompleteChar: '\u2591',
|
|
39
22
|
hideCursor: true,
|
|
40
|
-
clearOnComplete:
|
|
23
|
+
clearOnComplete: true
|
|
41
24
|
});
|
|
42
25
|
progressBar.start(totalFiles, 0);
|
|
43
26
|
|
|
@@ -47,149 +30,71 @@ async function showProgress(tsoft, theme) {
|
|
|
47
30
|
const content = tsoft.fileManager.readFile(file);
|
|
48
31
|
const env = tsoft.themeManager.getEnvironment(theme);
|
|
49
32
|
|
|
50
|
-
|
|
51
33
|
try {
|
|
52
34
|
await tsoft.saveFile(theme, fileName, content, env.bearer);
|
|
53
35
|
} catch (error) {
|
|
54
|
-
console.error(`
|
|
36
|
+
console.error(`Dosya yükleme hatası ${fileName}:`, error);
|
|
55
37
|
}
|
|
56
38
|
progressBar.update(i + 1);
|
|
57
39
|
}
|
|
58
40
|
|
|
59
41
|
progressBar.stop();
|
|
60
42
|
|
|
61
|
-
return '
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
async function updateTheme(tsoft, theme) {
|
|
65
|
-
const directoryName = path.basename(path.join(process.cwd(), tsoft.site, theme));
|
|
66
|
-
const response = await tsoft.updateTheme(directoryName);
|
|
67
|
-
if (response.status === true) {
|
|
68
|
-
return 'Successfully updated';
|
|
69
|
-
} else {
|
|
70
|
-
throw new Error('Update failed');
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function clearScreen() {
|
|
75
|
-
process.stdout.write('\x1B[2J\x1B[0f');
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
async function editThemeFile(themeManager, directoryName) {
|
|
79
|
-
const themePath = path.join(process.cwd(), themeManager.site, directoryName, '.theme');
|
|
80
|
-
|
|
81
|
-
if (!fs.existsSync(themePath)) {
|
|
82
|
-
console.error('.theme file not found.');
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
console.log(`Opening .theme file: ${themePath}`);
|
|
87
|
-
const openCommand = process.platform === 'win32' ? 'start' :
|
|
88
|
-
process.platform === 'darwin' ? 'open' :
|
|
89
|
-
'xdg-open';
|
|
90
|
-
|
|
91
|
-
exec(`${openCommand} ${themePath}`, (err) => {
|
|
92
|
-
if (err) {
|
|
93
|
-
console.error('Failed to open .theme file:', err);
|
|
94
|
-
} else {
|
|
95
|
-
console.log('.theme file opened successfully.');
|
|
96
|
-
}
|
|
97
|
-
});
|
|
43
|
+
return 'Tüm dosyalar ilerleme ile başarıyla yüklendi';
|
|
98
44
|
}
|
|
99
45
|
|
|
100
|
-
function
|
|
101
|
-
console.log('\n' +
|
|
102
|
-
'********************************************************\n' +
|
|
103
|
-
'* *\n' +
|
|
104
|
-
'* Press "q" to quit watching, "u" to update theme, *\n' +
|
|
105
|
-
'* "s" to save the theme, "e" to edit .theme file. *\n' +
|
|
106
|
-
'* *\n' +
|
|
107
|
-
'********************************************************\n'
|
|
108
|
-
);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
async function start() {
|
|
112
|
-
process.stdout.write('\x1B[2J\x1B[0f');
|
|
46
|
+
async function start(siteName, themeName) {
|
|
113
47
|
await displayAsciiArt();
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}).filter(file => fs.statSync(path.join(cwd, file)).isDirectory());
|
|
48
|
+
console.log('Geliştirme ortamı aşağıdaki ayrıntılarla başlatılıyor:');
|
|
49
|
+
console.log(`Site Adı: ${siteName}`);
|
|
50
|
+
console.log(`Tema Adı: ${themeName}`);
|
|
118
51
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const sitePrompt = new Select({
|
|
125
|
-
name: 'selectedSite',
|
|
126
|
-
message: 'Please select a site:',
|
|
127
|
-
choices: sites
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
const selectedSite = await sitePrompt.run();
|
|
131
|
-
|
|
132
|
-
const sitePath = path.join(cwd, selectedSite);
|
|
133
|
-
const themes = fs.readdirSync(sitePath).filter(file => fs.statSync(path.join(sitePath, file)).isDirectory());
|
|
134
|
-
|
|
135
|
-
if (themes.length === 0) {
|
|
136
|
-
console.error('No themes found in the selected site directory.');
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const themePrompt = new Select({
|
|
141
|
-
name: 'selectedTheme',
|
|
142
|
-
message: 'Please select a theme:',
|
|
143
|
-
choices: themes
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
const selectedTheme = await themePrompt.run();
|
|
147
|
-
const themeEnvPath = path.join(sitePath, selectedTheme, `${selectedTheme}.env`);
|
|
52
|
+
const tsoft = new Tsoft(siteName);
|
|
53
|
+
const themeEnvPath = path.join(process.cwd(), siteName, themeName, `${themeName}.env`);
|
|
148
54
|
|
|
149
|
-
//
|
|
55
|
+
// .env dosyasının var olup olmadığını ve geçerli bir JSON içerip içermediğini kontrol edin
|
|
150
56
|
let envData = {};
|
|
151
57
|
if (fs.existsSync(themeEnvPath)) {
|
|
152
58
|
try {
|
|
153
59
|
envData = JSON.parse(fs.readFileSync(themeEnvPath, 'utf-8'));
|
|
154
60
|
} catch (error) {
|
|
155
|
-
console.warn(
|
|
61
|
+
console.warn(`${themeEnvPath} dosyasında geçersiz JSON formatı. Bu dosya silinecek ve yeniden yetkilendirmeniz gerekecek.`);
|
|
156
62
|
fs.unlinkSync(themeEnvPath);
|
|
157
|
-
console.info('
|
|
63
|
+
console.info('Geçersiz ortam dosyası silindi. Başlatma işlemine devam ediliyor...');
|
|
158
64
|
}
|
|
159
65
|
|
|
160
66
|
if (envData.bearer) {
|
|
161
|
-
const
|
|
162
|
-
const bearerTokenValid = await tsoft.isTokenValid(selectedTheme);
|
|
67
|
+
const bearerTokenValid = await tsoft.isTokenValid(themeName);
|
|
163
68
|
|
|
164
69
|
if (bearerTokenValid) {
|
|
165
|
-
console.info('
|
|
166
|
-
//
|
|
167
|
-
await startWatching(
|
|
70
|
+
console.info('Geçerli bir taşıyıcı jetonuna sahip mevcut ortam dosyası bulundu. Mevcut yapılandırma ile devam ediliyor...');
|
|
71
|
+
// Dosya değişikliklerini izlemeye başlayın
|
|
72
|
+
await startWatching(siteName, themeName, tsoft);
|
|
168
73
|
return;
|
|
169
74
|
} else {
|
|
170
|
-
console.warn('
|
|
75
|
+
console.warn('Mevcut taşıyıcı jetonu geçersiz. Yeniden yetkilendirmeniz gerekecek.');
|
|
171
76
|
fs.unlinkSync(themeEnvPath);
|
|
172
77
|
}
|
|
173
78
|
}
|
|
174
79
|
}
|
|
175
80
|
|
|
176
|
-
|
|
177
|
-
const initializeResult = await t.initialize(selectedTheme, {reset: false});
|
|
81
|
+
await tsoft.initialize(themeName);
|
|
178
82
|
|
|
179
83
|
const approvalPrompt = new Input({
|
|
180
84
|
name: 'approval',
|
|
181
|
-
message: '
|
|
85
|
+
message: 'Lütfen onay kodunu sağlayın:'
|
|
182
86
|
});
|
|
183
87
|
|
|
184
88
|
const approval = await approvalPrompt.run();
|
|
185
89
|
|
|
186
90
|
if (approval) {
|
|
187
|
-
await constants.APPROVAL.handler(
|
|
188
|
-
|
|
189
|
-
console.info('
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
91
|
+
await constants.APPROVAL.handler(tsoft.clientCredentials.setClientSecret(approval));
|
|
92
|
+
tsoft.buildEnvironment();
|
|
93
|
+
console.info('Hazırsınız');
|
|
94
|
+
// Dosya değişikliklerini izlemeye başlayın
|
|
95
|
+
await startWatching(siteName, themeName, tsoft);
|
|
96
|
+
} else {
|
|
97
|
+
console.error('Onay kodu gerekli.');
|
|
193
98
|
}
|
|
194
99
|
}
|
|
195
100
|
|
|
@@ -198,31 +103,55 @@ async function startWatching(site, theme, tsoft) {
|
|
|
198
103
|
const envPath = path.join(themePath, `${theme}.env`);
|
|
199
104
|
|
|
200
105
|
if (!fs.existsSync(envPath)) {
|
|
201
|
-
console.error('
|
|
106
|
+
console.error('Ortam dosyası bulunamadı. Lütfen temayı önce başlatın.');
|
|
202
107
|
return;
|
|
203
108
|
}
|
|
204
109
|
|
|
205
110
|
const watcher = chokidar.watch(themePath, {
|
|
206
|
-
ignored: /(^|[\/\\])
|
|
111
|
+
ignored: /(^|[\/\\])(\.theme|(.*?)\.env)$/, // .theme ve .env dosyaları yoksayılır
|
|
207
112
|
persistent: true
|
|
208
113
|
});
|
|
209
114
|
|
|
210
115
|
watcher.on('change', async (filePath) => {
|
|
211
|
-
console.log(`
|
|
116
|
+
console.log(`Dosya değiştirildi ${filePath}`);
|
|
212
117
|
|
|
213
118
|
const env = JSON.parse(fs.readFileSync(envPath, 'utf-8'));
|
|
214
119
|
const fileName = filePath.replace(`${themePath}/`, '');
|
|
215
120
|
const content = fs.readFileSync(filePath).toString();
|
|
216
121
|
|
|
217
122
|
try {
|
|
218
|
-
|
|
219
|
-
console.log(`
|
|
123
|
+
await tsoft.saveFile(theme, fileName, content, env.bearer);
|
|
124
|
+
console.log(`Dosya başarıyla yüklendi ${fileName}`);
|
|
125
|
+
} catch (error) {
|
|
126
|
+
console.error(`Dosya yükleme hatası ${fileName}:`, error);
|
|
127
|
+
}
|
|
128
|
+
}).on('unlink', async (filePath) => {
|
|
129
|
+
console.log(`Dosya silindi ${filePath}`);
|
|
130
|
+
|
|
131
|
+
const env = JSON.parse(fs.readFileSync(envPath, 'utf-8'));
|
|
132
|
+
const fileName = filePath.replace(`${themePath}/`, '');
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
await tsoft.deleteFile(theme, fileName, env.bearer);
|
|
136
|
+
console.log(`Dosya başarıyla silindi ${fileName}`);
|
|
137
|
+
} catch (error) {
|
|
138
|
+
console.error(`Dosya silme hatası ${fileName}:`, error);
|
|
139
|
+
}
|
|
140
|
+
}).on('unlinkDir', async (dirPath) => {
|
|
141
|
+
console.log(`Dizin silindi ${dirPath}`);
|
|
142
|
+
|
|
143
|
+
const env = JSON.parse(fs.readFileSync(envPath, 'utf-8'));
|
|
144
|
+
const dirName = dirPath.replace(`${themePath}/`, '');
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
await tsoft.deleteDirectory(theme, dirName, env.bearer);
|
|
148
|
+
console.log(`Dizin başarıyla silindi ${dirName}`);
|
|
220
149
|
} catch (error) {
|
|
221
|
-
console.error(`
|
|
150
|
+
console.error(`Dizin silme hatası ${dirName}:`, error);
|
|
222
151
|
}
|
|
223
152
|
});
|
|
224
153
|
|
|
225
|
-
console.log(
|
|
154
|
+
console.log(`${themePath} dizinindeki dosya değişiklikleri izleniyor`);
|
|
226
155
|
|
|
227
156
|
const rl = readline.createInterface({
|
|
228
157
|
input: process.stdin,
|
|
@@ -233,40 +162,50 @@ async function startWatching(site, theme, tsoft) {
|
|
|
233
162
|
|
|
234
163
|
rl.on('line', async (input) => {
|
|
235
164
|
if (input.trim() === 'q') {
|
|
236
|
-
console.log('
|
|
165
|
+
console.log('Dosya izleme işlemi sonlandırılıyor...');
|
|
237
166
|
watcher.close();
|
|
238
167
|
rl.close();
|
|
239
168
|
process.exit(0);
|
|
240
169
|
} else if (input.trim() === 'u') {
|
|
241
|
-
console.log('
|
|
170
|
+
console.log('Tema güncelleniyor...');
|
|
242
171
|
try {
|
|
243
172
|
const result = await updateTheme(tsoft, theme);
|
|
244
173
|
console.log(result);
|
|
245
174
|
info();
|
|
246
175
|
} catch (error) {
|
|
247
|
-
console.error(`
|
|
176
|
+
console.error(`Tema güncelleme hatası:`, error);
|
|
248
177
|
}
|
|
249
178
|
} else if (input.trim() === 's') {
|
|
250
179
|
clearScreen();
|
|
251
|
-
console.log('
|
|
180
|
+
console.log('Tüm dosyalar ilerleme ile yüklenmeye başlanıyor...');
|
|
252
181
|
try {
|
|
253
182
|
const result = await showProgress(tsoft, theme);
|
|
254
183
|
console.log(result);
|
|
255
184
|
info();
|
|
256
185
|
} catch (error) {
|
|
257
|
-
console.error(
|
|
186
|
+
console.error(`İlerleme gösterim hatası:`, error);
|
|
258
187
|
}
|
|
259
188
|
} else if (input.trim() === 'e') {
|
|
260
|
-
console.log('
|
|
189
|
+
console.log('.theme dosyası düzenleniyor...');
|
|
261
190
|
try {
|
|
262
191
|
await editThemeFile(tsoft.themeManager, theme);
|
|
263
192
|
} catch (error) {
|
|
264
|
-
console.error(
|
|
193
|
+
console.error(`.theme dosyası düzenleme hatası:`, error);
|
|
265
194
|
}
|
|
195
|
+
} else if (input.trim() === 'o') {
|
|
196
|
+
console.log('Tema dizini açılıyor...');
|
|
197
|
+
const openCommand = process.platform === 'win32' ? 'start' :
|
|
198
|
+
process.platform === 'darwin' ? 'open' :
|
|
199
|
+
'xdg-open';
|
|
200
|
+
exec(`${openCommand} ${themePath}`, (err) => {
|
|
201
|
+
if (err) {
|
|
202
|
+
console.error('Tema dizini açılamadı:', err);
|
|
203
|
+
} else {
|
|
204
|
+
console.log('Tema dizini başarıyla açıldı.');
|
|
205
|
+
}
|
|
206
|
+
});
|
|
266
207
|
}
|
|
267
208
|
});
|
|
268
209
|
}
|
|
269
210
|
|
|
270
|
-
module.exports = {
|
|
271
|
-
start
|
|
272
|
-
};
|
|
211
|
+
module.exports = { start };
|
package/src/file-manager.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
+
const utils = require('./utils');
|
|
3
4
|
|
|
4
5
|
class FileManager {
|
|
5
6
|
constructor(site) {
|
|
@@ -14,7 +15,7 @@ class FileManager {
|
|
|
14
15
|
if (fs.statSync(fullPath).isDirectory()) {
|
|
15
16
|
this.listFilesRecursive(fullPath, fileList);
|
|
16
17
|
} else {
|
|
17
|
-
fileList.push(fullPath);
|
|
18
|
+
this.isAllowedExtension(fullPath) && fileList.push(fullPath);
|
|
18
19
|
}
|
|
19
20
|
});
|
|
20
21
|
return fileList;
|
|
@@ -28,6 +29,11 @@ class FileManager {
|
|
|
28
29
|
readFile(file) {
|
|
29
30
|
return fs.readFileSync(file).toString();
|
|
30
31
|
}
|
|
32
|
+
|
|
33
|
+
isAllowedExtension(file) {
|
|
34
|
+
const ext = path.extname(file).substring(1);
|
|
35
|
+
return utils.allowedExtensions.includes(ext);
|
|
36
|
+
}
|
|
31
37
|
}
|
|
32
38
|
|
|
33
39
|
module.exports = FileManager;
|
package/src/theme-manager.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
+
const {slugify} = require('./utils');
|
|
4
|
+
const http = require('http');
|
|
5
|
+
const https = require('https');
|
|
3
6
|
|
|
4
7
|
class ThemeManager {
|
|
5
8
|
constructor(site) {
|
|
@@ -10,14 +13,12 @@ class ThemeManager {
|
|
|
10
13
|
}
|
|
11
14
|
|
|
12
15
|
async initializeTheme(theme, reInit = false) {
|
|
13
|
-
|
|
14
16
|
this.theme = theme;
|
|
15
17
|
const themePath = path.join(this.cwd, this.site, theme);
|
|
16
18
|
const themeEnvPath = path.join(themePath, `${theme}.env`);
|
|
17
19
|
|
|
18
|
-
|
|
19
20
|
if (reInit) {
|
|
20
|
-
|
|
21
|
+
// await fs.rm(themePath, {recursive: true, force: true}, (err, file) => {});
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
if (!fs.existsSync(path.join(this.cwd, this.site))) {
|
|
@@ -38,6 +39,19 @@ class ThemeManager {
|
|
|
38
39
|
this.registered = false;
|
|
39
40
|
}
|
|
40
41
|
}
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
const isValid = await this.checkSiteValidity();
|
|
45
|
+
if (!isValid) {
|
|
46
|
+
console.error('Geçersiz site: Siteye ulaşılamıyor.');
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.error('Geçersiz site: Siteye ulaşılamıyor.', error.message);
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return true;
|
|
41
55
|
}
|
|
42
56
|
|
|
43
57
|
isRegistered() {
|
|
@@ -50,25 +64,46 @@ class ThemeManager {
|
|
|
50
64
|
}
|
|
51
65
|
|
|
52
66
|
getEnvironment(theme) {
|
|
53
|
-
const themeEnvPath = path.join(this.cwd, this.site, theme, `${theme}.env`);
|
|
67
|
+
const themeEnvPath = path.join(this.cwd, this.site, slugify(theme), `${slugify(theme)}.env`);
|
|
54
68
|
return JSON.parse(fs.readFileSync(themeEnvPath));
|
|
55
69
|
}
|
|
56
70
|
|
|
57
71
|
getThemeInfo(directoryName) {
|
|
58
|
-
const themePath = path.join(process.cwd(), this.site, directoryName, '.theme');
|
|
72
|
+
const themePath = path.join(process.cwd(), this.site, slugify(directoryName), '.theme');
|
|
59
73
|
if (fs.existsSync(themePath)) {
|
|
60
74
|
const themeInfo = fs.readFileSync(themePath, 'utf-8');
|
|
61
75
|
try {
|
|
62
76
|
return JSON.parse(themeInfo);
|
|
63
77
|
} catch (error) {
|
|
64
|
-
console.error('
|
|
78
|
+
console.error('.theme dosyasını ayrıştırma hatası:', error);
|
|
65
79
|
return null;
|
|
66
80
|
}
|
|
67
81
|
} else {
|
|
68
|
-
console.error('.theme
|
|
82
|
+
console.error('.theme dosyası bulunamadı:', themePath);
|
|
69
83
|
return null;
|
|
70
84
|
}
|
|
71
85
|
}
|
|
86
|
+
|
|
87
|
+
checkSiteValidity() {
|
|
88
|
+
return new Promise((resolve, reject) => {
|
|
89
|
+
const url = new URL(`https://${this.site}/Y/R`);
|
|
90
|
+
const request = url.protocol === 'https:' ? https : http;
|
|
91
|
+
|
|
92
|
+
const req = request.get(url, (res) => {
|
|
93
|
+
if (res.statusCode === 200) {
|
|
94
|
+
resolve(true);
|
|
95
|
+
} else {
|
|
96
|
+
resolve(false);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
req.on('error', (err) => {
|
|
101
|
+
reject(err);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
req.end();
|
|
105
|
+
});
|
|
106
|
+
}
|
|
72
107
|
}
|
|
73
108
|
|
|
74
109
|
module.exports = ThemeManager;
|
package/src/tsoft.js
CHANGED
|
@@ -8,6 +8,7 @@ const buildPostRequest = require('./request');
|
|
|
8
8
|
class Tsoft {
|
|
9
9
|
static TSOFT_CLI_UUID = '7583a318-8542-4ec8-980c-48ea67031be3';
|
|
10
10
|
static ONLINESTORE_SAVE_URI = 'api/v3/admin/online-store-2/theme/file-manager?q=save';
|
|
11
|
+
static ONLINESTORE_DELETE_URI = 'api/v3/admin/online-store-2/theme/file-manager?q=delete';
|
|
11
12
|
static UPDATE_THEME_URI = 'api/v3/admin/online-store-2/theme/update-theme';
|
|
12
13
|
|
|
13
14
|
|
|
@@ -21,7 +22,7 @@ class Tsoft {
|
|
|
21
22
|
async initialize(theme, reInit = false) {
|
|
22
23
|
await this.themeManager.initializeTheme(theme, reInit);
|
|
23
24
|
if (!this.themeManager.isRegistered()) {
|
|
24
|
-
return await this.register(Tsoft.TSOFT_CLI_UUID);
|
|
25
|
+
return await this.register(Tsoft.TSOFT_CLI_UUID, this.themeManager.getThemeInfo(theme));
|
|
25
26
|
} else {
|
|
26
27
|
console.warn('You are already registered');
|
|
27
28
|
}
|
|
@@ -35,8 +36,8 @@ class Tsoft {
|
|
|
35
36
|
await this.clientCredentials.authorize();
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
async register(CLIENT_UUID) {
|
|
39
|
-
const response = await this.clientCredentials.register(CLIENT_UUID);
|
|
39
|
+
async register(CLIENT_UUID, clientConfiguration = {}) {
|
|
40
|
+
const response = await this.clientCredentials.register(CLIENT_UUID, clientConfiguration);
|
|
40
41
|
return response === true ? constants.APPROVAL : null;
|
|
41
42
|
}
|
|
42
43
|
|
|
@@ -58,16 +59,14 @@ class Tsoft {
|
|
|
58
59
|
content: content
|
|
59
60
|
})
|
|
60
61
|
});
|
|
61
|
-
console.log({
|
|
62
|
-
result: result
|
|
63
|
-
})
|
|
64
62
|
}));
|
|
65
63
|
}
|
|
66
64
|
|
|
67
65
|
async saveFile(theme, fileName, content, bearerToken) {
|
|
68
|
-
|
|
66
|
+
return await buildPostRequest(this.site, Tsoft.ONLINESTORE_SAVE_URI, {
|
|
69
67
|
headers: {
|
|
70
68
|
Authorization: `Bearer ${bearerToken}`,
|
|
69
|
+
Accept: 'application/json',
|
|
71
70
|
'Content-Type': 'application/json'
|
|
72
71
|
},
|
|
73
72
|
body: JSON.stringify({
|
|
@@ -76,8 +75,39 @@ class Tsoft {
|
|
|
76
75
|
content: content
|
|
77
76
|
})
|
|
78
77
|
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async deleteFile(theme, fileName, bearerToken) {
|
|
81
|
+
|
|
82
|
+
return await buildPostRequest(this.site, Tsoft.ONLINESTORE_DELETE_URI, {
|
|
83
|
+
headers: {
|
|
84
|
+
Authorization: `Bearer ${bearerToken}`,
|
|
85
|
+
'Content-Type': 'application/json'
|
|
86
|
+
},
|
|
87
|
+
body: JSON.stringify({
|
|
88
|
+
theme: theme,
|
|
89
|
+
items: [
|
|
90
|
+
{type: 'file', path: fileName}
|
|
91
|
+
]
|
|
92
|
+
})
|
|
93
|
+
});
|
|
79
94
|
|
|
80
|
-
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async deleteDirectory(theme, folderName, bearerToken) {
|
|
98
|
+
return await buildPostRequest(this.site, Tsoft.ONLINESTORE_DELETE_URI, {
|
|
99
|
+
headers: {
|
|
100
|
+
Authorization: `Bearer ${bearerToken}`,
|
|
101
|
+
Accept: 'application/json',
|
|
102
|
+
'Content-Type': 'application/json'
|
|
103
|
+
},
|
|
104
|
+
body: JSON.stringify({
|
|
105
|
+
theme: theme,
|
|
106
|
+
items: [
|
|
107
|
+
{type: 'dir', path: folderName}
|
|
108
|
+
]
|
|
109
|
+
})
|
|
110
|
+
});
|
|
81
111
|
}
|
|
82
112
|
|
|
83
113
|
|
|
@@ -90,19 +120,17 @@ class Tsoft {
|
|
|
90
120
|
const env = this.themeManager.getEnvironment(directoryName);
|
|
91
121
|
const themeInfo = this.themeManager.getThemeInfo(directoryName); // .theme bilgisi alınıyor
|
|
92
122
|
|
|
93
|
-
|
|
123
|
+
return await buildPostRequest(this.site, Tsoft.UPDATE_THEME_URI, {
|
|
94
124
|
headers: {
|
|
95
125
|
Authorization: `Bearer ${env.bearer}`,
|
|
96
|
-
'
|
|
97
|
-
'
|
|
126
|
+
'Accept': 'application/json',
|
|
127
|
+
'Content-Type': 'application/json'
|
|
98
128
|
},
|
|
99
129
|
body: JSON.stringify({
|
|
100
130
|
theme: directoryName,
|
|
101
131
|
themeInfo: themeInfo
|
|
102
132
|
})
|
|
103
133
|
});
|
|
104
|
-
|
|
105
|
-
return response;
|
|
106
134
|
}
|
|
107
135
|
|
|
108
136
|
}
|
package/src/utils.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const figlet = require("figlet");
|
|
2
|
+
module.exports = {
|
|
3
|
+
slugify: function (text) {
|
|
4
|
+
return text.toString().toLowerCase()
|
|
5
|
+
.replace(/\s+/g, '-')
|
|
6
|
+
.replace(/[^\w\-]+/g, '')
|
|
7
|
+
.replace(/\-\-+/g, '-')
|
|
8
|
+
.replace(/^-+/, '')
|
|
9
|
+
.replace(/-+$/, '');
|
|
10
|
+
},
|
|
11
|
+
allowedExtensions: ['theme', 'twig', 'css', 'js', 'md', 'json', 'svg', 'jpeg', 'jpg', 'png', 'gif', 'webp'],
|
|
12
|
+
clearScreen: function () {
|
|
13
|
+
process.stdout.write('\x1B[2J\x1B[0f');
|
|
14
|
+
},
|
|
15
|
+
displayAsciiArt: async function () {
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
figlet('T-SOFT CLI', {
|
|
18
|
+
font: 'Standard',
|
|
19
|
+
}, (err, data) => {
|
|
20
|
+
if (err) {
|
|
21
|
+
console.log('Something went wrong...');
|
|
22
|
+
console.dir(err);
|
|
23
|
+
reject(err);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
console.log(data);
|
|
27
|
+
resolve();
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
},
|
|
31
|
+
info: function () {
|
|
32
|
+
console.log('\n' +
|
|
33
|
+
'********************************************************\n' +
|
|
34
|
+
'* *\n' +
|
|
35
|
+
'* Dosya izlemeyi sonlandırmak için "q" tuşuna basın, *\n' +
|
|
36
|
+
'* Temayı güncellemek için "u" tuşuna basın, *\n' +
|
|
37
|
+
'* Temayı kaydetmek için "s" tuşuna basın, *\n' +
|
|
38
|
+
'* .theme dosyasını düzenlemek için "e" tuşuna basın, *\n' +
|
|
39
|
+
'* Tema dizinini açmak için "o" tuşuna basın. *\n' +
|
|
40
|
+
'* *\n' +
|
|
41
|
+
'********************************************************\n'
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const mockFs = require('mock-fs');
|
|
3
|
+
const FileManager = require('../src/file-manager');
|
|
4
|
+
|
|
5
|
+
describe('FileManager', () => {
|
|
6
|
+
const site = 'testSite';
|
|
7
|
+
const fileManager = new FileManager(site);
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
mockFs({
|
|
11
|
+
'/testDir': {
|
|
12
|
+
'file1.js': 'console.log("file1");',
|
|
13
|
+
'file2.css': 'body { margin: 0; }',
|
|
14
|
+
'subdir': {
|
|
15
|
+
'file3.jpg': '',
|
|
16
|
+
'file4.png': ''
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
[`${process.cwd()}/${site}`]: {
|
|
20
|
+
'myTheme': {
|
|
21
|
+
'file.js': 'console.log("test");'
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
afterEach(() => {
|
|
28
|
+
mockFs.restore();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe('listFilesRecursive', () => {
|
|
32
|
+
it('should list all files recursively', () => {
|
|
33
|
+
// Act
|
|
34
|
+
const result = fileManager.listFilesRecursive('/testDir');
|
|
35
|
+
|
|
36
|
+
// Assert
|
|
37
|
+
expect(result).toEqual([
|
|
38
|
+
'/testDir/file1.js',
|
|
39
|
+
'/testDir/file2.css',
|
|
40
|
+
'/testDir/subdir/file3.jpg',
|
|
41
|
+
'/testDir/subdir/file4.png'
|
|
42
|
+
]);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
describe('getRelativePath', () => {
|
|
47
|
+
it('should get the relative path of a file', () => {
|
|
48
|
+
// Arrange
|
|
49
|
+
const theme = 'myTheme';
|
|
50
|
+
const file = path.join(process.cwd(), site, theme, 'file.js');
|
|
51
|
+
const expectedRelativePath = 'file.js';
|
|
52
|
+
|
|
53
|
+
// Act
|
|
54
|
+
const result = fileManager.getRelativePath(theme, file);
|
|
55
|
+
|
|
56
|
+
// Assert
|
|
57
|
+
expect(result).toBe(expectedRelativePath);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe('readFile', () => {
|
|
62
|
+
it('should read the contents of a file', () => {
|
|
63
|
+
// Arrange
|
|
64
|
+
const file = '/testDir/file1.js';
|
|
65
|
+
const fileContents = 'console.log("file1");';
|
|
66
|
+
|
|
67
|
+
// Act
|
|
68
|
+
const result = fileManager.readFile(file);
|
|
69
|
+
|
|
70
|
+
// Assert
|
|
71
|
+
expect(result).toBe(fileContents);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
describe('isAllowedExtension', () => {
|
|
76
|
+
it('should return true for allowed extensions', () => {
|
|
77
|
+
// Arrange
|
|
78
|
+
const allowedFile = 'file.js';
|
|
79
|
+
const notAllowedFile = 'file.exe';
|
|
80
|
+
|
|
81
|
+
// Act
|
|
82
|
+
const isAllowedFileResult = fileManager.isAllowedExtension(allowedFile);
|
|
83
|
+
const isNotAllowedFileResult = fileManager.isAllowedExtension(notAllowedFile);
|
|
84
|
+
|
|
85
|
+
// Assert
|
|
86
|
+
expect(isAllowedFileResult).toBe(true);
|
|
87
|
+
expect(isNotAllowedFileResult).toBe(false);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
});
|
package/src/commands/save.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
const Tsoft = require('../tsoft');
|
|
2
|
-
|
|
3
|
-
async function save(site, theme) {
|
|
4
|
-
const t = new Tsoft(site);
|
|
5
|
-
const isValid = await t.isTokenValid(theme);
|
|
6
|
-
|
|
7
|
-
if (isValid) {
|
|
8
|
-
await t.saveOnlineStore(theme);
|
|
9
|
-
console.log('Online store saved successfully.');
|
|
10
|
-
} else {
|
|
11
|
-
console.log('Invalid Bearer token. Please re-authenticate.');
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
module.exports = {
|
|
16
|
-
save
|
|
17
|
-
};
|