vladx 1.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/README.md +256 -0
- package/bin/cli.js +486 -0
- package/bin/vlad.js +539 -0
- package/bin/vladpm.js +710 -0
- package/bin/vladx.js +491 -0
- package/package.json +57 -0
- package/src/engine/jit-compiler.js +285 -0
- package/src/engine/vladx-engine.js +941 -0
- package/src/index.js +44 -0
- package/src/interpreter/interpreter.js +2114 -0
- package/src/lexer/lexer.js +658 -0
- package/src/lexer/optimized-lexer.js +106 -0
- package/src/lexer/regex-cache.js +83 -0
- package/src/parser/ast-nodes.js +472 -0
- package/src/parser/parser.js +1408 -0
- package/src/runtime/advanced-type-system.js +209 -0
- package/src/runtime/async-manager.js +252 -0
- package/src/runtime/builtins.js +143 -0
- package/src/runtime/bundler.js +422 -0
- package/src/runtime/cache-manager.js +126 -0
- package/src/runtime/data-structures.js +612 -0
- package/src/runtime/debugger.js +260 -0
- package/src/runtime/enhanced-module-system.js +196 -0
- package/src/runtime/environment-enhanced.js +272 -0
- package/src/runtime/environment.js +140 -0
- package/src/runtime/event-emitter.js +232 -0
- package/src/runtime/formatter.js +280 -0
- package/src/runtime/functional.js +359 -0
- package/src/runtime/io-operations.js +390 -0
- package/src/runtime/linter.js +374 -0
- package/src/runtime/logging.js +314 -0
- package/src/runtime/minifier.js +242 -0
- package/src/runtime/module-system.js +377 -0
- package/src/runtime/network-operations.js +373 -0
- package/src/runtime/profiler.js +295 -0
- package/src/runtime/repl.js +336 -0
- package/src/runtime/security-manager.js +244 -0
- package/src/runtime/source-map-generator.js +208 -0
- package/src/runtime/test-runner.js +394 -0
- package/src/runtime/transformer.js +277 -0
- package/src/runtime/type-system.js +244 -0
- package/src/runtime/vladx-object.js +250 -0
package/bin/vladpm.js
ADDED
|
@@ -0,0 +1,710 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* vladpm - Менеджер пакетов VladX (обновленный с интеграцией новых модулей)
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
|
|
8
|
+
import { join, dirname, resolve } from 'path';
|
|
9
|
+
import { fileURLToPath } from 'url';
|
|
10
|
+
|
|
11
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
|
|
13
|
+
class VladPM {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.configDir = join(process.env.HOME || process.env.USERPROFILE, '.vladx');
|
|
16
|
+
this.packagesDir = join(this.configDir, 'packages');
|
|
17
|
+
this.globalModulesDir = join(this.configDir, 'global_modules');
|
|
18
|
+
this.cacheDir = join(this.configDir, 'cache');
|
|
19
|
+
this.configFile = join(this.configDir, 'config.json');
|
|
20
|
+
|
|
21
|
+
this.config = this.loadConfig();
|
|
22
|
+
this.logger = console;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Загрузить конфигурацию
|
|
27
|
+
*/
|
|
28
|
+
loadConfig() {
|
|
29
|
+
if (!existsSync(this.configFile)) {
|
|
30
|
+
return {
|
|
31
|
+
registry: 'https://registry.vladx.dev',
|
|
32
|
+
token: null,
|
|
33
|
+
proxy: null,
|
|
34
|
+
cache: true
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return JSON.parse(readFileSync(this.configFile, 'utf-8'));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Сохранить конфигурацию
|
|
43
|
+
*/
|
|
44
|
+
saveConfig() {
|
|
45
|
+
if (!existsSync(this.configDir)) {
|
|
46
|
+
mkdirSync(this.configDir, { recursive: true });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
writeFileSync(this.configFile, JSON.stringify(this.config, null, 2), 'utf-8');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Инициализация проекта
|
|
54
|
+
*/
|
|
55
|
+
init() {
|
|
56
|
+
const packageFile = join(process.cwd(), 'vladx.json');
|
|
57
|
+
|
|
58
|
+
if (existsSync(packageFile)) {
|
|
59
|
+
this.logger.info('vladvx.json уже существует');
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const packageJson = {
|
|
64
|
+
name: 'vladx-project',
|
|
65
|
+
version: '1.0.0',
|
|
66
|
+
description: '',
|
|
67
|
+
main: 'index.vx',
|
|
68
|
+
scripts: {
|
|
69
|
+
start: 'vladx run index.vx',
|
|
70
|
+
test: 'vladx test',
|
|
71
|
+
build: 'vladx compile index.vx',
|
|
72
|
+
lint: 'vladx lint src/',
|
|
73
|
+
format: 'vladx format src/'
|
|
74
|
+
},
|
|
75
|
+
dependencies: {},
|
|
76
|
+
devDependencies: {}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
writeFileSync(packageFile, JSON.stringify(packageJson, null, 2), 'utf-8');
|
|
80
|
+
|
|
81
|
+
const dirs = ['src', 'tests', 'docs', 'lib'];
|
|
82
|
+
for (const dir of dirs) {
|
|
83
|
+
mkdirSync(join(process.cwd(), dir), { recursive: true });
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
writeFileSync(join(process.cwd(), 'src', 'index.vx'), '// Главная точка входа\nпечать("Привет, мир!");');
|
|
87
|
+
|
|
88
|
+
this.logger.info('Проект инициализирован');
|
|
89
|
+
this.logger.info('Создан файл: vladx.json');
|
|
90
|
+
this.logger.info('Созданы директории: src, tests, docs, lib');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Установка пакета
|
|
95
|
+
*/
|
|
96
|
+
async install(packageName, options = {}) {
|
|
97
|
+
const isDev = options.dev || false;
|
|
98
|
+
const isGlobal = options.global || false;
|
|
99
|
+
const save = options.save !== false;
|
|
100
|
+
|
|
101
|
+
if (isGlobal) {
|
|
102
|
+
await this.installGlobal(packageName, options);
|
|
103
|
+
} else {
|
|
104
|
+
await this.installLocal(packageName, isDev, save);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Установить локально
|
|
110
|
+
*/
|
|
111
|
+
async installLocal(packageName, isDev = false, save = true) {
|
|
112
|
+
const packageFile = join(process.cwd(), 'vladx.json');
|
|
113
|
+
|
|
114
|
+
if (!existsSync(packageFile)) {
|
|
115
|
+
throw new Error('vladvx.json не найден. Запустите "vladpm init"');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const packageJson = JSON.parse(readFileSync(packageFile, 'utf-8'));
|
|
119
|
+
const dependenciesKey = isDev ? 'devDependencies' : 'dependencies';
|
|
120
|
+
|
|
121
|
+
if (packageJson[dependenciesKey][packageName]) {
|
|
122
|
+
this.logger.info(`${packageName} уже установлен`);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
this.logger.info(`Установка ${packageName}...`);
|
|
127
|
+
|
|
128
|
+
const packageInfo = await this.fetchPackageInfo(packageName);
|
|
129
|
+
const packageDir = join(process.cwd(), 'node_modules', packageName);
|
|
130
|
+
|
|
131
|
+
mkdirSync(packageDir, { recursive: true });
|
|
132
|
+
|
|
133
|
+
await this.downloadPackage(packageInfo, packageDir);
|
|
134
|
+
|
|
135
|
+
if (save) {
|
|
136
|
+
packageJson[dependenciesKey][packageName] = packageInfo.version;
|
|
137
|
+
writeFileSync(packageFile, JSON.stringify(packageJson, null, 2), 'utf-8');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
this.logger.info(`${packageName}@${packageInfo.version} установлен`);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Установить глобально
|
|
145
|
+
*/
|
|
146
|
+
async installGlobal(packageName, options = {}) {
|
|
147
|
+
this.logger.info(`Глобальная установка ${packageName}...`);
|
|
148
|
+
|
|
149
|
+
const packageInfo = await this.fetchPackageInfo(packageName);
|
|
150
|
+
const packageDir = join(this.globalModulesDir, packageName);
|
|
151
|
+
|
|
152
|
+
mkdirSync(packageDir, { recursive: true });
|
|
153
|
+
|
|
154
|
+
await this.downloadPackage(packageInfo, packageDir);
|
|
155
|
+
|
|
156
|
+
this.logger.info(`${packageName}@${packageInfo.version} установлен глобально`);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Удалить пакет
|
|
161
|
+
*/
|
|
162
|
+
uninstall(packageName, options = {}) {
|
|
163
|
+
const isDev = options.dev || false;
|
|
164
|
+
const isGlobal = options.global || false;
|
|
165
|
+
|
|
166
|
+
if (isGlobal) {
|
|
167
|
+
this.uninstallGlobal(packageName);
|
|
168
|
+
} else {
|
|
169
|
+
this.uninstallLocal(packageName, isDev);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Удалить локально
|
|
175
|
+
*/
|
|
176
|
+
uninstallLocal(packageName, isDev = false) {
|
|
177
|
+
const packageFile = join(process.cwd(), 'vladvx.json');
|
|
178
|
+
|
|
179
|
+
if (!existsSync(packageFile)) {
|
|
180
|
+
throw new Error('vladvx.json не найден');
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const packageJson = JSON.parse(readFileSync(packageFile, 'utf-8'));
|
|
184
|
+
const dependenciesKey = isDev ? 'devDependencies' : 'dependencies';
|
|
185
|
+
|
|
186
|
+
if (!packageJson[dependenciesKey][packageName]) {
|
|
187
|
+
this.logger.info(`${packageName} не установлен`);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
delete packageJson[dependenciesKey][packageName];
|
|
192
|
+
writeFileSync(packageFile, JSON.stringify(packageJson, null, 2), 'utf-8');
|
|
193
|
+
|
|
194
|
+
// Удалить директорию node_modules/пакет
|
|
195
|
+
const packageDir = join(process.cwd(), 'node_modules', packageName);
|
|
196
|
+
const fs = require('fs');
|
|
197
|
+
|
|
198
|
+
const deleteRecursive = (dir) => {
|
|
199
|
+
if (!fs.existsSync(dir)) return;
|
|
200
|
+
|
|
201
|
+
const files = fs.readdirSync(dir);
|
|
202
|
+
|
|
203
|
+
for (const file of files) {
|
|
204
|
+
const filepath = join(dir, file);
|
|
205
|
+
const stat = fs.statSync(filepath);
|
|
206
|
+
|
|
207
|
+
if (stat.isDirectory()) {
|
|
208
|
+
deleteRecursive(filepath);
|
|
209
|
+
} else {
|
|
210
|
+
fs.unlinkSync(filepath);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
fs.rmdirSync(dir);
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
deleteRecursive(packageDir);
|
|
218
|
+
|
|
219
|
+
this.logger.info(`${packageName} удален`);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Удалить глобально
|
|
224
|
+
*/
|
|
225
|
+
uninstallGlobal(packageName) {
|
|
226
|
+
const packageDir = join(this.globalModulesDir, packageName);
|
|
227
|
+
|
|
228
|
+
if (!existsSync(packageDir)) {
|
|
229
|
+
this.logger.info(`${packageName} не установлен глобально`);
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const fs = require('fs');
|
|
234
|
+
|
|
235
|
+
const deleteRecursive = (dir) => {
|
|
236
|
+
if (!fs.existsSync(dir)) return;
|
|
237
|
+
|
|
238
|
+
const files = fs.readdirSync(dir);
|
|
239
|
+
|
|
240
|
+
for (const file of files) {
|
|
241
|
+
const filepath = join(dir, file);
|
|
242
|
+
const stat = fs.statSync(filepath);
|
|
243
|
+
|
|
244
|
+
if (stat.isDirectory()) {
|
|
245
|
+
deleteRecursive(filepath);
|
|
246
|
+
} else {
|
|
247
|
+
fs.unlinkSync(filepath);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
fs.rmdirSync(dir);
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
deleteRecursive(packageDir);
|
|
255
|
+
|
|
256
|
+
this.logger.info(`${packageName} удален глобально`);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Обновить пакет
|
|
261
|
+
*/
|
|
262
|
+
async update(packageName, options = {}) {
|
|
263
|
+
this.logger.info(`Обновление ${packageName}...`);
|
|
264
|
+
|
|
265
|
+
this.uninstall(packageName, options);
|
|
266
|
+
await this.install(packageName, options);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Поиск пакета
|
|
271
|
+
*/
|
|
272
|
+
async search(query) {
|
|
273
|
+
this.logger.info(`Поиск: ${query}...`);
|
|
274
|
+
|
|
275
|
+
const results = await this.searchPackages(query);
|
|
276
|
+
|
|
277
|
+
if (results.length === 0) {
|
|
278
|
+
this.logger.info('Ничего не найдено');
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
this.logger.info('Результаты:');
|
|
283
|
+
for (const pkg of results) {
|
|
284
|
+
this.logger.info(` ${pkg.name}@${pkg.version} - ${pkg.description || 'Без описания'}`);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Информация о пакете
|
|
290
|
+
*/
|
|
291
|
+
async info(packageName) {
|
|
292
|
+
this.logger.info(`Информация о ${packageName}...`);
|
|
293
|
+
|
|
294
|
+
const packageInfo = await this.fetchPackageInfo(packageName);
|
|
295
|
+
|
|
296
|
+
this.logger.info(`Название: ${packageInfo.name}`);
|
|
297
|
+
this.logger.info(`Версия: ${packageInfo.version}`);
|
|
298
|
+
this.logger.info(`Описание: ${packageInfo.description || 'Без описания'}`);
|
|
299
|
+
this.logger.info(`Автор: ${packageInfo.author || 'Неизвестен'}`);
|
|
300
|
+
this.logger.info(`Лицензия: ${packageInfo.license || 'Не указана'}`);
|
|
301
|
+
|
|
302
|
+
if (packageInfo.keywords && packageInfo.keywords.length > 0) {
|
|
303
|
+
this.logger.info(`Ключевые слова: ${packageInfo.keywords.join(', ')}`);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (packageInfo.repository) {
|
|
307
|
+
this.logger.info(`Репозиторий: ${packageInfo.repository}`);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
if (packageInfo.dependencies && Object.keys(packageInfo.dependencies).length > 0) {
|
|
311
|
+
this.logger.info('Зависимости:');
|
|
312
|
+
for (const [dep, version] of Object.entries(packageInfo.dependencies)) {
|
|
313
|
+
this.logger.info(` ${dep}: ${version}`);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Список установленных пакетов
|
|
320
|
+
*/
|
|
321
|
+
list(options = {}) {
|
|
322
|
+
const isGlobal = options.global || false;
|
|
323
|
+
|
|
324
|
+
if (isGlobal) {
|
|
325
|
+
this.listGlobal();
|
|
326
|
+
} else {
|
|
327
|
+
this.listLocal();
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Список локальных пакетов
|
|
333
|
+
*/
|
|
334
|
+
listLocal() {
|
|
335
|
+
const packageFile = join(process.cwd(), 'vladvx.json');
|
|
336
|
+
|
|
337
|
+
if (!existsSync(packageFile)) {
|
|
338
|
+
this.logger.info('vladvx.json не найден');
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const packageJson = JSON.parse(readFileSync(packageFile, 'utf-8'));
|
|
343
|
+
|
|
344
|
+
const hasDeps = Object.keys(packageJson.dependencies).length > 0;
|
|
345
|
+
|
|
346
|
+
if (!hasDeps) {
|
|
347
|
+
this.logger.info('Нет установленных пакетов');
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
this.logger.info('Зависимости:');
|
|
352
|
+
for (const [name, version] of Object.entries(packageJson.dependencies)) {
|
|
353
|
+
this.logger.info(` ${name}@${version}`);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const hasDevDeps = Object.keys(packageJson.devDependencies).length > 0;
|
|
357
|
+
|
|
358
|
+
if (hasDevDeps) {
|
|
359
|
+
this.logger.info('\nDev зависимости:');
|
|
360
|
+
for (const [name, version] of Object.entries(packageJson.devDependencies)) {
|
|
361
|
+
this.logger.info(` ${name}@${version}`);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Список глобальных пакетов
|
|
368
|
+
*/
|
|
369
|
+
listGlobal() {
|
|
370
|
+
const fs = require('fs');
|
|
371
|
+
|
|
372
|
+
if (!fs.existsSync(this.globalModulesDir)) {
|
|
373
|
+
this.logger.info('Нет глобальных пакетов');
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
const packages = fs.readdirSync(this.globalModulesDir);
|
|
378
|
+
|
|
379
|
+
if (packages.length === 0) {
|
|
380
|
+
this.logger.info('Нет глобальных пакетов');
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
this.logger.info('Глобальные пакеты:');
|
|
385
|
+
for (const pkg of packages) {
|
|
386
|
+
const packageFile = join(this.globalModulesDir, pkg, 'vladvx.json');
|
|
387
|
+
let version = 'неизвестно';
|
|
388
|
+
|
|
389
|
+
if (fs.existsSync(packageFile)) {
|
|
390
|
+
const pkgJson = JSON.parse(readFileSync(packageFile, 'utf-8'));
|
|
391
|
+
version = pkgJson.version;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
this.logger.info(` ${pkg}@${version}`);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Публикация пакета
|
|
400
|
+
*/
|
|
401
|
+
async publish(options = {}) {
|
|
402
|
+
const packageFile = join(process.cwd(), 'vladvx.json');
|
|
403
|
+
|
|
404
|
+
if (!existsSync(packageFile)) {
|
|
405
|
+
throw new Error('vladvx.json не найден');
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
const packageJson = JSON.parse(readFileSync(packageFile, 'utf-8'));
|
|
409
|
+
|
|
410
|
+
this.logger.info(`Публикация ${packageJson.name}@${packageJson.version}...`);
|
|
411
|
+
|
|
412
|
+
if (!packageJson.name) {
|
|
413
|
+
throw new Error('Название пакета не указано');
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
if (!packageJson.version) {
|
|
417
|
+
throw new Error('Версия пакета не указана');
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
if (!this.config.token) {
|
|
421
|
+
throw new Error('Вы не авторизованы. Используйте "vladpm login <token>"');
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
if (options.dryRun) {
|
|
425
|
+
this.logger.info('Dry run mode - без публикации');
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
this.logger.info('Пакет опубликован');
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Получить информацию о пакете
|
|
434
|
+
*/
|
|
435
|
+
async fetchPackageInfo(packageName) {
|
|
436
|
+
const url = `${this.config.registry}/packages/${encodeURIComponent(packageName)}`;
|
|
437
|
+
|
|
438
|
+
try {
|
|
439
|
+
const response = await fetch(url, {
|
|
440
|
+
headers: {
|
|
441
|
+
'Authorization': this.config.token ? `Bearer ${this.config.token}` : undefined
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
if (!response.ok) {
|
|
446
|
+
throw new Error(`Пакет не найден: ${packageName}`);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
return await response.json();
|
|
450
|
+
} catch (error) {
|
|
451
|
+
if (error.message.includes('Пакет не найден')) {
|
|
452
|
+
throw error;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
this.logger.warn(`Не удалось получить информацию о пакете, используется локальный кэш: ${error.message}`);
|
|
456
|
+
|
|
457
|
+
// Фолбэк на локальный пакет
|
|
458
|
+
const localPath = join(process.cwd(), 'node_modules', packageName, 'vladvx.json');
|
|
459
|
+
|
|
460
|
+
if (existsSync(localPath)) {
|
|
461
|
+
return JSON.parse(readFileSync(localPath, 'utf-8'));
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
throw new Error(`Пакет не найден: ${packageName}`);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Скачать пакет
|
|
470
|
+
*/
|
|
471
|
+
async downloadPackage(packageInfo, destDir) {
|
|
472
|
+
const tarballUrl = packageInfo.tarball;
|
|
473
|
+
|
|
474
|
+
try {
|
|
475
|
+
const response = await fetch(tarballUrl);
|
|
476
|
+
|
|
477
|
+
if (!response.ok) {
|
|
478
|
+
throw new Error('Не удалось скачать пакет');
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
const tarball = await response.arrayBuffer();
|
|
482
|
+
|
|
483
|
+
await this.extractTarball(tarball, destDir);
|
|
484
|
+
} catch (error) {
|
|
485
|
+
throw new Error(`Ошибка скачивания: ${error.message}`);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Поиск пакетов
|
|
491
|
+
*/
|
|
492
|
+
async searchPackages(query) {
|
|
493
|
+
const url = `${this.config.registry}/search?q=${encodeURIComponent(query)}`;
|
|
494
|
+
|
|
495
|
+
try {
|
|
496
|
+
const response = await fetch(url);
|
|
497
|
+
|
|
498
|
+
if (!response.ok) {
|
|
499
|
+
throw new Error('Ошибка поиска');
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
return await response.json();
|
|
503
|
+
} catch (error) {
|
|
504
|
+
this.logger.warn(`Ошибка поиска: ${error.message}`);
|
|
505
|
+
return [];
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Распаковать tarball
|
|
511
|
+
*/
|
|
512
|
+
async extractTarball(tarball, destDir) {
|
|
513
|
+
const tar = require('tar');
|
|
514
|
+
|
|
515
|
+
return new Promise((resolve, reject) => {
|
|
516
|
+
const extract = tar.x({
|
|
517
|
+
cwd: destDir,
|
|
518
|
+
strip: 1
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
const buffer = Buffer.from(tarball);
|
|
522
|
+
|
|
523
|
+
extract.on('finish', resolve);
|
|
524
|
+
extract.on('error', reject);
|
|
525
|
+
|
|
526
|
+
extract.write(buffer);
|
|
527
|
+
extract.end();
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/**
|
|
532
|
+
* Настроить реестр
|
|
533
|
+
*/
|
|
534
|
+
setRegistry(url) {
|
|
535
|
+
this.config.registry = url;
|
|
536
|
+
this.saveConfig();
|
|
537
|
+
this.logger.info(`Реестр изменен на: ${url}`);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Войти в систему
|
|
542
|
+
*/
|
|
543
|
+
async login(token) {
|
|
544
|
+
this.config.token = token;
|
|
545
|
+
this.saveConfig();
|
|
546
|
+
this.logger.info('Вы вошли в систему');
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
/**
|
|
550
|
+
* Выйти из системы
|
|
551
|
+
*/
|
|
552
|
+
logout() {
|
|
553
|
+
this.config.token = null;
|
|
554
|
+
this.saveConfig();
|
|
555
|
+
this.logger.info('Вы вышли из системы');
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* Кто я
|
|
560
|
+
*/
|
|
561
|
+
whoami() {
|
|
562
|
+
if (!this.config.token) {
|
|
563
|
+
this.logger.info('Не авторизован');
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
this.logger.info('Токен:', this.config.token);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* Запуск CLI
|
|
573
|
+
*/
|
|
574
|
+
const vladpm = new VladPM();
|
|
575
|
+
|
|
576
|
+
const command = process.argv[2];
|
|
577
|
+
const args = process.argv.slice(3);
|
|
578
|
+
|
|
579
|
+
try {
|
|
580
|
+
switch (command) {
|
|
581
|
+
case 'init':
|
|
582
|
+
vladpm.init();
|
|
583
|
+
break;
|
|
584
|
+
|
|
585
|
+
case 'install':
|
|
586
|
+
case 'i': {
|
|
587
|
+
const pkg = args[0];
|
|
588
|
+
const options = {
|
|
589
|
+
dev: args.includes('--dev') || args.includes('-D'),
|
|
590
|
+
global: args.includes('--global') || args.includes('-g'),
|
|
591
|
+
save: !args.includes('--no-save')
|
|
592
|
+
};
|
|
593
|
+
await vladpm.install(pkg, options);
|
|
594
|
+
break;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
case 'uninstall':
|
|
598
|
+
case 'remove':
|
|
599
|
+
case 'rm': {
|
|
600
|
+
const pkg = args[0];
|
|
601
|
+
const options = {
|
|
602
|
+
dev: args.includes('--dev') || args.includes('-D'),
|
|
603
|
+
global: args.includes('--global') || args.includes('-g')
|
|
604
|
+
};
|
|
605
|
+
vladpm.uninstall(pkg, options);
|
|
606
|
+
break;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
case 'update':
|
|
610
|
+
case 'upgrade': {
|
|
611
|
+
const pkg = args[0];
|
|
612
|
+
const options = {
|
|
613
|
+
dev: args.includes('--dev') || args.includes('-D'),
|
|
614
|
+
global: args.includes('--global') || args.includes('-g')
|
|
615
|
+
};
|
|
616
|
+
await vladpm.update(pkg, options);
|
|
617
|
+
break;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
case 'search': {
|
|
621
|
+
const query = args[0];
|
|
622
|
+
await vladpm.search(query);
|
|
623
|
+
break;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
case 'info': {
|
|
627
|
+
const pkg = args[0];
|
|
628
|
+
await vladpm.info(pkg);
|
|
629
|
+
break;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
case 'list':
|
|
633
|
+
case 'ls': {
|
|
634
|
+
const options = {
|
|
635
|
+
global: args.includes('--global') || args.includes('-g')
|
|
636
|
+
};
|
|
637
|
+
vladpm.list(options);
|
|
638
|
+
break;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
case 'publish': {
|
|
642
|
+
const options = {
|
|
643
|
+
dryRun: args.includes('--dry-run')
|
|
644
|
+
};
|
|
645
|
+
await vladpm.publish(options);
|
|
646
|
+
break;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
case 'login': {
|
|
650
|
+
const token = args[0];
|
|
651
|
+
await vladpm.login(token);
|
|
652
|
+
break;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
case 'logout':
|
|
656
|
+
vladpm.logout();
|
|
657
|
+
break;
|
|
658
|
+
|
|
659
|
+
case 'whoami':
|
|
660
|
+
vladpm.whoami();
|
|
661
|
+
break;
|
|
662
|
+
|
|
663
|
+
case 'set-registry': {
|
|
664
|
+
const url = args[0];
|
|
665
|
+
vladpm.setRegistry(url);
|
|
666
|
+
break;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
default:
|
|
670
|
+
console.log(`
|
|
671
|
+
VladPM - Менеджер пакетов VladX
|
|
672
|
+
|
|
673
|
+
Использование:
|
|
674
|
+
vladpm <команда> [опции]
|
|
675
|
+
|
|
676
|
+
Команды:
|
|
677
|
+
init Инициализировать новый проект
|
|
678
|
+
install [pkg] Установить пакет
|
|
679
|
+
uninstall [pkg] Удалить пакет
|
|
680
|
+
update [pkg] Обновить пакет
|
|
681
|
+
search [query] Поиск пакетов
|
|
682
|
+
info [pkg] Информация о пакете
|
|
683
|
+
list Список установленных пакетов
|
|
684
|
+
publish Опубликовать пакет
|
|
685
|
+
login [token] Войти в систему
|
|
686
|
+
logout Выйти из системы
|
|
687
|
+
whoami Кто авторизован
|
|
688
|
+
set-registry [url] Изменить реестр
|
|
689
|
+
|
|
690
|
+
Опции:
|
|
691
|
+
--dev, -D Установить как dev зависимость
|
|
692
|
+
--global, -g Установить глобально
|
|
693
|
+
--no-save Не сохранять в vladx.json
|
|
694
|
+
--dry-run Режим просмотра (без публикации)
|
|
695
|
+
|
|
696
|
+
Примеры:
|
|
697
|
+
vladpm init
|
|
698
|
+
vladpm install vladx-core
|
|
699
|
+
vladpm install typescript --dev
|
|
700
|
+
vladpm search math
|
|
701
|
+
vladpm info vladx-core
|
|
702
|
+
vladpm list
|
|
703
|
+
vladpm publish
|
|
704
|
+
vladpm login my-token
|
|
705
|
+
`.trim());
|
|
706
|
+
}
|
|
707
|
+
} catch (error) {
|
|
708
|
+
console.error(`Ошибка: ${error.message}`);
|
|
709
|
+
process.exit(1);
|
|
710
|
+
}
|