@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,135 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.removeImportExportTransformer = removeImportExportTransformer;
|
|
7
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
8
|
+
/**
|
|
9
|
+
* Трансформер для удаления import/export деклараций.
|
|
10
|
+
*
|
|
11
|
+
* BorisScript не поддерживает ES модули, поэтому все import/export
|
|
12
|
+
* должны быть удалены после обработки remodule трансформером.
|
|
13
|
+
*
|
|
14
|
+
* Обрабатывает:
|
|
15
|
+
* - ImportDeclaration: полностью удаляется
|
|
16
|
+
* - ExportDeclaration (named): export убирается, declaration остаётся
|
|
17
|
+
* - ExportDefaultDeclaration: полностью удаляется
|
|
18
|
+
* - ExportAllDeclaration (export * from): полностью удаляется
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* // Вход:
|
|
22
|
+
* import { foo } from './foo';
|
|
23
|
+
* export const bar = 1;
|
|
24
|
+
* export default function main() {}
|
|
25
|
+
*
|
|
26
|
+
* // Выход:
|
|
27
|
+
* const bar = 1;
|
|
28
|
+
*
|
|
29
|
+
* @returns TypeScript transformer factory
|
|
30
|
+
*/
|
|
31
|
+
function removeImportExportTransformer() {
|
|
32
|
+
return (context) => {
|
|
33
|
+
return (sourceFile) => {
|
|
34
|
+
/**
|
|
35
|
+
* Visitor для обработки statements на верхнем уровне
|
|
36
|
+
*/
|
|
37
|
+
const visitor = (node) => {
|
|
38
|
+
// Удаляем ImportDeclaration
|
|
39
|
+
if (typescript_1.default.isImportDeclaration(node)) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
// Обрабатываем ExportDeclaration (named exports)
|
|
43
|
+
if (typescript_1.default.isExportDeclaration(node)) {
|
|
44
|
+
// export { foo } from './bar' или export { foo }
|
|
45
|
+
// Полностью удаляем
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
// Обрабатываем ExportAssignment (export default ...)
|
|
49
|
+
if (typescript_1.default.isExportAssignment(node)) {
|
|
50
|
+
// export default expression
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
// Обрабатываем FunctionDeclaration с export модификатором
|
|
54
|
+
if (typescript_1.default.isFunctionDeclaration(node)) {
|
|
55
|
+
const modifiers = typescript_1.default.getModifiers(node);
|
|
56
|
+
const hasExport = modifiers?.some(m => m.kind === typescript_1.default.SyntaxKind.ExportKeyword);
|
|
57
|
+
const hasDefault = modifiers?.some(m => m.kind === typescript_1.default.SyntaxKind.DefaultKeyword);
|
|
58
|
+
if (hasDefault) {
|
|
59
|
+
// export default function ... -> удаляем полностью
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
if (hasExport) {
|
|
63
|
+
// export function foo() {} -> function foo() {}
|
|
64
|
+
const newModifiers = modifiers?.filter(m => m.kind !== typescript_1.default.SyntaxKind.ExportKeyword);
|
|
65
|
+
return typescript_1.default.factory.updateFunctionDeclaration(node, newModifiers, node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, node.body);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// Обрабатываем ClassDeclaration с export модификатором
|
|
69
|
+
if (typescript_1.default.isClassDeclaration(node)) {
|
|
70
|
+
const modifiers = typescript_1.default.getModifiers(node);
|
|
71
|
+
const hasExport = modifiers?.some(m => m.kind === typescript_1.default.SyntaxKind.ExportKeyword);
|
|
72
|
+
const hasDefault = modifiers?.some(m => m.kind === typescript_1.default.SyntaxKind.DefaultKeyword);
|
|
73
|
+
if (hasDefault) {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
if (hasExport) {
|
|
77
|
+
const newModifiers = modifiers?.filter(m => m.kind !== typescript_1.default.SyntaxKind.ExportKeyword);
|
|
78
|
+
return typescript_1.default.factory.updateClassDeclaration(node, newModifiers, node.name, node.typeParameters, node.heritageClauses, node.members);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// Обрабатываем VariableStatement с export модификатором
|
|
82
|
+
if (typescript_1.default.isVariableStatement(node)) {
|
|
83
|
+
const modifiers = typescript_1.default.getModifiers(node);
|
|
84
|
+
const hasExport = modifiers?.some(m => m.kind === typescript_1.default.SyntaxKind.ExportKeyword);
|
|
85
|
+
if (hasExport) {
|
|
86
|
+
// export const foo = 1 -> const foo = 1
|
|
87
|
+
const newModifiers = modifiers?.filter(m => m.kind !== typescript_1.default.SyntaxKind.ExportKeyword);
|
|
88
|
+
return typescript_1.default.factory.updateVariableStatement(node, newModifiers, node.declarationList);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// Обрабатываем InterfaceDeclaration, TypeAliasDeclaration с export
|
|
92
|
+
// (хотя они должны быть стёрты TypeScript, но на всякий случай)
|
|
93
|
+
if (typescript_1.default.isInterfaceDeclaration(node) || typescript_1.default.isTypeAliasDeclaration(node)) {
|
|
94
|
+
const modifiers = typescript_1.default.getModifiers(node);
|
|
95
|
+
const hasExport = modifiers?.some(m => m.kind === typescript_1.default.SyntaxKind.ExportKeyword);
|
|
96
|
+
if (hasExport) {
|
|
97
|
+
// Типы не попадают в JS, но если вдруг...
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Обрабатываем EnumDeclaration с export модификатором
|
|
102
|
+
if (typescript_1.default.isEnumDeclaration(node)) {
|
|
103
|
+
const modifiers = typescript_1.default.getModifiers(node);
|
|
104
|
+
const hasExport = modifiers?.some(m => m.kind === typescript_1.default.SyntaxKind.ExportKeyword);
|
|
105
|
+
if (hasExport) {
|
|
106
|
+
const newModifiers = modifiers?.filter(m => m.kind !== typescript_1.default.SyntaxKind.ExportKeyword);
|
|
107
|
+
return typescript_1.default.factory.updateEnumDeclaration(node, newModifiers, node.name, node.members);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return typescript_1.default.visitEachChild(node, visitor, context);
|
|
111
|
+
};
|
|
112
|
+
const result = typescript_1.default.visitNode(sourceFile, (node) => {
|
|
113
|
+
if (typescript_1.default.isSourceFile(node)) {
|
|
114
|
+
const newStatements = [];
|
|
115
|
+
for (const statement of node.statements) {
|
|
116
|
+
const result = visitor(statement);
|
|
117
|
+
if (result === undefined) {
|
|
118
|
+
// Удаляем statement
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
else if (Array.isArray(result)) {
|
|
122
|
+
newStatements.push(...result);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
newStatements.push(result);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return typescript_1.default.factory.updateSourceFile(node, newStatements);
|
|
129
|
+
}
|
|
130
|
+
return node;
|
|
131
|
+
});
|
|
132
|
+
return result;
|
|
133
|
+
};
|
|
134
|
+
};
|
|
135
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.replaceDollarTransformer = replaceDollarTransformer;
|
|
7
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
8
|
+
/**
|
|
9
|
+
* Трансформер для замены знака доллара ($) в идентификаторах.
|
|
10
|
+
* В BorisScript символ $ не разрешён в идентификаторах,
|
|
11
|
+
* поэтому заменяем его на _24_ (ASCII код $).
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* // Вход:
|
|
15
|
+
* const $value = 10;
|
|
16
|
+
* function $helper() {}
|
|
17
|
+
* obj.$prop;
|
|
18
|
+
*
|
|
19
|
+
* // Выход:
|
|
20
|
+
* const _24_value = 10;
|
|
21
|
+
* function _24_helper() {}
|
|
22
|
+
* obj._24_prop;
|
|
23
|
+
*
|
|
24
|
+
* @returns TypeScript transformer factory
|
|
25
|
+
*/
|
|
26
|
+
function replaceDollarTransformer() {
|
|
27
|
+
return (context) => {
|
|
28
|
+
return (sourceFile) => {
|
|
29
|
+
const visitor = (node) => {
|
|
30
|
+
// Обрабатываем идентификаторы
|
|
31
|
+
if (typescript_1.default.isIdentifier(node)) {
|
|
32
|
+
const name = node.text;
|
|
33
|
+
if (name.includes('$')) {
|
|
34
|
+
const newName = name.replace(/\$/g, '_24_');
|
|
35
|
+
return typescript_1.default.factory.createIdentifier(newName);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// Обрабатываем строковые литералы в property access (obj["$prop"])
|
|
39
|
+
// Это может понадобиться если $ используется в строках для доступа к свойствам
|
|
40
|
+
// Но обычно это не нужно, т.к. строки не являются идентификаторами
|
|
41
|
+
return typescript_1.default.visitEachChild(node, visitor, context);
|
|
42
|
+
};
|
|
43
|
+
return typescript_1.default.visitNode(sourceFile, visitor);
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.shorthandPropertiesTransformer = shorthandPropertiesTransformer;
|
|
7
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
8
|
+
/**
|
|
9
|
+
* Трансформер для преобразования сокращённых свойств объектов в полную форму.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* // Вход:
|
|
13
|
+
* const obj = { x, y, foo };
|
|
14
|
+
*
|
|
15
|
+
* // Выход:
|
|
16
|
+
* const obj = { x: x, y: y, foo: foo };
|
|
17
|
+
*
|
|
18
|
+
* @returns TypeScript transformer factory
|
|
19
|
+
*/
|
|
20
|
+
function shorthandPropertiesTransformer() {
|
|
21
|
+
return (context) => {
|
|
22
|
+
return (sourceFile) => {
|
|
23
|
+
const visitor = (node) => {
|
|
24
|
+
// Обрабатываем свойства объекта
|
|
25
|
+
if (typescript_1.default.isShorthandPropertyAssignment(node)) {
|
|
26
|
+
// Преобразуем { x } в { x: x }
|
|
27
|
+
return typescript_1.default.factory.createPropertyAssignment(node.name, typescript_1.default.factory.createIdentifier(node.name.text));
|
|
28
|
+
}
|
|
29
|
+
return typescript_1.default.visitEachChild(node, visitor, context);
|
|
30
|
+
};
|
|
31
|
+
return typescript_1.default.visitNode(sourceFile, visitor);
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.spreadArrayTransformer = spreadArrayTransformer;
|
|
7
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
8
|
+
/**
|
|
9
|
+
* Трансформер для преобразования spread-элементов в массивах.
|
|
10
|
+
* Заменяет [...arr] на вызов ArrayUnion().
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* // Вход:
|
|
14
|
+
* const arr = [1, ...other, 2, ...more];
|
|
15
|
+
*
|
|
16
|
+
* // Выход:
|
|
17
|
+
* const arr = ArrayUnion([1], other, [2], more);
|
|
18
|
+
*
|
|
19
|
+
* @returns TypeScript transformer factory
|
|
20
|
+
*/
|
|
21
|
+
function spreadArrayTransformer() {
|
|
22
|
+
return (context) => {
|
|
23
|
+
return (sourceFile) => {
|
|
24
|
+
const visitor = (node) => {
|
|
25
|
+
// Обрабатываем массивы
|
|
26
|
+
if (typescript_1.default.isArrayLiteralExpression(node)) {
|
|
27
|
+
// Проверяем наличие spread-элементов
|
|
28
|
+
const hasSpread = node.elements.some(el => typescript_1.default.isSpreadElement(el));
|
|
29
|
+
if (!hasSpread) {
|
|
30
|
+
return typescript_1.default.visitEachChild(node, visitor, context);
|
|
31
|
+
}
|
|
32
|
+
const args = [];
|
|
33
|
+
let currentLiteralArray = [];
|
|
34
|
+
// Обрабатываем элементы массива
|
|
35
|
+
for (const element of node.elements) {
|
|
36
|
+
if (typescript_1.default.isSpreadElement(element)) {
|
|
37
|
+
// Если есть накопленные литералы, добавляем их как массив
|
|
38
|
+
if (currentLiteralArray.length > 0) {
|
|
39
|
+
args.push(typescript_1.default.factory.createArrayLiteralExpression(currentLiteralArray));
|
|
40
|
+
currentLiteralArray = [];
|
|
41
|
+
}
|
|
42
|
+
// Добавляем аргумент spread-элемента (рекурсивно обрабатываем)
|
|
43
|
+
const visitedExpression = typescript_1.default.visitNode(element.expression, visitor);
|
|
44
|
+
args.push(visitedExpression);
|
|
45
|
+
}
|
|
46
|
+
else if (typescript_1.default.isOmittedExpression(element)) {
|
|
47
|
+
// Пропущенные элементы [1, , 3] -> сохраняем как undefined
|
|
48
|
+
currentLiteralArray.push(typescript_1.default.factory.createIdentifier('undefined'));
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
// Собираем не-spread элементы (рекурсивно обрабатываем)
|
|
52
|
+
const visitedElement = typescript_1.default.visitNode(element, visitor);
|
|
53
|
+
currentLiteralArray.push(visitedElement);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Добавляем оставшиеся литералы как массив
|
|
57
|
+
if (currentLiteralArray.length > 0) {
|
|
58
|
+
args.push(typescript_1.default.factory.createArrayLiteralExpression(currentLiteralArray));
|
|
59
|
+
}
|
|
60
|
+
// Заменяем выражение массива вызовом ArrayUnion
|
|
61
|
+
return typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createIdentifier('ArrayUnion'), undefined, args);
|
|
62
|
+
}
|
|
63
|
+
return typescript_1.default.visitEachChild(node, visitor, context);
|
|
64
|
+
};
|
|
65
|
+
return typescript_1.default.visitNode(sourceFile, visitor);
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.spreadObjectTransformer = spreadObjectTransformer;
|
|
7
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
8
|
+
/**
|
|
9
|
+
* Трансформер для преобразования spread-элементов в объектах.
|
|
10
|
+
* Заменяет {...obj} на вызовы ObjectUnion().
|
|
11
|
+
* Также добавляет определение функции ObjectUnion в начало файла при необходимости.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* // Вход:
|
|
15
|
+
* const obj = { a: 1, ...other, b: 2 };
|
|
16
|
+
*
|
|
17
|
+
* // Выход:
|
|
18
|
+
* function ObjectUnion(obj1, obj2) { ... }
|
|
19
|
+
* const obj = ObjectUnion(ObjectUnion({ a: 1 }, other), { b: 2 });
|
|
20
|
+
*
|
|
21
|
+
* @returns TypeScript transformer factory
|
|
22
|
+
*/
|
|
23
|
+
function spreadObjectTransformer() {
|
|
24
|
+
return (context) => {
|
|
25
|
+
return (sourceFile) => {
|
|
26
|
+
let needsObjectUnion = false;
|
|
27
|
+
const visitor = (node) => {
|
|
28
|
+
// Обрабатываем объектные литералы
|
|
29
|
+
if (typescript_1.default.isObjectLiteralExpression(node)) {
|
|
30
|
+
// Проверяем наличие spread-элементов
|
|
31
|
+
const hasSpread = node.properties.some(prop => typescript_1.default.isSpreadAssignment(prop));
|
|
32
|
+
if (!hasSpread) {
|
|
33
|
+
return typescript_1.default.visitEachChild(node, visitor, context);
|
|
34
|
+
}
|
|
35
|
+
needsObjectUnion = true;
|
|
36
|
+
const parts = [];
|
|
37
|
+
let currentProperties = [];
|
|
38
|
+
// Обрабатываем свойства объекта
|
|
39
|
+
for (const property of node.properties) {
|
|
40
|
+
if (typescript_1.default.isSpreadAssignment(property)) {
|
|
41
|
+
// Если есть накопленные свойства, добавляем их как объект
|
|
42
|
+
if (currentProperties.length > 0) {
|
|
43
|
+
parts.push(typescript_1.default.factory.createObjectLiteralExpression(currentProperties));
|
|
44
|
+
currentProperties = [];
|
|
45
|
+
}
|
|
46
|
+
// Добавляем аргумент spread-элемента (рекурсивно обрабатываем)
|
|
47
|
+
const visitedExpression = typescript_1.default.visitNode(property.expression, visitor);
|
|
48
|
+
parts.push(visitedExpression);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
// Собираем не-spread свойства (рекурсивно обрабатываем)
|
|
52
|
+
const visitedProperty = typescript_1.default.visitNode(property, visitor);
|
|
53
|
+
currentProperties.push(visitedProperty);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Добавляем оставшиеся свойства как объект
|
|
57
|
+
if (currentProperties.length > 0) {
|
|
58
|
+
parts.push(typescript_1.default.factory.createObjectLiteralExpression(currentProperties));
|
|
59
|
+
}
|
|
60
|
+
// Если частей нет, возвращаем пустой объект
|
|
61
|
+
if (parts.length === 0) {
|
|
62
|
+
return typescript_1.default.factory.createObjectLiteralExpression([]);
|
|
63
|
+
}
|
|
64
|
+
// Если только одна часть, оборачиваем в ObjectUnion с пустым объектом
|
|
65
|
+
if (parts.length === 1) {
|
|
66
|
+
return typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createIdentifier('ObjectUnion'), undefined, [typescript_1.default.factory.createObjectLiteralExpression([]), parts[0]]);
|
|
67
|
+
}
|
|
68
|
+
// Строим вложенные вызовы ObjectUnion попарно (left-associative)
|
|
69
|
+
let expression = parts[0];
|
|
70
|
+
for (let i = 1; i < parts.length; i++) {
|
|
71
|
+
expression = typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createIdentifier('ObjectUnion'), undefined, [expression, parts[i]]);
|
|
72
|
+
}
|
|
73
|
+
return expression;
|
|
74
|
+
}
|
|
75
|
+
return typescript_1.default.visitEachChild(node, visitor, context);
|
|
76
|
+
};
|
|
77
|
+
// Сначала обрабатываем всё дерево
|
|
78
|
+
const visitedSourceFile = typescript_1.default.visitNode(sourceFile, visitor);
|
|
79
|
+
// Если нужна функция ObjectUnion, добавляем её в начало файла
|
|
80
|
+
if (needsObjectUnion) {
|
|
81
|
+
const objectUnionFunction = createObjectUnionFunction();
|
|
82
|
+
return typescript_1.default.factory.updateSourceFile(visitedSourceFile, [objectUnionFunction, ...visitedSourceFile.statements]);
|
|
83
|
+
}
|
|
84
|
+
return visitedSourceFile;
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Создаёт AST для функции ObjectUnion:
|
|
90
|
+
*
|
|
91
|
+
* function ObjectUnion(obj1, obj2) {
|
|
92
|
+
* var newObject = {};
|
|
93
|
+
* var key;
|
|
94
|
+
* for (key in obj1) {
|
|
95
|
+
* newObject.SetProperty(key, obj1.GetProperty(key));
|
|
96
|
+
* }
|
|
97
|
+
* for (key in obj2) {
|
|
98
|
+
* newObject.SetProperty(key, obj2.GetProperty(key));
|
|
99
|
+
* }
|
|
100
|
+
* return newObject;
|
|
101
|
+
* }
|
|
102
|
+
*/
|
|
103
|
+
function createObjectUnionFunction() {
|
|
104
|
+
const obj1 = typescript_1.default.factory.createIdentifier('obj1');
|
|
105
|
+
const obj2 = typescript_1.default.factory.createIdentifier('obj2');
|
|
106
|
+
const newObject = typescript_1.default.factory.createIdentifier('newObject');
|
|
107
|
+
const key = typescript_1.default.factory.createIdentifier('key');
|
|
108
|
+
// var newObject = {};
|
|
109
|
+
const newObjectDecl = typescript_1.default.factory.createVariableStatement(undefined, typescript_1.default.factory.createVariableDeclarationList([typescript_1.default.factory.createVariableDeclaration(newObject, undefined, undefined, typescript_1.default.factory.createObjectLiteralExpression([]))], typescript_1.default.NodeFlags.None // var
|
|
110
|
+
));
|
|
111
|
+
// var key;
|
|
112
|
+
const keyDecl = typescript_1.default.factory.createVariableStatement(undefined, typescript_1.default.factory.createVariableDeclarationList([typescript_1.default.factory.createVariableDeclaration(key)], typescript_1.default.NodeFlags.None // var
|
|
113
|
+
));
|
|
114
|
+
// Создаём for-in цикл для объекта
|
|
115
|
+
const createForInLoop = (sourceObj) => {
|
|
116
|
+
// newObject.SetProperty(key, sourceObj.GetProperty(key))
|
|
117
|
+
const setPropertyCall = typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createPropertyAccessExpression(newObject, 'SetProperty'), undefined, [
|
|
118
|
+
key,
|
|
119
|
+
typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createPropertyAccessExpression(sourceObj, 'GetProperty'), undefined, [key])
|
|
120
|
+
]);
|
|
121
|
+
return typescript_1.default.factory.createForInStatement(key, sourceObj, typescript_1.default.factory.createBlock([typescript_1.default.factory.createExpressionStatement(setPropertyCall)], true));
|
|
122
|
+
};
|
|
123
|
+
// for (key in obj1) { ... }
|
|
124
|
+
const forInObj1 = createForInLoop(obj1);
|
|
125
|
+
// for (key in obj2) { ... }
|
|
126
|
+
const forInObj2 = createForInLoop(obj2);
|
|
127
|
+
// return newObject;
|
|
128
|
+
const returnStmt = typescript_1.default.factory.createReturnStatement(newObject);
|
|
129
|
+
// function ObjectUnion(obj1, obj2) { ... }
|
|
130
|
+
return typescript_1.default.factory.createFunctionDeclaration(undefined, undefined, 'ObjectUnion', undefined, [
|
|
131
|
+
typescript_1.default.factory.createParameterDeclaration(undefined, undefined, obj1),
|
|
132
|
+
typescript_1.default.factory.createParameterDeclaration(undefined, undefined, obj2)
|
|
133
|
+
], undefined, typescript_1.default.factory.createBlock([newObjectDecl, keyDecl, forInObj1, forInObj2, returnStmt], true));
|
|
134
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
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.default = stringTransformer;
|
|
37
|
+
const ts = __importStar(require("typescript"));
|
|
38
|
+
function stringTransformer(program) {
|
|
39
|
+
return (context) => (file) => {
|
|
40
|
+
const typeChecker = program.getTypeChecker();
|
|
41
|
+
function visit(node) {
|
|
42
|
+
// Проверяем обращения к свойству .length
|
|
43
|
+
if (ts.isPropertyAccessExpression(node) && node.name.text === 'length') {
|
|
44
|
+
const expression = node.expression;
|
|
45
|
+
const type = typeChecker.getTypeAtLocation(expression);
|
|
46
|
+
// Проверяем, является ли тип строкой или строковым литералом
|
|
47
|
+
const isStringType = typeChecker.typeToString(type) === 'string' ||
|
|
48
|
+
(type.isStringLiteral && type.isStringLiteral()) ||
|
|
49
|
+
(type.flags & ts.TypeFlags.StringLike) !== 0;
|
|
50
|
+
if (isStringType) {
|
|
51
|
+
// Заменяем str.length на StrCharCount(str)
|
|
52
|
+
return ts.factory.createCallExpression(ts.factory.createIdentifier('StrCharCount'), undefined, [expression]);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// Проверяем вызовы методов toUpperCase, toLowerCase, startsWith и endsWith
|
|
56
|
+
if (ts.isCallExpression(node)) {
|
|
57
|
+
const expression = node.expression;
|
|
58
|
+
if (ts.isPropertyAccessExpression(expression)) {
|
|
59
|
+
const methodName = expression.name.text;
|
|
60
|
+
const target = expression.expression;
|
|
61
|
+
const type = typeChecker.getTypeAtLocation(target);
|
|
62
|
+
// Проверяем, является ли тип строкой или строковым литералом
|
|
63
|
+
const isStringType = typeChecker.typeToString(type) === 'string' ||
|
|
64
|
+
(type.isStringLiteral && type.isStringLiteral()) ||
|
|
65
|
+
(type.flags & ts.TypeFlags.StringLike) !== 0;
|
|
66
|
+
if (isStringType) {
|
|
67
|
+
// Обработка toUpperCase и toLowerCase
|
|
68
|
+
if (methodName === 'toUpperCase' || methodName === 'toLowerCase') {
|
|
69
|
+
const functionName = methodName === 'toUpperCase' ? 'StrUpperCase' : 'StrLowerCase';
|
|
70
|
+
return ts.factory.createCallExpression(ts.factory.createIdentifier(functionName), undefined, [target]);
|
|
71
|
+
}
|
|
72
|
+
// Обработка trim
|
|
73
|
+
if (methodName === 'trim') {
|
|
74
|
+
return ts.factory.createCallExpression(ts.factory.createIdentifier('Trim'), undefined, [target]);
|
|
75
|
+
}
|
|
76
|
+
// Обработка startsWith
|
|
77
|
+
if (methodName === 'startsWith' && node.arguments.length > 0) {
|
|
78
|
+
const searchString = node.arguments[0];
|
|
79
|
+
const position = node.arguments[1];
|
|
80
|
+
if (position) {
|
|
81
|
+
// Если передан position, заменяем на StrBegins(StrCharRangePos(str, position, StrCharCount(str)), searchString)
|
|
82
|
+
const charRangePosCall = ts.factory.createCallExpression(ts.factory.createIdentifier('StrCharRangePos'), undefined, [
|
|
83
|
+
target,
|
|
84
|
+
position,
|
|
85
|
+
ts.factory.createCallExpression(ts.factory.createIdentifier('StrCharCount'), undefined, [target])
|
|
86
|
+
]);
|
|
87
|
+
return ts.factory.createCallExpression(ts.factory.createIdentifier('StrBegins'), undefined, [charRangePosCall, searchString]);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
// Если position не передан, заменяем на StrBegins(str, searchString)
|
|
91
|
+
return ts.factory.createCallExpression(ts.factory.createIdentifier('StrBegins'), undefined, [target, searchString]);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// Обработка includes
|
|
95
|
+
if (methodName === 'includes' && node.arguments.length > 0) {
|
|
96
|
+
const searchString = node.arguments[0];
|
|
97
|
+
const position = node.arguments[1];
|
|
98
|
+
if (position) {
|
|
99
|
+
// Если передан position, заменяем на StrContains(StrCharRangePos(str, position, StrCharCount(str)), searchString)
|
|
100
|
+
const charRangePosCall = ts.factory.createCallExpression(ts.factory.createIdentifier('StrCharRangePos'), undefined, [
|
|
101
|
+
target,
|
|
102
|
+
position,
|
|
103
|
+
ts.factory.createCallExpression(ts.factory.createIdentifier('StrCharCount'), undefined, [target])
|
|
104
|
+
]);
|
|
105
|
+
return ts.factory.createCallExpression(ts.factory.createIdentifier('StrContains'), undefined, [charRangePosCall, searchString]);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
// Если position не передан, заменяем на StrContains(str, searchString)
|
|
109
|
+
return ts.factory.createCallExpression(ts.factory.createIdentifier('StrContains'), undefined, [target, searchString]);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// Обработка endsWith
|
|
113
|
+
if (methodName === 'endsWith' && node.arguments.length > 0) {
|
|
114
|
+
const searchString = node.arguments[0];
|
|
115
|
+
const length = node.arguments[1];
|
|
116
|
+
if (length) {
|
|
117
|
+
// Если передан length, заменяем на StrEnds(StrCharRangePos(str, 0, length), searchString)
|
|
118
|
+
const charRangePosCall = ts.factory.createCallExpression(ts.factory.createIdentifier('StrCharRangePos'), undefined, [
|
|
119
|
+
target,
|
|
120
|
+
ts.factory.createNumericLiteral('0'),
|
|
121
|
+
length
|
|
122
|
+
]);
|
|
123
|
+
return ts.factory.createCallExpression(ts.factory.createIdentifier('StrEnds'), undefined, [charRangePosCall, searchString]);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
// Если length не передан, заменяем на StrEnds(str, searchString)
|
|
127
|
+
return ts.factory.createCallExpression(ts.factory.createIdentifier('StrEnds'), undefined, [target, searchString]);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// Рекурсивно обходим дочерние узлы
|
|
134
|
+
return ts.visitEachChild(node, visit, context);
|
|
135
|
+
}
|
|
136
|
+
return ts.visitNode(file, visit);
|
|
137
|
+
};
|
|
138
|
+
}
|