flow-api-translator 0.36.0 → 0.36.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.
@@ -827,7 +827,6 @@ function convertSuperClassHelper(detachedId, nodeForDependencies, superTypeArgum
827
827
 
828
828
  function convertSuperClass(superClass, superTypeArguments, context) {
829
829
  if (superClass == null) {
830
- // $FlowFixMe[incompatible-type]
831
830
  return EMPTY_TRANSLATION_RESULT;
832
831
  }
833
832
 
@@ -889,7 +888,10 @@ function convertClassMember(member, context) {
889
888
 
890
889
  // PrivateIdentifier's are not exposed so can be stripped.
891
890
  if (member.key.type === 'PrivateIdentifier') {
892
- // $FlowFixMe[incompatible-type]
891
+ return EMPTY_TRANSLATION_RESULT;
892
+ }
893
+
894
+ if (context.mungeUnderscores && member.key.type === 'Identifier' && member.key.name.length >= 2 && member.key.name[0] === '_' && member.key.name[1] !== '_') {
893
895
  return EMPTY_TRANSLATION_RESULT;
894
896
  }
895
897
 
@@ -924,7 +926,10 @@ function convertClassMember(member, context) {
924
926
  {
925
927
  // PrivateIdentifier's are not exposed so can be stripped.
926
928
  if (member.key.type === 'PrivateIdentifier') {
927
- // $FlowFixMe[incompatible-type]
929
+ return EMPTY_TRANSLATION_RESULT;
930
+ }
931
+
932
+ if (context.mungeUnderscores && member.key.type === 'Identifier' && member.key.name.length >= 2 && member.key.name[0] === '_' && member.key.name[1] !== '_') {
928
933
  return EMPTY_TRANSLATION_RESULT;
929
934
  }
930
935
 
@@ -987,31 +992,44 @@ function convertComponentDeclaration(comp, context) {
987
992
  }), [...typeParamsDeps, ...paramsAndRestDeps, ...rendersTypeDeps]];
988
993
  }
989
994
 
995
+ function hasNonIdentifierStringLiteralParam(params) {
996
+ return params.some(param => param.type === 'ComponentParameter' && (0, _hermesEstree.isStringLiteral)(param.name) && !/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(param.name.value));
997
+ }
998
+
999
+ function extractParamTypeInfo(param, context) {
1000
+ let optional = false;
1001
+ let local = param.local;
1002
+
1003
+ if (local.type === 'AssignmentPattern') {
1004
+ local = local.left;
1005
+ optional = true;
1006
+ }
1007
+
1008
+ if (!optional && local.type === 'Identifier') {
1009
+ optional = local.optional;
1010
+ }
1011
+
1012
+ return [optional, local, convertTypeAnnotation(local.typeAnnotation, param, context)];
1013
+ }
1014
+
990
1015
  function convertComponentParameters(params, context) {
1016
+ if (hasNonIdentifierStringLiteralParam(params)) {
1017
+ return convertComponentParametersToPropsObject(params, context);
1018
+ }
1019
+
991
1020
  return params.reduce(([resultParams, restParam, paramsDeps], param) => {
992
1021
  switch (param.type) {
993
1022
  case 'ComponentParameter':
994
1023
  {
995
- let optional = false;
996
- let local = param.local;
997
-
998
- if (local.type === 'AssignmentPattern') {
999
- local = local.left;
1000
- optional = true;
1001
- }
1002
-
1003
- if (!optional && local.type === 'Identifier') {
1004
- optional = local.optional;
1005
- }
1006
-
1007
- const [typeAnnotationType, typeDeps] = convertTypeAnnotation(local.typeAnnotation, param, context);
1008
-
1009
- const resultParam = _hermesTransform.t.ComponentTypeParameter({
1010
- name: (0, _hermesTransform.asDetachedNode)(param.name),
1024
+ const [optional, _local, [typeAnnotationType, typeDeps]] = extractParamTypeInfo(param, context);
1025
+ const name = (0, _hermesEstree.isStringLiteral)(param.name) && /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(param.name.value) ? _hermesTransform.t.Identifier({
1026
+ name: param.name.value
1027
+ }) : (0, _hermesTransform.asDetachedNode)(param.name);
1028
+ const resultParam = inheritComments(param, _hermesTransform.t.ComponentTypeParameter({
1029
+ name,
1011
1030
  typeAnnotation: typeAnnotationType,
1012
1031
  optional
1013
- });
1014
-
1032
+ }));
1015
1033
  return [[...resultParams, resultParam], restParam, [...paramsDeps, ...typeDeps]];
1016
1034
  }
1017
1035
 
@@ -1028,21 +1046,71 @@ function convertComponentParameters(params, context) {
1028
1046
  }
1029
1047
 
1030
1048
  const [typeAnnotationType, typeDeps] = convertTypeAnnotation(argument.typeAnnotation, argument, context);
1031
-
1032
- const resultRestParam = _hermesTransform.t.ComponentTypeParameter({
1049
+ const restName = argument.type === 'Identifier' ? argument.name : 'rest';
1050
+ const restOptional = argument.type === 'Identifier' ? argument.optional : false;
1051
+ const resultRestParam = inheritComments(param, _hermesTransform.t.ComponentTypeParameter({
1033
1052
  name: _hermesTransform.t.Identifier({
1034
- name: argument.type === 'Identifier' ? argument.name : 'rest'
1053
+ name: restName
1035
1054
  }),
1036
1055
  typeAnnotation: typeAnnotationType,
1037
- optional: argument.type === 'Identifier' ? argument.optional : false
1038
- });
1039
-
1056
+ optional: restOptional
1057
+ }));
1040
1058
  return [resultParams, resultRestParam, [...paramsDeps, ...typeDeps]];
1041
1059
  }
1042
1060
  }
1043
1061
  }, [[], null, []]);
1044
1062
  }
1045
1063
 
1064
+ function convertComponentParametersToPropsObject(params, context) {
1065
+ const properties = [];
1066
+ const allDeps = [];
1067
+
1068
+ for (const param of params) {
1069
+ if (param.type === 'RestElement') {
1070
+ const argument = param.argument;
1071
+
1072
+ if (argument.type !== 'AssignmentPattern' && argument.type !== 'ArrayPattern' && argument.type !== 'RestElement') {
1073
+ const [typeAnnotationType, typeDeps] = convertTypeAnnotation(argument.typeAnnotation, argument, context);
1074
+ allDeps.push(...typeDeps);
1075
+ properties.push(_hermesTransform.t.ObjectTypeSpreadProperty({
1076
+ argument: typeAnnotationType
1077
+ }));
1078
+ }
1079
+
1080
+ continue;
1081
+ }
1082
+
1083
+ const [optional, _local, [typeAnnotationType, typeDeps]] = extractParamTypeInfo(param, context);
1084
+ allDeps.push(...typeDeps);
1085
+ properties.push(inheritComments(param, _hermesTransform.t.ObjectTypePropertySignature({
1086
+ key: (0, _hermesTransform.asDetachedNode)(param.name),
1087
+ value: typeAnnotationType,
1088
+ optional,
1089
+ static: false,
1090
+ variance: null
1091
+ })));
1092
+ }
1093
+
1094
+ const propsType = _hermesTransform.t.ObjectTypeAnnotation({
1095
+ inexact: false,
1096
+ exact: false,
1097
+ properties,
1098
+ indexers: [],
1099
+ callProperties: [],
1100
+ internalSlots: []
1101
+ });
1102
+
1103
+ const restParam = _hermesTransform.t.ComponentTypeParameter({
1104
+ name: _hermesTransform.t.Identifier({
1105
+ name: 'props'
1106
+ }),
1107
+ typeAnnotation: propsType,
1108
+ optional: false
1109
+ });
1110
+
1111
+ return [[], restParam, allDeps];
1112
+ }
1113
+
1046
1114
  function convertHookDeclaration(hook, context) {
1047
1115
  var _hook$returnType;
1048
1116
 
@@ -1055,7 +1123,7 @@ function convertHookDeclaration(hook, context) {
1055
1123
  const [resultParams, restParam, paramsDeps] = convertFunctionParameters(hook.params, context);
1056
1124
  const [resultTypeParams, typeParamsDeps] = convertTypeParameterDeclarationOrNull(hook.typeParameters, context);
1057
1125
 
1058
- const resultFunc = _hermesTransform.t.FunctionTypeAnnotation({
1126
+ const resultFunc = _hermesTransform.t.HookTypeAnnotation({
1059
1127
  params: resultParams,
1060
1128
  returnType: resultReturnType,
1061
1129
  rest: restParam,
@@ -1200,7 +1268,6 @@ function convertTypeAnnotationType(annot, container, context) {
1200
1268
 
1201
1269
  function convertTypeAnnotationTypeOrNull(annot, context) {
1202
1270
  if (annot == null) {
1203
- // $FlowFixMe[incompatible-type]
1204
1271
  return EMPTY_TRANSLATION_RESULT;
1205
1272
  }
1206
1273
 
@@ -1209,7 +1276,6 @@ function convertTypeAnnotationTypeOrNull(annot, context) {
1209
1276
 
1210
1277
  function convertTypeParameterDeclarationOrNull(decl, context) {
1211
1278
  if (decl == null) {
1212
- // $FlowFixMe[incompatible-type]
1213
1279
  return EMPTY_TRANSLATION_RESULT;
1214
1280
  }
1215
1281
 
@@ -1218,7 +1284,6 @@ function convertTypeParameterDeclarationOrNull(decl, context) {
1218
1284
 
1219
1285
  function convertTypeParameterInstantiationOrNull(inst, context) {
1220
1286
  if (inst == null) {
1221
- // $FlowFixMe[incompatible-type]
1222
1287
  return EMPTY_TRANSLATION_RESULT;
1223
1288
  }
1224
1289
 
@@ -48,6 +48,7 @@ import type {
48
48
  ObjectExpression,
49
49
  ObjectTypeAnnotation,
50
50
  ObjectTypeProperty,
51
+ ObjectTypeSpreadProperty,
51
52
  OpaqueType,
52
53
  QualifiedTypeIdentifier,
53
54
  QualifiedTypeofIdentifier,
@@ -88,10 +89,12 @@ import {
88
89
  isMemberExpressionWithNonComputedProperty,
89
90
  } from 'hermes-estree';
90
91
 
91
- const EMPTY_TRANSLATION_RESULT = [null, []];
92
+ const EMPTY_TRANSLATION_RESULT: TranslatedResultOrNull<empty> = [null, []];
92
93
 
93
94
  type TranslatedDeps = $ReadOnlyArray<Dep>;
94
- type TranslatedResultOrNull<T> = [DetachedNode<T> | null, TranslatedDeps];
95
+ type TranslatedResultOrNull<+T> = Readonly<
96
+ [DetachedNode<T> | null, TranslatedDeps],
97
+ >;
95
98
  type TranslatedResultArray<T> = [
96
99
  $ReadOnlyArray<DetachedNode<T>>,
97
100
  TranslatedDeps,
@@ -1080,7 +1083,6 @@ function convertSuperClass(
1080
1083
  context: TranslationContext,
1081
1084
  ): TranslatedResultOrNull<InterfaceExtends> {
1082
1085
  if (superClass == null) {
1083
- // $FlowFixMe[incompatible-type]
1084
1086
  return EMPTY_TRANSLATION_RESULT;
1085
1087
  }
1086
1088
 
@@ -1175,7 +1177,15 @@ function convertClassMember(
1175
1177
  case 'PropertyDefinition': {
1176
1178
  // PrivateIdentifier's are not exposed so can be stripped.
1177
1179
  if (member.key.type === 'PrivateIdentifier') {
1178
- // $FlowFixMe[incompatible-type]
1180
+ return EMPTY_TRANSLATION_RESULT;
1181
+ }
1182
+ if (
1183
+ context.mungeUnderscores &&
1184
+ member.key.type === 'Identifier' &&
1185
+ member.key.name.length >= 2 &&
1186
+ member.key.name[0] === '_' &&
1187
+ member.key.name[1] !== '_'
1188
+ ) {
1179
1189
  return EMPTY_TRANSLATION_RESULT;
1180
1190
  }
1181
1191
  if (
@@ -1243,7 +1253,15 @@ function convertClassMember(
1243
1253
  case 'MethodDefinition': {
1244
1254
  // PrivateIdentifier's are not exposed so can be stripped.
1245
1255
  if (member.key.type === 'PrivateIdentifier') {
1246
- // $FlowFixMe[incompatible-type]
1256
+ return EMPTY_TRANSLATION_RESULT;
1257
+ }
1258
+ if (
1259
+ context.mungeUnderscores &&
1260
+ member.key.type === 'Identifier' &&
1261
+ member.key.name.length >= 2 &&
1262
+ member.key.name[0] === '_' &&
1263
+ member.key.name[1] !== '_'
1264
+ ) {
1247
1265
  return EMPTY_TRANSLATION_RESULT;
1248
1266
  }
1249
1267
  if (
@@ -1358,36 +1376,66 @@ type TranslatedComponentParametersResults = [
1358
1376
  TranslatedDeps,
1359
1377
  ];
1360
1378
 
1379
+ function hasNonIdentifierStringLiteralParam(
1380
+ params: $ReadOnlyArray<ComponentParameter | RestElement>,
1381
+ ): boolean {
1382
+ return params.some(
1383
+ param =>
1384
+ param.type === 'ComponentParameter' &&
1385
+ isStringLiteral(param.name) &&
1386
+ !/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(param.name.value),
1387
+ );
1388
+ }
1389
+
1390
+ function extractParamTypeInfo(
1391
+ param: ComponentParameter,
1392
+ context: TranslationContext,
1393
+ ): [boolean, BindingName, TranslatedResult<TypeAnnotationType>] {
1394
+ let optional = false;
1395
+ let local = param.local;
1396
+ if (local.type === 'AssignmentPattern') {
1397
+ local = local.left;
1398
+ optional = true;
1399
+ }
1400
+ if (!optional && local.type === 'Identifier') {
1401
+ optional = local.optional;
1402
+ }
1403
+ return [
1404
+ optional,
1405
+ local,
1406
+ convertTypeAnnotation(local.typeAnnotation, param, context),
1407
+ ];
1408
+ }
1409
+
1361
1410
  function convertComponentParameters(
1362
1411
  params: $ReadOnlyArray<ComponentParameter | RestElement>,
1363
1412
  context: TranslationContext,
1364
1413
  ): TranslatedComponentParametersResults {
1414
+ if (hasNonIdentifierStringLiteralParam(params)) {
1415
+ return convertComponentParametersToPropsObject(params, context);
1416
+ }
1417
+
1365
1418
  return params.reduce<TranslatedComponentParametersResults>(
1366
1419
  ([resultParams, restParam, paramsDeps], param) => {
1367
1420
  switch (param.type) {
1368
1421
  case 'ComponentParameter': {
1369
- let optional = false;
1370
- let local = param.local;
1371
- if (local.type === 'AssignmentPattern') {
1372
- local = local.left;
1373
- optional = true;
1374
- }
1375
- if (!optional && local.type === 'Identifier') {
1376
- optional = local.optional;
1377
- }
1378
-
1379
- const [typeAnnotationType, typeDeps] = convertTypeAnnotation(
1380
- local.typeAnnotation,
1422
+ const [optional, _local, [typeAnnotationType, typeDeps]] =
1423
+ extractParamTypeInfo(param, context);
1424
+
1425
+ const name =
1426
+ isStringLiteral(param.name) &&
1427
+ /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(param.name.value)
1428
+ ? t.Identifier({name: param.name.value})
1429
+ : asDetachedNode(param.name);
1430
+ const resultParam = inheritComments(
1381
1431
  param,
1382
- context,
1432
+ t.ComponentTypeParameter({
1433
+ name,
1434
+ typeAnnotation: typeAnnotationType,
1435
+ optional,
1436
+ }),
1383
1437
  );
1384
1438
 
1385
- const resultParam = t.ComponentTypeParameter({
1386
- name: asDetachedNode(param.name),
1387
- typeAnnotation: typeAnnotationType,
1388
- optional,
1389
- });
1390
-
1391
1439
  return [
1392
1440
  [...resultParams, resultParam],
1393
1441
  restParam,
@@ -1420,14 +1468,18 @@ function convertComponentParameters(
1420
1468
  context,
1421
1469
  );
1422
1470
 
1423
- const resultRestParam = t.ComponentTypeParameter({
1424
- name: t.Identifier({
1425
- name: argument.type === 'Identifier' ? argument.name : 'rest',
1471
+ const restName =
1472
+ argument.type === 'Identifier' ? argument.name : 'rest';
1473
+ const restOptional =
1474
+ argument.type === 'Identifier' ? argument.optional : false;
1475
+ const resultRestParam = inheritComments(
1476
+ param,
1477
+ t.ComponentTypeParameter({
1478
+ name: t.Identifier({name: restName}),
1479
+ typeAnnotation: typeAnnotationType,
1480
+ optional: restOptional,
1426
1481
  }),
1427
- typeAnnotation: typeAnnotationType,
1428
- optional:
1429
- argument.type === 'Identifier' ? argument.optional : false,
1430
- });
1482
+ );
1431
1483
 
1432
1484
  return [resultParams, resultRestParam, [...paramsDeps, ...typeDeps]];
1433
1485
  }
@@ -1437,6 +1489,72 @@ function convertComponentParameters(
1437
1489
  );
1438
1490
  }
1439
1491
 
1492
+ function convertComponentParametersToPropsObject(
1493
+ params: $ReadOnlyArray<ComponentParameter | RestElement>,
1494
+ context: TranslationContext,
1495
+ ): TranslatedComponentParametersResults {
1496
+ const properties: Array<
1497
+ DetachedNode<ObjectTypeProperty | ObjectTypeSpreadProperty>,
1498
+ > = [];
1499
+ const allDeps: Array<Dep> = [];
1500
+
1501
+ for (const param of params) {
1502
+ if (param.type === 'RestElement') {
1503
+ const argument = param.argument;
1504
+ if (
1505
+ argument.type !== 'AssignmentPattern' &&
1506
+ argument.type !== 'ArrayPattern' &&
1507
+ argument.type !== 'RestElement'
1508
+ ) {
1509
+ const [typeAnnotationType, typeDeps] = convertTypeAnnotation(
1510
+ argument.typeAnnotation,
1511
+ argument,
1512
+ context,
1513
+ );
1514
+ allDeps.push(...typeDeps);
1515
+ properties.push(
1516
+ t.ObjectTypeSpreadProperty({argument: typeAnnotationType}),
1517
+ );
1518
+ }
1519
+ continue;
1520
+ }
1521
+
1522
+ const [optional, _local, [typeAnnotationType, typeDeps]] =
1523
+ extractParamTypeInfo(param, context);
1524
+ allDeps.push(...typeDeps);
1525
+
1526
+ properties.push(
1527
+ inheritComments(
1528
+ param,
1529
+ t.ObjectTypePropertySignature({
1530
+ key: asDetachedNode(param.name),
1531
+ value: typeAnnotationType,
1532
+ optional,
1533
+ static: false,
1534
+ variance: null,
1535
+ }),
1536
+ ),
1537
+ );
1538
+ }
1539
+
1540
+ const propsType = t.ObjectTypeAnnotation({
1541
+ inexact: false,
1542
+ exact: false,
1543
+ properties,
1544
+ indexers: [],
1545
+ callProperties: [],
1546
+ internalSlots: [],
1547
+ });
1548
+
1549
+ const restParam = t.ComponentTypeParameter({
1550
+ name: t.Identifier({name: 'props'}),
1551
+ typeAnnotation: propsType,
1552
+ optional: false,
1553
+ });
1554
+
1555
+ return [[], restParam, allDeps];
1556
+ }
1557
+
1440
1558
  function convertHookDeclaration(
1441
1559
  hook: HookDeclaration,
1442
1560
  context: TranslationContext,
@@ -1461,7 +1579,7 @@ function convertHookDeclaration(
1461
1579
  const [resultTypeParams, typeParamsDeps] =
1462
1580
  convertTypeParameterDeclarationOrNull(hook.typeParameters, context);
1463
1581
 
1464
- const resultFunc = t.FunctionTypeAnnotation({
1582
+ const resultFunc = t.HookTypeAnnotation({
1465
1583
  params: resultParams,
1466
1584
  returnType: resultReturnType,
1467
1585
  rest: restParam,
@@ -1732,7 +1850,6 @@ function convertTypeAnnotationTypeOrNull(
1732
1850
  context: TranslationContext,
1733
1851
  ): TranslatedResultOrNull<TypeAnnotationType> {
1734
1852
  if (annot == null) {
1735
- // $FlowFixMe[incompatible-type]
1736
1853
  return EMPTY_TRANSLATION_RESULT;
1737
1854
  }
1738
1855
 
@@ -1743,7 +1860,6 @@ function convertTypeParameterDeclarationOrNull(
1743
1860
  context: TranslationContext,
1744
1861
  ): TranslatedResultOrNull<TypeParameterDeclaration> {
1745
1862
  if (decl == null) {
1746
- // $FlowFixMe[incompatible-type]
1747
1863
  return EMPTY_TRANSLATION_RESULT;
1748
1864
  }
1749
1865
  return [asDetachedNode(decl), analyzeTypeDependencies(decl, context)];
@@ -1753,7 +1869,6 @@ function convertTypeParameterInstantiationOrNull(
1753
1869
  context: TranslationContext,
1754
1870
  ): TranslatedResultOrNull<TypeParameterInstantiation> {
1755
1871
  if (inst == null) {
1756
- // $FlowFixMe[incompatible-type]
1757
1872
  return EMPTY_TRANSLATION_RESULT;
1758
1873
  }
1759
1874
  return [asDetachedNode(inst), analyzeTypeDependencies(inst, context)];
package/dist/index.js CHANGED
@@ -37,13 +37,14 @@ var _TSDefToFlowDef = require("./TSDefToFlowDef");
37
37
 
38
38
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
39
39
 
40
- async function translateFlowToFlowDef(code, prettierOptions = {}) {
40
+ async function translateFlowToFlowDef(code, prettierOptions = {}, opts) {
41
41
  const {
42
42
  ast,
43
43
  scopeManager
44
44
  } = await (0, _hermesTransform.parse)(code);
45
45
  const [flowDefAst, mutatedCode] = (0, _flowToFlowDef.default)(ast, code, scopeManager, {
46
- recoverFromErrors: true
46
+ recoverFromErrors: true,
47
+ mungeUnderscores: opts == null ? void 0 : opts.mungeUnderscores
47
48
  });
48
49
  return (0, _hermesTransform.print)(flowDefAst, mutatedCode, prettierOptions);
49
50
  }
@@ -24,11 +24,13 @@ import {TSDefToFlowDef} from './TSDefToFlowDef';
24
24
  export async function translateFlowToFlowDef(
25
25
  code: string,
26
26
  prettierOptions: {...} = {},
27
+ opts?: {mungeUnderscores?: boolean},
27
28
  ): Promise<string> {
28
29
  const {ast, scopeManager} = await parse(code);
29
30
 
30
31
  const [flowDefAst, mutatedCode] = flowToFlowDef(ast, code, scopeManager, {
31
32
  recoverFromErrors: true,
33
+ mungeUnderscores: opts?.mungeUnderscores,
32
34
  });
33
35
 
34
36
  return print(flowDefAst, mutatedCode, prettierOptions);
@@ -827,7 +827,6 @@ function convertSuperClassHelper(detachedId, nodeForDependencies, superTypeArgum
827
827
 
828
828
  function convertSuperClass(superClass, superTypeArguments, context) {
829
829
  if (superClass == null) {
830
- // $FlowFixMe[incompatible-type]
831
830
  return EMPTY_TRANSLATION_RESULT;
832
831
  }
833
832
 
@@ -889,7 +888,10 @@ function convertClassMember(member, context) {
889
888
 
890
889
  // PrivateIdentifier's are not exposed so can be stripped.
891
890
  if (member.key.type === 'PrivateIdentifier') {
892
- // $FlowFixMe[incompatible-type]
891
+ return EMPTY_TRANSLATION_RESULT;
892
+ }
893
+
894
+ if (context.mungeUnderscores && member.key.type === 'Identifier' && member.key.name.length >= 2 && member.key.name[0] === '_' && member.key.name[1] !== '_') {
893
895
  return EMPTY_TRANSLATION_RESULT;
894
896
  }
895
897
 
@@ -924,7 +926,10 @@ function convertClassMember(member, context) {
924
926
  {
925
927
  // PrivateIdentifier's are not exposed so can be stripped.
926
928
  if (member.key.type === 'PrivateIdentifier') {
927
- // $FlowFixMe[incompatible-type]
929
+ return EMPTY_TRANSLATION_RESULT;
930
+ }
931
+
932
+ if (context.mungeUnderscores && member.key.type === 'Identifier' && member.key.name.length >= 2 && member.key.name[0] === '_' && member.key.name[1] !== '_') {
928
933
  return EMPTY_TRANSLATION_RESULT;
929
934
  }
930
935
 
@@ -987,31 +992,44 @@ function convertComponentDeclaration(comp, context) {
987
992
  }), [...typeParamsDeps, ...paramsAndRestDeps, ...rendersTypeDeps]];
988
993
  }
989
994
 
995
+ function hasNonIdentifierStringLiteralParam(params) {
996
+ return params.some(param => param.type === 'ComponentParameter' && (0, _hermesEstree.isStringLiteral)(param.name) && !/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(param.name.value));
997
+ }
998
+
999
+ function extractParamTypeInfo(param, context) {
1000
+ let optional = false;
1001
+ let local = param.local;
1002
+
1003
+ if (local.type === 'AssignmentPattern') {
1004
+ local = local.left;
1005
+ optional = true;
1006
+ }
1007
+
1008
+ if (!optional && local.type === 'Identifier') {
1009
+ optional = local.optional;
1010
+ }
1011
+
1012
+ return [optional, local, convertTypeAnnotation(local.typeAnnotation, param, context)];
1013
+ }
1014
+
990
1015
  function convertComponentParameters(params, context) {
1016
+ if (hasNonIdentifierStringLiteralParam(params)) {
1017
+ return convertComponentParametersToPropsObject(params, context);
1018
+ }
1019
+
991
1020
  return params.reduce(([resultParams, restParam, paramsDeps], param) => {
992
1021
  switch (param.type) {
993
1022
  case 'ComponentParameter':
994
1023
  {
995
- let optional = false;
996
- let local = param.local;
997
-
998
- if (local.type === 'AssignmentPattern') {
999
- local = local.left;
1000
- optional = true;
1001
- }
1002
-
1003
- if (!optional && local.type === 'Identifier') {
1004
- optional = local.optional;
1005
- }
1006
-
1007
- const [typeAnnotationType, typeDeps] = convertTypeAnnotation(local.typeAnnotation, param, context);
1008
-
1009
- const resultParam = _hermesTransform.t.ComponentTypeParameter({
1010
- name: (0, _hermesTransform.asDetachedNode)(param.name),
1024
+ const [optional, _local, [typeAnnotationType, typeDeps]] = extractParamTypeInfo(param, context);
1025
+ const name = (0, _hermesEstree.isStringLiteral)(param.name) && /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(param.name.value) ? _hermesTransform.t.Identifier({
1026
+ name: param.name.value
1027
+ }) : (0, _hermesTransform.asDetachedNode)(param.name);
1028
+ const resultParam = inheritComments(param, _hermesTransform.t.ComponentTypeParameter({
1029
+ name,
1011
1030
  typeAnnotation: typeAnnotationType,
1012
1031
  optional
1013
- });
1014
-
1032
+ }));
1015
1033
  return [[...resultParams, resultParam], restParam, [...paramsDeps, ...typeDeps]];
1016
1034
  }
1017
1035
 
@@ -1028,21 +1046,71 @@ function convertComponentParameters(params, context) {
1028
1046
  }
1029
1047
 
1030
1048
  const [typeAnnotationType, typeDeps] = convertTypeAnnotation(argument.typeAnnotation, argument, context);
1031
-
1032
- const resultRestParam = _hermesTransform.t.ComponentTypeParameter({
1049
+ const restName = argument.type === 'Identifier' ? argument.name : 'rest';
1050
+ const restOptional = argument.type === 'Identifier' ? argument.optional : false;
1051
+ const resultRestParam = inheritComments(param, _hermesTransform.t.ComponentTypeParameter({
1033
1052
  name: _hermesTransform.t.Identifier({
1034
- name: argument.type === 'Identifier' ? argument.name : 'rest'
1053
+ name: restName
1035
1054
  }),
1036
1055
  typeAnnotation: typeAnnotationType,
1037
- optional: argument.type === 'Identifier' ? argument.optional : false
1038
- });
1039
-
1056
+ optional: restOptional
1057
+ }));
1040
1058
  return [resultParams, resultRestParam, [...paramsDeps, ...typeDeps]];
1041
1059
  }
1042
1060
  }
1043
1061
  }, [[], null, []]);
1044
1062
  }
1045
1063
 
1064
+ function convertComponentParametersToPropsObject(params, context) {
1065
+ const properties = [];
1066
+ const allDeps = [];
1067
+
1068
+ for (const param of params) {
1069
+ if (param.type === 'RestElement') {
1070
+ const argument = param.argument;
1071
+
1072
+ if (argument.type !== 'AssignmentPattern' && argument.type !== 'ArrayPattern' && argument.type !== 'RestElement') {
1073
+ const [typeAnnotationType, typeDeps] = convertTypeAnnotation(argument.typeAnnotation, argument, context);
1074
+ allDeps.push(...typeDeps);
1075
+ properties.push(_hermesTransform.t.ObjectTypeSpreadProperty({
1076
+ argument: typeAnnotationType
1077
+ }));
1078
+ }
1079
+
1080
+ continue;
1081
+ }
1082
+
1083
+ const [optional, _local, [typeAnnotationType, typeDeps]] = extractParamTypeInfo(param, context);
1084
+ allDeps.push(...typeDeps);
1085
+ properties.push(inheritComments(param, _hermesTransform.t.ObjectTypePropertySignature({
1086
+ key: (0, _hermesTransform.asDetachedNode)(param.name),
1087
+ value: typeAnnotationType,
1088
+ optional,
1089
+ static: false,
1090
+ variance: null
1091
+ })));
1092
+ }
1093
+
1094
+ const propsType = _hermesTransform.t.ObjectTypeAnnotation({
1095
+ inexact: false,
1096
+ exact: false,
1097
+ properties,
1098
+ indexers: [],
1099
+ callProperties: [],
1100
+ internalSlots: []
1101
+ });
1102
+
1103
+ const restParam = _hermesTransform.t.ComponentTypeParameter({
1104
+ name: _hermesTransform.t.Identifier({
1105
+ name: 'props'
1106
+ }),
1107
+ typeAnnotation: propsType,
1108
+ optional: false
1109
+ });
1110
+
1111
+ return [[], restParam, allDeps];
1112
+ }
1113
+
1046
1114
  function convertHookDeclaration(hook, context) {
1047
1115
  var _hook$returnType;
1048
1116
 
@@ -1055,7 +1123,7 @@ function convertHookDeclaration(hook, context) {
1055
1123
  const [resultParams, restParam, paramsDeps] = convertFunctionParameters(hook.params, context);
1056
1124
  const [resultTypeParams, typeParamsDeps] = convertTypeParameterDeclarationOrNull(hook.typeParameters, context);
1057
1125
 
1058
- const resultFunc = _hermesTransform.t.FunctionTypeAnnotation({
1126
+ const resultFunc = _hermesTransform.t.HookTypeAnnotation({
1059
1127
  params: resultParams,
1060
1128
  returnType: resultReturnType,
1061
1129
  rest: restParam,
@@ -1200,7 +1268,6 @@ function convertTypeAnnotationType(annot, container, context) {
1200
1268
 
1201
1269
  function convertTypeAnnotationTypeOrNull(annot, context) {
1202
1270
  if (annot == null) {
1203
- // $FlowFixMe[incompatible-type]
1204
1271
  return EMPTY_TRANSLATION_RESULT;
1205
1272
  }
1206
1273
 
@@ -1209,7 +1276,6 @@ function convertTypeAnnotationTypeOrNull(annot, context) {
1209
1276
 
1210
1277
  function convertTypeParameterDeclarationOrNull(decl, context) {
1211
1278
  if (decl == null) {
1212
- // $FlowFixMe[incompatible-type]
1213
1279
  return EMPTY_TRANSLATION_RESULT;
1214
1280
  }
1215
1281
 
@@ -1218,7 +1284,6 @@ function convertTypeParameterDeclarationOrNull(decl, context) {
1218
1284
 
1219
1285
  function convertTypeParameterInstantiationOrNull(inst, context) {
1220
1286
  if (inst == null) {
1221
- // $FlowFixMe[incompatible-type]
1222
1287
  return EMPTY_TRANSLATION_RESULT;
1223
1288
  }
1224
1289
 
package/dist/src/index.js CHANGED
@@ -37,13 +37,14 @@ var _TSDefToFlowDef = require("./TSDefToFlowDef");
37
37
 
38
38
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
39
39
 
40
- async function translateFlowToFlowDef(code, prettierOptions = {}) {
40
+ async function translateFlowToFlowDef(code, prettierOptions = {}, opts) {
41
41
  const {
42
42
  ast,
43
43
  scopeManager
44
44
  } = await (0, _hermesTransform.parse)(code);
45
45
  const [flowDefAst, mutatedCode] = (0, _flowToFlowDef.default)(ast, code, scopeManager, {
46
- recoverFromErrors: true
46
+ recoverFromErrors: true,
47
+ mungeUnderscores: opts == null ? void 0 : opts.mungeUnderscores
47
48
  });
48
49
  return (0, _hermesTransform.print)(flowDefAst, mutatedCode, prettierOptions);
49
50
  }
@@ -15,7 +15,8 @@ Object.defineProperty(exports, "__esModule", {
15
15
  exports.createTranslationContext = createTranslationContext;
16
16
 
17
17
  function createTranslationContext(code, scopeManager, {
18
- recoverFromErrors
18
+ recoverFromErrors,
19
+ mungeUnderscores = true
19
20
  }) {
20
21
  const referenceMap = new Map();
21
22
  const variableMap = new Map();
@@ -37,6 +38,7 @@ function createTranslationContext(code, scopeManager, {
37
38
  referenceMap,
38
39
  variableMap,
39
40
  recoverFromErrors,
41
+ mungeUnderscores,
40
42
  code
41
43
  };
42
44
  }
@@ -15,7 +15,8 @@ Object.defineProperty(exports, "__esModule", {
15
15
  exports.createTranslationContext = createTranslationContext;
16
16
 
17
17
  function createTranslationContext(code, scopeManager, {
18
- recoverFromErrors
18
+ recoverFromErrors,
19
+ mungeUnderscores = true
19
20
  }) {
20
21
  const referenceMap = new Map();
21
22
  const variableMap = new Map();
@@ -37,6 +38,7 @@ function createTranslationContext(code, scopeManager, {
37
38
  referenceMap,
38
39
  variableMap,
39
40
  recoverFromErrors,
41
+ mungeUnderscores,
40
42
  code
41
43
  };
42
44
  }
@@ -14,19 +14,23 @@ import type {Identifier, JSXIdentifier} from 'hermes-estree';
14
14
  import type {ScopeManager, Variable} from 'hermes-eslint';
15
15
 
16
16
  export type Dep = string;
17
- export type TranslationOptions = {recoverFromErrors: boolean};
17
+ export type TranslationOptions = {
18
+ recoverFromErrors: boolean,
19
+ mungeUnderscores?: boolean,
20
+ };
18
21
  export type TranslationContext = {
19
22
  scopeManager: ScopeManager,
20
23
  referenceMap: Map<Identifier | JSXIdentifier, Variable>,
21
24
  variableMap: Map<Dep, Variable>,
22
25
  recoverFromErrors: boolean,
26
+ mungeUnderscores: boolean,
23
27
  code: string,
24
28
  };
25
29
 
26
30
  export function createTranslationContext(
27
31
  code: string,
28
32
  scopeManager: ScopeManager,
29
- {recoverFromErrors}: TranslationOptions,
33
+ {recoverFromErrors, mungeUnderscores = true}: TranslationOptions,
30
34
  ): TranslationContext {
31
35
  const referenceMap = new Map<Identifier | JSXIdentifier, Variable>();
32
36
  const variableMap = new Map<Dep, Variable>();
@@ -40,5 +44,12 @@ export function createTranslationContext(
40
44
  variableMap.set(variable.name, variable);
41
45
  }
42
46
  }
43
- return {scopeManager, referenceMap, variableMap, recoverFromErrors, code};
47
+ return {
48
+ scopeManager,
49
+ referenceMap,
50
+ variableMap,
51
+ recoverFromErrors,
52
+ mungeUnderscores,
53
+ code,
54
+ };
44
55
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flow-api-translator",
3
- "version": "0.36.0",
3
+ "version": "0.36.1",
4
4
  "description": "Toolkit for creating Flow and TypeScript compatible libraries from Flow source code.",
5
5
  "main": "dist/index.js",
6
6
  "license": "MIT",
@@ -13,10 +13,10 @@
13
13
  "@typescript-eslint/parser": "8.38.0",
14
14
  "@typescript-eslint/visitor-keys": "8.38.0",
15
15
  "flow-enums-runtime": "^0.0.6",
16
- "hermes-eslint": "0.36.0",
17
- "hermes-estree": "0.36.0",
18
- "hermes-parser": "0.36.0",
19
- "hermes-transform": "0.36.0",
16
+ "hermes-eslint": "0.36.1",
17
+ "hermes-estree": "0.36.1",
18
+ "hermes-parser": "0.36.1",
19
+ "hermes-transform": "0.36.1",
20
20
  "typescript": "5.3.2"
21
21
  },
22
22
  "peerDependencies": {