@boristype/bt-cli 0.1.0-alpha.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/LICENSE +21 -0
- package/README.md +66 -0
- package/build/builder/config.js +88 -0
- package/build/cli/commands/artifact.js +14 -0
- package/build/cli/commands/build.js +25 -0
- package/build/cli/commands/dev.js +190 -0
- package/build/cli/commands/index.js +18 -0
- package/build/cli/commands/init.js +15 -0
- package/build/cli/commands/link.js +18 -0
- package/build/cli/commands/push.js +28 -0
- package/build/cli/index.js +14 -0
- package/build/cli/types.js +2 -0
- package/build/core/artifacting/context.js +54 -0
- package/build/core/artifacting/index.js +37 -0
- package/build/core/artifacting/stages/index.js +10 -0
- package/build/core/artifacting/stages/main-archive.js +72 -0
- package/build/core/artifacting/stages/validate.js +70 -0
- package/build/core/artifacting/types.js +6 -0
- package/build/core/artifacting/utils/index.js +10 -0
- package/build/core/artifacting/utils/zip.js +94 -0
- package/build/core/babel.js +96 -0
- package/build/core/btconfig.types.js +6 -0
- package/build/core/build.js +280 -0
- package/build/core/building/compile-mode.js +146 -0
- package/build/core/building/compiler.js +281 -0
- package/build/core/building/coordinator.js +71 -0
- package/build/core/building/files.js +290 -0
- package/build/core/building/index.js +102 -0
- package/build/core/building/output.js +92 -0
- package/build/core/building/transformers.js +110 -0
- package/build/core/building/types.js +19 -0
- package/build/core/config.js +157 -0
- package/build/core/dependencies.js +223 -0
- package/build/core/linking/cache.js +260 -0
- package/build/core/linking/context.js +149 -0
- package/build/core/linking/dependencies.js +240 -0
- package/build/core/linking/executables.js +61 -0
- package/build/core/linking/generators/api-ext.js +57 -0
- package/build/core/linking/generators/component.js +83 -0
- package/build/core/linking/generators/filemap.js +53 -0
- package/build/core/linking/generators/index.js +21 -0
- package/build/core/linking/generators/init-xml.js +37 -0
- package/build/core/linking/generators/package-json.js +50 -0
- package/build/core/linking/index.js +213 -0
- package/build/core/linking/linkers/component.js +175 -0
- package/build/core/linking/linkers/index.js +69 -0
- package/build/core/linking/linkers/standalone.js +144 -0
- package/build/core/linking/linkers/system.js +86 -0
- package/build/core/linking/parsers.js +278 -0
- package/build/core/linking/types.js +6 -0
- package/build/core/linking/utils/copy.js +101 -0
- package/build/core/linking/utils/index.js +26 -0
- package/build/core/linking/utils/node-modules.js +226 -0
- package/build/core/linking/utils/package-type.js +101 -0
- package/build/core/linking/utils/url.js +73 -0
- package/build/core/linking/utils/write.js +91 -0
- package/build/core/logger.js +10 -0
- package/build/core/pushing/config.js +90 -0
- package/build/core/pushing/index.js +96 -0
- package/build/core/pushing/init-scripts.js +173 -0
- package/build/core/pushing/queue.js +95 -0
- package/build/core/pushing/reinit.js +61 -0
- package/build/core/pushing/session.js +167 -0
- package/build/core/pushing/types.js +6 -0
- package/build/core/pushing/upload.js +35 -0
- package/build/core/tsconfig.js +78 -0
- package/build/core/utils/index.js +17 -0
- package/build/core/utils/logger.js +46 -0
- package/build/core/utils/properties.js +81 -0
- package/build/core/utils/xml.js +44 -0
- package/build/core/utils.js +59 -0
- package/build/index.js +76 -0
- package/build/plugins/destructuring.js +83 -0
- package/build/plugins/forOfToForIn.js +14 -0
- package/build/plugins/loopHoistVariables.js +160 -0
- package/build/plugins/precedence.js +172 -0
- package/build/plugins/removeImportExport.js +42 -0
- package/build/plugins/replaceDollar.js +16 -0
- package/build/plugins/spreadArray.js +42 -0
- package/build/plugins/spreadObject.js +91 -0
- package/build/transformers/arrayFunctional.js +467 -0
- package/build/transformers/arrayGeneral.js +222 -0
- package/build/transformers/blockScoping.js +212 -0
- package/build/transformers/destructuring.js +133 -0
- package/build/transformers/dirname.js +79 -0
- package/build/transformers/enumsToObjects.js +25 -0
- package/build/transformers/execObj.js +220 -0
- package/build/transformers/forOfToForIn.js +45 -0
- package/build/transformers/funcSemantic.js +113 -0
- package/build/transformers/functions.js +270 -0
- package/build/transformers/globalCache.js +34 -0
- package/build/transformers/loopHoistVariables.js +352 -0
- package/build/transformers/math.js +39 -0
- package/build/transformers/namespaces.js +22 -0
- package/build/transformers/numericSeparator.js +46 -0
- package/build/transformers/objectProperties.js +54 -0
- package/build/transformers/precedence.js +192 -0
- package/build/transformers/propSemantic.js +467 -0
- package/build/transformers/remodule.js +620 -0
- package/build/transformers/removeImportExport.js +135 -0
- package/build/transformers/replaceDollar.js +46 -0
- package/build/transformers/shorthandProperties.js +34 -0
- package/build/transformers/spreadArray.js +68 -0
- package/build/transformers/spreadObject.js +134 -0
- package/build/transformers/string.js +138 -0
- package/build/transformers/templateLiterals.js +104 -0
- package/build/transformers/tocodelibrary.js +178 -0
- package/build/transformers/utils.js +202 -0
- package/build/wshcm/client.js +193 -0
- package/build/wshcm/evaluator.js +111 -0
- package/build/wshcm/exceptions.js +25 -0
- package/build/wshcm/index.js +20 -0
- package/build/wshcm/soap-utils.js +228 -0
- package/build/wshcm/types.js +2 -0
- package/build/wshcm/uploader.js +320 -0
- package/package.json +51 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Конфигурация проекта — tsconfig.json и btconfig.json
|
|
4
|
+
*
|
|
5
|
+
* Единый модуль для чтения, парсинга и генерации конфигурационных файлов.
|
|
6
|
+
* Также содержит типы для btconfig.json.
|
|
7
|
+
*
|
|
8
|
+
* @module core/config
|
|
9
|
+
*/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
22
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
23
|
+
}) : function(o, v) {
|
|
24
|
+
o["default"] = v;
|
|
25
|
+
});
|
|
26
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
27
|
+
var ownKeys = function(o) {
|
|
28
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
29
|
+
var ar = [];
|
|
30
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
31
|
+
return ar;
|
|
32
|
+
};
|
|
33
|
+
return ownKeys(o);
|
|
34
|
+
};
|
|
35
|
+
return function (mod) {
|
|
36
|
+
if (mod && mod.__esModule) return mod;
|
|
37
|
+
var result = {};
|
|
38
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
39
|
+
__setModuleDefault(result, mod);
|
|
40
|
+
return result;
|
|
41
|
+
};
|
|
42
|
+
})();
|
|
43
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
44
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
45
|
+
};
|
|
46
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
47
|
+
exports.getTSConfig = getTSConfig;
|
|
48
|
+
exports.generateDefaultTSConfig = generateDefaultTSConfig;
|
|
49
|
+
exports.getBTConfig = getBTConfig;
|
|
50
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
51
|
+
const fs = __importStar(require("node:fs"));
|
|
52
|
+
const path = __importStar(require("node:path"));
|
|
53
|
+
const logger_js_1 = require("./utils/logger.js");
|
|
54
|
+
// ─── tsconfig.json ──────────────────────────────────────────────
|
|
55
|
+
/**
|
|
56
|
+
* Читает и парсит tsconfig.json.
|
|
57
|
+
*
|
|
58
|
+
* @param cwd - Рабочая директория для поиска tsconfig
|
|
59
|
+
* @param project - Имя файла конфигурации (по умолчанию tsconfig.json)
|
|
60
|
+
* @returns Распарсенная конфигурация TypeScript
|
|
61
|
+
*/
|
|
62
|
+
function getTSConfig(cwd, project = 'tsconfig.json') {
|
|
63
|
+
const tsconfigPath = typescript_1.default.findConfigFile(cwd, typescript_1.default.sys.fileExists, project);
|
|
64
|
+
if (!tsconfigPath) {
|
|
65
|
+
logger_js_1.logger.error(`There is no any configuration files at "${cwd}". Execute npx tsc -init to create a new one.`);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
const { config, error } = typescript_1.default.readConfigFile(tsconfigPath, typescript_1.default.sys.readFile);
|
|
69
|
+
if (error) {
|
|
70
|
+
logger_js_1.logger.error(error.messageText.toString());
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
// Используем директорию tsconfig.json как базу для резолва путей
|
|
74
|
+
const configDir = path.dirname(tsconfigPath);
|
|
75
|
+
const configFileContent = typescript_1.default.parseJsonConfigFileContent(config, typescript_1.default.sys, configDir);
|
|
76
|
+
if (configFileContent.errors.length > 0) {
|
|
77
|
+
configFileContent.errors.forEach(diagnostic => {
|
|
78
|
+
logger_js_1.logger.error(diagnostic.messageText.toString());
|
|
79
|
+
});
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
return configFileContent;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Генерирует tsconfig.json с дефолтными настройками для BorisType проекта.
|
|
86
|
+
*
|
|
87
|
+
* @param cwd - Рабочая директория (по умолчанию process.cwd())
|
|
88
|
+
* @returns true если файл создан, false если уже существует
|
|
89
|
+
*/
|
|
90
|
+
function generateDefaultTSConfig(cwd = process.cwd()) {
|
|
91
|
+
const tsconfigContent = `{
|
|
92
|
+
"compilerOptions": {
|
|
93
|
+
"target": "esnext",
|
|
94
|
+
"module": "esnext",
|
|
95
|
+
"moduleResolution": "Bundler",
|
|
96
|
+
"rootDir": "./src/",
|
|
97
|
+
"outDir": "./build/",
|
|
98
|
+
"strict": true,
|
|
99
|
+
"noImplicitAny": true,
|
|
100
|
+
"allowJs": true,
|
|
101
|
+
"strictNullChecks": true,
|
|
102
|
+
"strictFunctionTypes": true,
|
|
103
|
+
"strictBindCallApply": true,
|
|
104
|
+
"noImplicitThis": true,
|
|
105
|
+
"alwaysStrict": true,
|
|
106
|
+
"noLib": true,
|
|
107
|
+
"typeRoots": [
|
|
108
|
+
"node_modules/@boristype/types/lib",
|
|
109
|
+
"node_modules/@boristype/types/lib/xml"
|
|
110
|
+
]
|
|
111
|
+
},
|
|
112
|
+
"include": [
|
|
113
|
+
"src/**/*"
|
|
114
|
+
],
|
|
115
|
+
"exclude": [
|
|
116
|
+
"node_modules"
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
`;
|
|
120
|
+
const tsconfigPath = path.join(cwd, 'tsconfig.json');
|
|
121
|
+
if (fs.existsSync(tsconfigPath)) {
|
|
122
|
+
logger_js_1.logger.warning('⚠️ tsconfig.json already exists. Skipping generation.');
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
try {
|
|
126
|
+
fs.writeFileSync(tsconfigPath, tsconfigContent, 'utf8');
|
|
127
|
+
logger_js_1.logger.success('Created a new tsconfig.json');
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
logger_js_1.logger.error('❌ Failed to create tsconfig.json');
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// ─── btconfig.json ──────────────────────────────────────────────
|
|
136
|
+
/**
|
|
137
|
+
* Читает и парсит btconfig.json.
|
|
138
|
+
*
|
|
139
|
+
* @param cwd - Рабочая директория
|
|
140
|
+
* @param project - Имя файла конфигурации (по умолчанию btconfig.json)
|
|
141
|
+
* @returns Объект конфигурации BtConfig или undefined если файл не найден
|
|
142
|
+
*/
|
|
143
|
+
function getBTConfig(cwd, project = 'btconfig.json') {
|
|
144
|
+
const btconfigPath = path.join(cwd, project);
|
|
145
|
+
if (!fs.existsSync(btconfigPath)) {
|
|
146
|
+
return undefined;
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
const configContent = fs.readFileSync(btconfigPath, 'utf-8');
|
|
150
|
+
const config = JSON.parse(configContent);
|
|
151
|
+
return config;
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
logger_js_1.logger.error(`Error reading or parsing ${project}: ${error}`);
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
@@ -0,0 +1,223 @@
|
|
|
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 () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.DependencyNode = void 0;
|
|
37
|
+
exports.getCompilerRequiredDependencies = getCompilerRequiredDependencies;
|
|
38
|
+
exports.buildDependencyTree = buildDependencyTree;
|
|
39
|
+
exports.flattenDependencyTreeIterative = flattenDependencyTreeIterative;
|
|
40
|
+
exports.printDependencyTree = printDependencyTree;
|
|
41
|
+
exports.printFlattenedTree = printFlattenedTree;
|
|
42
|
+
exports.extractBorisTypeDependencies = extractBorisTypeDependencies;
|
|
43
|
+
const fs_1 = require("fs");
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
const crypto_1 = require("crypto");
|
|
46
|
+
// Класс для узла дерева зависимостей
|
|
47
|
+
class DependencyNode {
|
|
48
|
+
packageJson;
|
|
49
|
+
constructor(packageJson, projectPath = '') {
|
|
50
|
+
this.packageJson = packageJson;
|
|
51
|
+
this.name = packageJson.name;
|
|
52
|
+
this.version = packageJson.version;
|
|
53
|
+
this.dependencies = [];
|
|
54
|
+
this.projectPath = projectPath;
|
|
55
|
+
this.hash = (0, crypto_1.randomUUID)();
|
|
56
|
+
}
|
|
57
|
+
name;
|
|
58
|
+
version;
|
|
59
|
+
dependencies;
|
|
60
|
+
projectPath;
|
|
61
|
+
hash;
|
|
62
|
+
}
|
|
63
|
+
exports.DependencyNode = DependencyNode;
|
|
64
|
+
async function getCompilerRequiredDependencies(projectPath) {
|
|
65
|
+
const rootPackageJsonPath = path.join(projectPath, 'package.json');
|
|
66
|
+
const nodeModulesPath = path.join(projectPath, 'node_modules');
|
|
67
|
+
const rootPackageJson = JSON.parse(await fs_1.promises.readFile(rootPackageJsonPath, 'utf-8'));
|
|
68
|
+
const devDependencies = rootPackageJson.devDependencies || {};
|
|
69
|
+
const btcRemoteDependency = devDependencies['@boristype/btc'] !== undefined;
|
|
70
|
+
const btcLocalDependency = devDependencies['btc'] !== undefined;
|
|
71
|
+
if (!btcLocalDependency && !btcRemoteDependency) {
|
|
72
|
+
console.warn(`Предупреждение: В devDependencies отсутствует зависимость 'btc'.`);
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
75
|
+
const btcPath = btcRemoteDependency ? path.join(nodeModulesPath, '@boristype', 'btc') : path.join(nodeModulesPath, 'btc');
|
|
76
|
+
const btcPackageJsonPath = path.join(btcPath, 'package.json');
|
|
77
|
+
const btcPackageJson = JSON.parse(await fs_1.promises.readFile(btcPackageJsonPath, 'utf-8'));
|
|
78
|
+
const btcDependencies = btcPackageJson.dependencies || {};
|
|
79
|
+
const result = [];
|
|
80
|
+
console.log(`Загрузка зависимостей компилятора из ${btcPath}`);
|
|
81
|
+
for (const [depName, depVersion] of Object.entries(btcDependencies)) {
|
|
82
|
+
if (depName.startsWith('@boristype/')) {
|
|
83
|
+
// Если btc установлен из репозитория, ищем в node_modules проекта
|
|
84
|
+
// Если btc установлен локально (file:...), ищем в node_modules внутри btc
|
|
85
|
+
const btcNodeModulesPath = btcRemoteDependency ? nodeModulesPath : path.join(btcPath, 'node_modules');
|
|
86
|
+
const depPath = btcRemoteDependency ? path.join(btcNodeModulesPath, '@boristype', depName.replace('@boristype/', '')) : path.join(btcNodeModulesPath, depName);
|
|
87
|
+
console.log(`Загрузка зависимости компилятора: ${depName} из ${depPath}`);
|
|
88
|
+
try {
|
|
89
|
+
const depPackageJsonPath = path.join(depPath, 'package.json');
|
|
90
|
+
const depPackageJson = JSON.parse(await fs_1.promises.readFile(depPackageJsonPath, 'utf-8'));
|
|
91
|
+
const depNode = new DependencyNode(depPackageJson, depPath);
|
|
92
|
+
result.push(depNode);
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
if (err instanceof Error) {
|
|
96
|
+
console.warn(`Не удалось обработать зависимость ${depName}: ${err.message}`);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
console.warn(`Не удалось обработать зависимость ${depName}: ${String(err)}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
async function buildDependencyTree(projectPath) {
|
|
107
|
+
const rootPackageJsonPath = path.join(projectPath, 'package.json');
|
|
108
|
+
const nodeModulesPath = path.join(projectPath, 'node_modules');
|
|
109
|
+
const rootPackageJson = JSON.parse(await fs_1.promises.readFile(rootPackageJsonPath, 'utf-8'));
|
|
110
|
+
const rootNode = new DependencyNode(rootPackageJson, projectPath);
|
|
111
|
+
const processedModules = new Map();
|
|
112
|
+
async function processDependencies(parentNode, nodeModulesDir, packageJsonPath, visited = new Set()) {
|
|
113
|
+
let dependencies = {};
|
|
114
|
+
try {
|
|
115
|
+
const packageJson = JSON.parse(await fs_1.promises.readFile(packageJsonPath, 'utf-8'));
|
|
116
|
+
dependencies = packageJson.dependencies || {};
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
console.warn(`Не удалось прочитать package.json для ${parentNode.name}: ${packageJsonPath}`);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
for (const [depName, depVersion] of Object.entries(dependencies)) {
|
|
123
|
+
const depKey = `${depName}@${depVersion}`;
|
|
124
|
+
if (visited.has(depKey)) {
|
|
125
|
+
console.warn(`Обнаружена циклическая зависимость: ${depKey}`);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
const depPath = path.join(nodeModulesDir, depName);
|
|
129
|
+
try {
|
|
130
|
+
const depPackageJsonPath = path.join(depPath, 'package.json');
|
|
131
|
+
const depPackageJson = JSON.parse(await fs_1.promises.readFile(depPackageJsonPath, 'utf-8'));
|
|
132
|
+
const processedKey = `${depPackageJson.name}@${depPackageJson.version}`;
|
|
133
|
+
let depNode;
|
|
134
|
+
if (processedModules.has(processedKey)) {
|
|
135
|
+
depNode = processedModules.get(processedKey);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
depNode = new DependencyNode(depPackageJson, depPath);
|
|
139
|
+
processedModules.set(processedKey, depNode);
|
|
140
|
+
const newVisited = new Set(visited);
|
|
141
|
+
newVisited.add(depKey);
|
|
142
|
+
await processDependencies(depNode, nodeModulesDir, depPackageJsonPath, newVisited);
|
|
143
|
+
}
|
|
144
|
+
parentNode.dependencies.push(depNode);
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
if (err instanceof Error) {
|
|
148
|
+
console.warn(`Не удалось обработать зависимость ${depName}: ${err.message}`);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
console.warn(`Не удалось обработать зависимость ${depName}: ${String(err)}`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
await processDependencies(rootNode, nodeModulesPath, rootPackageJsonPath);
|
|
157
|
+
return rootNode;
|
|
158
|
+
}
|
|
159
|
+
// Альтернативная версия с итеративным подходом (более безопасная для больших деревьев)
|
|
160
|
+
function flattenDependencyTreeIterative(rootNode) {
|
|
161
|
+
const visited = new Set();
|
|
162
|
+
const result = [];
|
|
163
|
+
const stack = [];
|
|
164
|
+
stack.push({ node: rootNode, path: new Set() });
|
|
165
|
+
while (stack.length > 0) {
|
|
166
|
+
const { node, path } = stack.pop();
|
|
167
|
+
// Проверяем циклические зависимости
|
|
168
|
+
if (path.has(node.hash)) {
|
|
169
|
+
console.warn(`Обнаружена циклическая зависимость: ${node.name}@${node.version}`);
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
// Если узел уже был обработан, пропускаем
|
|
173
|
+
if (visited.has(node.hash)) {
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
// Проверяем, все ли зависимости уже обработаны
|
|
177
|
+
const unprocessedDeps = node.dependencies.filter(dep => !visited.has(dep.hash));
|
|
178
|
+
if (unprocessedDeps.length === 0) {
|
|
179
|
+
// Все зависимости обработаны - добавляем текущий узел
|
|
180
|
+
visited.add(node.hash);
|
|
181
|
+
result.push(node);
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
// Есть необработанные зависимости - откладываем текущий узел и обрабатываем зависимости
|
|
185
|
+
stack.push({ node, path });
|
|
186
|
+
// Добавляем необработанные зависимости в стек
|
|
187
|
+
const newPath = new Set(path);
|
|
188
|
+
newPath.add(node.hash);
|
|
189
|
+
for (const dep of unprocessedDeps) {
|
|
190
|
+
if (!path.has(dep.hash)) { // Проверяем циклы только для новых узлов
|
|
191
|
+
stack.push({ node: dep, path: newPath });
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return result;
|
|
197
|
+
}
|
|
198
|
+
// Функция для вывода дерева (без изменений)
|
|
199
|
+
function printDependencyTree(node, depth = 0) {
|
|
200
|
+
console.log('\n📦 Дерево зависимостей:');
|
|
201
|
+
function printInternal(node, depth) {
|
|
202
|
+
console.log('='.repeat(50));
|
|
203
|
+
console.log(`${' '.repeat(depth * 2)}${node.name}@${node.version} [${node.hash}]`);
|
|
204
|
+
for (const dep of node.dependencies) {
|
|
205
|
+
printInternal(dep, depth + 1);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
printInternal(node, depth);
|
|
209
|
+
}
|
|
210
|
+
// Функция для вывода плоского массива
|
|
211
|
+
function printFlattenedTree(flatTree) {
|
|
212
|
+
console.log('\n📦 Плоский список зависимостей (в порядке загрузки):');
|
|
213
|
+
console.log('='.repeat(50));
|
|
214
|
+
flatTree.forEach((node, index) => {
|
|
215
|
+
console.log(`${(index + 1).toString().padStart(2)}. ${node.name}@${node.version} [${node.hash}]`);
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
function extractBorisTypeDependencies(flatTree) {
|
|
219
|
+
return flatTree.filter(node => {
|
|
220
|
+
const wsPackage = node.packageJson['ws:package']; // для libs
|
|
221
|
+
return typeof wsPackage === 'string';
|
|
222
|
+
});
|
|
223
|
+
}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Кэширование для линковки
|
|
4
|
+
*
|
|
5
|
+
* Управляет кэшем в директории .btc/ для оптимизации линковки:
|
|
6
|
+
* - Кэширование hash от package-lock.json для node_modules
|
|
7
|
+
* - Позволяет пропускать копирование если зависимости не изменились
|
|
8
|
+
*
|
|
9
|
+
* @module linking/cache
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.LinkingCache = void 0;
|
|
46
|
+
const fs = __importStar(require("fs"));
|
|
47
|
+
const path = __importStar(require("path"));
|
|
48
|
+
const crypto = __importStar(require("crypto"));
|
|
49
|
+
/** Текущая версия формата кэша */
|
|
50
|
+
const CACHE_VERSION = 1;
|
|
51
|
+
/** Имя директории кэша */
|
|
52
|
+
const CACHE_DIR_NAME = '.btc';
|
|
53
|
+
/** Имя файла состояния кэша */
|
|
54
|
+
const CACHE_STATE_FILE = 'linking-cache.json';
|
|
55
|
+
/**
|
|
56
|
+
* Менеджер кэша линковки
|
|
57
|
+
*
|
|
58
|
+
* @remarks
|
|
59
|
+
* Хранит состояние кэша в `.btc/linking-cache.json`
|
|
60
|
+
* Позволяет проверять нужно ли перекопировать node_modules
|
|
61
|
+
*/
|
|
62
|
+
class LinkingCache {
|
|
63
|
+
projectPath;
|
|
64
|
+
cachePath;
|
|
65
|
+
stateFilePath;
|
|
66
|
+
state;
|
|
67
|
+
enabled;
|
|
68
|
+
/**
|
|
69
|
+
* Создаёт экземпляр менеджера кэша
|
|
70
|
+
*
|
|
71
|
+
* @param projectPath - Корневая директория проекта
|
|
72
|
+
* @param enabled - Включён ли кэш (false при --no-cache)
|
|
73
|
+
*/
|
|
74
|
+
constructor(projectPath, enabled = true) {
|
|
75
|
+
this.projectPath = projectPath;
|
|
76
|
+
this.cachePath = path.join(projectPath, CACHE_DIR_NAME);
|
|
77
|
+
this.stateFilePath = path.join(this.cachePath, CACHE_STATE_FILE);
|
|
78
|
+
this.enabled = enabled;
|
|
79
|
+
this.state = this.loadState();
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Загружает состояние кэша из файла
|
|
83
|
+
*/
|
|
84
|
+
loadState() {
|
|
85
|
+
if (!this.enabled) {
|
|
86
|
+
return this.createEmptyState();
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
if (fs.existsSync(this.stateFilePath)) {
|
|
90
|
+
const content = fs.readFileSync(this.stateFilePath, 'utf-8');
|
|
91
|
+
const state = JSON.parse(content);
|
|
92
|
+
// Проверяем версию кэша
|
|
93
|
+
if (state.version !== CACHE_VERSION) {
|
|
94
|
+
// Версия устарела - сбрасываем кэш
|
|
95
|
+
return this.createEmptyState();
|
|
96
|
+
}
|
|
97
|
+
return state;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
// Ошибка чтения - начинаем с чистого состояния
|
|
102
|
+
}
|
|
103
|
+
return this.createEmptyState();
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Создаёт пустое состояние кэша
|
|
107
|
+
*/
|
|
108
|
+
createEmptyState() {
|
|
109
|
+
return {
|
|
110
|
+
version: CACHE_VERSION,
|
|
111
|
+
nodeModules: {}
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Сохраняет состояние кэша в файл
|
|
116
|
+
*/
|
|
117
|
+
saveState() {
|
|
118
|
+
if (!this.enabled) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
// Создаём директорию .btc если её нет
|
|
123
|
+
if (!fs.existsSync(this.cachePath)) {
|
|
124
|
+
fs.mkdirSync(this.cachePath, { recursive: true });
|
|
125
|
+
}
|
|
126
|
+
fs.writeFileSync(this.stateFilePath, JSON.stringify(this.state, null, 2), 'utf-8');
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
// Не критично если не удалось сохранить кэш
|
|
130
|
+
console.warn('Warning: Failed to save linking cache:', error);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Вычисляет hash от содержимого файла
|
|
135
|
+
*
|
|
136
|
+
* @param filePath - Путь к файлу
|
|
137
|
+
* @returns SHA256 hash или null если файл не существует
|
|
138
|
+
*/
|
|
139
|
+
computeFileHash(filePath) {
|
|
140
|
+
try {
|
|
141
|
+
if (!fs.existsSync(filePath)) {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
const content = fs.readFileSync(filePath);
|
|
145
|
+
return crypto.createHash('sha256').update(content).digest('hex');
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Получает hash от lockfile пакета
|
|
153
|
+
* Пробует package-lock.json, затем pnpm-lock.yaml, затем package.json как fallback
|
|
154
|
+
*
|
|
155
|
+
* @param packagePath - Путь к директории пакета
|
|
156
|
+
* @returns Hash от lockfile
|
|
157
|
+
*/
|
|
158
|
+
getLockfileHash(packagePath) {
|
|
159
|
+
// Сначала пробуем package-lock.json (npm)
|
|
160
|
+
const npmLockPath = path.join(packagePath, 'package-lock.json');
|
|
161
|
+
let hash = this.computeFileHash(npmLockPath);
|
|
162
|
+
if (hash) {
|
|
163
|
+
return hash;
|
|
164
|
+
}
|
|
165
|
+
// Затем пробуем pnpm-lock.yaml (pnpm workspaces)
|
|
166
|
+
const pnpmLockPath = path.join(packagePath, 'pnpm-lock.yaml');
|
|
167
|
+
hash = this.computeFileHash(pnpmLockPath);
|
|
168
|
+
if (hash) {
|
|
169
|
+
return hash;
|
|
170
|
+
}
|
|
171
|
+
// Fallback на package.json
|
|
172
|
+
const packageJsonPath = path.join(packagePath, 'package.json');
|
|
173
|
+
return this.computeFileHash(packageJsonPath);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Проверяет нужно ли копировать node_modules для пакета
|
|
177
|
+
*
|
|
178
|
+
* @param wsName - ws:name пакета
|
|
179
|
+
* @param packagePath - Путь к директории пакета (где находится package-lock.json)
|
|
180
|
+
* @returns true если нужно копировать, false если можно пропустить
|
|
181
|
+
*
|
|
182
|
+
* @remarks
|
|
183
|
+
* Возвращает true (нужно копировать) если:
|
|
184
|
+
* - Кэш отключён (--no-cache)
|
|
185
|
+
* - Нет записи в кэше для этого пакета
|
|
186
|
+
* - Hash от package-lock.json изменился
|
|
187
|
+
* - Не удалось вычислить hash
|
|
188
|
+
*/
|
|
189
|
+
shouldCopyNodeModules(wsName, packagePath) {
|
|
190
|
+
if (!this.enabled) {
|
|
191
|
+
return true;
|
|
192
|
+
}
|
|
193
|
+
const currentHash = this.getLockfileHash(packagePath);
|
|
194
|
+
if (!currentHash) {
|
|
195
|
+
// Не удалось получить hash - копируем на всякий случай
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
const cached = this.state.nodeModules[wsName];
|
|
199
|
+
if (!cached) {
|
|
200
|
+
// Нет записи в кэше
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
// Сравниваем hash
|
|
204
|
+
return cached.lockfileHash !== currentHash;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Обновляет запись кэша после копирования node_modules
|
|
208
|
+
*
|
|
209
|
+
* @param wsName - ws:name пакета
|
|
210
|
+
* @param packagePath - Путь к директории пакета
|
|
211
|
+
*/
|
|
212
|
+
updateNodeModulesCache(wsName, packagePath) {
|
|
213
|
+
if (!this.enabled) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
const hash = this.getLockfileHash(packagePath);
|
|
217
|
+
if (!hash) {
|
|
218
|
+
// Удаляем запись если не можем вычислить hash
|
|
219
|
+
delete this.state.nodeModules[wsName];
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
this.state.nodeModules[wsName] = {
|
|
223
|
+
lockfileHash: hash,
|
|
224
|
+
linkedAt: new Date().toISOString(),
|
|
225
|
+
version: CACHE_VERSION
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
this.saveState();
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Очищает весь кэш
|
|
232
|
+
*/
|
|
233
|
+
clear() {
|
|
234
|
+
this.state = this.createEmptyState();
|
|
235
|
+
try {
|
|
236
|
+
if (fs.existsSync(this.stateFilePath)) {
|
|
237
|
+
fs.unlinkSync(this.stateFilePath);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
catch (error) {
|
|
241
|
+
// Не критично
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Полностью удаляет директорию .btc
|
|
246
|
+
*/
|
|
247
|
+
static removeAll(projectPath) {
|
|
248
|
+
const cachePath = path.join(projectPath, CACHE_DIR_NAME);
|
|
249
|
+
if (fs.existsSync(cachePath)) {
|
|
250
|
+
fs.rmSync(cachePath, { recursive: true, force: true });
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Проверяет включён ли кэш
|
|
255
|
+
*/
|
|
256
|
+
isEnabled() {
|
|
257
|
+
return this.enabled;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
exports.LinkingCache = LinkingCache;
|