@knapsack/spec-utils 4.75.8--canary.5662.4aaa414.0 → 4.75.8
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/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-lint.log +1 -1
- package/.turbo/turbo-test.log +3 -3
- package/CHANGELOG.md +35 -0
- package/dist/analyze-type.d.ts +12 -2
- package/dist/analyze-type.d.ts.map +1 -1
- package/dist/analyze-type.js +137 -69
- package/dist/analyze-type.js.map +1 -1
- package/package.json +10 -10
- package/src/analyze-type.ts +156 -77
package/.turbo/turbo-build.log
CHANGED
package/.turbo/turbo-lint.log
CHANGED
package/.turbo/turbo-test.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @knapsack/spec-utils@4.75.
|
|
2
|
+
> @knapsack/spec-utils@4.75.7 test /home/runner/work/app-monorepo/app-monorepo/apps/client/libs/spec-utils
|
|
3
3
|
> ava
|
|
4
4
|
|
|
5
5
|
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
✔ analyze-exports › function with basic parameters: .d.ts
|
|
24
24
|
✔ analyze-exports › async function with basic parameters: .d.ts
|
|
25
25
|
✔ analyze-exports › function with complex parameters: .d.ts
|
|
26
|
-
✔ analyze-exports.sandbox-components › analyzeExports react (3.
|
|
27
|
-
✔ analyze-exports.sandbox-components › analyzeExports angular (2.
|
|
26
|
+
✔ analyze-exports.sandbox-components › analyzeExports react (3.4s)
|
|
27
|
+
✔ analyze-exports.sandbox-components › analyzeExports angular (2.1s)
|
|
28
28
|
✔ convert-to-spec › string
|
|
29
29
|
✔ convert-to-spec › boolean
|
|
30
30
|
✔ convert-to-spec › object
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,38 @@
|
|
|
1
|
+
# v4.75.8 (Tue Feb 25 2025)
|
|
2
|
+
|
|
3
|
+
#### 🐛 Bug Fix
|
|
4
|
+
|
|
5
|
+
- updates handling of visited types, adds depth limit [#5694](https://github.com/knapsack-labs/app-monorepo/pull/5694) ([@mabry1985](https://github.com/mabry1985))
|
|
6
|
+
|
|
7
|
+
#### Authors: 1
|
|
8
|
+
|
|
9
|
+
- Josh Mabry ([@mabry1985](https://github.com/mabry1985))
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# v4.75.7 (Mon Feb 24 2025)
|
|
14
|
+
|
|
15
|
+
#### 🐛 Bug Fix
|
|
16
|
+
|
|
17
|
+
- merge from latest ([@illepic](https://github.com/illepic))
|
|
18
|
+
- Merge branch 'latest' into feature/strictNullChecks-gitlab-rest-api ([@illepic](https://github.com/illepic))
|
|
19
|
+
- Merge branch 'latest' into feature/strictNullChecks-github-api-2 ([@illepic](https://github.com/illepic))
|
|
20
|
+
- Merge branch 'latest' into feature/strictNullChecks-bitbucket-cloud-api ([@illepic](https://github.com/illepic))
|
|
21
|
+
- Merge branch 'latest' into 12-12-start_of_strictNullChecks_in_lambdas ([@illepic](https://github.com/illepic))
|
|
22
|
+
|
|
23
|
+
#### 🏠 Internal
|
|
24
|
+
|
|
25
|
+
- strictNullChecks: github-api [#5376](https://github.com/knapsack-labs/app-monorepo/pull/5376) ([@illepic](https://github.com/illepic))
|
|
26
|
+
- strictNullChecks: gitlab-rest-api [#5386](https://github.com/knapsack-labs/app-monorepo/pull/5386) ([@illepic](https://github.com/illepic) [@freneticpixel](https://github.com/freneticpixel))
|
|
27
|
+
- strictNullChecks: bitbucket-cloud-api [#5333](https://github.com/knapsack-labs/app-monorepo/pull/5333) ([@illepic](https://github.com/illepic))
|
|
28
|
+
|
|
29
|
+
#### Authors: 2
|
|
30
|
+
|
|
31
|
+
- Christopher Bloom ([@illepic](https://github.com/illepic))
|
|
32
|
+
- Jim Frenette ([@freneticpixel](https://github.com/freneticpixel))
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
1
36
|
# v4.75.6 (Fri Feb 14 2025)
|
|
2
37
|
|
|
3
38
|
#### 🏠 Internal
|
package/dist/analyze-type.d.ts
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
2
|
import { TypeInfo } from './types.js';
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Analyzes a TypeScript type and returns a structured TypeInfo representation
|
|
5
|
+
*/
|
|
6
|
+
export declare function analyzeType({ type, checker, isOptional, visitedTypes, depth,
|
|
7
|
+
/**
|
|
8
|
+
* The maximum depth of type analysis.
|
|
9
|
+
* This is used to avoid infinite recursion.
|
|
10
|
+
*/
|
|
11
|
+
maxDepth, }: {
|
|
4
12
|
type: ts.Type;
|
|
5
13
|
checker: ts.TypeChecker;
|
|
6
14
|
isOptional?: boolean;
|
|
7
|
-
visitedTypes?:
|
|
15
|
+
visitedTypes?: Map<string, TypeInfo>;
|
|
16
|
+
depth?: number;
|
|
17
|
+
maxDepth?: number;
|
|
8
18
|
}): TypeInfo;
|
|
9
19
|
//# sourceMappingURL=analyze-type.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyze-type.d.ts","sourceRoot":"","sources":["../src/analyze-type.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,QAAQ,EAAkB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"analyze-type.d.ts","sourceRoot":"","sources":["../src/analyze-type.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,QAAQ,EAAkB,MAAM,YAAY,CAAC;AA4CtD;;GAEG;AACH,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,OAAO,EACP,UAAU,EACV,YAA0C,EAC1C,KAAS;AACT;;;GAGG;AACH,QAAY,GACb,EAAE;IACD,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC;IACd,OAAO,EAAE,EAAE,CAAC,WAAW,CAAC;IACxB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,QAAQ,CAyPX"}
|
package/dist/analyze-type.js
CHANGED
|
@@ -1,26 +1,52 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
2
|
import { getSetFlags } from './utils.js';
|
|
3
|
-
|
|
3
|
+
// Cache for type IDs to improve performance
|
|
4
|
+
const typeIdMap = new WeakMap();
|
|
5
|
+
/**
|
|
6
|
+
* Generates a consistent identifier for a TypeScript type
|
|
7
|
+
* Uses the type's string representation to ensure identical types get the same ID
|
|
8
|
+
*/
|
|
9
|
+
function getTypeId(type, checker) {
|
|
10
|
+
// Check if we already have an ID for this type
|
|
11
|
+
const existingId = typeIdMap.get(type);
|
|
12
|
+
if (existingId) {
|
|
13
|
+
return existingId;
|
|
14
|
+
}
|
|
15
|
+
// Generate a new ID based on the type's string representation
|
|
16
|
+
// This ensures identical types get the same ID
|
|
17
|
+
const typeString = checker.typeToString(type, undefined,
|
|
18
|
+
// eslint-disable-next-line no-bitwise
|
|
19
|
+
ts.TypeFormatFlags.NoTruncation);
|
|
20
|
+
// Add some additional information to help distinguish types
|
|
21
|
+
// that might have the same string representation
|
|
22
|
+
const idComponents = [typeString];
|
|
23
|
+
// Add symbol name if available
|
|
24
|
+
const symbol = type.getSymbol();
|
|
25
|
+
if (symbol) {
|
|
26
|
+
idComponents.push(symbol.getName());
|
|
27
|
+
}
|
|
28
|
+
// Add type flags to help distinguish types
|
|
29
|
+
idComponents.push(String(type.flags));
|
|
30
|
+
const newId = idComponents.join('_');
|
|
31
|
+
typeIdMap.set(type, newId);
|
|
32
|
+
return newId;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Analyzes a TypeScript type and returns a structured TypeInfo representation
|
|
36
|
+
*/
|
|
37
|
+
export function analyzeType({ type, checker, isOptional, visitedTypes = new Map(), depth = 0,
|
|
38
|
+
/**
|
|
39
|
+
* The maximum depth of type analysis.
|
|
40
|
+
* This is used to avoid infinite recursion.
|
|
41
|
+
*/
|
|
42
|
+
maxDepth = 3, }) {
|
|
4
43
|
var _a;
|
|
5
|
-
//
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
// eslint-disable-next-line no-bitwise
|
|
11
|
-
ts.TypeFormatFlags.MultilineObjectLiterals |
|
|
12
|
-
ts.TypeFormatFlags.NoTruncation),
|
|
13
|
-
tsMetadata: {
|
|
14
|
-
typeFlags: getSetFlags({
|
|
15
|
-
flags: type.flags,
|
|
16
|
-
enumObject: ts.TypeFlags,
|
|
17
|
-
}),
|
|
18
|
-
type,
|
|
19
|
-
},
|
|
20
|
-
isOptional,
|
|
21
|
-
};
|
|
44
|
+
// Generate a unique key for the type
|
|
45
|
+
const typeId = getTypeId(type, checker);
|
|
46
|
+
// Check if we've already analyzed this type
|
|
47
|
+
if (visitedTypes.has(typeId)) {
|
|
48
|
+
return visitedTypes.get(typeId);
|
|
22
49
|
}
|
|
23
|
-
visitedTypes.add(type);
|
|
24
50
|
const tsRawType = checker.typeToString(type, undefined,
|
|
25
51
|
// eslint-disable-next-line no-bitwise
|
|
26
52
|
ts.TypeFormatFlags.MultilineObjectLiterals |
|
|
@@ -37,42 +63,71 @@ export function analyzeType({ type, checker, isOptional, visitedTypes = new Set(
|
|
|
37
63
|
},
|
|
38
64
|
isOptional,
|
|
39
65
|
};
|
|
66
|
+
// If we've reached max depth, return a simplified type
|
|
67
|
+
if (depth >= maxDepth) {
|
|
68
|
+
const result = {
|
|
69
|
+
type: 'misc',
|
|
70
|
+
...typeInfoCommon,
|
|
71
|
+
};
|
|
72
|
+
visitedTypes.set(typeId, result);
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
let result;
|
|
40
76
|
// Handle primitive types first
|
|
41
77
|
if (tsRawType === 'number' ||
|
|
42
78
|
tsRawType === 'boolean' ||
|
|
43
79
|
tsRawType === 'string') {
|
|
44
|
-
|
|
80
|
+
result = {
|
|
45
81
|
type: tsRawType,
|
|
46
82
|
...typeInfoCommon,
|
|
47
83
|
};
|
|
84
|
+
visitedTypes.set(typeId, result);
|
|
85
|
+
return result;
|
|
48
86
|
}
|
|
49
87
|
// Handle literal types
|
|
50
88
|
if (type.isStringLiteral()) {
|
|
51
|
-
|
|
89
|
+
result = {
|
|
52
90
|
type: 'stringLiteral',
|
|
53
91
|
value: type.value,
|
|
54
92
|
...typeInfoCommon,
|
|
55
93
|
};
|
|
94
|
+
visitedTypes.set(typeId, result);
|
|
95
|
+
return result;
|
|
56
96
|
}
|
|
57
97
|
if (type.isNumberLiteral()) {
|
|
58
|
-
|
|
98
|
+
result = {
|
|
59
99
|
type: 'numberLiteral',
|
|
60
100
|
value: type.value,
|
|
61
101
|
...typeInfoCommon,
|
|
62
102
|
};
|
|
103
|
+
visitedTypes.set(typeId, result);
|
|
104
|
+
return result;
|
|
63
105
|
}
|
|
106
|
+
// Create a placeholder to avoid infinite recursion
|
|
107
|
+
const placeholder = {
|
|
108
|
+
type: 'misc',
|
|
109
|
+
...typeInfoCommon,
|
|
110
|
+
};
|
|
111
|
+
visitedTypes.set(typeId, placeholder);
|
|
64
112
|
// Handle unions
|
|
65
113
|
if (type.isUnion()) {
|
|
66
|
-
|
|
114
|
+
result = {
|
|
67
115
|
type: 'union',
|
|
68
|
-
items: type.types.map((t) => analyzeType({
|
|
116
|
+
items: type.types.map((t) => analyzeType({
|
|
117
|
+
type: t,
|
|
118
|
+
checker,
|
|
119
|
+
isOptional,
|
|
120
|
+
visitedTypes,
|
|
121
|
+
depth: depth + 1,
|
|
122
|
+
maxDepth,
|
|
123
|
+
})),
|
|
69
124
|
...typeInfoCommon,
|
|
70
125
|
};
|
|
71
126
|
}
|
|
72
127
|
// Handle arrays
|
|
73
|
-
if (checker.isArrayType(type) || checker.isArrayLikeType(type)) {
|
|
128
|
+
else if (checker.isArrayType(type) || checker.isArrayLikeType(type)) {
|
|
74
129
|
const indexInfos = checker.getIndexInfosOfType(type);
|
|
75
|
-
|
|
130
|
+
result = {
|
|
76
131
|
type: 'array',
|
|
77
132
|
items: indexInfos.length === 1
|
|
78
133
|
? analyzeType({
|
|
@@ -80,6 +135,8 @@ export function analyzeType({ type, checker, isOptional, visitedTypes = new Set(
|
|
|
80
135
|
checker,
|
|
81
136
|
isOptional,
|
|
82
137
|
visitedTypes,
|
|
138
|
+
depth: depth + 1,
|
|
139
|
+
maxDepth,
|
|
83
140
|
})
|
|
84
141
|
: { type: 'misc', ...typeInfoCommon },
|
|
85
142
|
...typeInfoCommon,
|
|
@@ -91,7 +148,7 @@ export function analyzeType({ type, checker, isOptional, visitedTypes = new Set(
|
|
|
91
148
|
// from each type in the intersection, but we may want to limit the depth of the intersection
|
|
92
149
|
// to avoid bringing in too much.
|
|
93
150
|
// https://linear.app/knapsack/issue/KSP-5885/update-handling-of-intersection-types-in-spec-utils
|
|
94
|
-
if (type.isIntersection()) {
|
|
151
|
+
else if (type.isIntersection()) {
|
|
95
152
|
const properties = type.getProperties();
|
|
96
153
|
if (properties.length > 0) {
|
|
97
154
|
const analyzedProperties = properties.reduce((acc, prop) => {
|
|
@@ -105,6 +162,8 @@ export function analyzeType({ type, checker, isOptional, visitedTypes = new Set(
|
|
|
105
162
|
// eslint-disable-next-line no-bitwise
|
|
106
163
|
isOptional: !!(prop.flags & ts.SymbolFlags.Optional),
|
|
107
164
|
visitedTypes,
|
|
165
|
+
depth: depth + 1,
|
|
166
|
+
maxDepth,
|
|
108
167
|
});
|
|
109
168
|
acc[prop.getName()] = {
|
|
110
169
|
name: prop.getName(),
|
|
@@ -126,17 +185,24 @@ export function analyzeType({ type, checker, isOptional, visitedTypes = new Set(
|
|
|
126
185
|
return acc;
|
|
127
186
|
}, {});
|
|
128
187
|
if (Object.keys(analyzedProperties).length > 0) {
|
|
129
|
-
|
|
188
|
+
result = {
|
|
130
189
|
type: 'object',
|
|
131
190
|
properties: analyzedProperties,
|
|
132
191
|
...typeInfoCommon,
|
|
133
192
|
};
|
|
134
193
|
}
|
|
194
|
+
else {
|
|
195
|
+
result = placeholder;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
result = placeholder;
|
|
135
200
|
}
|
|
136
201
|
}
|
|
137
202
|
// Handle function types
|
|
138
|
-
if (typeFlags.includes('Object') &&
|
|
139
|
-
|
|
203
|
+
else if (typeFlags.includes('Object') &&
|
|
204
|
+
type.getCallSignatures().length > 0) {
|
|
205
|
+
result = {
|
|
140
206
|
type: 'function',
|
|
141
207
|
parameters: [],
|
|
142
208
|
returnType: { type: 'misc', ...typeInfoCommon },
|
|
@@ -146,57 +212,59 @@ export function analyzeType({ type, checker, isOptional, visitedTypes = new Set(
|
|
|
146
212
|
// Handle object types
|
|
147
213
|
// @TODO: update handling of object type inference
|
|
148
214
|
// https://linear.app/knapsack/issue/KSP-5880/handle-arrays-of-objects-in-react-renderer-infer-spec
|
|
149
|
-
// if (typeFlags.includes('Object')) {
|
|
215
|
+
// else if (typeFlags.includes('Object')) {
|
|
150
216
|
// const properties = type.getProperties();
|
|
151
217
|
// if (properties.length > 0) {
|
|
152
|
-
// const analyzedProperties = properties.reduce
|
|
153
|
-
//
|
|
154
|
-
//
|
|
155
|
-
//
|
|
156
|
-
//
|
|
157
|
-
//
|
|
218
|
+
// const analyzedProperties = properties.reduce((acc, prop) => {
|
|
219
|
+
// try {
|
|
220
|
+
// const propType = checker.getTypeOfSymbol(prop);
|
|
221
|
+
// if (propType) {
|
|
222
|
+
// const propAnalysis = analyzeType({
|
|
223
|
+
// type: propType,
|
|
224
|
+
// checker,
|
|
225
|
+
// // eslint-disable-next-line no-bitwise
|
|
226
|
+
// isOptional: !!(prop.flags & ts.SymbolFlags.Optional),
|
|
227
|
+
// visitedTypes,
|
|
228
|
+
// depth: depth + 1,
|
|
229
|
+
// maxDepth,
|
|
230
|
+
// });
|
|
231
|
+
// acc[prop.getName()] = {
|
|
232
|
+
// name: prop.getName(),
|
|
233
|
+
// typeInfo: propAnalysis,
|
|
234
|
+
// tsMetadata: {
|
|
235
|
+
// symbol: prop,
|
|
158
236
|
// type: propType,
|
|
159
|
-
//
|
|
160
|
-
//
|
|
161
|
-
//
|
|
162
|
-
//
|
|
163
|
-
//
|
|
164
|
-
//
|
|
165
|
-
// acc[prop.getName()] = {
|
|
166
|
-
// name: prop.getName(),
|
|
167
|
-
// typeInfo: propAnalysis,
|
|
168
|
-
// tsMetadata: {
|
|
169
|
-
// symbol: prop,
|
|
170
|
-
// type: propType,
|
|
171
|
-
// symbolFlags: getSetFlags({
|
|
172
|
-
// flags: prop.flags,
|
|
173
|
-
// enumObject: ts.SymbolFlags,
|
|
174
|
-
// }),
|
|
175
|
-
// },
|
|
176
|
-
// };
|
|
177
|
-
// }
|
|
178
|
-
// } catch (error) {
|
|
179
|
-
// console.debug(
|
|
180
|
-
// `Error analyzing property ${prop.getName()}: ${error}`,
|
|
181
|
-
// );
|
|
237
|
+
// symbolFlags: getSetFlags({
|
|
238
|
+
// flags: prop.flags,
|
|
239
|
+
// enumObject: ts.SymbolFlags,
|
|
240
|
+
// }),
|
|
241
|
+
// },
|
|
242
|
+
// };
|
|
182
243
|
// }
|
|
183
|
-
//
|
|
184
|
-
//
|
|
185
|
-
//
|
|
186
|
-
//
|
|
244
|
+
// } catch (error) {
|
|
245
|
+
// console.debug(`Error analyzing property ${prop.getName()}: ${error}`);
|
|
246
|
+
// }
|
|
247
|
+
// return acc;
|
|
248
|
+
// }, {} as Record<string, any>);
|
|
187
249
|
// if (Object.keys(analyzedProperties).length > 0) {
|
|
188
|
-
//
|
|
250
|
+
// result = {
|
|
189
251
|
// type: 'object',
|
|
190
252
|
// properties: analyzedProperties,
|
|
191
253
|
// ...typeInfoCommon,
|
|
192
254
|
// };
|
|
255
|
+
// } else {
|
|
256
|
+
// result = placeholder;
|
|
193
257
|
// }
|
|
258
|
+
// } else {
|
|
259
|
+
// result = placeholder;
|
|
194
260
|
// }
|
|
195
261
|
// }
|
|
196
262
|
// Default to misc type for anything we can't properly analyze
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
263
|
+
else {
|
|
264
|
+
result = placeholder;
|
|
265
|
+
}
|
|
266
|
+
// Update the cache with the actual result
|
|
267
|
+
visitedTypes.set(typeId, result);
|
|
268
|
+
return result;
|
|
201
269
|
}
|
|
202
270
|
//# sourceMappingURL=analyze-type.js.map
|
package/dist/analyze-type.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyze-type.js","sourceRoot":"","sources":["../src/analyze-type.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,
|
|
1
|
+
{"version":3,"file":"analyze-type.js","sourceRoot":"","sources":["../src/analyze-type.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@knapsack/spec-utils",
|
|
3
3
|
"description": "",
|
|
4
|
-
"version": "4.75.8
|
|
4
|
+
"version": "4.75.8",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": {
|
|
@@ -19,17 +19,17 @@
|
|
|
19
19
|
"test": "ava"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@knapsack/utils": "4.75.8
|
|
22
|
+
"@knapsack/utils": "4.75.8",
|
|
23
23
|
"typescript": "^5.7.3"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@knapsack/angular-sandbox-components": "4.75.8
|
|
27
|
-
"@knapsack/eslint-config-starter": "4.75.8
|
|
28
|
-
"@knapsack/prettier-config": "4.75.8
|
|
29
|
-
"@knapsack/sandbox-components": "4.75.8
|
|
30
|
-
"@knapsack/test-ava": "4.75.8
|
|
31
|
-
"@knapsack/types": "4.75.8
|
|
32
|
-
"@knapsack/typescript-config-starter": "4.75.8
|
|
26
|
+
"@knapsack/angular-sandbox-components": "4.75.8",
|
|
27
|
+
"@knapsack/eslint-config-starter": "4.75.8",
|
|
28
|
+
"@knapsack/prettier-config": "4.75.8",
|
|
29
|
+
"@knapsack/sandbox-components": "4.75.8",
|
|
30
|
+
"@knapsack/test-ava": "4.75.8",
|
|
31
|
+
"@knapsack/types": "4.75.8",
|
|
32
|
+
"@knapsack/typescript-config-starter": "4.75.8",
|
|
33
33
|
"@types/node": "^20.17.17",
|
|
34
34
|
"ava": "^6.2.0",
|
|
35
35
|
"eslint": "^8.57.0"
|
|
@@ -43,5 +43,5 @@
|
|
|
43
43
|
"directory": "apps/client/libs/spec-utils",
|
|
44
44
|
"type": "git"
|
|
45
45
|
},
|
|
46
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "56fb9c1d8b39ce275d2dba24b9b93d97c9a213ca"
|
|
47
47
|
}
|
package/src/analyze-type.ts
CHANGED
|
@@ -2,39 +2,76 @@ import ts from 'typescript';
|
|
|
2
2
|
import { TypeInfo, TypeInfoCommon } from './types.js';
|
|
3
3
|
import { getSetFlags } from './utils.js';
|
|
4
4
|
|
|
5
|
+
// Cache for type IDs to improve performance
|
|
6
|
+
const typeIdMap = new WeakMap<ts.Type, string>();
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Generates a consistent identifier for a TypeScript type
|
|
10
|
+
* Uses the type's string representation to ensure identical types get the same ID
|
|
11
|
+
*/
|
|
12
|
+
function getTypeId(type: ts.Type, checker: ts.TypeChecker): string {
|
|
13
|
+
// Check if we already have an ID for this type
|
|
14
|
+
const existingId = typeIdMap.get(type);
|
|
15
|
+
if (existingId) {
|
|
16
|
+
return existingId;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Generate a new ID based on the type's string representation
|
|
20
|
+
// This ensures identical types get the same ID
|
|
21
|
+
const typeString = checker.typeToString(
|
|
22
|
+
type,
|
|
23
|
+
undefined,
|
|
24
|
+
// eslint-disable-next-line no-bitwise
|
|
25
|
+
ts.TypeFormatFlags.NoTruncation,
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
// Add some additional information to help distinguish types
|
|
29
|
+
// that might have the same string representation
|
|
30
|
+
const idComponents = [typeString];
|
|
31
|
+
|
|
32
|
+
// Add symbol name if available
|
|
33
|
+
const symbol = type.getSymbol();
|
|
34
|
+
if (symbol) {
|
|
35
|
+
idComponents.push(symbol.getName());
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Add type flags to help distinguish types
|
|
39
|
+
idComponents.push(String(type.flags));
|
|
40
|
+
|
|
41
|
+
const newId = idComponents.join('_');
|
|
42
|
+
typeIdMap.set(type, newId);
|
|
43
|
+
return newId;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Analyzes a TypeScript type and returns a structured TypeInfo representation
|
|
48
|
+
*/
|
|
5
49
|
export function analyzeType({
|
|
6
50
|
type,
|
|
7
51
|
checker,
|
|
8
52
|
isOptional,
|
|
9
|
-
visitedTypes = new
|
|
53
|
+
visitedTypes = new Map<string, TypeInfo>(),
|
|
54
|
+
depth = 0,
|
|
55
|
+
/**
|
|
56
|
+
* The maximum depth of type analysis.
|
|
57
|
+
* This is used to avoid infinite recursion.
|
|
58
|
+
*/
|
|
59
|
+
maxDepth = 3,
|
|
10
60
|
}: {
|
|
11
61
|
type: ts.Type;
|
|
12
62
|
checker: ts.TypeChecker;
|
|
13
63
|
isOptional?: boolean;
|
|
14
|
-
visitedTypes?:
|
|
64
|
+
visitedTypes?: Map<string, TypeInfo>;
|
|
65
|
+
depth?: number;
|
|
66
|
+
maxDepth?: number;
|
|
15
67
|
}): TypeInfo {
|
|
16
|
-
//
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
undefined,
|
|
23
|
-
// eslint-disable-next-line no-bitwise
|
|
24
|
-
ts.TypeFormatFlags.MultilineObjectLiterals |
|
|
25
|
-
ts.TypeFormatFlags.NoTruncation,
|
|
26
|
-
),
|
|
27
|
-
tsMetadata: {
|
|
28
|
-
typeFlags: getSetFlags({
|
|
29
|
-
flags: type.flags,
|
|
30
|
-
enumObject: ts.TypeFlags,
|
|
31
|
-
}),
|
|
32
|
-
type,
|
|
33
|
-
},
|
|
34
|
-
isOptional,
|
|
35
|
-
};
|
|
68
|
+
// Generate a unique key for the type
|
|
69
|
+
const typeId = getTypeId(type, checker);
|
|
70
|
+
|
|
71
|
+
// Check if we've already analyzed this type
|
|
72
|
+
if (visitedTypes.has(typeId)) {
|
|
73
|
+
return visitedTypes.get(typeId)!;
|
|
36
74
|
}
|
|
37
|
-
visitedTypes.add(type);
|
|
38
75
|
|
|
39
76
|
const tsRawType = checker.typeToString(
|
|
40
77
|
type,
|
|
@@ -56,51 +93,82 @@ export function analyzeType({
|
|
|
56
93
|
isOptional,
|
|
57
94
|
};
|
|
58
95
|
|
|
96
|
+
// If we've reached max depth, return a simplified type
|
|
97
|
+
if (depth >= maxDepth) {
|
|
98
|
+
const result: TypeInfo = {
|
|
99
|
+
type: 'misc',
|
|
100
|
+
...typeInfoCommon,
|
|
101
|
+
};
|
|
102
|
+
visitedTypes.set(typeId, result);
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
let result: TypeInfo;
|
|
107
|
+
|
|
59
108
|
// Handle primitive types first
|
|
60
109
|
if (
|
|
61
110
|
tsRawType === 'number' ||
|
|
62
111
|
tsRawType === 'boolean' ||
|
|
63
112
|
tsRawType === 'string'
|
|
64
113
|
) {
|
|
65
|
-
|
|
114
|
+
result = {
|
|
66
115
|
type: tsRawType,
|
|
67
116
|
...typeInfoCommon,
|
|
68
117
|
};
|
|
118
|
+
visitedTypes.set(typeId, result);
|
|
119
|
+
return result;
|
|
69
120
|
}
|
|
70
121
|
|
|
71
122
|
// Handle literal types
|
|
72
123
|
if (type.isStringLiteral()) {
|
|
73
|
-
|
|
124
|
+
result = {
|
|
74
125
|
type: 'stringLiteral',
|
|
75
126
|
value: type.value,
|
|
76
127
|
...typeInfoCommon,
|
|
77
128
|
};
|
|
129
|
+
visitedTypes.set(typeId, result);
|
|
130
|
+
return result;
|
|
78
131
|
}
|
|
79
132
|
|
|
80
133
|
if (type.isNumberLiteral()) {
|
|
81
|
-
|
|
134
|
+
result = {
|
|
82
135
|
type: 'numberLiteral',
|
|
83
136
|
value: type.value,
|
|
84
137
|
...typeInfoCommon,
|
|
85
138
|
};
|
|
139
|
+
visitedTypes.set(typeId, result);
|
|
140
|
+
return result;
|
|
86
141
|
}
|
|
87
142
|
|
|
143
|
+
// Create a placeholder to avoid infinite recursion
|
|
144
|
+
const placeholder: TypeInfo = {
|
|
145
|
+
type: 'misc',
|
|
146
|
+
...typeInfoCommon,
|
|
147
|
+
};
|
|
148
|
+
visitedTypes.set(typeId, placeholder);
|
|
149
|
+
|
|
88
150
|
// Handle unions
|
|
89
151
|
if (type.isUnion()) {
|
|
90
|
-
|
|
152
|
+
result = {
|
|
91
153
|
type: 'union',
|
|
92
154
|
items: type.types.map((t) =>
|
|
93
|
-
analyzeType({
|
|
155
|
+
analyzeType({
|
|
156
|
+
type: t,
|
|
157
|
+
checker,
|
|
158
|
+
isOptional,
|
|
159
|
+
visitedTypes,
|
|
160
|
+
depth: depth + 1,
|
|
161
|
+
maxDepth,
|
|
162
|
+
}),
|
|
94
163
|
),
|
|
95
164
|
...typeInfoCommon,
|
|
96
165
|
};
|
|
97
166
|
}
|
|
98
|
-
|
|
99
167
|
// Handle arrays
|
|
100
|
-
if (checker.isArrayType(type) || checker.isArrayLikeType(type)) {
|
|
168
|
+
else if (checker.isArrayType(type) || checker.isArrayLikeType(type)) {
|
|
101
169
|
const indexInfos = checker.getIndexInfosOfType(type);
|
|
102
170
|
|
|
103
|
-
|
|
171
|
+
result = {
|
|
104
172
|
type: 'array',
|
|
105
173
|
items:
|
|
106
174
|
indexInfos.length === 1
|
|
@@ -109,19 +177,20 @@ export function analyzeType({
|
|
|
109
177
|
checker,
|
|
110
178
|
isOptional,
|
|
111
179
|
visitedTypes,
|
|
180
|
+
depth: depth + 1,
|
|
181
|
+
maxDepth,
|
|
112
182
|
})
|
|
113
183
|
: { type: 'misc', ...typeInfoCommon },
|
|
114
184
|
...typeInfoCommon,
|
|
115
185
|
};
|
|
116
186
|
}
|
|
117
|
-
|
|
118
187
|
// Handle intersections
|
|
119
188
|
// This is where ForwardRef is being inferred
|
|
120
189
|
// @TODO: We need to find a way to handle depth here. Currently we bring in all of the properties
|
|
121
190
|
// from each type in the intersection, but we may want to limit the depth of the intersection
|
|
122
191
|
// to avoid bringing in too much.
|
|
123
192
|
// https://linear.app/knapsack/issue/KSP-5885/update-handling-of-intersection-types-in-spec-utils
|
|
124
|
-
if (type.isIntersection()) {
|
|
193
|
+
else if (type.isIntersection()) {
|
|
125
194
|
const properties = type.getProperties();
|
|
126
195
|
if (properties.length > 0) {
|
|
127
196
|
const analyzedProperties = properties.reduce((acc, prop) => {
|
|
@@ -136,6 +205,8 @@ export function analyzeType({
|
|
|
136
205
|
// eslint-disable-next-line no-bitwise
|
|
137
206
|
isOptional: !!(prop.flags & ts.SymbolFlags.Optional),
|
|
138
207
|
visitedTypes,
|
|
208
|
+
depth: depth + 1,
|
|
209
|
+
maxDepth,
|
|
139
210
|
});
|
|
140
211
|
|
|
141
212
|
acc[prop.getName()] = {
|
|
@@ -158,18 +229,24 @@ export function analyzeType({
|
|
|
158
229
|
}, {} as Record<string, any>);
|
|
159
230
|
|
|
160
231
|
if (Object.keys(analyzedProperties).length > 0) {
|
|
161
|
-
|
|
232
|
+
result = {
|
|
162
233
|
type: 'object',
|
|
163
234
|
properties: analyzedProperties,
|
|
164
235
|
...typeInfoCommon,
|
|
165
236
|
};
|
|
237
|
+
} else {
|
|
238
|
+
result = placeholder;
|
|
166
239
|
}
|
|
240
|
+
} else {
|
|
241
|
+
result = placeholder;
|
|
167
242
|
}
|
|
168
243
|
}
|
|
169
|
-
|
|
170
244
|
// Handle function types
|
|
171
|
-
if (
|
|
172
|
-
|
|
245
|
+
else if (
|
|
246
|
+
typeFlags.includes('Object') &&
|
|
247
|
+
type.getCallSignatures().length > 0
|
|
248
|
+
) {
|
|
249
|
+
result = {
|
|
173
250
|
type: 'function',
|
|
174
251
|
parameters: [],
|
|
175
252
|
returnType: { type: 'misc', ...typeInfoCommon },
|
|
@@ -180,58 +257,60 @@ export function analyzeType({
|
|
|
180
257
|
// Handle object types
|
|
181
258
|
// @TODO: update handling of object type inference
|
|
182
259
|
// https://linear.app/knapsack/issue/KSP-5880/handle-arrays-of-objects-in-react-renderer-infer-spec
|
|
183
|
-
// if (typeFlags.includes('Object')) {
|
|
260
|
+
// else if (typeFlags.includes('Object')) {
|
|
184
261
|
// const properties = type.getProperties();
|
|
185
262
|
// if (properties.length > 0) {
|
|
186
|
-
// const analyzedProperties = properties.reduce
|
|
187
|
-
//
|
|
188
|
-
//
|
|
189
|
-
//
|
|
190
|
-
//
|
|
191
|
-
//
|
|
263
|
+
// const analyzedProperties = properties.reduce((acc, prop) => {
|
|
264
|
+
// try {
|
|
265
|
+
// const propType = checker.getTypeOfSymbol(prop);
|
|
266
|
+
// if (propType) {
|
|
267
|
+
// const propAnalysis = analyzeType({
|
|
268
|
+
// type: propType,
|
|
269
|
+
// checker,
|
|
270
|
+
// // eslint-disable-next-line no-bitwise
|
|
271
|
+
// isOptional: !!(prop.flags & ts.SymbolFlags.Optional),
|
|
272
|
+
// visitedTypes,
|
|
273
|
+
// depth: depth + 1,
|
|
274
|
+
// maxDepth,
|
|
275
|
+
// });
|
|
276
|
+
// acc[prop.getName()] = {
|
|
277
|
+
// name: prop.getName(),
|
|
278
|
+
// typeInfo: propAnalysis,
|
|
279
|
+
// tsMetadata: {
|
|
280
|
+
// symbol: prop,
|
|
192
281
|
// type: propType,
|
|
193
|
-
//
|
|
194
|
-
//
|
|
195
|
-
//
|
|
196
|
-
//
|
|
197
|
-
//
|
|
198
|
-
//
|
|
199
|
-
// acc[prop.getName()] = {
|
|
200
|
-
// name: prop.getName(),
|
|
201
|
-
// typeInfo: propAnalysis,
|
|
202
|
-
// tsMetadata: {
|
|
203
|
-
// symbol: prop,
|
|
204
|
-
// type: propType,
|
|
205
|
-
// symbolFlags: getSetFlags({
|
|
206
|
-
// flags: prop.flags,
|
|
207
|
-
// enumObject: ts.SymbolFlags,
|
|
208
|
-
// }),
|
|
209
|
-
// },
|
|
210
|
-
// };
|
|
211
|
-
// }
|
|
212
|
-
// } catch (error) {
|
|
213
|
-
// console.debug(
|
|
214
|
-
// `Error analyzing property ${prop.getName()}: ${error}`,
|
|
215
|
-
// );
|
|
282
|
+
// symbolFlags: getSetFlags({
|
|
283
|
+
// flags: prop.flags,
|
|
284
|
+
// enumObject: ts.SymbolFlags,
|
|
285
|
+
// }),
|
|
286
|
+
// },
|
|
287
|
+
// };
|
|
216
288
|
// }
|
|
217
|
-
//
|
|
218
|
-
//
|
|
219
|
-
//
|
|
220
|
-
//
|
|
289
|
+
// } catch (error) {
|
|
290
|
+
// console.debug(`Error analyzing property ${prop.getName()}: ${error}`);
|
|
291
|
+
// }
|
|
292
|
+
// return acc;
|
|
293
|
+
// }, {} as Record<string, any>);
|
|
221
294
|
|
|
222
295
|
// if (Object.keys(analyzedProperties).length > 0) {
|
|
223
|
-
//
|
|
296
|
+
// result = {
|
|
224
297
|
// type: 'object',
|
|
225
298
|
// properties: analyzedProperties,
|
|
226
299
|
// ...typeInfoCommon,
|
|
227
300
|
// };
|
|
301
|
+
// } else {
|
|
302
|
+
// result = placeholder;
|
|
228
303
|
// }
|
|
304
|
+
// } else {
|
|
305
|
+
// result = placeholder;
|
|
229
306
|
// }
|
|
230
307
|
// }
|
|
231
|
-
|
|
232
308
|
// Default to misc type for anything we can't properly analyze
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
309
|
+
else {
|
|
310
|
+
result = placeholder;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Update the cache with the actual result
|
|
314
|
+
visitedTypes.set(typeId, result);
|
|
315
|
+
return result;
|
|
237
316
|
}
|