tsoft-cli 1.4.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +11 -0
- package/.github/workflows/node.js.yml +25 -0
- package/.nvmrc +1 -0
- package/.prettierrc.json +8 -0
- package/.vscode/extensions.json +3 -0
- package/.vscode/settings.json +4 -0
- package/CHANGELOG.md +35 -4
- package/package.json +14 -25
- package/packages/cli/README.md +53 -0
- package/packages/cli/bin/dev.js +5 -0
- package/packages/cli/bin/run.cmd +3 -0
- package/packages/cli/bin/run.js +5 -0
- package/packages/cli/enums.ts +4 -0
- package/packages/cli/index.ts +11 -0
- package/packages/cli/package.json +59 -0
- package/packages/cli/tsconfig.json +9 -0
- package/packages/shared/index.ts +6 -0
- package/packages/shared/package.json +45 -0
- package/packages/shared/src/cli-progress.ts +3 -0
- package/packages/shared/src/commands/cli-all-commands.ts +6 -0
- package/packages/shared/src/commands/version-command.ts +12 -0
- package/packages/shared/src/consola.ts +1 -0
- package/packages/shared/src/open.ts +3 -0
- package/packages/shared/src/unzip.ts +15 -0
- package/packages/shared/tsconfig.json +9 -0
- package/packages/theme/bin/dev.js +5 -0
- package/packages/theme/bin/run.cmd +3 -0
- package/packages/theme/bin/run.js +5 -0
- package/packages/theme/index.ts +21 -0
- package/packages/theme/jest.config.ts +3 -0
- package/packages/theme/package.json +66 -0
- package/packages/theme/src/commands/theme/create.ts +51 -0
- package/packages/theme/src/commands/theme/delete-site.ts +30 -0
- package/packages/theme/src/commands/theme/delete-theme.ts +39 -0
- package/packages/theme/src/commands/theme/dev.ts +47 -0
- package/packages/theme/src/commands/theme/pull.ts +26 -0
- package/packages/theme/src/enums.ts +55 -0
- package/packages/theme/src/services/ClientCredentials.ts +127 -0
- package/packages/theme/src/services/Constants.ts +19 -0
- package/packages/theme/src/services/CreateTheme.ts +88 -0
- package/packages/theme/src/services/DeleteSite.ts +30 -0
- package/packages/theme/src/services/DeleteTheme.ts +46 -0
- package/packages/theme/src/services/FileManager.ts +62 -0
- package/packages/theme/src/services/Request.ts +18 -0
- package/packages/theme/src/services/StartTheme.ts +363 -0
- package/packages/theme/src/services/SyncTheme.ts +108 -0
- package/packages/theme/src/services/ThemeManager.ts +118 -0
- package/packages/theme/src/services/Tsoft.ts +151 -0
- package/packages/theme/src/services/types.ts +90 -0
- package/packages/theme/src/types.ts +20 -0
- package/packages/theme/src/utils/screen.ts +28 -0
- package/packages/theme/src/utils/utils.ts +83 -0
- package/packages/theme/tests/FileManager.test.js +90 -0
- package/packages/theme/tsconfig.json +9 -0
- package/pnpm-workspace.yaml +2 -0
- package/pull_request_template.md +5 -0
- package/scripts/prebuild.js +45 -0
- package/scripts/versions.js +70 -0
- package/tsconfig.build.json +21 -0
- package/bin/index.js +0 -77
- package/jest.config.js +0 -3
- package/src/Tsoft.js +0 -137
- package/src/commands/CreateCommand.js +0 -102
- package/src/commands/StartCommand.js +0 -280
- package/src/commands/SyncCommand.js +0 -97
- package/src/core/ClientCredentials.js +0 -107
- package/src/core/Constants.js +0 -19
- package/src/core/FileManager.js +0 -53
- package/src/core/Request.js +0 -41
- package/src/core/ThemeManager.js +0 -113
- package/src/core/Utils.js +0 -104
- package/tests/FileManager.test.js +0 -90
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
const {buildPostRequest} = require('./Request');
|
|
2
|
-
|
|
3
|
-
class ClientCredentials {
|
|
4
|
-
constructor(site) {
|
|
5
|
-
this.site = site;
|
|
6
|
-
this.clientId = null;
|
|
7
|
-
this.clientSecret = null;
|
|
8
|
-
this.bearer = null;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
setClientId(clientId) {
|
|
12
|
-
this.clientId = clientId;
|
|
13
|
-
return this;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
setClientSecret(clientSecret) {
|
|
17
|
-
this.clientSecret = clientSecret;
|
|
18
|
-
return this;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
getEnvironment() {
|
|
22
|
-
return {
|
|
23
|
-
site: this.site,
|
|
24
|
-
clientId: this.clientId,
|
|
25
|
-
clientSecret: this.clientSecret,
|
|
26
|
-
bearer: this.bearer
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
async register(CLIENT_UUID, clientConfiguration = {}) {
|
|
31
|
-
const uri = "api/v3/admin/auth/auth-application";
|
|
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: {
|
|
40
|
-
name: clientConfiguration.name,
|
|
41
|
-
author: clientConfiguration.author,
|
|
42
|
-
version: clientConfiguration.version
|
|
43
|
-
}
|
|
44
|
-
})
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
if (result.status === true) {
|
|
48
|
-
this.clientId = result.data.public_key;
|
|
49
|
-
return true;
|
|
50
|
-
} else {
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
async authorize() {
|
|
56
|
-
const uri = "api/v3/admin/auth/auth-application/authorize";
|
|
57
|
-
return await buildPostRequest(this.site, uri, {
|
|
58
|
-
headers: {
|
|
59
|
-
'Content-Type': 'application/json',
|
|
60
|
-
'Accept': 'application/json'
|
|
61
|
-
},
|
|
62
|
-
body: JSON.stringify({
|
|
63
|
-
public_key: this.clientId,
|
|
64
|
-
secret: this.clientSecret
|
|
65
|
-
})
|
|
66
|
-
}).then((result) => {
|
|
67
|
-
if (result.status === true) {
|
|
68
|
-
this.bearer = result.data.token.plainTextToken;
|
|
69
|
-
return result;
|
|
70
|
-
}
|
|
71
|
-
return false;
|
|
72
|
-
}).catch((error) => {
|
|
73
|
-
console.error('Hata:', error.message);
|
|
74
|
-
return false;
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
async validateToken(token) {
|
|
79
|
-
const uri = 'api/v3/admin/auth/me';
|
|
80
|
-
const response = await buildPostRequest(this.site, uri, {
|
|
81
|
-
headers: {
|
|
82
|
-
Authorization: `Bearer ${token}`
|
|
83
|
-
},
|
|
84
|
-
body: JSON.stringify({
|
|
85
|
-
_method: 'GET'
|
|
86
|
-
})
|
|
87
|
-
});
|
|
88
|
-
return response.message === 'ok';
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
async recovery(token) {
|
|
92
|
-
const uri = `api/v3/admin/auth/auth-application/recovery/${token}`;
|
|
93
|
-
const response = await buildPostRequest(this.site, uri);
|
|
94
|
-
if (response.status) {
|
|
95
|
-
return {
|
|
96
|
-
secret: response.data.secret,
|
|
97
|
-
public_key: response.data.public_key
|
|
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}`);
|
|
102
|
-
}
|
|
103
|
-
return null;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
module.exports = ClientCredentials;
|
package/src/core/Constants.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
const handleAuthorization = async (credentialHandler) => {
|
|
2
|
-
await credentialHandler.authorize();
|
|
3
|
-
};
|
|
4
|
-
|
|
5
|
-
const Constants = Object.freeze({
|
|
6
|
-
INITIALIZE: {
|
|
7
|
-
type: 'input',
|
|
8
|
-
name: 'site',
|
|
9
|
-
message: 'Lütfen site adresini giriniz (örnek: https://tsoft.com.tr):'
|
|
10
|
-
},
|
|
11
|
-
APPROVAL: {
|
|
12
|
-
type: 'input',
|
|
13
|
-
name: 'approval',
|
|
14
|
-
message: 'Parolanızı giriniz (Lütfen panelden onaylayınız):',
|
|
15
|
-
handler: handleAuthorization
|
|
16
|
-
}
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
module.exports = Constants;
|
package/src/core/FileManager.js
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const Utils = require('./Utils');
|
|
4
|
-
const { buildDownloadZipRequest } = require('./Request');
|
|
5
|
-
|
|
6
|
-
class FileManager {
|
|
7
|
-
constructor(site) {
|
|
8
|
-
this.site = site;
|
|
9
|
-
this.cwd = process.cwd();
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
listFilesRecursive(directory, fileList = []) {
|
|
13
|
-
const files = fs.readdirSync(directory);
|
|
14
|
-
files.forEach(file => {
|
|
15
|
-
const fullPath = path.join(directory, file);
|
|
16
|
-
if (fs.statSync(fullPath).isDirectory()) {
|
|
17
|
-
this.listFilesRecursive(fullPath, fileList);
|
|
18
|
-
} else {
|
|
19
|
-
this.isAllowedExtension(fullPath) && fileList.push(fullPath);
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
return fileList;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
getRelativePath(theme, file) {
|
|
26
|
-
const themePath = path.join(this.cwd, this.site, theme);
|
|
27
|
-
return file.replace(`${themePath}/`, '');
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
readFile(file) {
|
|
31
|
-
return fs.readFileSync(file).toString();
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
isAllowedExtension(file) {
|
|
35
|
-
const ext = path.extname(file).substring(1);
|
|
36
|
-
return Utils.allowedExtensions.includes(ext);
|
|
37
|
-
}
|
|
38
|
-
|
|
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}`, {
|
|
41
|
-
headers: {
|
|
42
|
-
'Content-Type': 'application/zip',
|
|
43
|
-
'Accept': 'application/zip',
|
|
44
|
-
'Authorization': `Bearer ${bearerToken}`
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
fs.writeFileSync(zipFilePath, Buffer.from(response));
|
|
49
|
-
console.log(`Zip dosyası ${zipFilePath} konumuna kaydedildi.`);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
module.exports = FileManager;
|
package/src/core/Request.js
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
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;
|
package/src/core/ThemeManager.js
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const { slugify } = require('./Utils');
|
|
4
|
-
const http = require('http');
|
|
5
|
-
const https = require('https');
|
|
6
|
-
|
|
7
|
-
class ThemeManager {
|
|
8
|
-
constructor(site) {
|
|
9
|
-
this.site = site;
|
|
10
|
-
this.cwd = process.cwd();
|
|
11
|
-
this.theme = null;
|
|
12
|
-
this.registered = false;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
async initializeTheme(theme, reInit = false) {
|
|
16
|
-
this.theme = theme;
|
|
17
|
-
const themePath = path.join(this.cwd, this.site, theme);
|
|
18
|
-
const themeEnvPath = path.join(themePath, `${theme}.env`);
|
|
19
|
-
|
|
20
|
-
if (reInit) {
|
|
21
|
-
// await fs.rm(themePath, {recursive: true, force: true}, (err, file) => {});
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if (!fs.existsSync(path.join(this.cwd, this.site))) {
|
|
25
|
-
fs.mkdirSync(path.join(this.cwd, this.site));
|
|
26
|
-
}
|
|
27
|
-
if (!fs.existsSync(themePath)) {
|
|
28
|
-
fs.mkdirSync(themePath);
|
|
29
|
-
}
|
|
30
|
-
if (reInit || !fs.existsSync(themeEnvPath)) {
|
|
31
|
-
fs.writeFileSync(themeEnvPath, '');
|
|
32
|
-
this.registered = false;
|
|
33
|
-
} else {
|
|
34
|
-
const data = fs.readFileSync(themeEnvPath);
|
|
35
|
-
try {
|
|
36
|
-
const environment = JSON.parse(data.toString());
|
|
37
|
-
this.registered = Boolean(environment.bearer);
|
|
38
|
-
} catch (e) {
|
|
39
|
-
this.registered = false;
|
|
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;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
setTheme(theme) {
|
|
58
|
-
this.theme = slugify(theme);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
isRegistered() {
|
|
62
|
-
return this.registered;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
buildEnvironment(environment) {
|
|
66
|
-
const envPath = path.join(this.cwd, this.site, this.theme, `${this.theme}.env`);
|
|
67
|
-
fs.writeFileSync(envPath, JSON.stringify(environment));
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
getEnvironment(theme) {
|
|
71
|
-
const themeEnvPath = path.join(this.cwd, this.site, slugify(theme), `${slugify(theme)}.env`);
|
|
72
|
-
return JSON.parse(fs.readFileSync(themeEnvPath));
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
getThemeInfo(directoryName) {
|
|
76
|
-
const themePath = path.join(process.cwd(), this.site, slugify(directoryName), '.theme');
|
|
77
|
-
if (fs.existsSync(themePath)) {
|
|
78
|
-
const themeInfo = fs.readFileSync(themePath, 'utf-8');
|
|
79
|
-
try {
|
|
80
|
-
return JSON.parse(themeInfo);
|
|
81
|
-
} catch (error) {
|
|
82
|
-
console.error('.theme dosyasını ayrıştırma hatası:', error);
|
|
83
|
-
return null;
|
|
84
|
-
}
|
|
85
|
-
} else {
|
|
86
|
-
console.error('.theme dosyası bulunamadı:', themePath);
|
|
87
|
-
return null;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
checkSiteValidity() {
|
|
92
|
-
return new Promise((resolve, reject) => {
|
|
93
|
-
const url = new URL(`https://${this.site}/Y/R`);
|
|
94
|
-
const request = url.protocol === 'https:' ? https : http;
|
|
95
|
-
|
|
96
|
-
const req = request.get(url, (res) => {
|
|
97
|
-
if (res.statusCode === 200) {
|
|
98
|
-
resolve(true);
|
|
99
|
-
} else {
|
|
100
|
-
resolve(false);
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
req.on('error', (err) => {
|
|
105
|
-
reject(err);
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
req.end();
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
module.exports = ThemeManager;
|
package/src/core/Utils.js
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
const figlet = require("figlet");
|
|
2
|
-
const packageJson = require('../../package.json');
|
|
3
|
-
const fs = require("fs");
|
|
4
|
-
const unzipper = require("unzipper");
|
|
5
|
-
const path = require("path");
|
|
6
|
-
|
|
7
|
-
class Utils {
|
|
8
|
-
static slugify(text) {
|
|
9
|
-
return text.toString().toLowerCase()
|
|
10
|
-
.replace(/\s+/g, '-')
|
|
11
|
-
.replace(/[^\w\-]+/g, '')
|
|
12
|
-
.replace(/\-\-+/g, '-')
|
|
13
|
-
.replace(/^-+/, '')
|
|
14
|
-
.replace(/-+$/, '');
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
static get allowedExtensions() {
|
|
18
|
-
return ['theme', 'twig', 'css', 'js', 'md', 'json', 'svg', 'jpeg', 'jpg', 'png', 'gif', 'webp'];
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
static clearScreen() {
|
|
22
|
-
process.stdout.write('\x1B[2J\x1B[0f');
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
static displayAsciiArt() {
|
|
26
|
-
return new Promise((resolve, reject) => {
|
|
27
|
-
figlet('T-SOFT CLI', {
|
|
28
|
-
font: 'Standard',
|
|
29
|
-
}, (err, data) => {
|
|
30
|
-
if (err) {
|
|
31
|
-
console.log('Something went wrong...');
|
|
32
|
-
console.dir(err);
|
|
33
|
-
reject(err);
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
console.log(data);
|
|
37
|
-
resolve();
|
|
38
|
-
});
|
|
39
|
-
}).then(() => {
|
|
40
|
-
console.log('Versiyon: ' + packageJson.version);
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
static info(tsoft, theme) {
|
|
45
|
-
Utils.clearScreen()
|
|
46
|
-
|
|
47
|
-
console.log('\n' +
|
|
48
|
-
'********************************************************\n' +
|
|
49
|
-
'* *\n' +
|
|
50
|
-
'* Dosya izlemeyi sonlandırmak için "q" tuşuna basın, *\n' +
|
|
51
|
-
'* Temayı güncellemek için "u" tuşuna basın, *\n' +
|
|
52
|
-
'* Temayı kaydetmek için "s" tuşuna basın, *\n' +
|
|
53
|
-
'* .theme dosyasını düzenlemek için "e" tuşuna basın, *\n' +
|
|
54
|
-
'* Tema dizinini açmak için "o" tuşuna basın. *\n' +
|
|
55
|
-
'* URL\'yi tarayıcıda açmak için "p" tuşuna basın. *\n' +
|
|
56
|
-
'* *\n' +
|
|
57
|
-
'********************************************************\n'
|
|
58
|
-
);
|
|
59
|
-
const {clientId, clientSecret} = tsoft.themeManager.getEnvironment(theme);
|
|
60
|
-
|
|
61
|
-
const url = 'https://' + tsoft.site + '?tsoft-cli=' + clientId + '&tsoft-cli-secret=' + clientSecret;
|
|
62
|
-
console.log('İzlenen tema: ' + theme);
|
|
63
|
-
console.log('Önizleme: \n')
|
|
64
|
-
console.log(url+ '\n');
|
|
65
|
-
|
|
66
|
-
process.stdin.setRawMode(true);
|
|
67
|
-
process.stdin.resume();
|
|
68
|
-
process.stdin.on('data', async (key) => {
|
|
69
|
-
if (key.toString() === 'p') {
|
|
70
|
-
console.log('URL tarayıcıda açılıyor...');
|
|
71
|
-
const open = (await import('open')).default;
|
|
72
|
-
await open(url);
|
|
73
|
-
} else if (key.toString() === 'q') {
|
|
74
|
-
console.log('Programdan çıkılıyor. Hoşça kalın!');
|
|
75
|
-
process.exit(0);
|
|
76
|
-
}
|
|
77
|
-
// Other keypress handlers can go here
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
static unzipFile(zipFilePath, extractToDir) {
|
|
83
|
-
return new Promise((resolve, reject) => {
|
|
84
|
-
fs.createReadStream(zipFilePath)
|
|
85
|
-
.pipe(unzipper.Extract({ path: extractToDir }))
|
|
86
|
-
.on('close', resolve)
|
|
87
|
-
.on('error', reject);
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
static async getSites(opt = {}) {
|
|
92
|
-
const cwd = opt.cwd ?? process.cwd();
|
|
93
|
-
return fs.readdirSync(cwd).filter(file => {
|
|
94
|
-
const filePath = path.join(cwd, file);
|
|
95
|
-
return file.charAt(0) !== '.'
|
|
96
|
-
&& !['node_modules', 'build', 'dist'].includes(file)
|
|
97
|
-
&& fs.statSync(filePath).isDirectory()
|
|
98
|
-
&& fs.existsSync(path.join(filePath, '.tsoft'));
|
|
99
|
-
}).filter(file => fs.statSync(path.join(cwd, file)).isDirectory());
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
module.exports = Utils;
|
|
@@ -1,90 +0,0 @@
|
|
|
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
|
-
});
|