1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.convertPath = exports.isAutoGeneratedTypeUnion = exports.isAutoGeneratedEnumUnion = exports.isDynamicallyAdded = exports.insertAt = exports.replaceImportPath = exports.isPromiseOrObservable = exports.getTypeReferenceAsString = void 0;
|
4 | const lodash_1 = require("lodash");
|
5 | const path_1 = require("path");
|
6 | const ts = require("typescript");
|
7 | const ast_utils_1 = require("./ast-utils");
|
8 | function getTypeReferenceAsString(type, typeChecker, arrayDepth = 0) {
|
9 | if ((0, ast_utils_1.isArray)(type)) {
|
10 | const arrayType = (0, ast_utils_1.getTypeArguments)(type)[0];
|
11 | const { typeName, arrayDepth: depth } = getTypeReferenceAsString(arrayType, typeChecker, arrayDepth + 1);
|
12 | if (!typeName) {
|
13 | return { typeName: undefined };
|
14 | }
|
15 | return {
|
16 | typeName: `${typeName}`,
|
17 | isArray: true,
|
18 | arrayDepth: depth,
|
19 | };
|
20 | }
|
21 | if ((0, ast_utils_1.isBoolean)(type)) {
|
22 | return { typeName: Boolean.name, arrayDepth };
|
23 | }
|
24 | if ((0, ast_utils_1.isNumber)(type) || (0, ast_utils_1.isBigInt)(type)) {
|
25 | return { typeName: Number.name, arrayDepth };
|
26 | }
|
27 | if ((0, ast_utils_1.isString)(type) || (0, ast_utils_1.isStringLiteral)(type)) {
|
28 | return { typeName: String.name, arrayDepth };
|
29 | }
|
30 | if (isPromiseOrObservable((0, ast_utils_1.getText)(type, typeChecker))) {
|
31 | const typeArguments = (0, ast_utils_1.getTypeArguments)(type);
|
32 | const elementType = getTypeReferenceAsString((0, lodash_1.head)(typeArguments), typeChecker, arrayDepth);
|
33 | return elementType;
|
34 | }
|
35 | if (type.isClass()) {
|
36 | return { typeName: (0, ast_utils_1.getText)(type, typeChecker), arrayDepth };
|
37 | }
|
38 | try {
|
39 | const text = (0, ast_utils_1.getText)(type, typeChecker);
|
40 | if (text === Date.name) {
|
41 | return { typeName: text, arrayDepth };
|
42 | }
|
43 | if (isOptionalBoolean(text)) {
|
44 | return { typeName: Boolean.name, arrayDepth };
|
45 | }
|
46 | if ((0, ast_utils_1.isEnum)(type)) {
|
47 | return { typeName: text, arrayDepth };
|
48 | }
|
49 | const isEnumMember = type.symbol && type.symbol.flags === ts.SymbolFlags.EnumMember;
|
50 | if (isEnumMember) {
|
51 | type = typeChecker.getDeclaredTypeOfSymbol(type.symbol.parent);
|
52 | if (!type) {
|
53 | return undefined;
|
54 | }
|
55 | return { typeName: text, arrayDepth };
|
56 | }
|
57 | if (isAutoGeneratedTypeUnion(type) ||
|
58 | isAutoGeneratedEnumUnion(type, typeChecker)) {
|
59 | const types = type.types;
|
60 | return getTypeReferenceAsString(types[types.length - 1], typeChecker);
|
61 | }
|
62 | if (text === 'any' ||
|
63 | text === 'unknown' ||
|
64 | text === 'object' ||
|
65 | (0, ast_utils_1.isInterface)(type) ||
|
66 | (type.isUnionOrIntersection() && !(0, ast_utils_1.isEnum)(type))) {
|
67 | return { typeName: 'Object', arrayDepth };
|
68 | }
|
69 | if (type.aliasSymbol) {
|
70 | return { typeName: 'Object', arrayDepth };
|
71 | }
|
72 | return { typeName: 'Object', arrayDepth };
|
73 | }
|
74 | catch {
|
75 | return { typeName: 'Object', arrayDepth };
|
76 | }
|
77 | }
|
78 | exports.getTypeReferenceAsString = getTypeReferenceAsString;
|
79 | function isPromiseOrObservable(type) {
|
80 | return type.includes('Promise') || type.includes('Observable');
|
81 | }
|
82 | exports.isPromiseOrObservable = isPromiseOrObservable;
|
83 | function replaceImportPath(typeReference, fileName, options) {
|
84 | if (!typeReference.includes('import')) {
|
85 | return { typeReference, importPath: null };
|
86 | }
|
87 | let importPath = /\("([^)]).+(")/.exec(typeReference)[0];
|
88 | if (!importPath) {
|
89 | return { typeReference: undefined, importPath: null };
|
90 | }
|
91 | importPath = convertPath(importPath);
|
92 | importPath = importPath.slice(2, importPath.length - 1);
|
93 | const from = options?.readonly
|
94 | ? convertPath(options.pathToSource)
|
95 | : path_1.posix.dirname(convertPath(fileName));
|
96 | let relativePath = path_1.posix.relative(from, importPath);
|
97 | relativePath =
|
98 | !(0, path_1.isAbsolute)(relativePath) && relativePath[0] !== '.'
|
99 | ? './' + relativePath
|
100 | : relativePath;
|
101 | const nodeModulesText = 'node_modules';
|
102 | const nodeModulePos = relativePath.indexOf(nodeModulesText);
|
103 | if (nodeModulePos >= 0) {
|
104 | relativePath = relativePath.slice(nodeModulePos + nodeModulesText.length + 1);
|
105 | const typesText = '@types';
|
106 | const typesPos = relativePath.indexOf(typesText);
|
107 | if (typesPos >= 0) {
|
108 | relativePath = relativePath.slice(typesPos + typesText.length + 1);
|
109 | }
|
110 | const indexText = '/index';
|
111 | const indexPos = relativePath.indexOf(indexText);
|
112 | if (indexPos >= 0) {
|
113 | relativePath = relativePath.slice(0, indexPos);
|
114 | }
|
115 | }
|
116 | typeReference = typeReference.replace(importPath, relativePath);
|
117 | if (options.readonly) {
|
118 | const { typeName, typeImportStatement } = convertToAsyncImport(typeReference);
|
119 | return {
|
120 | typeReference: typeImportStatement,
|
121 | typeName,
|
122 | importPath: relativePath,
|
123 | };
|
124 | }
|
125 | return {
|
126 | typeReference: typeReference.replace('import', 'require'),
|
127 | importPath: relativePath,
|
128 | };
|
129 | }
|
130 | exports.replaceImportPath = replaceImportPath;
|
131 | function convertToAsyncImport(typeReference) {
|
132 | const regexp = /import\(.+\).([^\]]+)(\])?/;
|
133 | const match = regexp.exec(typeReference);
|
134 | if (match?.length >= 2) {
|
135 | const importPos = typeReference.indexOf(match[0]);
|
136 | typeReference = typeReference.replace(`.${match[1]}`, '');
|
137 | return {
|
138 | typeImportStatement: insertAt(typeReference, importPos, 'await '),
|
139 | typeName: match[1],
|
140 | };
|
141 | }
|
142 | return { typeImportStatement: typeReference };
|
143 | }
|
144 | function insertAt(string, index, substring) {
|
145 | return string.slice(0, index) + substring + string.slice(index);
|
146 | }
|
147 | exports.insertAt = insertAt;
|
148 | function isDynamicallyAdded(identifier) {
|
149 | return identifier && !identifier.parent && identifier.pos === -1;
|
150 | }
|
151 | exports.isDynamicallyAdded = isDynamicallyAdded;
|
152 |
|
153 |
|
154 |
|
155 |
|
156 |
|
157 |
|
158 | function isAutoGeneratedEnumUnion(type, typeChecker) {
|
159 | if (type.isUnionOrIntersection() && !(0, ast_utils_1.isEnum)(type)) {
|
160 | if (!type.types) {
|
161 | return undefined;
|
162 | }
|
163 | const undefinedTypeIndex = type.types.findIndex((type) => type.intrinsicName === 'undefined');
|
164 | if (undefinedTypeIndex < 0) {
|
165 | return undefined;
|
166 | }
|
167 |
|
168 | let parentType = undefined;
|
169 | const isParentSymbolEqual = type.types.every((item, index) => {
|
170 | if (index === undefinedTypeIndex) {
|
171 | return true;
|
172 | }
|
173 | if (!item.symbol) {
|
174 | return false;
|
175 | }
|
176 | if (!item.symbol.parent ||
|
177 | item.symbol.flags !== ts.SymbolFlags.EnumMember) {
|
178 | return false;
|
179 | }
|
180 | const symbolType = typeChecker.getDeclaredTypeOfSymbol(item.symbol.parent);
|
181 | if (symbolType === parentType || !parentType) {
|
182 | parentType = symbolType;
|
183 | return true;
|
184 | }
|
185 | return false;
|
186 | });
|
187 | if (isParentSymbolEqual) {
|
188 | return parentType;
|
189 | }
|
190 | }
|
191 | return undefined;
|
192 | }
|
193 | exports.isAutoGeneratedEnumUnion = isAutoGeneratedEnumUnion;
|
194 |
|
195 |
|
196 |
|
197 |
|
198 |
|
199 | function isAutoGeneratedTypeUnion(type) {
|
200 | if (type.isUnionOrIntersection() && !(0, ast_utils_1.isEnum)(type)) {
|
201 | if (!type.types) {
|
202 | return false;
|
203 | }
|
204 | const undefinedTypeIndex = type.types.findIndex((type) => type.intrinsicName === 'undefined');
|
205 |
|
206 | if (type.types.length === 2 && undefinedTypeIndex >= 0) {
|
207 | return true;
|
208 | }
|
209 | }
|
210 | return false;
|
211 | }
|
212 | exports.isAutoGeneratedTypeUnion = isAutoGeneratedTypeUnion;
|
213 |
|
214 |
|
215 |
|
216 |
|
217 | function isOptionalBoolean(text) {
|
218 | return typeof text === 'string' && text === 'boolean | undefined';
|
219 | }
|
220 |
|
221 |
|
222 |
|
223 |
|
224 | function convertPath(windowsPath) {
|
225 | return windowsPath
|
226 | .replace(/^\\\\\?\\/, '')
|
227 | .replace(/\\/g, '/')
|
228 | .replace(/\/\/+/g, '/');
|
229 | }
|
230 | exports.convertPath = convertPath;
|