@next/codemod 15.0.0-rc.0 → 15.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/bin/next-codemod.js +55 -3
  2. package/bin/shared.js +7 -0
  3. package/bin/transform.js +124 -0
  4. package/bin/upgrade.js +390 -0
  5. package/lib/cra-to-next/global-css-transform.js +5 -5
  6. package/lib/cra-to-next/index-to-component.js +5 -5
  7. package/lib/handle-package.js +110 -0
  8. package/lib/install.js +2 -3
  9. package/lib/parser.js +28 -0
  10. package/lib/run-jscodeshift.js +18 -2
  11. package/lib/utils.js +115 -0
  12. package/package.json +13 -6
  13. package/transforms/add-missing-react-import.js +4 -3
  14. package/transforms/app-dir-runtime-config-experimental-edge.js +34 -0
  15. package/transforms/built-in-next-font.js +4 -3
  16. package/transforms/cra-to-next.js +238 -236
  17. package/transforms/lib/async-request-api/index.js +16 -0
  18. package/transforms/lib/async-request-api/next-async-dynamic-api.js +274 -0
  19. package/transforms/lib/async-request-api/next-async-dynamic-prop.js +715 -0
  20. package/transforms/lib/async-request-api/utils.js +374 -0
  21. package/transforms/metadata-to-viewport-export.js +4 -3
  22. package/transforms/name-default-component.js +6 -6
  23. package/transforms/new-link.js +9 -7
  24. package/transforms/next-async-request-api.js +9 -0
  25. package/transforms/next-dynamic-access-named-export.js +66 -0
  26. package/transforms/next-image-experimental.js +12 -15
  27. package/transforms/next-image-to-legacy-image.js +8 -9
  28. package/transforms/next-og-import.js +4 -3
  29. package/transforms/next-request-geo-ip.js +339 -0
  30. package/transforms/url-to-withrouter.js +1 -1
  31. package/transforms/withamp-to-config.js +1 -1
  32. package/bin/cli.js +0 -216
  33. package/lib/uninstall-package.js +0 -32
@@ -0,0 +1,374 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TARGET_PROP_NAMES = exports.TARGET_NAMED_EXPORTS = exports.TARGET_ROUTE_EXPORTS = exports.NEXT_CODEMOD_ERROR_PREFIX = exports.NEXTJS_ENTRY_FILES = 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.isFunctionScope = isFunctionScope;
12
+ exports.findClosetParentFunctionScope = findClosetParentFunctionScope;
13
+ exports.getFunctionPathFromExportPath = getFunctionPathFromExportPath;
14
+ exports.wrapParentheseIfNeeded = wrapParentheseIfNeeded;
15
+ exports.insertCommentOnce = insertCommentOnce;
16
+ exports.getVariableDeclaratorId = getVariableDeclaratorId;
17
+ exports.NEXTJS_ENTRY_FILES = /([\\/]|^)(page|layout|route|default)\.(t|j)sx?$/;
18
+ exports.NEXT_CODEMOD_ERROR_PREFIX = '@next-codemod-error';
19
+ const NEXT_CODEMOD_IGNORE_ERROR_PREFIX = '@next-codemod-ignore';
20
+ exports.TARGET_ROUTE_EXPORTS = new Set([
21
+ 'GET',
22
+ 'POST',
23
+ 'PUT',
24
+ 'PATCH',
25
+ 'DELETE',
26
+ 'OPTIONS',
27
+ 'HEAD',
28
+ ]);
29
+ exports.TARGET_NAMED_EXPORTS = new Set([
30
+ // For page and layout
31
+ 'generateMetadata',
32
+ 'generateViewport',
33
+ ...exports.TARGET_ROUTE_EXPORTS,
34
+ ]);
35
+ exports.TARGET_PROP_NAMES = new Set(['params', 'searchParams']);
36
+ function isFunctionType(type) {
37
+ return (type === 'FunctionDeclaration' ||
38
+ type === 'FunctionExpression' ||
39
+ type === 'ArrowFunctionExpression');
40
+ }
41
+ function isMatchedFunctionExported(path, j) {
42
+ const matchedFunctionNameFilter = (idName) => exports.TARGET_NAMED_EXPORTS.has(idName);
43
+ const directNamedExport = j(path).closest(j.ExportNamedDeclaration, {
44
+ declaration: {
45
+ type: 'FunctionDeclaration',
46
+ id: {
47
+ name: matchedFunctionNameFilter,
48
+ },
49
+ },
50
+ });
51
+ if (directNamedExport.size() > 0) {
52
+ return true;
53
+ }
54
+ // Check for default export (`export default function() {}`)
55
+ const isDefaultExport = j(path).closest(j.ExportDefaultDeclaration).size() > 0;
56
+ if (isDefaultExport) {
57
+ return true;
58
+ }
59
+ // Look for named export elsewhere in the file (`export { <named> }`)
60
+ const root = j(path).closestScope().closest(j.Program);
61
+ const isNamedExport = root
62
+ .find(j.ExportNamedDeclaration, {
63
+ specifiers: [
64
+ {
65
+ type: 'ExportSpecifier',
66
+ exported: {
67
+ name: matchedFunctionNameFilter,
68
+ },
69
+ },
70
+ ],
71
+ })
72
+ .size() > 0;
73
+ // Look for variable export but still function, e.g. `export const <named> = function() {}`,
74
+ // also check if variable is a function or arrow function
75
+ const isVariableExport = root
76
+ .find(j.ExportNamedDeclaration, {
77
+ declaration: {
78
+ declarations: [
79
+ {
80
+ type: 'VariableDeclarator',
81
+ id: {
82
+ type: 'Identifier',
83
+ name: matchedFunctionNameFilter,
84
+ },
85
+ init: {
86
+ type: isFunctionType,
87
+ },
88
+ },
89
+ ],
90
+ },
91
+ })
92
+ .size() > 0;
93
+ if (isVariableExport)
94
+ return true;
95
+ return isNamedExport;
96
+ }
97
+ // directive is not parsed into AST, so we need to manually find it
98
+ // by going through the tokens. Use the 1st string token as the directive
99
+ function determineClientDirective(root, j) {
100
+ const { program } = root.get().node;
101
+ const directive = program.directives[0];
102
+ if (j.Directive.check(directive)) {
103
+ return directive.value.value === 'use client';
104
+ }
105
+ return false;
106
+ }
107
+ function isPromiseType(typeAnnotation) {
108
+ return (typeAnnotation.type === 'TSTypeReference' &&
109
+ typeAnnotation.typeName.name === 'Promise');
110
+ }
111
+ function turnFunctionReturnTypeToAsync(node, j) {
112
+ if (j.FunctionDeclaration.check(node) ||
113
+ j.FunctionExpression.check(node) ||
114
+ j.ArrowFunctionExpression.check(node)) {
115
+ if (node.returnType) {
116
+ const returnTypeAnnotation = node.returnType.typeAnnotation;
117
+ const isReturnTypePromise = isPromiseType(returnTypeAnnotation);
118
+ // Turn <return type> to Promise<return type>
119
+ // e.g. () => { slug: string } to () => Promise<{ slug: string }>
120
+ // e.g. Anything to Promise<Anything>
121
+ if (!isReturnTypePromise) {
122
+ if (node.returnType &&
123
+ j.TSTypeAnnotation.check(node.returnType) &&
124
+ (j.TSTypeReference.check(node.returnType.typeAnnotation) ||
125
+ j.TSUnionType.check(node.returnType.typeAnnotation) ||
126
+ j.TSTypePredicate.check(node.returnType.typeAnnotation))) {
127
+ // Change the return type to Promise<void>
128
+ node.returnType.typeAnnotation = j.tsTypeReference(j.identifier('Promise'),
129
+ // @ts-ignore ignore the super strict type checking on the type annotation
130
+ j.tsTypeParameterInstantiation([returnTypeAnnotation]));
131
+ }
132
+ }
133
+ }
134
+ }
135
+ }
136
+ function insertReactUseImport(root, j) {
137
+ const hasReactUseImport = root
138
+ .find(j.ImportSpecifier, {
139
+ imported: {
140
+ type: 'Identifier',
141
+ name: 'use',
142
+ },
143
+ })
144
+ .size() > 0;
145
+ if (!hasReactUseImport) {
146
+ const reactImportDeclaration = root.find(j.ImportDeclaration, {
147
+ source: {
148
+ value: 'react',
149
+ },
150
+ // Skip the type only react imports
151
+ importKind: 'value',
152
+ });
153
+ if (reactImportDeclaration.size() > 0) {
154
+ const importNode = reactImportDeclaration.get().node;
155
+ // Add 'use' to existing 'react' import declaration
156
+ importNode.specifiers.push(j.importSpecifier(j.identifier('use')));
157
+ }
158
+ else {
159
+ // Final all type imports to 'react'
160
+ if (reactImportDeclaration.size() > 0) {
161
+ reactImportDeclaration
162
+ .get()
163
+ .node.specifiers.push(j.importSpecifier(j.identifier('use')));
164
+ }
165
+ else {
166
+ // Add new import declaration for 'react' and 'use'
167
+ root
168
+ .get()
169
+ .node.program.body.unshift(j.importDeclaration([j.importSpecifier(j.identifier('use'))], j.literal('react')));
170
+ }
171
+ }
172
+ }
173
+ }
174
+ function findSubScopeArgumentIdentifier(path, j, argName) {
175
+ const defCount = j(path).find(j.Identifier, { name: argName }).size();
176
+ return defCount > 0;
177
+ }
178
+ function generateUniqueIdentifier(defaultIdName, path, j) {
179
+ let idName = defaultIdName;
180
+ let idNameSuffix = 0;
181
+ while (findSubScopeArgumentIdentifier(path, j, idName)) {
182
+ idName = defaultIdName + idNameSuffix;
183
+ idNameSuffix++;
184
+ }
185
+ const propsIdentifier = j.identifier(idName);
186
+ return propsIdentifier;
187
+ }
188
+ function isFunctionScope(path, j) {
189
+ if (!path)
190
+ return false;
191
+ const node = path.node;
192
+ // Check if the node is a function (declaration, expression, or arrow function)
193
+ return (j.FunctionDeclaration.check(node) ||
194
+ j.FunctionExpression.check(node) ||
195
+ j.ArrowFunctionExpression.check(node));
196
+ }
197
+ function findClosetParentFunctionScope(path, j) {
198
+ let parentFunctionPath = path.scope.path;
199
+ while (parentFunctionPath && !isFunctionScope(parentFunctionPath, j)) {
200
+ parentFunctionPath = parentFunctionPath.parent;
201
+ }
202
+ return parentFunctionPath;
203
+ }
204
+ function getFunctionNodeFromBinding(bindingPath, idName, j, root) {
205
+ const bindingNode = bindingPath.node;
206
+ if (j.FunctionDeclaration.check(bindingNode) ||
207
+ j.FunctionExpression.check(bindingNode) ||
208
+ j.ArrowFunctionExpression.check(bindingNode)) {
209
+ return bindingPath;
210
+ }
211
+ else if (j.VariableDeclarator.check(bindingNode)) {
212
+ const init = bindingNode.init;
213
+ // If the initializer is a function (arrow or function expression), record it
214
+ if (j.FunctionExpression.check(init) ||
215
+ j.ArrowFunctionExpression.check(init)) {
216
+ return bindingPath.get('init');
217
+ }
218
+ }
219
+ else if (j.Identifier.check(bindingNode)) {
220
+ const variablePath = root.find(j.VariableDeclaration, {
221
+ // declarations, each is VariableDeclarator
222
+ declarations: [
223
+ {
224
+ // VariableDeclarator
225
+ type: 'VariableDeclarator',
226
+ // id is Identifier
227
+ id: {
228
+ type: 'Identifier',
229
+ name: idName,
230
+ },
231
+ },
232
+ ],
233
+ });
234
+ if (variablePath.size()) {
235
+ const variableDeclarator = variablePath.get()?.node?.declarations?.[0];
236
+ if (j.VariableDeclarator.check(variableDeclarator)) {
237
+ const init = variableDeclarator.init;
238
+ if (j.FunctionExpression.check(init) ||
239
+ j.ArrowFunctionExpression.check(init)) {
240
+ return variablePath.get('declarations', 0, 'init');
241
+ }
242
+ }
243
+ }
244
+ const functionDeclarations = root.find(j.FunctionDeclaration, {
245
+ id: {
246
+ name: idName,
247
+ },
248
+ });
249
+ if (functionDeclarations.size()) {
250
+ return functionDeclarations.get();
251
+ }
252
+ }
253
+ return undefined;
254
+ }
255
+ function getFunctionPathFromExportPath(exportPath, j, root, namedExportFilter) {
256
+ // Default export
257
+ if (j.ExportDefaultDeclaration.check(exportPath.node)) {
258
+ const { declaration } = exportPath.node;
259
+ if (declaration) {
260
+ if (j.FunctionDeclaration.check(declaration) ||
261
+ j.FunctionExpression.check(declaration) ||
262
+ j.ArrowFunctionExpression.check(declaration)) {
263
+ return exportPath.get('declaration');
264
+ }
265
+ else if (j.Identifier.check(declaration)) {
266
+ const idName = declaration.name;
267
+ if (!namedExportFilter(idName))
268
+ return;
269
+ const exportBinding = exportPath.scope.getBindings()[idName]?.[0];
270
+ if (exportBinding) {
271
+ return getFunctionNodeFromBinding(exportBinding, idName, j, root);
272
+ }
273
+ }
274
+ }
275
+ }
276
+ else if (
277
+ // Named exports
278
+ j.ExportNamedDeclaration.check(exportPath.node)) {
279
+ const namedExportPath = exportPath;
280
+ // extract the named exports, name specifiers, and default specifiers
281
+ const { declaration, specifiers } = namedExportPath.node;
282
+ if (declaration) {
283
+ if (j.VariableDeclaration.check(declaration)) {
284
+ const { declarations } = declaration;
285
+ for (const decl of declarations) {
286
+ if (j.VariableDeclarator.check(decl) && j.Identifier.check(decl.id)) {
287
+ const idName = decl.id.name;
288
+ if (!namedExportFilter(idName))
289
+ return;
290
+ // get bindings for each variable declarator
291
+ const exportBinding = namedExportPath.scope.getBindings()[idName]?.[0];
292
+ if (exportBinding) {
293
+ return getFunctionNodeFromBinding(exportBinding, idName, j, root);
294
+ }
295
+ }
296
+ }
297
+ }
298
+ else if (j.FunctionDeclaration.check(declaration) ||
299
+ j.FunctionExpression.check(declaration) ||
300
+ j.ArrowFunctionExpression.check(declaration)) {
301
+ const funcName = declaration.id?.name;
302
+ if (!namedExportFilter(funcName))
303
+ return;
304
+ return namedExportPath.get('declaration');
305
+ }
306
+ }
307
+ if (specifiers) {
308
+ for (const specifier of specifiers) {
309
+ if (j.ExportSpecifier.check(specifier)) {
310
+ const idName = specifier.local.name;
311
+ if (!namedExportFilter(idName))
312
+ return;
313
+ const exportBinding = namedExportPath.scope.getBindings()[idName]?.[0];
314
+ if (exportBinding) {
315
+ return getFunctionNodeFromBinding(exportBinding, idName, j, root);
316
+ }
317
+ }
318
+ }
319
+ }
320
+ }
321
+ return undefined;
322
+ }
323
+ function wrapParentheseIfNeeded(hasChainAccess, j, expression) {
324
+ return hasChainAccess ? j.parenthesizedExpression(expression) : expression;
325
+ }
326
+ function existsComment(comments, comment) {
327
+ const isCodemodErrorComment = comment
328
+ .trim()
329
+ .startsWith(exports.NEXT_CODEMOD_ERROR_PREFIX);
330
+ let hasIgnoreComment = false;
331
+ let hasComment = false;
332
+ if (comments) {
333
+ comments.forEach((commentNode) => {
334
+ const currentComment = commentNode.value;
335
+ if (currentComment.trim().startsWith(NEXT_CODEMOD_IGNORE_ERROR_PREFIX)) {
336
+ hasIgnoreComment = true;
337
+ }
338
+ if (currentComment === comment) {
339
+ hasComment = true;
340
+ }
341
+ });
342
+ // If it's inserting codemod error comment,
343
+ // check if there's already a @next-codemod-ignore comment.
344
+ // if ignore comment exists, bypass the comment insertion.
345
+ if (hasIgnoreComment && isCodemodErrorComment) {
346
+ return true;
347
+ }
348
+ if (hasComment) {
349
+ return true;
350
+ }
351
+ }
352
+ return false;
353
+ }
354
+ function insertCommentOnce(node, j, comment) {
355
+ const hasCommentInInlineComments = existsComment(node.comments, comment);
356
+ const hasCommentInLeadingComments = existsComment(node.leadingComments, comment);
357
+ if (!hasCommentInInlineComments && !hasCommentInLeadingComments) {
358
+ // Always insert into inline comment
359
+ node.comments = [j.commentBlock(comment), ...(node.comments || [])];
360
+ return true;
361
+ }
362
+ return false;
363
+ }
364
+ function getVariableDeclaratorId(path, j) {
365
+ const parent = path.parentPath;
366
+ if (j.VariableDeclarator.check(parent.node)) {
367
+ const id = parent.node.id;
368
+ if (j.Identifier.check(id)) {
369
+ return id;
370
+ }
371
+ }
372
+ return undefined;
373
+ }
374
+ //# sourceMappingURL=utils.js.map
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- function transformer(file, api) {
4
- const j = api.jscodeshift;
3
+ exports.default = transformer;
4
+ const parser_1 = require("../lib/parser");
5
+ function transformer(file, _api) {
6
+ const j = (0, parser_1.createParserFromPath)(file.path);
5
7
  const root = j(file.source);
6
8
  // Find the metadata export
7
9
  const metadataExport = root.find(j.ExportNamedDeclaration, {
@@ -56,5 +58,4 @@ function transformer(file, api) {
56
58
  }
57
59
  return root.toSource();
58
60
  }
59
- exports.default = transformer;
60
61
  //# sourceMappingURL=metadata-to-viewport-export.js.map
@@ -1,24 +1,25 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = transformer;
3
4
  const path_1 = require("path");
5
+ const parser_1 = require("../lib/parser");
4
6
  const camelCase = (value) => {
5
7
  const val = value.replace(/[-_\s.]+(.)?/g, (_match, chr) => chr ? chr.toUpperCase() : '');
6
8
  return val.slice(0, 1).toUpperCase() + val.slice(1);
7
9
  };
8
10
  const isValidIdentifier = (value) => /^[a-zA-ZÀ-ÿ][0-9a-zA-ZÀ-ÿ]+$/.test(value);
9
- function transformer(file, api, options) {
10
- const j = api.jscodeshift.withParser('tsx');
11
+ function transformer(file, _api, options) {
12
+ const j = (0, parser_1.createParserFromPath)(file.path);
11
13
  const root = j(file.source);
12
14
  let hasModifications;
13
15
  const returnsJSX = (node) => node.type === 'JSXElement' ||
14
16
  (node.type === 'BlockStatement' &&
15
17
  j(node)
16
18
  .find(j.ReturnStatement)
17
- .some((path) => { var _a; return ((_a = path.value.argument) === null || _a === void 0 ? void 0 : _a.type) === 'JSXElement'; }));
19
+ .some((path) => path.value.argument?.type === 'JSXElement'));
18
20
  const hasRootAsParent = (path) => {
19
- var _a;
20
21
  const program = path.parentPath.parentPath.parentPath.parentPath.parentPath;
21
- return !program || ((_a = program === null || program === void 0 ? void 0 : program.value) === null || _a === void 0 ? void 0 : _a.type) === 'Program';
22
+ return !program || program?.value?.type === 'Program';
22
23
  };
23
24
  const nameFunctionComponent = (path) => {
24
25
  const node = path.value;
@@ -62,5 +63,4 @@ function transformer(file, api, options) {
62
63
  root.find(j.ExportDefaultDeclaration).forEach(nameFunctionComponent);
63
64
  return hasModifications ? root.toSource(options) : null;
64
65
  }
65
- exports.default = transformer;
66
66
  //# sourceMappingURL=name-default-component.js.map
@@ -1,7 +1,11 @@
1
1
  "use strict";
2
+ // It might insert extra parnes for JSX components
3
+ // x-ref: https://github.com/facebook/jscodeshift/issues/534
2
4
  Object.defineProperty(exports, "__esModule", { value: true });
3
- function transformer(file, api) {
4
- const j = api.jscodeshift.withParser('tsx');
5
+ exports.default = transformer;
6
+ const parser_1 = require("../lib/parser");
7
+ function transformer(file, _api) {
8
+ const j = (0, parser_1.createParserFromPath)(file.path);
5
9
  const $j = j(file.source);
6
10
  return $j
7
11
  .find(j.ImportDeclaration, { source: { value: 'next/link' } })
@@ -34,7 +38,7 @@ function transformer(file, api) {
34
38
  return;
35
39
  }
36
40
  // If file has <style jsx> enable legacyBehavior
37
- // and keep <a> to stay on the safe side
41
+ // and keep <a> to stay on the safe side
38
42
  if (hasStylesJSX) {
39
43
  $link
40
44
  .get('attributes')
@@ -68,11 +72,10 @@ function transformer(file, api) {
68
72
  // Add only unique props to <Link> (skip duplicate props)
69
73
  const linkPropNames = $link
70
74
  .get('attributes')
71
- .value.map((linkProp) => { var _a; return (_a = linkProp === null || linkProp === void 0 ? void 0 : linkProp.name) === null || _a === void 0 ? void 0 : _a.name; });
75
+ .value.map((linkProp) => linkProp?.name?.name);
72
76
  const uniqueProps = [];
73
77
  props.forEach((anchorProp) => {
74
- var _a;
75
- if (!linkPropNames.includes((_a = anchorProp === null || anchorProp === void 0 ? void 0 : anchorProp.name) === null || _a === void 0 ? void 0 : _a.name)) {
78
+ if (!linkPropNames.includes(anchorProp?.name?.name)) {
76
79
  uniqueProps.push(anchorProp);
77
80
  }
78
81
  });
@@ -86,5 +89,4 @@ function transformer(file, api) {
86
89
  })
87
90
  .toSource();
88
91
  }
89
- exports.default = transformer;
90
92
  //# sourceMappingURL=new-link.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
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = transformer;
4
+ const parser_1 = require("../lib/parser");
5
+ function transformer(file, _api) {
6
+ const j = (0, parser_1.createParserFromPath)(file.path);
7
+ const root = j(file.source);
8
+ // Find the import declaration for 'next/dynamic'
9
+ const dynamicImportDeclaration = root.find(j.ImportDeclaration, {
10
+ source: { value: 'next/dynamic' },
11
+ });
12
+ // If the import declaration is found
13
+ if (dynamicImportDeclaration.size() > 0) {
14
+ const importDecl = dynamicImportDeclaration.get(0).node;
15
+ const dynamicImportName = importDecl.specifiers?.[0]?.local?.name;
16
+ if (!dynamicImportName) {
17
+ return file.source;
18
+ }
19
+ // Find call expressions where the callee is the imported 'dynamic'
20
+ root
21
+ .find(j.CallExpression, {
22
+ callee: { name: dynamicImportName },
23
+ })
24
+ .forEach((path) => {
25
+ const arrowFunction = path.node.arguments[0];
26
+ // Ensure the argument is an ArrowFunctionExpression
27
+ if (arrowFunction && arrowFunction.type === 'ArrowFunctionExpression') {
28
+ const importCall = arrowFunction.body;
29
+ // Ensure the parent of the import call is a CallExpression with a .then
30
+ if (importCall &&
31
+ importCall.type === 'CallExpression' &&
32
+ importCall.callee.type === 'MemberExpression' &&
33
+ 'name' in importCall.callee.property &&
34
+ importCall.callee.property.name === 'then') {
35
+ const thenFunction = importCall.arguments[0];
36
+ // handle case of block statement case `=> { return mod.Component }`
37
+ // transform to`=> { return { default: mod.Component } }`
38
+ if (thenFunction &&
39
+ thenFunction.type === 'ArrowFunctionExpression' &&
40
+ thenFunction.body.type === 'BlockStatement') {
41
+ const returnStatement = thenFunction.body.body[0];
42
+ // Ensure the body of the arrow function has a return statement with a MemberExpression
43
+ if (returnStatement &&
44
+ returnStatement.type === 'ReturnStatement' &&
45
+ returnStatement.argument?.type === 'MemberExpression') {
46
+ returnStatement.argument = j.objectExpression([
47
+ j.property('init', j.identifier('default'), returnStatement.argument),
48
+ ]);
49
+ }
50
+ }
51
+ // handle case `=> mod.Component`
52
+ // transform to`=> ({ default: mod.Component })`
53
+ if (thenFunction &&
54
+ thenFunction.type === 'ArrowFunctionExpression' &&
55
+ thenFunction.body.type === 'MemberExpression') {
56
+ thenFunction.body = j.objectExpression([
57
+ j.property('init', j.identifier('default'), thenFunction.body),
58
+ ]);
59
+ }
60
+ }
61
+ }
62
+ });
63
+ }
64
+ return root.toSource();
65
+ }
66
+ //# sourceMappingURL=next-dynamic-access-named-export.js.map
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = transformer;
3
4
  const path_1 = require("path");
4
5
  const fs_1 = require("fs");
6
+ const parser_1 = require("../lib/parser");
5
7
  function findAndReplaceProps(j, root, tagName) {
6
8
  const layoutToStyle = {
7
9
  intrinsic: { maxWidth: '100%', height: 'auto' },
@@ -21,14 +23,12 @@ function findAndReplaceProps(j, root, tagName) {
21
23
  el.value.openingElement.name.type === 'JSXIdentifier' &&
22
24
  el.value.openingElement.name.name === tagName)
23
25
  .forEach((el) => {
24
- var _a;
25
26
  let layout = 'intrinsic';
26
27
  let objectFit = null;
27
28
  let objectPosition = null;
28
29
  let styleExpProps = [];
29
30
  let sizesAttr = null;
30
- const attributes = (_a = el.node.openingElement.attributes) === null || _a === void 0 ? void 0 : _a.filter((a) => {
31
- var _a, _b;
31
+ const attributes = el.node.openingElement.attributes?.filter((a) => {
32
32
  if (a.type !== 'JSXAttribute') {
33
33
  return true;
34
34
  }
@@ -51,11 +51,11 @@ function findAndReplaceProps(j, root, tagName) {
51
51
  return false;
52
52
  }
53
53
  if (a.name.name === 'style') {
54
- if (((_a = a.value) === null || _a === void 0 ? void 0 : _a.type) === 'JSXExpressionContainer' &&
54
+ if (a.value?.type === 'JSXExpressionContainer' &&
55
55
  a.value.expression.type === 'ObjectExpression') {
56
56
  styleExpProps = a.value.expression.properties;
57
57
  }
58
- else if (((_b = a.value) === null || _b === void 0 ? void 0 : _b.type) === 'JSXExpressionContainer' &&
58
+ else if (a.value?.type === 'JSXExpressionContainer' &&
59
59
  a.value.expression.type === 'Identifier') {
60
60
  styleExpProps = [
61
61
  j.spreadElement(j.identifier(a.value.expression.name)),
@@ -189,8 +189,8 @@ function nextConfigTransformer(j, root, appDir) {
189
189
  });
190
190
  return root;
191
191
  }
192
- function transformer(file, api, options) {
193
- const j = api.jscodeshift.withParser('tsx');
192
+ function transformer(file, _api, options) {
193
+ const j = (0, parser_1.createParserFromPath)(file.path);
194
194
  const root = j(file.source);
195
195
  const parsed = (0, path_1.parse)(file.path || '/');
196
196
  const isConfig = parsed.base === 'next.config.js' ||
@@ -208,9 +208,8 @@ function transformer(file, api, options) {
208
208
  source: { value: 'next/legacy/image' },
209
209
  })
210
210
  .forEach((imageImport) => {
211
- var _a, _b;
212
- const defaultSpecifier = (_a = imageImport.node.specifiers) === null || _a === void 0 ? void 0 : _a.find((node) => node.type === 'ImportDefaultSpecifier');
213
- const tagName = (_b = defaultSpecifier === null || defaultSpecifier === void 0 ? void 0 : defaultSpecifier.local) === null || _b === void 0 ? void 0 : _b.name;
211
+ const defaultSpecifier = imageImport.node.specifiers?.find((node) => node.type === 'ImportDefaultSpecifier');
212
+ const tagName = defaultSpecifier?.local?.name;
214
213
  imageImport.node.source = j.stringLiteral('next/image');
215
214
  if (tagName) {
216
215
  findAndReplaceProps(j, root, tagName);
@@ -220,7 +219,7 @@ function transformer(file, api, options) {
220
219
  // After: const Image = await import("next/image")
221
220
  root.find(j.AwaitExpression).forEach((awaitExp) => {
222
221
  const arg = awaitExp.value.argument;
223
- if ((arg === null || arg === void 0 ? void 0 : arg.type) === 'CallExpression' && arg.callee.type === 'Import') {
222
+ if (arg?.type === 'CallExpression' && arg.callee.type === 'Import') {
224
223
  if (arg.arguments[0].type === 'StringLiteral' &&
225
224
  arg.arguments[0].value === 'next/legacy/image') {
226
225
  arg.arguments[0] = j.stringLiteral('next/image');
@@ -230,14 +229,13 @@ function transformer(file, api, options) {
230
229
  // Before: const Image = require("next/legacy/image")
231
230
  // After: const Image = require("next/image")
232
231
  root.find(j.CallExpression).forEach((requireExp) => {
233
- var _a, _b, _c, _d, _e;
234
- if (((_b = (_a = requireExp === null || requireExp === void 0 ? void 0 : requireExp.value) === null || _a === void 0 ? void 0 : _a.callee) === null || _b === void 0 ? void 0 : _b.type) === 'Identifier' &&
232
+ if (requireExp?.value?.callee?.type === 'Identifier' &&
235
233
  requireExp.value.callee.name === 'require') {
236
234
  let firstArg = requireExp.value.arguments[0];
237
235
  if (firstArg &&
238
236
  firstArg.type === 'StringLiteral' &&
239
237
  firstArg.value === 'next/legacy/image') {
240
- const tagName = (_e = (_d = (_c = requireExp === null || requireExp === void 0 ? void 0 : requireExp.parentPath) === null || _c === void 0 ? void 0 : _c.value) === null || _d === void 0 ? void 0 : _d.id) === null || _e === void 0 ? void 0 : _e.name;
238
+ const tagName = requireExp?.parentPath?.value?.id?.name;
241
239
  if (tagName) {
242
240
  requireExp.value.arguments[0] = j.stringLiteral('next/image');
243
241
  findAndReplaceProps(j, root, tagName);
@@ -248,5 +246,4 @@ function transformer(file, api, options) {
248
246
  // TODO: do the same transforms for dynamic imports
249
247
  return root.toSource(options);
250
248
  }
251
- exports.default = transformer;
252
249
  //# sourceMappingURL=next-image-experimental.js.map