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.
Files changed (72) hide show
  1. package/.editorconfig +11 -0
  2. package/.github/workflows/node.js.yml +25 -0
  3. package/.nvmrc +1 -0
  4. package/.prettierrc.json +8 -0
  5. package/.vscode/extensions.json +3 -0
  6. package/.vscode/settings.json +4 -0
  7. package/CHANGELOG.md +35 -4
  8. package/package.json +14 -25
  9. package/packages/cli/README.md +53 -0
  10. package/packages/cli/bin/dev.js +5 -0
  11. package/packages/cli/bin/run.cmd +3 -0
  12. package/packages/cli/bin/run.js +5 -0
  13. package/packages/cli/enums.ts +4 -0
  14. package/packages/cli/index.ts +11 -0
  15. package/packages/cli/package.json +59 -0
  16. package/packages/cli/tsconfig.json +9 -0
  17. package/packages/shared/index.ts +6 -0
  18. package/packages/shared/package.json +45 -0
  19. package/packages/shared/src/cli-progress.ts +3 -0
  20. package/packages/shared/src/commands/cli-all-commands.ts +6 -0
  21. package/packages/shared/src/commands/version-command.ts +12 -0
  22. package/packages/shared/src/consola.ts +1 -0
  23. package/packages/shared/src/open.ts +3 -0
  24. package/packages/shared/src/unzip.ts +15 -0
  25. package/packages/shared/tsconfig.json +9 -0
  26. package/packages/theme/bin/dev.js +5 -0
  27. package/packages/theme/bin/run.cmd +3 -0
  28. package/packages/theme/bin/run.js +5 -0
  29. package/packages/theme/index.ts +21 -0
  30. package/packages/theme/jest.config.ts +3 -0
  31. package/packages/theme/package.json +66 -0
  32. package/packages/theme/src/commands/theme/create.ts +51 -0
  33. package/packages/theme/src/commands/theme/delete-site.ts +30 -0
  34. package/packages/theme/src/commands/theme/delete-theme.ts +39 -0
  35. package/packages/theme/src/commands/theme/dev.ts +47 -0
  36. package/packages/theme/src/commands/theme/pull.ts +26 -0
  37. package/packages/theme/src/enums.ts +55 -0
  38. package/packages/theme/src/services/ClientCredentials.ts +127 -0
  39. package/packages/theme/src/services/Constants.ts +19 -0
  40. package/packages/theme/src/services/CreateTheme.ts +88 -0
  41. package/packages/theme/src/services/DeleteSite.ts +30 -0
  42. package/packages/theme/src/services/DeleteTheme.ts +46 -0
  43. package/packages/theme/src/services/FileManager.ts +62 -0
  44. package/packages/theme/src/services/Request.ts +18 -0
  45. package/packages/theme/src/services/StartTheme.ts +363 -0
  46. package/packages/theme/src/services/SyncTheme.ts +108 -0
  47. package/packages/theme/src/services/ThemeManager.ts +118 -0
  48. package/packages/theme/src/services/Tsoft.ts +151 -0
  49. package/packages/theme/src/services/types.ts +90 -0
  50. package/packages/theme/src/types.ts +20 -0
  51. package/packages/theme/src/utils/screen.ts +28 -0
  52. package/packages/theme/src/utils/utils.ts +83 -0
  53. package/packages/theme/tests/FileManager.test.js +90 -0
  54. package/packages/theme/tsconfig.json +9 -0
  55. package/pnpm-workspace.yaml +2 -0
  56. package/pull_request_template.md +5 -0
  57. package/scripts/prebuild.js +45 -0
  58. package/scripts/versions.js +70 -0
  59. package/tsconfig.build.json +21 -0
  60. package/bin/index.js +0 -77
  61. package/jest.config.js +0 -3
  62. package/src/Tsoft.js +0 -137
  63. package/src/commands/CreateCommand.js +0 -102
  64. package/src/commands/StartCommand.js +0 -280
  65. package/src/commands/SyncCommand.js +0 -97
  66. package/src/core/ClientCredentials.js +0 -107
  67. package/src/core/Constants.js +0 -19
  68. package/src/core/FileManager.js +0 -53
  69. package/src/core/Request.js +0 -41
  70. package/src/core/ThemeManager.js +0 -113
  71. package/src/core/Utils.js +0 -104
  72. 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;
@@ -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;
@@ -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;
@@ -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;
@@ -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
- });