nexushub-commands 1.11.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/lib/Client.d.ts CHANGED
@@ -26,5 +26,6 @@ export interface DepositConfig {
26
26
  }>;
27
27
  }
28
28
  export declare class Client {
29
+ static API: AxiosInstance;
29
30
  static config: (context: CommandContext) => DepositConfig;
30
31
  }
@@ -0,0 +1,61 @@
1
+ export declare class ParserSharedCommandsService {
2
+ /**
3
+ * Парсит название класса из кода команды
4
+ * @param commandContent - исходный код команды
5
+ * @returns название класса или null, если не найдено
6
+ */
7
+ static parseClassName(commandContent: string): string | null;
8
+ /**
9
+ * Преобразует команду, заменяя приватные методы на API вызовы
10
+ * @param commandContent - исходный код команды
11
+ * @returns преобразованный код команды
12
+ */
13
+ static transformCommand(commandContent: string): string;
14
+ /**
15
+ * Создает API вызов для метода
16
+ * @param methodName - название метода
17
+ * @param args - аргументы метода
18
+ * @returns строка с API вызовом
19
+ */
20
+ private static createApiCall;
21
+ /**
22
+ * Преобразует команду и возвращает объект с кодом и названием класса
23
+ * @param commandContent - исходный код команды
24
+ * @returns объект с преобразованным кодом и названием класса
25
+ */
26
+ static transformCommandWithMetadata(commandContent: string): {
27
+ transformedCode: string;
28
+ className: string | null;
29
+ };
30
+ /**
31
+ * Преобразует файл команды
32
+ * @param filePath - путь к файлу команды
33
+ * @returns преобразованный код команды
34
+ */
35
+ static transformCommandFile(filePath: string): string;
36
+ /**
37
+ * Преобразует файл команды и возвращает объект с кодом и названием класса
38
+ * @param filePath - путь к файлу команды
39
+ * @returns объект с преобразованным кодом и названием класса
40
+ */
41
+ static transformCommandFileWithMetadata(filePath: string): {
42
+ transformedCode: string;
43
+ className: string | null;
44
+ };
45
+ /**
46
+ * Преобразует команду и возвращает строку с кодом
47
+ * @param originalFilePath - путь к оригинальному файлу
48
+ * @returns преобразованный код команды
49
+ */
50
+ static transformCommandToCode(originalFilePath: string): string;
51
+ /**
52
+ * Рекурсивно находит все .srdcmd файлы в директории src и преобразует их
53
+ * @param srcDir - директория src для поиска команд
54
+ * @returns массив объектов с путем к файлу, преобразованным кодом и названием класса
55
+ */
56
+ static transformAllCommands(srcDir?: string): Array<{
57
+ filePath: string;
58
+ transformedCode: string;
59
+ className: string | null;
60
+ }>;
61
+ }
@@ -0,0 +1,184 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ParserSharedCommandsService = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const fs = tslib_1.__importStar(require("fs"));
6
+ const path = tslib_1.__importStar(require("path"));
7
+ class ParserSharedCommandsService {
8
+ /**
9
+ * Парсит название класса из кода команды
10
+ * @param commandContent - исходный код команды
11
+ * @returns название класса или null, если не найдено
12
+ */
13
+ static parseClassName(commandContent) {
14
+ // Ищем объявление класса: class ClassName extends ...
15
+ const classRegex = /class\s+(\w+)\s+extends\s+\w+/g;
16
+ const match = classRegex.exec(commandContent);
17
+ if (match && match[1])
18
+ return match[1];
19
+ else
20
+ return null;
21
+ }
22
+ /**
23
+ * Преобразует команду, заменяя приватные методы на API вызовы
24
+ * @param commandContent - исходный код команды
25
+ * @returns преобразованный код команды
26
+ */
27
+ static transformCommand(commandContent) {
28
+ // Убираем все импорты
29
+ let transformedContent = commandContent.replace(/import\s+.*?from\s+['"][^'"]*['"];?\n?/g, '');
30
+ // Заменяем extends на SharedCommand
31
+ transformedContent = transformedContent.replace(/extends\s+\w+/g, 'extends SharedCommand');
32
+ // Находим все приватные методы (включая статические)
33
+ const privateMethodRegex = /private\s+(?:static\s+)?(?:async\s+)?(\w+)\s*\([^)]*\)\s*\{[\s\S]*?\n\s*\}\n?/g;
34
+ const privateMethods = [];
35
+ let match;
36
+ while ((match = privateMethodRegex.exec(commandContent)) !== null) {
37
+ privateMethods.push(match[1]);
38
+ }
39
+ // Получаем название класса для замены вызовов
40
+ const className = this.parseClassName(commandContent);
41
+ // Заменяем вызовы приватных методов на API вызовы
42
+ privateMethods.forEach((methodName) => {
43
+ // Паттерн для поиска вызовов this.methodName(...) и ClassName.methodName(...)
44
+ const thisMethodCallRegex = new RegExp(`this\\.${methodName}\\s*\\(([^)]*)\\)`, 'g');
45
+ const staticMethodCallRegex = new RegExp(`${className}\\.${methodName}\\s*\\(([^)]*)\\)`, 'g');
46
+ // Заменяем вызовы this.methodName(...)
47
+ transformedContent = transformedContent.replace(thisMethodCallRegex, (match, args) => {
48
+ return this.createApiCall(methodName, args);
49
+ });
50
+ // Заменяем вызовы ClassName.methodName(...)
51
+ if (className) {
52
+ transformedContent = transformedContent.replace(staticMethodCallRegex, (match, args) => {
53
+ return this.createApiCall(methodName, args);
54
+ });
55
+ }
56
+ });
57
+ // Удаляем все приватные методы по одному
58
+ privateMethods.forEach((methodName) => {
59
+ const methodRegex = new RegExp(`private\\s+(?:static\\s+)?(?:async\\s+)?${methodName}\\s*\\([^)]*\\)\\s*\\{[\\s\\S]*?\\n\\s*\\}\\n?`, 'g');
60
+ transformedContent = transformedContent.replace(methodRegex, '');
61
+ });
62
+ // Убираем лишние скобки и пустые строки
63
+ transformedContent = transformedContent.replace(/\n\s*\}\s*\n\s*\}/g, '\n}');
64
+ // Убираем лишние пустые строки
65
+ transformedContent = transformedContent.replace(/\n\s*\n\s*\n/g, '\n\n');
66
+ return transformedContent;
67
+ }
68
+ /**
69
+ * Создает API вызов для метода
70
+ * @param methodName - название метода
71
+ * @param args - аргументы метода
72
+ * @returns строка с API вызовом
73
+ */
74
+ static createApiCall(methodName, args) {
75
+ // Обрабатываем аргументы
76
+ let processedArgs = args.trim();
77
+ // Если аргументы пустые, создаем пустой объект
78
+ if (!processedArgs) {
79
+ processedArgs = '{}';
80
+ }
81
+ else {
82
+ // Если это объект, оставляем как есть
83
+ if (processedArgs.startsWith('{') && processedArgs.endsWith('}')) {
84
+ // Убираем лишние пробелы
85
+ processedArgs = processedArgs.replace(/\s+/g, ' ');
86
+ }
87
+ else {
88
+ // Если это не объект, оборачиваем в объект
89
+ processedArgs = `{ value: ${processedArgs} }`;
90
+ }
91
+ }
92
+ return `this.API.post(\`/commands/\${this.constructor.name}/${methodName}\`, ${processedArgs})`;
93
+ }
94
+ /**
95
+ * Преобразует команду и возвращает объект с кодом и названием класса
96
+ * @param commandContent - исходный код команды
97
+ * @returns объект с преобразованным кодом и названием класса
98
+ */
99
+ static transformCommandWithMetadata(commandContent) {
100
+ const className = this.parseClassName(commandContent);
101
+ const transformedCode = this.transformCommand(commandContent);
102
+ return {
103
+ transformedCode,
104
+ className,
105
+ };
106
+ }
107
+ /**
108
+ * Преобразует файл команды
109
+ * @param filePath - путь к файлу команды
110
+ * @returns преобразованный код команды
111
+ */
112
+ static transformCommandFile(filePath) {
113
+ try {
114
+ const content = fs.readFileSync(filePath, 'utf-8');
115
+ return this.transformCommand(content);
116
+ }
117
+ catch (error) {
118
+ throw new Error(`Ошибка при чтении файла ${filePath}: ${error}`);
119
+ }
120
+ }
121
+ /**
122
+ * Преобразует файл команды и возвращает объект с кодом и названием класса
123
+ * @param filePath - путь к файлу команды
124
+ * @returns объект с преобразованным кодом и названием класса
125
+ */
126
+ static transformCommandFileWithMetadata(filePath) {
127
+ try {
128
+ const content = fs.readFileSync(filePath, 'utf-8');
129
+ return this.transformCommandWithMetadata(content);
130
+ }
131
+ catch (error) {
132
+ throw new Error(`Ошибка при чтении файла ${filePath}: ${error}`);
133
+ }
134
+ }
135
+ /**
136
+ * Преобразует команду и возвращает строку с кодом
137
+ * @param originalFilePath - путь к оригинальному файлу
138
+ * @returns преобразованный код команды
139
+ */
140
+ static transformCommandToCode(originalFilePath) {
141
+ return this.transformCommandFile(originalFilePath);
142
+ }
143
+ /**
144
+ * Рекурсивно находит все .srdcmd файлы в директории src и преобразует их
145
+ * @param srcDir - директория src для поиска команд
146
+ * @returns массив объектов с путем к файлу, преобразованным кодом и названием класса
147
+ */
148
+ static transformAllCommands(srcDir = './src') {
149
+ if (!fs.existsSync(srcDir)) {
150
+ throw new Error(`Директория src не существует: ${srcDir}`);
151
+ }
152
+ const results = [];
153
+ // Рекурсивно проходим по всем файлам в src
154
+ const processDirectory = (dir) => {
155
+ const items = fs.readdirSync(dir);
156
+ items.forEach((item) => {
157
+ const fullPath = path.join(dir, item);
158
+ const stat = fs.statSync(fullPath);
159
+ if (stat.isDirectory()) {
160
+ // Рекурсивно обрабатываем поддиректории
161
+ processDirectory(fullPath);
162
+ }
163
+ else if (item.endsWith('.srdcmd.ts')) {
164
+ // Нашли .srdcmd файл - преобразуем его
165
+ try {
166
+ const { transformedCode, className } = this.transformCommandFileWithMetadata(fullPath);
167
+ results.push({
168
+ filePath: fullPath,
169
+ transformedCode,
170
+ className,
171
+ });
172
+ console.log(`Команда преобразована: ${fullPath} (Класс: ${className || 'не найден'})`);
173
+ }
174
+ catch (error) {
175
+ console.error(`Ошибка при преобразовании ${fullPath}: ${error}`);
176
+ }
177
+ }
178
+ });
179
+ };
180
+ processDirectory(srcDir);
181
+ return results;
182
+ }
183
+ }
184
+ exports.ParserSharedCommandsService = ParserSharedCommandsService;
@@ -0,0 +1,6 @@
1
+ import { Express } from 'express';
2
+ export declare class SharedCommandsServer {
3
+ private app;
4
+ constructor(app: Express);
5
+ initialize(): Promise<void>;
6
+ }
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SharedCommandsServer = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const SharedCommands_service_1 = require("./SharedCommands.service");
6
+ class SharedCommandsServer {
7
+ constructor(app) {
8
+ this.app = app;
9
+ }
10
+ initialize() {
11
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
12
+ this.app.post('/commands/:name/:method', (req, res) => tslib_1.__awaiter(this, void 0, void 0, function* () {
13
+ var _a;
14
+ const { name, method } = req.params;
15
+ //@ts-ignore
16
+ const execute = (_a = SharedCommands_service_1.SharedCommandsService.commands.find((c) => c.className === name)) === null || _a === void 0 ? void 0 : _a[method];
17
+ if (execute)
18
+ res.send(yield execute(req.body));
19
+ }));
20
+ });
21
+ }
22
+ }
23
+ exports.SharedCommandsServer = SharedCommandsServer;
@@ -0,0 +1,8 @@
1
+ export declare class SharedCommandsService {
2
+ static commands: {
3
+ filePath: string;
4
+ transformedCode: string;
5
+ className: string | null;
6
+ }[];
7
+ static init(projectName: string): Promise<void>;
8
+ }
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SharedCommandsService = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const __1 = require("..");
6
+ const ParserSharedCommands_service_1 = require("./ParserSharedCommands.service");
7
+ class SharedCommandsService {
8
+ static init(projectName) {
9
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
10
+ this.commands = ParserSharedCommands_service_1.ParserSharedCommandsService.transformAllCommands();
11
+ yield __1.Client.API.delete(`/projects/${projectName}/commands`).catch(console.error);
12
+ for (const command of this.commands)
13
+ yield __1.Client.API.post(`/projects/${projectName}/commands`, {
14
+ name: command.className,
15
+ code: command.transformedCode,
16
+ }).catch(console.error);
17
+ });
18
+ }
19
+ }
20
+ exports.SharedCommandsService = SharedCommandsService;
21
+ SharedCommandsService.commands = [];
package/package.json CHANGED
@@ -1,16 +1,19 @@
1
1
  {
2
2
  "name": "nexushub-commands",
3
- "version": "1.11.2",
3
+ "version": "2.0.0",
4
4
  "main": "./lib/index.js",
5
5
  "license": "MIT",
6
6
  "dependencies": {
7
7
  "axios": "^1.9.0",
8
- "chalk": "^5.4.1"
8
+ "chalk": "^5.4.1",
9
+ "express": "^5.1.0"
9
10
  },
10
11
  "peerDependencies": {
11
12
  "evogram": "^2.0.8"
12
13
  },
13
14
  "devDependencies": {
15
+ "@types/express": "^5.0.3",
16
+ "@types/node": "^24.3.0",
14
17
  "evogram": "^2.2.3"
15
18
  }
16
19
  }
package/src/Client.ts CHANGED
@@ -61,5 +61,6 @@ const defaultConfig: DepositConfig = {
61
61
  }
62
62
 
63
63
  export class Client {
64
+ public static API: AxiosInstance
64
65
  public static config: (context: CommandContext) => DepositConfig
65
66
  }
@@ -0,0 +1,199 @@
1
+ import * as fs from 'fs'
2
+ import * as path from 'path'
3
+
4
+ export class ParserSharedCommandsService {
5
+ /**
6
+ * Парсит название класса из кода команды
7
+ * @param commandContent - исходный код команды
8
+ * @returns название класса или null, если не найдено
9
+ */
10
+ static parseClassName(commandContent: string): string | null {
11
+ // Ищем объявление класса: class ClassName extends ...
12
+ const classRegex = /class\s+(\w+)\s+extends\s+\w+/g
13
+ const match = classRegex.exec(commandContent)
14
+
15
+ if (match && match[1]) return match[1]
16
+ else return null
17
+ }
18
+
19
+ /**
20
+ * Преобразует команду, заменяя приватные методы на API вызовы
21
+ * @param commandContent - исходный код команды
22
+ * @returns преобразованный код команды
23
+ */
24
+ static transformCommand(commandContent: string): string {
25
+ // Убираем все импорты
26
+ let transformedContent = commandContent.replace(/import\s+.*?from\s+['"][^'"]*['"];?\n?/g, '')
27
+
28
+ // Заменяем extends на SharedCommand
29
+ transformedContent = transformedContent.replace(/extends\s+\w+/g, 'extends SharedCommand')
30
+
31
+ // Находим все приватные методы (включая статические)
32
+ const privateMethodRegex = /private\s+(?:static\s+)?(?:async\s+)?(\w+)\s*\([^)]*\)\s*\{[\s\S]*?\n\s*\}\n?/g
33
+ const privateMethods: string[] = []
34
+ let match
35
+
36
+ while ((match = privateMethodRegex.exec(commandContent)) !== null) {
37
+ privateMethods.push(match[1])
38
+ }
39
+
40
+ // Получаем название класса для замены вызовов
41
+ const className = this.parseClassName(commandContent)
42
+
43
+ // Заменяем вызовы приватных методов на API вызовы
44
+ privateMethods.forEach((methodName) => {
45
+ // Паттерн для поиска вызовов this.methodName(...) и ClassName.methodName(...)
46
+ const thisMethodCallRegex = new RegExp(`this\\.${methodName}\\s*\\(([^)]*)\\)`, 'g')
47
+ const staticMethodCallRegex = new RegExp(`${className}\\.${methodName}\\s*\\(([^)]*)\\)`, 'g')
48
+
49
+ // Заменяем вызовы this.methodName(...)
50
+ transformedContent = transformedContent.replace(thisMethodCallRegex, (match, args) => {
51
+ return this.createApiCall(methodName, args)
52
+ })
53
+
54
+ // Заменяем вызовы ClassName.methodName(...)
55
+ if (className) {
56
+ transformedContent = transformedContent.replace(staticMethodCallRegex, (match, args) => {
57
+ return this.createApiCall(methodName, args)
58
+ })
59
+ }
60
+ })
61
+
62
+ // Удаляем все приватные методы по одному
63
+ privateMethods.forEach((methodName) => {
64
+ const methodRegex = new RegExp(`private\\s+(?:static\\s+)?(?:async\\s+)?${methodName}\\s*\\([^)]*\\)\\s*\\{[\\s\\S]*?\\n\\s*\\}\\n?`, 'g')
65
+ transformedContent = transformedContent.replace(methodRegex, '')
66
+ })
67
+
68
+ // Убираем лишние скобки и пустые строки
69
+ transformedContent = transformedContent.replace(/\n\s*\}\s*\n\s*\}/g, '\n}')
70
+
71
+ // Убираем лишние пустые строки
72
+ transformedContent = transformedContent.replace(/\n\s*\n\s*\n/g, '\n\n')
73
+
74
+ return transformedContent
75
+ }
76
+
77
+ /**
78
+ * Создает API вызов для метода
79
+ * @param methodName - название метода
80
+ * @param args - аргументы метода
81
+ * @returns строка с API вызовом
82
+ */
83
+ private static createApiCall(methodName: string, args: string): string {
84
+ // Обрабатываем аргументы
85
+ let processedArgs = args.trim()
86
+
87
+ // Если аргументы пустые, создаем пустой объект
88
+ if (!processedArgs) {
89
+ processedArgs = '{}'
90
+ } else {
91
+ // Если это объект, оставляем как есть
92
+ if (processedArgs.startsWith('{') && processedArgs.endsWith('}')) {
93
+ // Убираем лишние пробелы
94
+ processedArgs = processedArgs.replace(/\s+/g, ' ')
95
+ } else {
96
+ // Если это не объект, оборачиваем в объект
97
+ processedArgs = `{ value: ${processedArgs} }`
98
+ }
99
+ }
100
+
101
+ return `this.API.post(\`/commands/\${this.constructor.name}/${methodName}\`, ${processedArgs})`
102
+ }
103
+
104
+ /**
105
+ * Преобразует команду и возвращает объект с кодом и названием класса
106
+ * @param commandContent - исходный код команды
107
+ * @returns объект с преобразованным кодом и названием класса
108
+ */
109
+ static transformCommandWithMetadata(commandContent: string): { transformedCode: string; className: string | null } {
110
+ const className = this.parseClassName(commandContent)
111
+ const transformedCode = this.transformCommand(commandContent)
112
+
113
+ return {
114
+ transformedCode,
115
+ className,
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Преобразует файл команды
121
+ * @param filePath - путь к файлу команды
122
+ * @returns преобразованный код команды
123
+ */
124
+ static transformCommandFile(filePath: string): string {
125
+ try {
126
+ const content = fs.readFileSync(filePath, 'utf-8')
127
+ return this.transformCommand(content)
128
+ } catch (error) {
129
+ throw new Error(`Ошибка при чтении файла ${filePath}: ${error}`)
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Преобразует файл команды и возвращает объект с кодом и названием класса
135
+ * @param filePath - путь к файлу команды
136
+ * @returns объект с преобразованным кодом и названием класса
137
+ */
138
+ static transformCommandFileWithMetadata(filePath: string): { transformedCode: string; className: string | null } {
139
+ try {
140
+ const content = fs.readFileSync(filePath, 'utf-8')
141
+ return this.transformCommandWithMetadata(content)
142
+ } catch (error) {
143
+ throw new Error(`Ошибка при чтении файла ${filePath}: ${error}`)
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Преобразует команду и возвращает строку с кодом
149
+ * @param originalFilePath - путь к оригинальному файлу
150
+ * @returns преобразованный код команды
151
+ */
152
+ static transformCommandToCode(originalFilePath: string): string {
153
+ return this.transformCommandFile(originalFilePath)
154
+ }
155
+
156
+ /**
157
+ * Рекурсивно находит все .srdcmd файлы в директории src и преобразует их
158
+ * @param srcDir - директория src для поиска команд
159
+ * @returns массив объектов с путем к файлу, преобразованным кодом и названием класса
160
+ */
161
+ static transformAllCommands(srcDir: string = './src'): Array<{ filePath: string; transformedCode: string; className: string | null }> {
162
+ if (!fs.existsSync(srcDir)) {
163
+ throw new Error(`Директория src не существует: ${srcDir}`)
164
+ }
165
+
166
+ const results: Array<{ filePath: string; transformedCode: string; className: string | null }> = []
167
+
168
+ // Рекурсивно проходим по всем файлам в src
169
+ const processDirectory = (dir: string) => {
170
+ const items = fs.readdirSync(dir)
171
+
172
+ items.forEach((item: string) => {
173
+ const fullPath = path.join(dir, item)
174
+ const stat = fs.statSync(fullPath)
175
+
176
+ if (stat.isDirectory()) {
177
+ // Рекурсивно обрабатываем поддиректории
178
+ processDirectory(fullPath)
179
+ } else if (item.endsWith('.srdcmd.ts')) {
180
+ // Нашли .srdcmd файл - преобразуем его
181
+ try {
182
+ const { transformedCode, className } = this.transformCommandFileWithMetadata(fullPath)
183
+ results.push({
184
+ filePath: fullPath,
185
+ transformedCode,
186
+ className,
187
+ })
188
+ console.log(`Команда преобразована: ${fullPath} (Класс: ${className || 'не найден'})`)
189
+ } catch (error) {
190
+ console.error(`Ошибка при преобразовании ${fullPath}: ${error}`)
191
+ }
192
+ }
193
+ })
194
+ }
195
+
196
+ processDirectory(srcDir)
197
+ return results
198
+ }
199
+ }
@@ -0,0 +1,16 @@
1
+ import { Express } from 'express'
2
+ import { SharedCommandsService } from './SharedCommands.service'
3
+
4
+ export class SharedCommandsServer {
5
+ constructor(private app: Express) {}
6
+
7
+ async initialize() {
8
+ this.app.post('/commands/:name/:method', async (req, res) => {
9
+ const { name, method } = req.params
10
+
11
+ //@ts-ignore
12
+ const execute = SharedCommandsService.commands.find((c) => c.className === name)?.[method]
13
+ if (execute) res.send(await execute(req.body))
14
+ })
15
+ }
16
+ }
@@ -0,0 +1,17 @@
1
+ import { Client } from '..'
2
+ import { ParserSharedCommandsService } from './ParserSharedCommands.service'
3
+
4
+ export class SharedCommandsService {
5
+ public static commands: { filePath: string; transformedCode: string; className: string | null }[] = []
6
+
7
+ public static async init(projectName: string) {
8
+ this.commands = ParserSharedCommandsService.transformAllCommands()
9
+
10
+ await Client.API.delete(`/projects/${projectName}/commands`).catch(console.error)
11
+ for (const command of this.commands)
12
+ await Client.API.post(`/projects/${projectName}/commands`, {
13
+ name: command.className,
14
+ code: command.transformedCode,
15
+ }).catch(console.error)
16
+ }
17
+ }