@next/codemod 15.0.0-canary.17 → 15.0.0-canary.170

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.
@@ -0,0 +1,221 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.transformDynamicAPI = transformDynamicAPI;
4
+ const utils_1 = require("./utils");
5
+ function wrapParathnessIfNeeded(hasChainAccess, j, expression) {
6
+ return hasChainAccess ? j.parenthesizedExpression(expression) : expression;
7
+ }
8
+ function transformDynamicAPI(source, api, filePath) {
9
+ const j = api.jscodeshift.withParser('tsx');
10
+ const root = j(source);
11
+ let modified = false;
12
+ // Check if 'use' from 'react' needs to be imported
13
+ let needsReactUseImport = false;
14
+ const insertedTypes = new Set();
15
+ function isImportedInModule(path, functionName) {
16
+ const closestDef = j(path)
17
+ .closestScope()
18
+ .findVariableDeclarators(functionName);
19
+ return closestDef.size() === 0;
20
+ }
21
+ function processAsyncApiCalls(asyncRequestApiName, originRequestApiName) {
22
+ // Process each call to cookies() or headers()
23
+ root
24
+ .find(j.CallExpression, {
25
+ callee: {
26
+ type: 'Identifier',
27
+ name: asyncRequestApiName,
28
+ },
29
+ })
30
+ .forEach((path) => {
31
+ const isImportedTopLevel = isImportedInModule(path, asyncRequestApiName);
32
+ if (!isImportedTopLevel) {
33
+ return;
34
+ }
35
+ const closetScope = j(path).closestScope();
36
+ // First search the closed function of the current path
37
+ let closestFunction;
38
+ closestFunction = j(path).closest(j.FunctionDeclaration);
39
+ if (closestFunction.size() === 0) {
40
+ closestFunction = j(path).closest(j.FunctionExpression);
41
+ }
42
+ if (closestFunction.size() === 0) {
43
+ closestFunction = j(path).closest(j.ArrowFunctionExpression);
44
+ }
45
+ const isAsyncFunction = closestFunction
46
+ .nodes()
47
+ .some((node) => node.async);
48
+ const isCallAwaited = path.parentPath?.node?.type === 'AwaitExpression';
49
+ const hasChainAccess = path.parentPath.value.type === 'MemberExpression' &&
50
+ path.parentPath.value.object === path.node;
51
+ // For cookies/headers API, only transform server and shared components
52
+ if (isAsyncFunction) {
53
+ if (!isCallAwaited) {
54
+ // Add 'await' in front of cookies() call
55
+ const expr = j.awaitExpression(
56
+ // add parentheses to wrap the function call
57
+ j.callExpression(j.identifier(asyncRequestApiName), []));
58
+ j(path).replaceWith(wrapParathnessIfNeeded(hasChainAccess, j, expr));
59
+ modified = true;
60
+ }
61
+ }
62
+ else {
63
+ // Determine if the function is an export
64
+ const closetScopePath = closetScope.get();
65
+ const isFromExport = (0, utils_1.isMatchedFunctionExported)(closetScopePath, j);
66
+ const closestFunctionNode = closetScope.size()
67
+ ? closetScopePath.node
68
+ : null;
69
+ // If it's exporting a function directly, exportFunctionNode is same as exportNode
70
+ // e.g. export default function MyComponent() {}
71
+ // If it's exporting a variable declaration, exportFunctionNode is the function declaration
72
+ // e.g. export const MyComponent = function() {}
73
+ let exportFunctionNode;
74
+ if (isFromExport) {
75
+ if (closestFunctionNode &&
76
+ (0, utils_1.isFunctionType)(closestFunctionNode.type)) {
77
+ exportFunctionNode = closestFunctionNode;
78
+ }
79
+ }
80
+ else {
81
+ // Is normal async function
82
+ exportFunctionNode = closestFunctionNode;
83
+ }
84
+ let canConvertToAsync = false;
85
+ // check if current path is under the default export function
86
+ if (isFromExport) {
87
+ // if default export function is not async, convert it to async, and await the api call
88
+ if (!isCallAwaited) {
89
+ // If the scoped function is async function
90
+ if ((0, utils_1.isFunctionType)(exportFunctionNode.type) &&
91
+ exportFunctionNode.async === false) {
92
+ canConvertToAsync = true;
93
+ exportFunctionNode.async = true;
94
+ }
95
+ if (canConvertToAsync) {
96
+ const expr = j.awaitExpression(j.callExpression(j.identifier(asyncRequestApiName), []));
97
+ j(path).replaceWith(wrapParathnessIfNeeded(hasChainAccess, j, expr));
98
+ (0, utils_1.turnFunctionReturnTypeToAsync)(closetScopePath.node, j);
99
+ modified = true;
100
+ }
101
+ }
102
+ }
103
+ else {
104
+ // if parent is function and it's a hook, which starts with 'use', wrap the api call with 'use()'
105
+ const parentFunction = j(path).closest(j.FunctionDeclaration) ||
106
+ j(path).closest(j.FunctionExpression) ||
107
+ j(path).closest(j.ArrowFunctionExpression);
108
+ if (parentFunction.size() > 0) {
109
+ const parentFunctionName = parentFunction.get().node.id?.name;
110
+ const isParentFunctionHook = parentFunctionName?.startsWith('use');
111
+ if (isParentFunctionHook) {
112
+ j(path).replaceWith(j.callExpression(j.identifier('use'), [
113
+ j.callExpression(j.identifier(asyncRequestApiName), []),
114
+ ]));
115
+ needsReactUseImport = true;
116
+ }
117
+ else {
118
+ castTypesOrAddComment(j, path, originRequestApiName, root, filePath, insertedTypes);
119
+ }
120
+ }
121
+ else {
122
+ castTypesOrAddComment(j, path, originRequestApiName, root, filePath, insertedTypes);
123
+ }
124
+ modified = true;
125
+ }
126
+ }
127
+ });
128
+ }
129
+ const isClientComponent = (0, utils_1.determineClientDirective)(root, j, source);
130
+ const importedNextAsyncRequestApisMapping = findImportMappingFromNextHeaders(root, j);
131
+ // Only transform the valid calls in server or shared components
132
+ if (!isClientComponent) {
133
+ for (const originName in importedNextAsyncRequestApisMapping) {
134
+ const aliasName = importedNextAsyncRequestApisMapping[originName];
135
+ processAsyncApiCalls(aliasName, originName);
136
+ }
137
+ // Add import { use } from 'react' if needed and not already imported
138
+ if (needsReactUseImport) {
139
+ (0, utils_1.insertReactUseImport)(root, j);
140
+ }
141
+ }
142
+ return modified ? root.toSource() : null;
143
+ }
144
+ // cast to unknown first, then the specific type
145
+ const API_CAST_TYPE_MAP = {
146
+ cookies: 'UnsafeUnwrappedCookies',
147
+ headers: 'UnsafeUnwrappedHeaders',
148
+ draftMode: 'UnsafeUnwrappedDraftMode',
149
+ };
150
+ function castTypesOrAddComment(j, path, originRequestApiName, root, filePath, insertedTypes) {
151
+ const isTsFile = filePath.endsWith('.ts') || filePath.endsWith('.tsx');
152
+ if (isTsFile) {
153
+ /* Do type cast for headers, cookies, draftMode
154
+ import {
155
+ type UnsafeUnwrappedHeaders,
156
+ type UnsafeUnwrappedCookies,
157
+ type UnsafeUnwrappedDraftMode
158
+ } from 'next/headers'
159
+
160
+ cookies() as unknown as UnsafeUnwrappedCookies
161
+ headers() as unknown as UnsafeUnwrappedHeaders
162
+ draftMode() as unknown as UnsafeUnwrappedDraftMode
163
+
164
+ e.g. `<path>` is cookies(), convert it to `(<path> as unknown as UnsafeUnwrappedCookies)`
165
+ */
166
+ const targetType = API_CAST_TYPE_MAP[originRequestApiName];
167
+ const newCastExpression = j.tsAsExpression(j.tsAsExpression(path.node, j.tsUnknownKeyword()), j.tsTypeReference(j.identifier(targetType)));
168
+ // Replace the original expression with the new cast expression,
169
+ // also wrap () around the new cast expression.
170
+ j(path).replaceWith(j.parenthesizedExpression(newCastExpression));
171
+ // If cast types are not imported, add them to the import list
172
+ const importDeclaration = root.find(j.ImportDeclaration, {
173
+ source: { value: 'next/headers' },
174
+ });
175
+ if (importDeclaration.size() > 0) {
176
+ const hasImportedType = importDeclaration
177
+ .find(j.TSTypeAliasDeclaration, {
178
+ id: { name: targetType },
179
+ })
180
+ .size() > 0 ||
181
+ importDeclaration
182
+ .find(j.ImportSpecifier, {
183
+ imported: { name: targetType },
184
+ })
185
+ .size() > 0;
186
+ if (!hasImportedType && !insertedTypes.has(targetType)) {
187
+ importDeclaration
188
+ .get()
189
+ .node.specifiers.push(j.importSpecifier(j.identifier(`type ${targetType}`)));
190
+ insertedTypes.add(targetType);
191
+ }
192
+ }
193
+ }
194
+ else {
195
+ // Otherwise for JS file, leave a message to the user to manually handle the transformation
196
+ path.node.comments = [
197
+ j.commentBlock(' TODO: please manually await this call, codemod cannot transform due to undetermined async scope '),
198
+ ...(path.node.comments || []),
199
+ ];
200
+ }
201
+ }
202
+ function findImportMappingFromNextHeaders(root, j) {
203
+ const mappings = {};
204
+ // Find the import declaration from 'next/headers'
205
+ root
206
+ .find(j.ImportDeclaration, { source: { value: 'next/headers' } })
207
+ .forEach((importPath) => {
208
+ const importDeclaration = importPath.node;
209
+ // Iterate over the specifiers and build the mappings
210
+ importDeclaration.specifiers.forEach((specifier) => {
211
+ if (j.ImportSpecifier.check(specifier)) {
212
+ const importedName = specifier.imported.name; // Original name (e.g., cookies)
213
+ const localName = specifier.local.name; // Local name (e.g., myCookies or same as importedName)
214
+ // Add to the mappings
215
+ mappings[importedName] = localName;
216
+ }
217
+ });
218
+ });
219
+ return mappings;
220
+ }
221
+ //# sourceMappingURL=next-async-dynamic-api.js.map
@@ -0,0 +1,345 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.transformDynamicProps = transformDynamicProps;
4
+ const utils_1 = require("./utils");
5
+ const PAGE_PROPS = 'props';
6
+ function isAsyncFunctionDeclaration(path) {
7
+ const decl = path.value.declaration;
8
+ const isAsyncFunction = (decl.type === 'FunctionDeclaration' ||
9
+ decl.type === 'FunctionExpression' ||
10
+ decl.type === 'ArrowFunctionExpression') &&
11
+ decl.async;
12
+ return isAsyncFunction;
13
+ }
14
+ function transformDynamicProps(source, api, _filePath) {
15
+ let modified = false;
16
+ const j = api.jscodeshift.withParser('tsx');
17
+ const root = j(source);
18
+ // Check if 'use' from 'react' needs to be imported
19
+ let needsReactUseImport = false;
20
+ // Based on the prop names
21
+ // e.g. destruct `params` { slug } = params
22
+ // e.g. destruct `searchParams `{ search } = searchParams
23
+ let insertedDestructPropNames = new Set();
24
+ // Rename props to `prop` argument for the function
25
+ let insertedRenamedPropFunctionNames = new Set();
26
+ function processAsyncPropOfEntryFile(isClientComponent) {
27
+ // find `params` and `searchParams` in file, and transform the access to them
28
+ function renameAsyncPropIfExisted(path) {
29
+ const decl = path.value.declaration;
30
+ if (decl.type !== 'FunctionDeclaration' &&
31
+ decl.type !== 'FunctionExpression' &&
32
+ decl.type !== 'ArrowFunctionExpression') {
33
+ return;
34
+ }
35
+ const params = decl.params;
36
+ const propertiesMap = new Map();
37
+ // If there's no first param, return
38
+ if (params.length !== 1) {
39
+ return;
40
+ }
41
+ const propsIdentifier = (0, utils_1.generateUniqueIdentifier)(PAGE_PROPS, path, j);
42
+ const currentParam = params[0];
43
+ // Argument destructuring case
44
+ if (currentParam.type === 'ObjectPattern') {
45
+ // Validate if the properties are not `params` and `searchParams`,
46
+ // if they are, quit the transformation
47
+ for (const prop of currentParam.properties) {
48
+ if ('key' in prop && prop.key.type === 'Identifier') {
49
+ const propName = prop.key.name;
50
+ if (!utils_1.TARGET_PROP_NAMES.has(propName)) {
51
+ return;
52
+ }
53
+ }
54
+ }
55
+ currentParam.properties.forEach((prop) => {
56
+ if (
57
+ // Could be `Property` or `ObjectProperty`
58
+ 'key' in prop &&
59
+ prop.key.type === 'Identifier') {
60
+ const value = 'value' in prop ? prop.value : null;
61
+ propertiesMap.set(prop.key.name, value);
62
+ }
63
+ });
64
+ const paramTypeAnnotation = currentParam.typeAnnotation;
65
+ if (paramTypeAnnotation && paramTypeAnnotation.typeAnnotation) {
66
+ const typeAnnotation = paramTypeAnnotation.typeAnnotation;
67
+ if (typeAnnotation.type === 'TSTypeLiteral') {
68
+ const typeLiteral = typeAnnotation;
69
+ // Find the type property for `params`
70
+ typeLiteral.members.forEach((member) => {
71
+ if (member.type === 'TSPropertySignature' &&
72
+ member.key.type === 'Identifier' &&
73
+ propertiesMap.has(member.key.name)) {
74
+ // if it's already a Promise, don't wrap it again, return
75
+ if (member.typeAnnotation &&
76
+ member.typeAnnotation.typeAnnotation &&
77
+ member.typeAnnotation.typeAnnotation.type ===
78
+ 'TSTypeReference' &&
79
+ member.typeAnnotation.typeAnnotation.typeName.type ===
80
+ 'Identifier' &&
81
+ member.typeAnnotation.typeAnnotation.typeName.name ===
82
+ 'Promise') {
83
+ return;
84
+ }
85
+ // Wrap the `params` type in Promise<>
86
+ if (member.typeAnnotation &&
87
+ member.typeAnnotation.typeAnnotation &&
88
+ j.TSType.check(member.typeAnnotation.typeAnnotation)) {
89
+ member.typeAnnotation.typeAnnotation = j.tsTypeReference(j.identifier('Promise'), j.tsTypeParameterInstantiation([
90
+ // @ts-ignore
91
+ member.typeAnnotation.typeAnnotation,
92
+ ]));
93
+ }
94
+ }
95
+ });
96
+ }
97
+ else if (typeAnnotation.type === 'TSTypeReference') {
98
+ // If typeAnnotation is a type or interface, change the properties to Promise<type of property>
99
+ // e.g. interface PageProps { params: { slug: string } } => interface PageProps { params: Promise<{ slug: string }> }
100
+ const typeReference = typeAnnotation;
101
+ if (typeReference.typeName.type === 'Identifier') {
102
+ // Find the actual type of the type reference
103
+ const foundTypes = findAllTypes(root, j, typeReference.typeName.name);
104
+ // Deal with interfaces
105
+ if (foundTypes.interfaces.length > 0) {
106
+ const interfaceDeclaration = foundTypes.interfaces[0];
107
+ if (interfaceDeclaration.type === 'TSInterfaceDeclaration' &&
108
+ interfaceDeclaration.body?.type === 'TSInterfaceBody') {
109
+ const typeBody = interfaceDeclaration.body.body;
110
+ // if it's already a Promise, don't wrap it again, return
111
+ // traverse the typeReference's properties, if any is in propNames, wrap it in Promise<> if needed
112
+ typeBody.forEach((member) => {
113
+ if (member.type === 'TSPropertySignature' &&
114
+ member.key.type === 'Identifier' &&
115
+ utils_1.TARGET_PROP_NAMES.has(member.key.name)) {
116
+ // if it's already a Promise, don't wrap it again, return
117
+ if (member.typeAnnotation &&
118
+ member.typeAnnotation.typeAnnotation &&
119
+ member.typeAnnotation?.typeAnnotation?.typeName
120
+ ?.name === 'Promise') {
121
+ return;
122
+ }
123
+ // Wrap the prop type in Promise<>
124
+ if (member.typeAnnotation &&
125
+ member.typeAnnotation.typeAnnotation &&
126
+ // check if member name is in propNames
127
+ utils_1.TARGET_PROP_NAMES.has(member.key.name)) {
128
+ member.typeAnnotation.typeAnnotation =
129
+ j.tsTypeReference(j.identifier('Promise'), j.tsTypeParameterInstantiation([
130
+ member.typeAnnotation.typeAnnotation,
131
+ ]));
132
+ }
133
+ }
134
+ });
135
+ }
136
+ }
137
+ }
138
+ }
139
+ propsIdentifier.typeAnnotation = paramTypeAnnotation;
140
+ }
141
+ // Override the first param to `props`
142
+ params[0] = propsIdentifier;
143
+ modified = true;
144
+ }
145
+ if (modified) {
146
+ resolveAsyncProp(path, propertiesMap, propsIdentifier.name);
147
+ }
148
+ }
149
+ function getBodyOfFunctionDeclaration(path) {
150
+ const decl = path.value.declaration;
151
+ let functionBody;
152
+ if (decl.type === 'FunctionDeclaration' ||
153
+ decl.type === 'FunctionExpression' ||
154
+ decl.type === 'ArrowFunctionExpression') {
155
+ if (decl.body && decl.body.type === 'BlockStatement') {
156
+ functionBody = decl.body.body;
157
+ }
158
+ }
159
+ return functionBody;
160
+ }
161
+ // Helper function to insert `const params = await asyncParams;` at the beginning of the function body
162
+ function resolveAsyncProp(path, propertiesMap, propsIdentifierName) {
163
+ const isDefaultExport = path.value.type === 'ExportDefaultDeclaration';
164
+ // If it's sync default export, and it's also server component, make the function async
165
+ if (isDefaultExport &&
166
+ !isClientComponent &&
167
+ !isAsyncFunctionDeclaration(path)) {
168
+ if ('async' in path.value.declaration) {
169
+ path.value.declaration.async = true;
170
+ (0, utils_1.turnFunctionReturnTypeToAsync)(path.value.declaration, j);
171
+ }
172
+ }
173
+ const isAsyncFunc = isAsyncFunctionDeclaration(path);
174
+ // @ts-ignore quick way to check if it's a function and it has a name
175
+ const functionName = path.value.declaration.id?.name || 'default';
176
+ const functionBody = getBodyOfFunctionDeclaration(path);
177
+ for (const [propName, paramsProperty] of propertiesMap) {
178
+ const propNameIdentifier = j.identifier(propName);
179
+ const propsIdentifier = j.identifier(propsIdentifierName);
180
+ const accessedPropId = j.memberExpression(propsIdentifier, propNameIdentifier);
181
+ // Check param property value, if it's destructed, we need to destruct it as well
182
+ // e.g.
183
+ // input: Page({ params: { slug } })
184
+ // output: const { slug } = await props.params; rather than const props = await props.params;
185
+ const uid = functionName + ':' + propName;
186
+ if (paramsProperty?.type === 'ObjectPattern') {
187
+ const objectPattern = paramsProperty;
188
+ const objectPatternProperties = objectPattern.properties;
189
+ // destruct the object pattern, e.g. { slug } => const { slug } = params;
190
+ const destructedObjectPattern = j.variableDeclaration('const', [
191
+ j.variableDeclarator(j.objectPattern(objectPatternProperties.map((prop) => {
192
+ if (prop.type === 'Property' &&
193
+ prop.key.type === 'Identifier') {
194
+ return j.objectProperty(j.identifier(prop.key.name), j.identifier(prop.key.name));
195
+ }
196
+ return prop;
197
+ })), propNameIdentifier),
198
+ ]);
199
+ if (!insertedDestructPropNames.has(uid) && functionBody) {
200
+ functionBody.unshift(destructedObjectPattern);
201
+ insertedDestructPropNames.add(uid);
202
+ }
203
+ }
204
+ if (isAsyncFunc) {
205
+ // If it's async function, add await to the async props.<propName>
206
+ const paramAssignment = j.variableDeclaration('const', [
207
+ j.variableDeclarator(j.identifier(propName), j.awaitExpression(accessedPropId)),
208
+ ]);
209
+ if (!insertedRenamedPropFunctionNames.has(uid) && functionBody) {
210
+ functionBody.unshift(paramAssignment);
211
+ insertedRenamedPropFunctionNames.add(uid);
212
+ }
213
+ }
214
+ else {
215
+ const isFromExport = path.value.type === 'ExportNamedDeclaration';
216
+ if (isFromExport) {
217
+ // If it's export function, populate the function to async
218
+ if ((0, utils_1.isFunctionType)(path.value.declaration.type) &&
219
+ // Make TS happy
220
+ 'async' in path.value.declaration) {
221
+ path.value.declaration.async = true;
222
+ (0, utils_1.turnFunctionReturnTypeToAsync)(path.value.declaration, j);
223
+ // Insert `const <propName> = await props.<propName>;` at the beginning of the function body
224
+ const paramAssignment = j.variableDeclaration('const', [
225
+ j.variableDeclarator(j.identifier(propName), j.awaitExpression(accessedPropId)),
226
+ ]);
227
+ if (!insertedRenamedPropFunctionNames.has(uid) && functionBody) {
228
+ functionBody.unshift(paramAssignment);
229
+ insertedRenamedPropFunctionNames.add(uid);
230
+ }
231
+ }
232
+ }
233
+ else {
234
+ const paramAssignment = j.variableDeclaration('const', [
235
+ j.variableDeclarator(j.identifier(propName), j.callExpression(j.identifier('use'), [accessedPropId])),
236
+ ]);
237
+ if (!insertedRenamedPropFunctionNames.has(uid) && functionBody) {
238
+ needsReactUseImport = true;
239
+ functionBody.unshift(paramAssignment);
240
+ insertedRenamedPropFunctionNames.add(uid);
241
+ }
242
+ }
243
+ }
244
+ }
245
+ }
246
+ // Process Function Declarations
247
+ // Matching: default export function XXX(...) { ... }
248
+ const defaultExportFunctionDeclarations = root.find(j.ExportDefaultDeclaration, {
249
+ declaration: {
250
+ type: (type) => type === 'FunctionDeclaration' ||
251
+ type === 'FunctionExpression' ||
252
+ type === 'ArrowFunctionExpression',
253
+ },
254
+ });
255
+ defaultExportFunctionDeclarations.forEach((path) => {
256
+ renameAsyncPropIfExisted(path);
257
+ });
258
+ // Matching Next.js functional named export of route entry:
259
+ // - export function <named>(...) { ... }
260
+ // - export const <named> = ...
261
+ const targetNamedExportDeclarations = root.find(j.ExportNamedDeclaration,
262
+ // Filter the name is in TARGET_NAMED_EXPORTS
263
+ {
264
+ declaration: {
265
+ id: {
266
+ name: (idName) => {
267
+ return utils_1.TARGET_NAMED_EXPORTS.has(idName);
268
+ },
269
+ },
270
+ },
271
+ });
272
+ targetNamedExportDeclarations.forEach((path) => {
273
+ renameAsyncPropIfExisted(path);
274
+ });
275
+ // TDOO: handle targetNamedDeclarators
276
+ // const targetNamedDeclarators = root.find(
277
+ // j.VariableDeclarator,
278
+ // (node) =>
279
+ // node.id.type === 'Identifier' &&
280
+ // TARGET_NAMED_EXPORTS.has(node.id.name)
281
+ // )
282
+ }
283
+ const isClientComponent = (0, utils_1.determineClientDirective)(root, j, source);
284
+ // Apply to `params` and `searchParams`
285
+ processAsyncPropOfEntryFile(isClientComponent);
286
+ // Add import { use } from 'react' if needed and not already imported
287
+ if (needsReactUseImport) {
288
+ (0, utils_1.insertReactUseImport)(root, j);
289
+ }
290
+ return modified ? root.toSource() : null;
291
+ }
292
+ function findAllTypes(root, j, typeName) {
293
+ const types = {
294
+ interfaces: [],
295
+ typeAliases: [],
296
+ imports: [],
297
+ references: [],
298
+ };
299
+ // Step 1: Find all interface declarations with the specified name
300
+ root
301
+ .find(j.TSInterfaceDeclaration, {
302
+ id: {
303
+ type: 'Identifier',
304
+ name: typeName,
305
+ },
306
+ })
307
+ .forEach((path) => {
308
+ types.interfaces.push(path.node);
309
+ });
310
+ // Step 2: Find all type alias declarations with the specified name
311
+ root
312
+ .find(j.TSTypeAliasDeclaration, {
313
+ id: {
314
+ type: 'Identifier',
315
+ name: typeName,
316
+ },
317
+ })
318
+ .forEach((path) => {
319
+ types.typeAliases.push(path.node);
320
+ });
321
+ // Step 3: Find all imported types with the specified name
322
+ root
323
+ .find(j.ImportSpecifier, {
324
+ imported: {
325
+ type: 'Identifier',
326
+ name: typeName,
327
+ },
328
+ })
329
+ .forEach((path) => {
330
+ types.imports.push(path.node);
331
+ });
332
+ // Step 4: Find all references to the specified type
333
+ root
334
+ .find(j.TSTypeReference, {
335
+ typeName: {
336
+ type: 'Identifier',
337
+ name: typeName,
338
+ },
339
+ })
340
+ .forEach((path) => {
341
+ types.references.push(path.node);
342
+ });
343
+ return types;
344
+ }
345
+ //# sourceMappingURL=next-async-dynamic-prop.js.map