@gravity-ui/app-builder 0.28.0 → 0.28.1-beta.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/dist/commands/dev/index.js +85 -7
- package/dist/commands/dev/ui/LogCollector.d.ts +13 -0
- package/dist/commands/dev/ui/LogCollector.js +89 -0
- package/dist/commands/dev/ui/TerminalTabs.d.ts +25 -0
- package/dist/commands/dev/ui/TerminalTabs.js +183 -0
- package/dist/commands/dev/ui/demo.d.ts +2 -0
- package/dist/commands/dev/ui/demo.js +61 -0
- package/package.json +5 -2
|
@@ -34,8 +34,70 @@ const rimraf_1 = require("rimraf");
|
|
|
34
34
|
const utils_1 = require("../../common/utils");
|
|
35
35
|
const logger_1 = __importDefault(require("../../common/logger"));
|
|
36
36
|
const paths_1 = __importDefault(require("../../common/paths"));
|
|
37
|
+
// Импортируем систему табов для логирования
|
|
38
|
+
const TerminalTabs_1 = require("./ui/TerminalTabs");
|
|
39
|
+
// Глобальная система табов
|
|
40
|
+
let terminalTabs;
|
|
41
|
+
// Функция для добавления лога в систему табов
|
|
42
|
+
function addLogToTabs(type, message, level = 'message') {
|
|
43
|
+
if (terminalTabs && process.stdout.isTTY) {
|
|
44
|
+
terminalTabs.addLog({
|
|
45
|
+
type,
|
|
46
|
+
message,
|
|
47
|
+
timestamp: Date.now(),
|
|
48
|
+
level,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// Обёртка для logger с интеграцией в табы
|
|
53
|
+
function createLoggerWrapper(type) {
|
|
54
|
+
return {
|
|
55
|
+
message: (...args) => {
|
|
56
|
+
const message = args.join(' ');
|
|
57
|
+
addLogToTabs(type, message, 'message');
|
|
58
|
+
if (!process.stdout.isTTY) {
|
|
59
|
+
logger_1.default.message(`[${type}]`, message);
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
success: (...args) => {
|
|
63
|
+
const message = args.join(' ');
|
|
64
|
+
addLogToTabs(type, message, 'success');
|
|
65
|
+
if (!process.stdout.isTTY) {
|
|
66
|
+
logger_1.default.success(`[${type}]`, message);
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
warning: (...args) => {
|
|
70
|
+
const message = args.join(' ');
|
|
71
|
+
addLogToTabs(type, message, 'warning');
|
|
72
|
+
if (!process.stdout.isTTY) {
|
|
73
|
+
logger_1.default.warning(`[${type}]`, message);
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
error: (...args) => {
|
|
77
|
+
const message = args.join(' ');
|
|
78
|
+
addLogToTabs(type, message, 'error');
|
|
79
|
+
if (!process.stdout.isTTY) {
|
|
80
|
+
logger_1.default.error(`[${type}]`, message);
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
verbose: (...args) => {
|
|
84
|
+
const message = args.join(' ');
|
|
85
|
+
addLogToTabs(type, message, 'verbose');
|
|
86
|
+
if (!process.stdout.isTTY) {
|
|
87
|
+
logger_1.default.verbose(`[${type}]`, message);
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
37
92
|
async function default_1(config) {
|
|
38
93
|
process.env.NODE_ENV = 'development';
|
|
94
|
+
// Инициализируем систему табов только в TTY
|
|
95
|
+
if (process.stdout.isTTY) {
|
|
96
|
+
terminalTabs = new TerminalTabs_1.TerminalTabs();
|
|
97
|
+
terminalTabs.initialize();
|
|
98
|
+
// Добавляем начальный лог
|
|
99
|
+
addLogToTabs('all', 'Запуск режима разработки...', 'message');
|
|
100
|
+
}
|
|
39
101
|
const shouldCompileClient = (0, utils_1.shouldCompileTarget)(config.target, 'client');
|
|
40
102
|
const shouldCompileServer = (0, utils_1.shouldCompileTarget)(config.target, 'server');
|
|
41
103
|
if (shouldCompileClient && shouldCompileServer) {
|
|
@@ -48,7 +110,8 @@ async function default_1(config) {
|
|
|
48
110
|
const { inspect, inspectBrk } = config.server;
|
|
49
111
|
const startNodemon = () => {
|
|
50
112
|
if (needToStartNodemon && serverCompiled && clientCompiled) {
|
|
51
|
-
|
|
113
|
+
const serverLogger = createLoggerWrapper('server');
|
|
114
|
+
serverLogger.message('Starting application at', serverPath);
|
|
52
115
|
const nodeArgs = ['--enable-source-maps'];
|
|
53
116
|
if (inspect || inspectBrk) {
|
|
54
117
|
nodeArgs.push(`--${inspect ? 'inspect' : 'inspect-brk'}=:::${inspect || inspectBrk}`);
|
|
@@ -77,6 +140,8 @@ async function default_1(config) {
|
|
|
77
140
|
serverCompilation.onMessage((msg) => {
|
|
78
141
|
if (typeof msg === 'object' && 'type' in msg && msg.type === 'Emitted') {
|
|
79
142
|
serverCompiled = true;
|
|
143
|
+
const serverLogger = createLoggerWrapper('server');
|
|
144
|
+
serverLogger.success('Server compilation completed');
|
|
80
145
|
startNodemon();
|
|
81
146
|
}
|
|
82
147
|
});
|
|
@@ -85,25 +150,38 @@ async function default_1(config) {
|
|
|
85
150
|
if (shouldCompileClient) {
|
|
86
151
|
const { watchClientCompilation } = await import('./client.js');
|
|
87
152
|
clientCompilation = await watchClientCompilation(config, () => {
|
|
88
|
-
|
|
153
|
+
const clientLogger = createLoggerWrapper('client');
|
|
154
|
+
clientLogger.success('Manifest was compiled successfully');
|
|
89
155
|
clientCompiled = true;
|
|
90
156
|
startNodemon();
|
|
91
157
|
});
|
|
92
158
|
}
|
|
93
|
-
|
|
94
|
-
|
|
159
|
+
const cleanup = async () => {
|
|
160
|
+
if (terminalTabs) {
|
|
161
|
+
terminalTabs.destroy();
|
|
162
|
+
}
|
|
95
163
|
await serverCompilation?.stop('SIGINT');
|
|
96
164
|
await clientCompilation?.stop();
|
|
165
|
+
};
|
|
166
|
+
process.on('SIGINT', async () => {
|
|
167
|
+
if (!process.stdout.isTTY) {
|
|
168
|
+
logger_1.default.success('\nCleaning up...');
|
|
169
|
+
}
|
|
170
|
+
await cleanup();
|
|
97
171
|
process.exit(1);
|
|
98
172
|
});
|
|
99
173
|
process.on('SIGTERM', async () => {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
174
|
+
if (!process.stdout.isTTY) {
|
|
175
|
+
logger_1.default.success('\nCleaning up...');
|
|
176
|
+
}
|
|
177
|
+
await cleanup();
|
|
103
178
|
process.exit(1);
|
|
104
179
|
});
|
|
105
180
|
(0, signal_exit_1.onExit)((_code, signal) => {
|
|
106
181
|
serverCompilation?.stop(signal);
|
|
107
182
|
clientCompilation?.stop();
|
|
183
|
+
if (terminalTabs) {
|
|
184
|
+
terminalTabs.destroy();
|
|
185
|
+
}
|
|
108
186
|
});
|
|
109
187
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import { BaseLogger } from '../../../common/logger';
|
|
3
|
+
import type { LogEntry } from './TerminalTabs';
|
|
4
|
+
export declare class LogCollector extends EventEmitter {
|
|
5
|
+
private logs;
|
|
6
|
+
private maxLogs;
|
|
7
|
+
constructor(maxLogs?: number);
|
|
8
|
+
addLog(entry: LogEntry): void;
|
|
9
|
+
getLogs(): LogEntry[];
|
|
10
|
+
clear(): void;
|
|
11
|
+
createLogger(type: 'server' | 'client', namespace?: string, verbose?: boolean): BaseLogger;
|
|
12
|
+
}
|
|
13
|
+
export declare const globalLogCollector: LogCollector;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.globalLogCollector = exports.LogCollector = void 0;
|
|
4
|
+
const events_1 = require("events");
|
|
5
|
+
const logger_1 = require("../../../common/logger");
|
|
6
|
+
class LogCollector extends events_1.EventEmitter {
|
|
7
|
+
logs = [];
|
|
8
|
+
maxLogs = 1000;
|
|
9
|
+
constructor(maxLogs = 1000) {
|
|
10
|
+
super();
|
|
11
|
+
this.maxLogs = maxLogs;
|
|
12
|
+
}
|
|
13
|
+
addLog(entry) {
|
|
14
|
+
this.logs.push(entry);
|
|
15
|
+
if (this.logs.length > this.maxLogs) {
|
|
16
|
+
this.logs = this.logs.slice(-this.maxLogs);
|
|
17
|
+
}
|
|
18
|
+
this.emit('log', entry);
|
|
19
|
+
}
|
|
20
|
+
getLogs() {
|
|
21
|
+
return [...this.logs];
|
|
22
|
+
}
|
|
23
|
+
clear() {
|
|
24
|
+
this.logs = [];
|
|
25
|
+
this.emit('clear');
|
|
26
|
+
}
|
|
27
|
+
createLogger(type, namespace, verbose = false) {
|
|
28
|
+
const logger = new logger_1.Logger(namespace, verbose);
|
|
29
|
+
// Перехватываем методы логирования
|
|
30
|
+
const originalMessage = logger.message.bind(logger);
|
|
31
|
+
const originalSuccess = logger.success.bind(logger);
|
|
32
|
+
const originalWarning = logger.warning.bind(logger);
|
|
33
|
+
const originalError = logger.error.bind(logger);
|
|
34
|
+
const originalVerbose = logger.verbose.bind(logger);
|
|
35
|
+
logger.message = (...args) => {
|
|
36
|
+
const message = args.join(' ');
|
|
37
|
+
this.addLog({
|
|
38
|
+
type,
|
|
39
|
+
message,
|
|
40
|
+
timestamp: Date.now(),
|
|
41
|
+
level: 'message',
|
|
42
|
+
});
|
|
43
|
+
return originalMessage(...args);
|
|
44
|
+
};
|
|
45
|
+
logger.success = (...args) => {
|
|
46
|
+
const message = args.join(' ');
|
|
47
|
+
this.addLog({
|
|
48
|
+
type,
|
|
49
|
+
message,
|
|
50
|
+
timestamp: Date.now(),
|
|
51
|
+
level: 'success',
|
|
52
|
+
});
|
|
53
|
+
return originalSuccess(...args);
|
|
54
|
+
};
|
|
55
|
+
logger.warning = (...args) => {
|
|
56
|
+
const message = args.join(' ');
|
|
57
|
+
this.addLog({
|
|
58
|
+
type,
|
|
59
|
+
message,
|
|
60
|
+
timestamp: Date.now(),
|
|
61
|
+
level: 'warning',
|
|
62
|
+
});
|
|
63
|
+
return originalWarning(...args);
|
|
64
|
+
};
|
|
65
|
+
logger.error = (...args) => {
|
|
66
|
+
const message = args.join(' ');
|
|
67
|
+
this.addLog({
|
|
68
|
+
type,
|
|
69
|
+
message,
|
|
70
|
+
timestamp: Date.now(),
|
|
71
|
+
level: 'error',
|
|
72
|
+
});
|
|
73
|
+
return originalError(...args);
|
|
74
|
+
};
|
|
75
|
+
logger.verbose = (...args) => {
|
|
76
|
+
const message = args.join(' ');
|
|
77
|
+
this.addLog({
|
|
78
|
+
type,
|
|
79
|
+
message,
|
|
80
|
+
timestamp: Date.now(),
|
|
81
|
+
level: 'verbose',
|
|
82
|
+
});
|
|
83
|
+
return originalVerbose(...args);
|
|
84
|
+
};
|
|
85
|
+
return logger;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
exports.LogCollector = LogCollector;
|
|
89
|
+
exports.globalLogCollector = new LogCollector();
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
export interface LogEntry {
|
|
3
|
+
type: 'server' | 'client' | 'all';
|
|
4
|
+
message: string;
|
|
5
|
+
timestamp: number;
|
|
6
|
+
level: 'message' | 'success' | 'warning' | 'error' | 'verbose';
|
|
7
|
+
}
|
|
8
|
+
export declare class TerminalTabs extends EventEmitter {
|
|
9
|
+
private logs;
|
|
10
|
+
private activeTab;
|
|
11
|
+
private maxLogs;
|
|
12
|
+
private rl;
|
|
13
|
+
private isInitialized;
|
|
14
|
+
constructor(maxLogs?: number);
|
|
15
|
+
initialize(): void;
|
|
16
|
+
addLog(entry: LogEntry): void;
|
|
17
|
+
destroy(): void;
|
|
18
|
+
private setupKeyHandlers;
|
|
19
|
+
private clearLogs;
|
|
20
|
+
private render;
|
|
21
|
+
private renderTabs;
|
|
22
|
+
private renderLogs;
|
|
23
|
+
private formatLogMessage;
|
|
24
|
+
private renderHelp;
|
|
25
|
+
}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.TerminalTabs = void 0;
|
|
27
|
+
const readline = __importStar(require("readline"));
|
|
28
|
+
const events_1 = require("events");
|
|
29
|
+
// ANSI escape codes для цветов
|
|
30
|
+
const ansi = {
|
|
31
|
+
reset: '\x1b[0m',
|
|
32
|
+
bold: '\x1b[1m',
|
|
33
|
+
dim: '\x1b[2m',
|
|
34
|
+
cyan: '\x1b[36m',
|
|
35
|
+
blue: '\x1b[34m',
|
|
36
|
+
green: '\x1b[32m',
|
|
37
|
+
yellow: '\x1b[33m',
|
|
38
|
+
red: '\x1b[31m',
|
|
39
|
+
white: '\x1b[37m',
|
|
40
|
+
bgBlue: '\x1b[44m',
|
|
41
|
+
};
|
|
42
|
+
const tabs = [
|
|
43
|
+
{ key: 'all', title: 'Все логи', filter: () => true },
|
|
44
|
+
{ key: 'server', title: 'Сервер', filter: (log) => log.type === 'server' },
|
|
45
|
+
{ key: 'client', title: 'Клиент', filter: (log) => log.type === 'client' },
|
|
46
|
+
];
|
|
47
|
+
class TerminalTabs extends events_1.EventEmitter {
|
|
48
|
+
logs = [];
|
|
49
|
+
activeTab = 0;
|
|
50
|
+
maxLogs = 1000;
|
|
51
|
+
rl;
|
|
52
|
+
isInitialized = false;
|
|
53
|
+
constructor(maxLogs = 1000) {
|
|
54
|
+
super();
|
|
55
|
+
this.maxLogs = maxLogs;
|
|
56
|
+
this.rl = readline.createInterface({
|
|
57
|
+
input: process.stdin,
|
|
58
|
+
output: process.stdout,
|
|
59
|
+
});
|
|
60
|
+
this.setupKeyHandlers();
|
|
61
|
+
}
|
|
62
|
+
initialize() {
|
|
63
|
+
if (this.isInitialized)
|
|
64
|
+
return;
|
|
65
|
+
this.isInitialized = true;
|
|
66
|
+
console.clear();
|
|
67
|
+
this.render();
|
|
68
|
+
}
|
|
69
|
+
addLog(entry) {
|
|
70
|
+
this.logs.push(entry);
|
|
71
|
+
if (this.logs.length > this.maxLogs) {
|
|
72
|
+
this.logs = this.logs.slice(-this.maxLogs);
|
|
73
|
+
}
|
|
74
|
+
// Обновляем только если таб инициализирован
|
|
75
|
+
if (this.isInitialized) {
|
|
76
|
+
this.render();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
destroy() {
|
|
80
|
+
if (process.stdin.isTTY) {
|
|
81
|
+
process.stdin.setRawMode(false);
|
|
82
|
+
}
|
|
83
|
+
this.rl.close();
|
|
84
|
+
}
|
|
85
|
+
setupKeyHandlers() {
|
|
86
|
+
if (process.stdin.isTTY) {
|
|
87
|
+
process.stdin.setRawMode(true);
|
|
88
|
+
process.stdin.setEncoding('utf8');
|
|
89
|
+
process.stdin.on('data', (key) => {
|
|
90
|
+
// Ctrl+C
|
|
91
|
+
if (key === '\u0003') {
|
|
92
|
+
process.exit();
|
|
93
|
+
}
|
|
94
|
+
switch (key) {
|
|
95
|
+
case '\u001b[D': // Стрелка влево
|
|
96
|
+
case 'h':
|
|
97
|
+
this.activeTab = this.activeTab > 0 ? this.activeTab - 1 : tabs.length - 1;
|
|
98
|
+
this.render();
|
|
99
|
+
break;
|
|
100
|
+
case '\u001b[C': // Стрелка вправо
|
|
101
|
+
case 'l':
|
|
102
|
+
this.activeTab = this.activeTab < tabs.length - 1 ? this.activeTab + 1 : 0;
|
|
103
|
+
this.render();
|
|
104
|
+
break;
|
|
105
|
+
case 'c':
|
|
106
|
+
this.clearLogs();
|
|
107
|
+
break;
|
|
108
|
+
case 'q':
|
|
109
|
+
process.exit();
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
clearLogs() {
|
|
116
|
+
this.logs = [];
|
|
117
|
+
this.render();
|
|
118
|
+
}
|
|
119
|
+
render() {
|
|
120
|
+
if (!process.stdout.isTTY)
|
|
121
|
+
return;
|
|
122
|
+
// Очищаем экран
|
|
123
|
+
console.clear();
|
|
124
|
+
// Рендерим табы
|
|
125
|
+
this.renderTabs();
|
|
126
|
+
// Рендерим логи для активного таба
|
|
127
|
+
this.renderLogs();
|
|
128
|
+
// Рендерим справку
|
|
129
|
+
this.renderHelp();
|
|
130
|
+
}
|
|
131
|
+
renderTabs() {
|
|
132
|
+
let tabsLine = '';
|
|
133
|
+
tabs.forEach((tab, index) => {
|
|
134
|
+
const isActive = index === this.activeTab;
|
|
135
|
+
const title = ` ${tab.title} `;
|
|
136
|
+
if (isActive) {
|
|
137
|
+
tabsLine += `${ansi.cyan}${ansi.bold}${ansi.bgBlue}${title}${ansi.reset}`;
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
tabsLine += `${ansi.white}${title}${ansi.reset}`;
|
|
141
|
+
}
|
|
142
|
+
tabsLine += ' ';
|
|
143
|
+
});
|
|
144
|
+
console.log(tabsLine);
|
|
145
|
+
console.log(`${ansi.dim}${'─'.repeat(process.stdout.columns || 80)}${ansi.reset}`);
|
|
146
|
+
}
|
|
147
|
+
renderLogs() {
|
|
148
|
+
const currentTab = tabs[this.activeTab];
|
|
149
|
+
if (!currentTab)
|
|
150
|
+
return;
|
|
151
|
+
const filteredLogs = this.logs.filter(currentTab.filter);
|
|
152
|
+
const displayLogs = filteredLogs.slice(-40); // Показываем последние 40 логов
|
|
153
|
+
displayLogs.forEach((log) => {
|
|
154
|
+
console.log(this.formatLogMessage(log));
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
formatLogMessage(log) {
|
|
158
|
+
const timestamp = new Date(log.timestamp).toLocaleTimeString();
|
|
159
|
+
const prefix = `${ansi.dim}[${timestamp}] ${ansi.reset}`;
|
|
160
|
+
let colorCode = ansi.white;
|
|
161
|
+
switch (log.level) {
|
|
162
|
+
case 'success':
|
|
163
|
+
colorCode = ansi.green;
|
|
164
|
+
break;
|
|
165
|
+
case 'warning':
|
|
166
|
+
colorCode = ansi.yellow;
|
|
167
|
+
break;
|
|
168
|
+
case 'error':
|
|
169
|
+
colorCode = ansi.red;
|
|
170
|
+
break;
|
|
171
|
+
case 'verbose':
|
|
172
|
+
colorCode = ansi.dim;
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
return `${prefix}${colorCode}${log.message}${ansi.reset}`;
|
|
176
|
+
}
|
|
177
|
+
renderHelp() {
|
|
178
|
+
const filteredCount = this.logs.filter(tabs[this.activeTab]?.filter || (() => true)).length;
|
|
179
|
+
const help = `${ansi.dim}\nУправление: ← → (или h/l) - переключение табов | c - очистить | q - выход | Показано: ${filteredCount} логов${ansi.reset}`;
|
|
180
|
+
console.log(help);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
exports.TerminalTabs = TerminalTabs;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const TerminalTabs_1 = require("./TerminalTabs");
|
|
5
|
+
const tabs = new TerminalTabs_1.TerminalTabs();
|
|
6
|
+
// Инициализируем интерфейс табов
|
|
7
|
+
tabs.initialize();
|
|
8
|
+
// Симулируем логи от сервера и клиента
|
|
9
|
+
let logCounter = 0;
|
|
10
|
+
const addServerLog = () => {
|
|
11
|
+
tabs.addLog({
|
|
12
|
+
type: 'server',
|
|
13
|
+
message: `Server log message ${++logCounter}`,
|
|
14
|
+
timestamp: Date.now(),
|
|
15
|
+
level: Math.random() > 0.7 ? 'success' : 'message',
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
const addClientLog = () => {
|
|
19
|
+
tabs.addLog({
|
|
20
|
+
type: 'client',
|
|
21
|
+
message: `Client build progress ${++logCounter}`,
|
|
22
|
+
timestamp: Date.now(),
|
|
23
|
+
level: Math.random() > 0.8 ? 'warning' : 'message',
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
const addErrorLog = () => {
|
|
27
|
+
const type = Math.random() > 0.5 ? 'server' : 'client';
|
|
28
|
+
tabs.addLog({
|
|
29
|
+
type,
|
|
30
|
+
message: `Error in ${type}: Something went wrong ${++logCounter}`,
|
|
31
|
+
timestamp: Date.now(),
|
|
32
|
+
level: 'error',
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
// Добавляем начальные логи
|
|
36
|
+
tabs.addLog({
|
|
37
|
+
type: 'all',
|
|
38
|
+
message: 'Демонстрация системы табов запущена',
|
|
39
|
+
timestamp: Date.now(),
|
|
40
|
+
level: 'success',
|
|
41
|
+
});
|
|
42
|
+
// Симулируем активность
|
|
43
|
+
setInterval(() => {
|
|
44
|
+
const rand = Math.random();
|
|
45
|
+
if (rand > 0.7) {
|
|
46
|
+
addServerLog();
|
|
47
|
+
}
|
|
48
|
+
else if (rand > 0.4) {
|
|
49
|
+
addClientLog();
|
|
50
|
+
}
|
|
51
|
+
else if (rand > 0.9) {
|
|
52
|
+
addErrorLog();
|
|
53
|
+
}
|
|
54
|
+
}, 500);
|
|
55
|
+
// Обработка выхода
|
|
56
|
+
process.on('SIGINT', () => {
|
|
57
|
+
tabs.destroy();
|
|
58
|
+
console.log('\nДемонстрация завершена');
|
|
59
|
+
process.exit(0);
|
|
60
|
+
});
|
|
61
|
+
console.log('Нажмите Ctrl+C для выхода, стрелки влево/вправо для переключения табов, c для очистки');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gravity-ui/app-builder",
|
|
3
|
-
"version": "0.28.0",
|
|
3
|
+
"version": "0.28.1-beta.0",
|
|
4
4
|
"description": "Develop and build your React client-server projects, powered by typescript and webpack",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -75,15 +75,16 @@
|
|
|
75
75
|
"@rspack/core": "1.3.9",
|
|
76
76
|
"@rspack/dev-server": "^1.1.1",
|
|
77
77
|
"@rspack/plugin-react-refresh": "^1.4.1",
|
|
78
|
-
"@statoscope/webpack-plugin": "^5.29.0",
|
|
79
78
|
"@statoscope/stats": "^5.28.1",
|
|
80
79
|
"@statoscope/stats-extension-compressed": "^5.28.1",
|
|
81
80
|
"@statoscope/webpack-model": "^5.29.0",
|
|
81
|
+
"@statoscope/webpack-plugin": "^5.29.0",
|
|
82
82
|
"@svgr/core": "^8.1.0",
|
|
83
83
|
"@svgr/plugin-jsx": "^8.1.0",
|
|
84
84
|
"@svgr/webpack": "^8.1.0",
|
|
85
85
|
"@swc/core": "1.11.24",
|
|
86
86
|
"@swc/plugin-transform-imports": "7.0.3",
|
|
87
|
+
"@types/react": "^19.1.6",
|
|
87
88
|
"babel-loader": "^9.2.1",
|
|
88
89
|
"babel-plugin-import": "^1.13.8",
|
|
89
90
|
"babel-plugin-inline-react-svg": "^2.0.2",
|
|
@@ -107,6 +108,8 @@
|
|
|
107
108
|
"fork-ts-checker-webpack-plugin": "^9.0.2",
|
|
108
109
|
"fs-extra": "^11.2.0",
|
|
109
110
|
"get-port": "^7.1.0",
|
|
111
|
+
"ink": "^5.2.1",
|
|
112
|
+
"keypress": "^0.2.1",
|
|
110
113
|
"mime-types": "^2.1.35",
|
|
111
114
|
"mini-css-extract-plugin": "^2.9.1",
|
|
112
115
|
"moment-timezone-data-webpack-plugin": "^1.5.1",
|