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