@next/codemod 15.0.3-canary.5 → 15.0.3-canary.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@next/codemod",
3
- "version": "15.0.3-canary.5",
3
+ "version": "15.0.3-canary.7",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -4,6 +4,9 @@ exports.transformDynamicProps = transformDynamicProps;
4
4
  const utils_1 = require("./utils");
5
5
  const parser_1 = require("../../../lib/parser");
6
6
  const PAGE_PROPS = 'props';
7
+ // Find all the member access of the prop, and await them
8
+ // e.g. If there's argument `props`, find all the member access of props.<name>.
9
+ // If the member access can be awaited, await them.
7
10
  function awaitMemberAccessOfProp(propIdName, path, j) {
8
11
  // search the member access of the prop
9
12
  const functionBody = (0, utils_1.findFunctionBody)(path);
@@ -30,6 +33,17 @@ function awaitMemberAccessOfProp(propIdName, path, j) {
30
33
  if (memberAccessPath.parentPath?.value.type === 'AwaitExpression') {
31
34
  return;
32
35
  }
36
+ const parentScopeOfMemberAccess = (0, utils_1.findClosetParentFunctionScope)(memberAccessPath, j);
37
+ // When the parent scope is sync, and it's also not the function itself, which means it's not able to convert to async.
38
+ if (parentScopeOfMemberAccess &&
39
+ !parentScopeOfMemberAccess.value?.async &&
40
+ parentScopeOfMemberAccess.node !== path.node) {
41
+ // If it's not able to convert, add a comment to the prop access to warn the user
42
+ // e.g. the parent scope is sync, await keyword can't be applied
43
+ const comment = ` ${utils_1.NEXT_CODEMOD_ERROR_PREFIX} '${propIdName}.${memberProperty.name}' is accessed without awaiting.`;
44
+ (0, utils_1.insertCommentOnce)(member, j, comment);
45
+ return;
46
+ }
33
47
  const awaitedExpr = j.awaitExpression(member);
34
48
  const awaitMemberAccess = (0, utils_1.wrapParentheseIfNeeded)(true, j, awaitedExpr);
35
49
  memberAccessPath.replace(awaitMemberAccess);
@@ -238,6 +252,43 @@ function modifyTypes(paramTypeAnnotation, propsIdentifier, root, j) {
238
252
  }
239
253
  }
240
254
  }
255
+ if (foundTypes.imports.length > 0) {
256
+ // console.log('typeReference.typeName.name', typeReference.typeName.name, foundTypes)
257
+ // If it's React PropsWithChildren
258
+ if (typeReference.typeName.name === 'PropsWithChildren') {
259
+ const propType = typeReference.typeParameters?.params[0];
260
+ if (propType &&
261
+ j.TSTypeLiteral.check(propType) &&
262
+ propType.members.length > 0) {
263
+ const typeLiteral = propType;
264
+ typeLiteral.members.forEach((member) => {
265
+ if (j.TSPropertySignature.check(member) &&
266
+ j.Identifier.check(member.key) &&
267
+ utils_1.TARGET_PROP_NAMES.has(member.key.name)) {
268
+ // if it's already a Promise, don't wrap it again, return
269
+ if (member.typeAnnotation &&
270
+ member.typeAnnotation.typeAnnotation &&
271
+ member.typeAnnotation.typeAnnotation.type ===
272
+ 'TSTypeReference' &&
273
+ member.typeAnnotation.typeAnnotation.typeName.type ===
274
+ 'Identifier' &&
275
+ member.typeAnnotation.typeAnnotation.typeName.name ===
276
+ 'Promise') {
277
+ return;
278
+ }
279
+ // Wrap the prop type in Promise<>
280
+ if (member.typeAnnotation &&
281
+ j.TSTypeLiteral.check(member.typeAnnotation.typeAnnotation)) {
282
+ member.typeAnnotation.typeAnnotation = j.tsTypeReference(j.identifier('Promise'), j.tsTypeParameterInstantiation([
283
+ member.typeAnnotation.typeAnnotation,
284
+ ]));
285
+ modified = true;
286
+ }
287
+ }
288
+ });
289
+ }
290
+ }
291
+ }
241
292
  }
242
293
  }
243
294
  propsIdentifier.typeAnnotation = paramTypeAnnotation;
@@ -335,6 +386,9 @@ function transformDynamicProps(source, _api, filePath) {
335
386
  }
336
387
  }
337
388
  else {
389
+ // If it's (props.params).<name>, await the member access
390
+ // const pathOfCurrentParam = path.get('params', propsArgumentIndex)
391
+ // const paramScope = findClosetParentFunctionScope(pathOfCurrentParam, j)
338
392
  const awaited = awaitMemberAccessOfProp(argName, path, j);
339
393
  modified ||= awaited;
340
394
  }
@@ -199,6 +199,8 @@ function isFunctionScope(path, j) {
199
199
  j.ArrowFunctionExpression.check(node));
200
200
  }
201
201
  function findClosetParentFunctionScope(path, j) {
202
+ if (!path.scope)
203
+ return null;
202
204
  let parentFunctionPath = path.scope.path;
203
205
  while (parentFunctionPath && !isFunctionScope(parentFunctionPath, j)) {
204
206
  parentFunctionPath = parentFunctionPath.parent;