@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.
Files changed (116) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +66 -0
  3. package/build/builder/config.js +88 -0
  4. package/build/cli/commands/artifact.js +14 -0
  5. package/build/cli/commands/build.js +25 -0
  6. package/build/cli/commands/dev.js +190 -0
  7. package/build/cli/commands/index.js +18 -0
  8. package/build/cli/commands/init.js +15 -0
  9. package/build/cli/commands/link.js +18 -0
  10. package/build/cli/commands/push.js +28 -0
  11. package/build/cli/index.js +14 -0
  12. package/build/cli/types.js +2 -0
  13. package/build/core/artifacting/context.js +54 -0
  14. package/build/core/artifacting/index.js +37 -0
  15. package/build/core/artifacting/stages/index.js +10 -0
  16. package/build/core/artifacting/stages/main-archive.js +72 -0
  17. package/build/core/artifacting/stages/validate.js +70 -0
  18. package/build/core/artifacting/types.js +6 -0
  19. package/build/core/artifacting/utils/index.js +10 -0
  20. package/build/core/artifacting/utils/zip.js +94 -0
  21. package/build/core/babel.js +96 -0
  22. package/build/core/btconfig.types.js +6 -0
  23. package/build/core/build.js +280 -0
  24. package/build/core/building/compile-mode.js +146 -0
  25. package/build/core/building/compiler.js +281 -0
  26. package/build/core/building/coordinator.js +71 -0
  27. package/build/core/building/files.js +290 -0
  28. package/build/core/building/index.js +102 -0
  29. package/build/core/building/output.js +92 -0
  30. package/build/core/building/transformers.js +110 -0
  31. package/build/core/building/types.js +19 -0
  32. package/build/core/config.js +157 -0
  33. package/build/core/dependencies.js +223 -0
  34. package/build/core/linking/cache.js +260 -0
  35. package/build/core/linking/context.js +149 -0
  36. package/build/core/linking/dependencies.js +240 -0
  37. package/build/core/linking/executables.js +61 -0
  38. package/build/core/linking/generators/api-ext.js +57 -0
  39. package/build/core/linking/generators/component.js +83 -0
  40. package/build/core/linking/generators/filemap.js +53 -0
  41. package/build/core/linking/generators/index.js +21 -0
  42. package/build/core/linking/generators/init-xml.js +37 -0
  43. package/build/core/linking/generators/package-json.js +50 -0
  44. package/build/core/linking/index.js +213 -0
  45. package/build/core/linking/linkers/component.js +175 -0
  46. package/build/core/linking/linkers/index.js +69 -0
  47. package/build/core/linking/linkers/standalone.js +144 -0
  48. package/build/core/linking/linkers/system.js +86 -0
  49. package/build/core/linking/parsers.js +278 -0
  50. package/build/core/linking/types.js +6 -0
  51. package/build/core/linking/utils/copy.js +101 -0
  52. package/build/core/linking/utils/index.js +26 -0
  53. package/build/core/linking/utils/node-modules.js +226 -0
  54. package/build/core/linking/utils/package-type.js +101 -0
  55. package/build/core/linking/utils/url.js +73 -0
  56. package/build/core/linking/utils/write.js +91 -0
  57. package/build/core/logger.js +10 -0
  58. package/build/core/pushing/config.js +90 -0
  59. package/build/core/pushing/index.js +96 -0
  60. package/build/core/pushing/init-scripts.js +173 -0
  61. package/build/core/pushing/queue.js +95 -0
  62. package/build/core/pushing/reinit.js +61 -0
  63. package/build/core/pushing/session.js +167 -0
  64. package/build/core/pushing/types.js +6 -0
  65. package/build/core/pushing/upload.js +35 -0
  66. package/build/core/tsconfig.js +78 -0
  67. package/build/core/utils/index.js +17 -0
  68. package/build/core/utils/logger.js +46 -0
  69. package/build/core/utils/properties.js +81 -0
  70. package/build/core/utils/xml.js +44 -0
  71. package/build/core/utils.js +59 -0
  72. package/build/index.js +76 -0
  73. package/build/plugins/destructuring.js +83 -0
  74. package/build/plugins/forOfToForIn.js +14 -0
  75. package/build/plugins/loopHoistVariables.js +160 -0
  76. package/build/plugins/precedence.js +172 -0
  77. package/build/plugins/removeImportExport.js +42 -0
  78. package/build/plugins/replaceDollar.js +16 -0
  79. package/build/plugins/spreadArray.js +42 -0
  80. package/build/plugins/spreadObject.js +91 -0
  81. package/build/transformers/arrayFunctional.js +467 -0
  82. package/build/transformers/arrayGeneral.js +222 -0
  83. package/build/transformers/blockScoping.js +212 -0
  84. package/build/transformers/destructuring.js +133 -0
  85. package/build/transformers/dirname.js +79 -0
  86. package/build/transformers/enumsToObjects.js +25 -0
  87. package/build/transformers/execObj.js +220 -0
  88. package/build/transformers/forOfToForIn.js +45 -0
  89. package/build/transformers/funcSemantic.js +113 -0
  90. package/build/transformers/functions.js +270 -0
  91. package/build/transformers/globalCache.js +34 -0
  92. package/build/transformers/loopHoistVariables.js +352 -0
  93. package/build/transformers/math.js +39 -0
  94. package/build/transformers/namespaces.js +22 -0
  95. package/build/transformers/numericSeparator.js +46 -0
  96. package/build/transformers/objectProperties.js +54 -0
  97. package/build/transformers/precedence.js +192 -0
  98. package/build/transformers/propSemantic.js +467 -0
  99. package/build/transformers/remodule.js +620 -0
  100. package/build/transformers/removeImportExport.js +135 -0
  101. package/build/transformers/replaceDollar.js +46 -0
  102. package/build/transformers/shorthandProperties.js +34 -0
  103. package/build/transformers/spreadArray.js +68 -0
  104. package/build/transformers/spreadObject.js +134 -0
  105. package/build/transformers/string.js +138 -0
  106. package/build/transformers/templateLiterals.js +104 -0
  107. package/build/transformers/tocodelibrary.js +178 -0
  108. package/build/transformers/utils.js +202 -0
  109. package/build/wshcm/client.js +193 -0
  110. package/build/wshcm/evaluator.js +111 -0
  111. package/build/wshcm/exceptions.js +25 -0
  112. package/build/wshcm/index.js +20 -0
  113. package/build/wshcm/soap-utils.js +228 -0
  114. package/build/wshcm/types.js +2 -0
  115. package/build/wshcm/uploader.js +320 -0
  116. package/package.json +51 -0
@@ -0,0 +1,104 @@
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.templateLiteralsTransformer = templateLiteralsTransformer;
7
+ const typescript_1 = __importDefault(require("typescript"));
8
+ /**
9
+ * Трансформер для преобразования шаблонных строк в конкатенацию.
10
+ * Использует режим "loose" — все части приводятся к строкам через конкатенацию с "".
11
+ *
12
+ * @example
13
+ * // Вход:
14
+ * const msg = `Hello, ${name}!`;
15
+ * const multi = `a${b}c${d}e`;
16
+ *
17
+ * // Выход:
18
+ * const msg = "Hello, " + name + "!";
19
+ * const multi = "a" + b + "c" + d + "e";
20
+ *
21
+ * @returns TypeScript transformer factory
22
+ */
23
+ function templateLiteralsTransformer() {
24
+ return (context) => {
25
+ return (sourceFile) => {
26
+ const visitor = (node) => {
27
+ // Обрабатываем шаблонные литералы (template literals)
28
+ if (typescript_1.default.isTemplateExpression(node)) {
29
+ return transformTemplateExpression(node, context);
30
+ }
31
+ // Обрабатываем tagged template expressions (например: tag`hello`)
32
+ if (typescript_1.default.isTaggedTemplateExpression(node)) {
33
+ // Tagged templates требуют особой обработки, пока пропускаем
34
+ // TODO: поддержка tagged templates если нужно
35
+ return typescript_1.default.visitEachChild(node, visitor, context);
36
+ }
37
+ // Обрабатываем простые шаблонные строки без выражений (`hello`)
38
+ if (typescript_1.default.isNoSubstitutionTemplateLiteral(node)) {
39
+ // Просто превращаем в обычную строку
40
+ return typescript_1.default.factory.createStringLiteral(node.text);
41
+ }
42
+ return typescript_1.default.visitEachChild(node, visitor, context);
43
+ };
44
+ return typescript_1.default.visitNode(sourceFile, visitor);
45
+ };
46
+ };
47
+ }
48
+ /**
49
+ * Преобразует TemplateExpression в конкатенацию строк.
50
+ *
51
+ * @param node - узел TemplateExpression
52
+ * @param context - контекст трансформации
53
+ * @returns выражение конкатенации строк
54
+ */
55
+ function transformTemplateExpression(node, context) {
56
+ const parts = [];
57
+ // Добавляем начальную часть (head)
58
+ if (node.head.text.length > 0) {
59
+ parts.push(typescript_1.default.factory.createStringLiteral(node.head.text));
60
+ }
61
+ // Обрабатываем каждый span (выражение + следующий текст)
62
+ for (const span of node.templateSpans) {
63
+ // Добавляем выражение (рекурсивно обрабатываем на случай вложенных шаблонов)
64
+ const visitedExpression = typescript_1.default.visitNode(span.expression, (n) => {
65
+ if (typescript_1.default.isTemplateExpression(n)) {
66
+ return transformTemplateExpression(n, context);
67
+ }
68
+ if (typescript_1.default.isNoSubstitutionTemplateLiteral(n)) {
69
+ return typescript_1.default.factory.createStringLiteral(n.text);
70
+ }
71
+ return n;
72
+ });
73
+ parts.push(visitedExpression);
74
+ // Добавляем текстовую часть после выражения
75
+ const literal = span.literal;
76
+ if (literal.text.length > 0) {
77
+ parts.push(typescript_1.default.factory.createStringLiteral(literal.text));
78
+ }
79
+ }
80
+ // Если нет частей, возвращаем пустую строку
81
+ if (parts.length === 0) {
82
+ return typescript_1.default.factory.createStringLiteral('');
83
+ }
84
+ // Если только одна часть — возвращаем её
85
+ if (parts.length === 1) {
86
+ // Если это не строка, нужно привести к строке через конкатенацию с ""
87
+ const part = parts[0];
88
+ if (typescript_1.default.isStringLiteral(part)) {
89
+ return part;
90
+ }
91
+ // "" + expr для приведения к строке
92
+ return typescript_1.default.factory.createBinaryExpression(typescript_1.default.factory.createStringLiteral(''), typescript_1.default.SyntaxKind.PlusToken, part);
93
+ }
94
+ // Строим цепочку конкатенации слева направо
95
+ let result = parts[0];
96
+ // Если первая часть не строка, начинаем с "" + для приведения к строке
97
+ if (!typescript_1.default.isStringLiteral(result)) {
98
+ result = typescript_1.default.factory.createBinaryExpression(typescript_1.default.factory.createStringLiteral(''), typescript_1.default.SyntaxKind.PlusToken, result);
99
+ }
100
+ for (let i = 1; i < parts.length; i++) {
101
+ result = typescript_1.default.factory.createBinaryExpression(result, typescript_1.default.SyntaxKind.PlusToken, parts[i]);
102
+ }
103
+ return result;
104
+ }
@@ -0,0 +1,178 @@
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.tocodelibraryTransformer = tocodelibraryTransformer;
7
+ const typescript_1 = __importDefault(require("typescript"));
8
+ const utils_1 = require("./utils");
9
+ function tocodelibraryTransformer() {
10
+ return (context) => {
11
+ return (sourceFile) => {
12
+ if (sourceFile.fileName.endsWith(".test.ts")) {
13
+ return sourceFile;
14
+ }
15
+ // Пропускаем трансформацию для executable objects
16
+ if ((0, utils_1.isExecutableObject)(sourceFile)) {
17
+ return sourceFile;
18
+ }
19
+ const hoistedFunctions = [];
20
+ let functionCounter = 0;
21
+ const functionNameMap = new Map();
22
+ const nameToHoistedName = new Map(); // Маппинг имени -> hoisted имя
23
+ const functionDepthMap = new Map(); // Маппинг функции -> уровень вложенности
24
+ let currentDepth = 0;
25
+ // Генерация уникального имени для функции
26
+ function generateUniqueName(originalName, node, depth) {
27
+ const baseName = originalName || "anonymous";
28
+ // Top-level функции (depth === 0) сохраняют оригинальное имя
29
+ let uniqueName;
30
+ if (depth === 0 && originalName) {
31
+ uniqueName = originalName;
32
+ }
33
+ else {
34
+ // Вложенные функции получают префикс __hoisted_
35
+ uniqueName = `__hoisted_${baseName}_${functionCounter++}`;
36
+ }
37
+ functionNameMap.set(node, uniqueName);
38
+ functionDepthMap.set(node, depth);
39
+ if (originalName) {
40
+ // Маппинг для всех функций (и top-level и вложенных)
41
+ nameToHoistedName.set(originalName, uniqueName);
42
+ }
43
+ return uniqueName;
44
+ }
45
+ // Генерация пути к __codelibrary через цепочку __parent
46
+ function generateCodelibaryPath(depth) {
47
+ if (depth === 0) {
48
+ return context.factory.createPropertyAccessExpression((0, utils_1.markUntouchable)(context.factory.createIdentifier("__module_env")), "__codelibrary");
49
+ }
50
+ let expr = context.factory.createIdentifier("__env");
51
+ for (let i = 0; i < depth; i++) {
52
+ expr = context.factory.createPropertyAccessExpression(expr, "__parent");
53
+ }
54
+ return context.factory.createPropertyAccessExpression((0, utils_1.markUntouchable)(expr), "__codelibrary");
55
+ }
56
+ // Первый проход: собираем все функции и даем им уникальные имена
57
+ function collectFunctions(node) {
58
+ if (typescript_1.default.isFunctionDeclaration(node)) {
59
+ const originalName = node.name?.text;
60
+ const uniqueName = generateUniqueName(originalName, node, currentDepth);
61
+ const hoistedFunction = context.factory.createFunctionDeclaration(node.modifiers, node.asteriskToken, context.factory.createIdentifier(uniqueName), node.typeParameters, node.parameters, node.type, node.body);
62
+ hoistedFunctions.push(hoistedFunction);
63
+ // Увеличиваем глубину для вложенных функций
64
+ currentDepth++;
65
+ typescript_1.default.forEachChild(node, collectFunctions);
66
+ currentDepth--;
67
+ return;
68
+ }
69
+ typescript_1.default.forEachChild(node, collectFunctions);
70
+ }
71
+ // Второй проход: заменяем объявления функций и callable на ref, добавляем lib
72
+ function visitor(node, depth = 0) {
73
+ if (typescript_1.default.isFunctionDeclaration(node)) {
74
+ const originalName = node.name?.text;
75
+ const uniqueName = functionNameMap.get(node);
76
+ if (!uniqueName) {
77
+ return node;
78
+ }
79
+ // Увеличиваем глубину для обработки тела функции
80
+ const newDepth = depth + 1;
81
+ // Обрабатываем тело функции для замены вложенных функций
82
+ const transformedBody = node.body
83
+ ? typescript_1.default.visitNode(node.body, (n) => visitor(n, newDepth))
84
+ : undefined;
85
+ // Обновляем hoisted функцию с трансформированным телом
86
+ const hoistedIndex = hoistedFunctions.findIndex(f => f.name?.text === uniqueName);
87
+ if (hoistedIndex !== -1 && transformedBody) {
88
+ hoistedFunctions[hoistedIndex] = context.factory.createFunctionDeclaration(hoistedFunctions[hoistedIndex].modifiers, hoistedFunctions[hoistedIndex].asteriskToken, hoistedFunctions[hoistedIndex].name, hoistedFunctions[hoistedIndex].typeParameters, hoistedFunctions[hoistedIndex].parameters, hoistedFunctions[hoistedIndex].type, transformedBody);
89
+ }
90
+ // Удаляем объявление функции из кода
91
+ return [];
92
+ }
93
+ // Обрабатываем дескрипторы функций
94
+ if (typescript_1.default.isObjectLiteralExpression(node)) {
95
+ const hasDescriptor = node.properties.some(prop => typescript_1.default.isPropertyAssignment(prop) &&
96
+ ((typescript_1.default.isIdentifier(prop.name) && prop.name.text === "@descriptor") ||
97
+ (typescript_1.default.isStringLiteral(prop.name) && prop.name.text === "@descriptor")));
98
+ if (hasDescriptor) {
99
+ // Это дескриптор, добавляем свойство lib
100
+ const codelibPath = generateCodelibaryPath(depth);
101
+ const newProperties = node.properties.map(prop => {
102
+ // Заменяем callable на ref
103
+ if (typescript_1.default.isPropertyAssignment(prop)) {
104
+ const propertyName = typescript_1.default.isIdentifier(prop.name)
105
+ ? prop.name.text
106
+ : typescript_1.default.isStringLiteral(prop.name)
107
+ ? prop.name.text
108
+ : undefined;
109
+ if (propertyName === "callable") {
110
+ if (typescript_1.default.isIdentifier(prop.initializer)) {
111
+ const functionName = prop.initializer.text;
112
+ const hoistedName = nameToHoistedName.get(functionName);
113
+ if (hoistedName) {
114
+ return context.factory.createPropertyAssignment(context.factory.createStringLiteral("ref"), context.factory.createStringLiteral(hoistedName));
115
+ }
116
+ }
117
+ return context.factory.createPropertyAssignment(context.factory.createStringLiteral("ref"), typescript_1.default.visitNode(prop.initializer, (n) => visitor(n, depth)));
118
+ }
119
+ }
120
+ return prop;
121
+ });
122
+ // Добавляем свойство lib
123
+ const propertiesWithLib = [
124
+ ...newProperties,
125
+ context.factory.createPropertyAssignment(context.factory.createStringLiteral("lib"), codelibPath)
126
+ ];
127
+ return context.factory.updateObjectLiteralExpression(node, propertiesWithLib);
128
+ }
129
+ }
130
+ return typescript_1.default.visitEachChild(node, (n) => visitor(n, depth), context);
131
+ }
132
+ // Собираем все функции
133
+ collectFunctions(sourceFile);
134
+ // Трансформируем исходный файл
135
+ const transformedStatements = sourceFile.statements.map(statement => typescript_1.default.visitNode(statement, visitor)).flat().filter((s) => s !== undefined);
136
+ // Разделяем statements на export декларации и остальной код
137
+ const exportStatements = [];
138
+ const initStatements = [];
139
+ transformedStatements.forEach(statement => {
140
+ // Проверяем, содержит ли statement модификатор export или является export декларацией
141
+ const hasExportModifier = typescript_1.default.canHaveModifiers(statement) &&
142
+ typescript_1.default.getModifiers(statement)?.some((m) => m.kind === typescript_1.default.SyntaxKind.ExportKeyword);
143
+ const isExportDeclaration = typescript_1.default.isExportDeclaration(statement) || typescript_1.default.isExportAssignment(statement);
144
+ // Все что содержит export остается на top-level
145
+ // Это включает: export type, export interface, export {}, export default, export function, export const и т.д.
146
+ if (hasExportModifier || isExportDeclaration) {
147
+ exportStatements.push(statement);
148
+ }
149
+ else {
150
+ initStatements.push(statement);
151
+ }
152
+ });
153
+ // Ищем var __module_env = {} и добавляем __codelibrary
154
+ const statementsWithCodelibrary = initStatements.flatMap(statement => {
155
+ // Проверяем, является ли это var __module_env = {}
156
+ if (typescript_1.default.isVariableStatement(statement)) {
157
+ const decl = statement.declarationList.declarations[0];
158
+ if (decl && typescript_1.default.isIdentifier(decl.name) && decl.name.text === "__module_env") {
159
+ // Нашли __module_env, добавляем после него __module_env.__codelibrary = __codelibrary
160
+ const codelibAssignment = context.factory.createExpressionStatement(context.factory.createBinaryExpression(context.factory.createPropertyAccessExpression((0, utils_1.markUntouchable)(context.factory.createIdentifier("__module_env")), "__codelibrary"), typescript_1.default.SyntaxKind.EqualsToken, context.factory.createIdentifier("__codelibrary")));
161
+ return [statement, codelibAssignment];
162
+ }
163
+ }
164
+ return [statement];
165
+ });
166
+ // Создаем функцию __init с оставшимися statements (без export деклараций)
167
+ const initFunction = context.factory.createFunctionDeclaration(undefined, undefined, context.factory.createIdentifier("__init"), undefined, [
168
+ context.factory.createParameterDeclaration(undefined, undefined, context.factory.createIdentifier("__codelibrary")),
169
+ context.factory.createParameterDeclaration(undefined, undefined, context.factory.createIdentifier("__module"))
170
+ ], undefined, context.factory.createBlock(statementsWithCodelibrary, true));
171
+ // Объединяем: hoisted функции, __init, и export декларации в конце
172
+ const newStatements = [...hoistedFunctions, initFunction, ...exportStatements];
173
+ newStatements.forEach(stmt => (0, utils_1.setParentNodes)(stmt, sourceFile));
174
+ // Возвращаем новый файл с hoisted функциями, __init и export декларациями
175
+ return context.factory.updateSourceFile(sourceFile, newStatements);
176
+ };
177
+ };
178
+ }
@@ -0,0 +1,202 @@
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.printAstNode = printAstNode;
37
+ exports.markUntouchable = markUntouchable;
38
+ exports.isUntouchable = isUntouchable;
39
+ exports.markExecutableObject = markExecutableObject;
40
+ exports.isExecutableObject = isExecutableObject;
41
+ exports.setExecutableObjectKey = setExecutableObjectKey;
42
+ exports.getExecutableObjectKey = getExecutableObjectKey;
43
+ exports.preserveSymbolsFrom = preserveSymbolsFrom;
44
+ exports.setParentNodes = setParentNodes;
45
+ exports.visitNodeWithParents = visitNodeWithParents;
46
+ exports.visitEachChildWithParents = visitEachChildWithParents;
47
+ const ts = __importStar(require("typescript"));
48
+ /**
49
+ * Utility functions for TypeScript AST transformers.
50
+ *
51
+ * Эти функции обеспечивают корректную работу последовательных трансформеров,
52
+ * устанавливая parent ссылки для узлов, созданных через factory методы.
53
+ *
54
+ * Проблема: Когда трансформер создает новые узлы через ts.factory.create*(),
55
+ * у этих узлов нет parent ссылок. Последующие трансформеры, которые полагаются
56
+ * на node.parent для определения контекста, не могут корректно обработать такие узлы.
57
+ *
58
+ * Решение: Использовать setParentNodes() после создания новых узлов.
59
+ *
60
+ * @example
61
+ * // Создание новых узлов без parent:
62
+ * const newNode = ts.factory.createObjectLiteralExpression(properties, true);
63
+ * return setParentNodes(newNode); // Устанавливаем parent для всех детей
64
+ *
65
+ * @example
66
+ * // Замена узла в visitor с сохранением parent из оригинальной ноды:
67
+ * if (ts.isArrowFunction(node)) {
68
+ * const newFunc = ts.factory.createFunctionExpression(...);
69
+ * return setParentNodes(newFunc, node.parent); // Parent от оригинального узла
70
+ * }
71
+ *
72
+ * @example
73
+ * // Использование wrapper для visitNode:
74
+ * const transformed = visitNodeWithParents(node, visitor); // Автоматически сохраняет parent
75
+ */
76
+ function printAstNode(node, sourceCode) {
77
+ const printer = ts.createPrinter({
78
+ newLine: ts.NewLineKind.LineFeed,
79
+ });
80
+ let sourceFile;
81
+ if (sourceCode) {
82
+ // Используем существующий исходный код
83
+ sourceFile = ts.createSourceFile('temp.ts', sourceCode, ts.ScriptTarget.Latest, true);
84
+ }
85
+ else {
86
+ // Создаем минимальный sourceFile для контекста
87
+ sourceFile = ts.createSourceFile('temp.ts', '', ts.ScriptTarget.Latest);
88
+ }
89
+ const result = printer.printNode(ts.EmitHint.Unspecified, node, sourceFile);
90
+ // console.log(result);
91
+ return result;
92
+ }
93
+ const untouchable = Symbol('untouchable');
94
+ function markUntouchable(obj) {
95
+ obj[untouchable] = true;
96
+ return obj;
97
+ }
98
+ function isUntouchable(obj) {
99
+ return obj && obj[untouchable] === true;
100
+ }
101
+ const executableObject = Symbol('executableObject');
102
+ function markExecutableObject(obj) {
103
+ obj[executableObject] = true;
104
+ return obj;
105
+ }
106
+ function isExecutableObject(obj) {
107
+ return obj && obj[executableObject] === true;
108
+ }
109
+ const executableObjectKey = Symbol('executableObjectKey');
110
+ function setExecutableObjectKey(obj, key) {
111
+ obj[executableObjectKey] = key;
112
+ return obj;
113
+ }
114
+ function getExecutableObjectKey(obj) {
115
+ return obj && obj[executableObjectKey];
116
+ }
117
+ function preserveSymbolsFrom(target, source) {
118
+ if (isUntouchable(source)) {
119
+ markUntouchable(target);
120
+ }
121
+ if (isExecutableObject(source)) {
122
+ markExecutableObject(target);
123
+ }
124
+ if (getExecutableObjectKey(source) !== undefined) {
125
+ setExecutableObjectKey(target, getExecutableObjectKey(source));
126
+ }
127
+ return target;
128
+ }
129
+ /**
130
+ * Устанавливает parent ссылки для всех дочерних узлов в AST.
131
+ * Используется после создания новых узлов через factory методы,
132
+ * чтобы последующие трансформеры могли корректно работать с node.parent.
133
+ *
134
+ * @param node - Корневой узел, для которого нужно установить parent ссылки
135
+ * @param parentNode - Опциональный parent для корневого узла (полезно при замене узлов в visitor)
136
+ * @returns Тот же узел с установленными parent ссылками
137
+ *
138
+ * @example
139
+ * // Замена узла в visitor с сохранением parent:
140
+ * if (ts.isArrowFunction(node)) {
141
+ * const newNode = ts.factory.createFunctionExpression(...);
142
+ * return setParentNodes(newNode, node.parent); // Сохраняем parent из оригинальной ноды
143
+ * }
144
+ */
145
+ function setParentNodes(node, parentNode) {
146
+ function visit(currentNode, parent) {
147
+ // Устанавливаем parent для текущего узла
148
+ if (parent && currentNode !== parent && currentNode.kind !== 308) {
149
+ currentNode.parent = parent;
150
+ }
151
+ // Рекурсивно обходим всех детей
152
+ ts.forEachChild(currentNode, child => {
153
+ visit(child, currentNode);
154
+ });
155
+ }
156
+ if (!node)
157
+ return node;
158
+ // Устанавливаем parent для корневого узла, если указан
159
+ if (parentNode && node !== parentNode && node.kind !== 308) {
160
+ node.parent = parentNode;
161
+ }
162
+ // Обходим детей корневого узла
163
+ ts.forEachChild(node, child => {
164
+ visit(child, node);
165
+ });
166
+ return node;
167
+ }
168
+ /**
169
+ * Wrapper для ts.visitNode, который автоматически устанавливает parent ссылки
170
+ * для результата трансформации.
171
+ *
172
+ * @param node - Узел для трансформации
173
+ * @param visitor - Visitor функция
174
+ * @param preserveParent - Если true, сохраняет parent из оригинального узла
175
+ * @returns Трансформированный узел с установленными parent ссылками
176
+ */
177
+ function visitNodeWithParents(node, visitor, preserveParent = true) {
178
+ if (!node)
179
+ return undefined;
180
+ const originalParent = node.parent;
181
+ const result = ts.visitNode(node, visitor);
182
+ if (result) {
183
+ setParentNodes(result, preserveParent ? originalParent : undefined);
184
+ }
185
+ return result;
186
+ }
187
+ /**
188
+ * Wrapper для ts.visitEachChild, который автоматически устанавливает parent ссылки
189
+ * для результата трансформации.
190
+ *
191
+ * @param node - Узел для трансформации
192
+ * @param visitor - Visitor функция
193
+ * @param context - Контекст трансформации
194
+ * @param preserveParent - Если true, сохраняет parent из оригинального узла
195
+ * @returns Трансформированный узел с установленными parent ссылками
196
+ */
197
+ function visitEachChildWithParents(node, visitor, context, preserveParent = true) {
198
+ const originalParent = node.parent;
199
+ const result = ts.visitEachChild(node, visitor, context);
200
+ setParentNodes(result, preserveParent ? originalParent : undefined);
201
+ return result;
202
+ }