@react-native-windows/codegen 0.71.3 → 0.72.0-preview.2

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 (43) hide show
  1. package/CHANGELOG.md +81 -22
  2. package/README.md +1 -1
  3. package/lib-commonjs/Cli.js +5 -1
  4. package/lib-commonjs/Cli.js.map +1 -1
  5. package/lib-commonjs/generators/AliasGen.d.ts +1 -1
  6. package/lib-commonjs/generators/AliasGen.js.map +1 -1
  7. package/lib-commonjs/generators/AliasManaging.d.ts +1 -1
  8. package/lib-commonjs/generators/AliasManaging.js.map +1 -1
  9. package/lib-commonjs/generators/GenerateNM2.d.ts +1 -1
  10. package/lib-commonjs/generators/GenerateNM2.js +1 -1
  11. package/lib-commonjs/generators/GenerateNM2.js.map +1 -1
  12. package/lib-commonjs/generators/GenerateTypeScript.d.ts +1 -1
  13. package/lib-commonjs/generators/GenerateTypeScript.js +2 -2
  14. package/lib-commonjs/generators/GenerateTypeScript.js.map +1 -1
  15. package/lib-commonjs/generators/ObjectTypes.d.ts +2 -1
  16. package/lib-commonjs/generators/ObjectTypes.js +26 -6
  17. package/lib-commonjs/generators/ObjectTypes.js.map +1 -1
  18. package/lib-commonjs/generators/ParamTypes.d.ts +1 -1
  19. package/lib-commonjs/generators/ParamTypes.js +50 -29
  20. package/lib-commonjs/generators/ParamTypes.js.map +1 -1
  21. package/lib-commonjs/generators/ReturnTypes.d.ts +1 -1
  22. package/lib-commonjs/generators/ReturnTypes.js +2 -36
  23. package/lib-commonjs/generators/ReturnTypes.js.map +1 -1
  24. package/lib-commonjs/generators/ValidateConstants.d.ts +1 -1
  25. package/lib-commonjs/generators/ValidateConstants.js.map +1 -1
  26. package/lib-commonjs/generators/ValidateMethods.d.ts +1 -1
  27. package/lib-commonjs/generators/ValidateMethods.js +14 -9
  28. package/lib-commonjs/generators/ValidateMethods.js.map +1 -1
  29. package/lib-commonjs/index.d.ts +1 -1
  30. package/lib-commonjs/index.js +26 -15
  31. package/lib-commonjs/index.js.map +1 -1
  32. package/package.json +15 -12
  33. package/src/Cli.ts +8 -1
  34. package/src/generators/AliasGen.ts +1 -1
  35. package/src/generators/AliasManaging.ts +1 -1
  36. package/src/generators/GenerateNM2.ts +2 -2
  37. package/src/generators/GenerateTypeScript.ts +3 -3
  38. package/src/generators/ObjectTypes.ts +45 -8
  39. package/src/generators/ParamTypes.ts +93 -51
  40. package/src/generators/ReturnTypes.ts +9 -46
  41. package/src/generators/ValidateConstants.ts +1 -1
  42. package/src/generators/ValidateMethods.ts +25 -11
  43. package/src/index.ts +40 -19
@@ -7,19 +7,40 @@
7
7
  'use strict';
8
8
 
9
9
  import type {
10
+ NativeModuleEnumDeclaration,
10
11
  NativeModuleBaseTypeAnnotation,
12
+ NativeModuleUnionTypeAnnotation,
11
13
  Nullable,
12
- } from 'react-native-tscodegen';
14
+ } from '@react-native/codegen/lib/CodegenSchema';
13
15
  import {
14
16
  AliasMap,
15
17
  getAliasCppName,
16
18
  getAnonymousAliasCppName,
17
19
  } from './AliasManaging';
18
20
 
19
- export function translateField(
21
+ function translateUnionReturnType(
22
+ type: NativeModuleEnumDeclaration | NativeModuleUnionTypeAnnotation,
23
+ ): string {
24
+ const memberType = type.memberType;
25
+ switch (type.memberType) {
26
+ case 'StringTypeAnnotation':
27
+ return 'std::string';
28
+ case 'NumberTypeAnnotation':
29
+ return 'double';
30
+ case 'ObjectTypeAnnotation':
31
+ return '::React::JSValue';
32
+ default:
33
+ throw new Error(
34
+ `Unknown enum/union member type in translateReturnType: ${memberType}`,
35
+ );
36
+ }
37
+ }
38
+
39
+ export function translateFieldOrReturnType(
20
40
  type: Nullable<NativeModuleBaseTypeAnnotation>,
21
41
  aliases: AliasMap,
22
42
  baseAliasName: string,
43
+ callerName: 'translateField' | 'translateReturnType',
23
44
  ): string {
24
45
  // avoid: Property 'type' does not exist on type 'never'
25
46
  const returnType = type.type;
@@ -36,10 +57,11 @@ export function translateField(
36
57
  return 'bool';
37
58
  case 'ArrayTypeAnnotation':
38
59
  if (type.elementType) {
39
- return `std::vector<${translateField(
60
+ return `std::vector<${translateFieldOrReturnType(
40
61
  type.elementType,
41
62
  aliases,
42
63
  `${baseAliasName}_element`,
64
+ callerName,
43
65
  )}>`;
44
66
  } else {
45
67
  return `::React::JSValueArray`;
@@ -54,20 +76,35 @@ export function translateField(
54
76
  // (#6597)
55
77
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
56
78
  if (name !== 'RootTag')
57
- throw new Error(
58
- `Unknown reserved function: ${name} in translateReturnType`,
59
- );
79
+ throw new Error(`Unknown reserved function: ${name} in ${callerName}`);
60
80
  return 'double';
61
81
  }
62
82
  case 'TypeAliasTypeAnnotation':
63
83
  return getAliasCppName(type.name);
64
84
  case 'NullableTypeAnnotation':
65
- return `std::optional<${translateField(
85
+ return `std::optional<${translateFieldOrReturnType(
66
86
  type.typeAnnotation,
67
87
  aliases,
68
88
  baseAliasName,
89
+ callerName,
69
90
  )}>`;
91
+ case 'EnumDeclaration':
92
+ case 'UnionTypeAnnotation':
93
+ return translateUnionReturnType(type);
70
94
  default:
71
- throw new Error(`Unhandled type in translateReturnType: ${returnType}`);
95
+ throw new Error(`Unhandled type in ${callerName}: ${returnType}`);
72
96
  }
73
97
  }
98
+
99
+ export function translateField(
100
+ type: Nullable<NativeModuleBaseTypeAnnotation>,
101
+ aliases: AliasMap,
102
+ baseAliasName: string,
103
+ ): string {
104
+ return translateFieldOrReturnType(
105
+ type,
106
+ aliases,
107
+ baseAliasName,
108
+ 'translateField',
109
+ );
110
+ }
@@ -8,9 +8,14 @@
8
8
 
9
9
  import type {
10
10
  NamedShape,
11
+ NativeModuleArrayTypeAnnotation,
12
+ NativeModuleBaseTypeAnnotation,
13
+ NativeModuleEnumDeclaration,
14
+ NativeModuleFunctionTypeAnnotation,
11
15
  NativeModuleParamTypeAnnotation,
16
+ NativeModuleUnionTypeAnnotation,
12
17
  Nullable,
13
- } from 'react-native-tscodegen';
18
+ } from '@react-native/codegen/lib/CodegenSchema';
14
19
  import {
15
20
  AliasMap,
16
21
  getAliasCppName,
@@ -34,6 +39,87 @@ function decorateType(type: string, target: ParamTarget): string {
34
39
  }
35
40
  }
36
41
 
42
+ function translateUnionReturnType(
43
+ type: NativeModuleEnumDeclaration | NativeModuleUnionTypeAnnotation,
44
+ target: ParamTarget,
45
+ ): string {
46
+ const memberType = type.memberType;
47
+ switch (type.memberType) {
48
+ case 'StringTypeAnnotation':
49
+ return 'std::string';
50
+ case 'NumberTypeAnnotation':
51
+ return 'double';
52
+ case 'ObjectTypeAnnotation':
53
+ return decorateType('::React::JSValue', target);
54
+ default:
55
+ throw new Error(
56
+ `Unknown enum/union member type in translateReturnType: ${memberType}`,
57
+ );
58
+ }
59
+ }
60
+
61
+ function translateFunction(
62
+ param: NativeModuleFunctionTypeAnnotation,
63
+ aliases: AliasMap,
64
+ baseAliasName: string,
65
+ target: ParamTarget,
66
+ ): string {
67
+ // TODO: type.returnTypeAnnotation
68
+ switch (target) {
69
+ case 'spec':
70
+ return `Callback<${param.params
71
+ .map((p: NativeModuleParamShape) =>
72
+ translateSpecFunctionParam(p, aliases, `${baseAliasName}_${p.name}`),
73
+ )
74
+ .join(', ')}>`;
75
+ case 'template':
76
+ return `std::function<void(${param.params
77
+ .map((p: NativeModuleParamShape) =>
78
+ translateCallbackParam(p, aliases, `${baseAliasName}_${p.name}`),
79
+ )
80
+ .join(', ')})>`;
81
+ default:
82
+ return `std::function<void(${param.params
83
+ .map((p: NativeModuleParamShape) =>
84
+ translateCallbackParam(p, aliases, `${baseAliasName}_${p.name}`),
85
+ )
86
+ .join(', ')})> const &`;
87
+ }
88
+ }
89
+
90
+ function translateArray(
91
+ param: NativeModuleArrayTypeAnnotation<
92
+ Nullable<NativeModuleBaseTypeAnnotation>
93
+ >,
94
+ aliases: AliasMap,
95
+ baseAliasName: string,
96
+ target: ParamTarget,
97
+ ): string {
98
+ if (param.elementType) {
99
+ switch (target) {
100
+ case 'spec':
101
+ case 'template':
102
+ return `std::vector<${translateNullableParamType(
103
+ param.elementType,
104
+ aliases,
105
+ `${baseAliasName}_element`,
106
+ 'template',
107
+ 'template',
108
+ )}>`;
109
+ default:
110
+ return `std::vector<${translateNullableParamType(
111
+ param.elementType,
112
+ aliases,
113
+ `${baseAliasName}_element`,
114
+ 'template',
115
+ 'template',
116
+ )}> const &`;
117
+ }
118
+ } else {
119
+ return decorateType('::React::JSValueArray', target);
120
+ }
121
+ }
122
+
37
123
  function translateParam(
38
124
  param: NativeModuleParamTypeAnnotation,
39
125
  aliases: AliasMap,
@@ -53,57 +139,10 @@ function translateParam(
53
139
  return 'int';
54
140
  case 'BooleanTypeAnnotation':
55
141
  return 'bool';
56
- case 'FunctionTypeAnnotation': {
57
- // TODO: type.returnTypeAnnotation
58
- switch (target) {
59
- case 'spec':
60
- return `Callback<${param.params
61
- .map((p: NativeModuleParamShape) =>
62
- translateSpecFunctionParam(
63
- p,
64
- aliases,
65
- `${baseAliasName}_${p.name}`,
66
- ),
67
- )
68
- .join(', ')}>`;
69
- case 'template':
70
- return `std::function<void(${param.params
71
- .map((p: NativeModuleParamShape) =>
72
- translateCallbackParam(p, aliases, `${baseAliasName}_${p.name}`),
73
- )
74
- .join(', ')})>`;
75
- default:
76
- return `std::function<void(${param.params
77
- .map((p: NativeModuleParamShape) =>
78
- translateCallbackParam(p, aliases, `${baseAliasName}_${p.name}`),
79
- )
80
- .join(', ')})> const &`;
81
- }
82
- }
142
+ case 'FunctionTypeAnnotation':
143
+ return translateFunction(param, aliases, baseAliasName, target);
83
144
  case 'ArrayTypeAnnotation':
84
- if (param.elementType) {
85
- switch (target) {
86
- case 'spec':
87
- case 'template':
88
- return `std::vector<${translateNullableParamType(
89
- param.elementType,
90
- aliases,
91
- `${baseAliasName}_element`,
92
- 'template',
93
- 'template',
94
- )}>`;
95
- default:
96
- return `std::vector<${translateNullableParamType(
97
- param.elementType,
98
- aliases,
99
- `${baseAliasName}_element`,
100
- 'template',
101
- 'template',
102
- )}> const &`;
103
- }
104
- } else {
105
- return decorateType('::React::JSValueArray', target);
106
- }
145
+ return translateArray(param, aliases, baseAliasName, target);
107
146
  case 'GenericObjectTypeAnnotation':
108
147
  return decorateType('::React::JSValue', target);
109
148
  case 'ObjectTypeAnnotation':
@@ -122,6 +161,9 @@ function translateParam(
122
161
  }
123
162
  case 'TypeAliasTypeAnnotation':
124
163
  return decorateType(getAliasCppName(param.name), target);
164
+ case 'EnumDeclaration':
165
+ case 'UnionTypeAnnotation':
166
+ return translateUnionReturnType(param, target);
125
167
  default:
126
168
  throw new Error(`Unhandled type in translateParam: ${paramType}`);
127
169
  }
@@ -9,61 +9,19 @@
9
9
  import type {
10
10
  NativeModuleReturnTypeAnnotation,
11
11
  Nullable,
12
- } from 'react-native-tscodegen';
13
- import {
14
- AliasMap,
15
- getAliasCppName,
16
- getAnonymousAliasCppName,
17
- } from './AliasManaging';
12
+ } from '@react-native/codegen/lib/CodegenSchema';
13
+ import {AliasMap} from './AliasManaging';
14
+ import {translateFieldOrReturnType} from './ObjectTypes';
18
15
 
19
16
  function translateReturnType(
20
17
  type: Nullable<NativeModuleReturnTypeAnnotation>,
21
18
  aliases: AliasMap,
22
19
  baseAliasName: string,
23
20
  ): string {
24
- // avoid: Property 'type' does not exist on type 'never'
25
- const returnType = type.type;
26
21
  switch (type.type) {
27
22
  case 'VoidTypeAnnotation':
28
23
  case 'PromiseTypeAnnotation':
29
24
  return 'void';
30
- case 'StringTypeAnnotation':
31
- return 'std::string';
32
- case 'NumberTypeAnnotation':
33
- case 'FloatTypeAnnotation':
34
- case 'DoubleTypeAnnotation':
35
- return 'double';
36
- case 'Int32TypeAnnotation':
37
- return 'int';
38
- case 'BooleanTypeAnnotation':
39
- return 'bool';
40
- case 'ArrayTypeAnnotation':
41
- if (type.elementType) {
42
- return `std::vector<${translateReturnType(
43
- type.elementType,
44
- aliases,
45
- `${baseAliasName}_element`,
46
- )}>`;
47
- } else {
48
- return '::React::JSValueArray';
49
- }
50
- case 'GenericObjectTypeAnnotation':
51
- return '::React::JSValue';
52
- case 'ObjectTypeAnnotation':
53
- return getAnonymousAliasCppName(aliases, baseAliasName, type);
54
- case 'ReservedTypeAnnotation': {
55
- // avoid: Property 'name' does not exist on type 'never'
56
- const name = type.name;
57
- // (#6597)
58
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
59
- if (name !== 'RootTag')
60
- throw new Error(
61
- `Unknown reserved function: ${name} in translateReturnType`,
62
- );
63
- return 'double';
64
- }
65
- case 'TypeAliasTypeAnnotation':
66
- return getAliasCppName(type.name);
67
25
  case 'NullableTypeAnnotation':
68
26
  return `std::optional<${translateReturnType(
69
27
  type.typeAnnotation,
@@ -71,7 +29,12 @@ function translateReturnType(
71
29
  baseAliasName,
72
30
  )}>`;
73
31
  default:
74
- throw new Error(`Unhandled type in translateReturnType: ${returnType}`);
32
+ return translateFieldOrReturnType(
33
+ type,
34
+ aliases,
35
+ baseAliasName,
36
+ 'translateReturnType',
37
+ );
75
38
  }
76
39
  }
77
40
 
@@ -6,7 +6,7 @@
6
6
 
7
7
  'use strict';
8
8
 
9
- import type {NativeModuleSchema} from 'react-native-tscodegen';
9
+ import type {NativeModuleSchema} from '@react-native/codegen/lib/CodegenSchema';
10
10
  import {AliasMap, getAnonymousAliasCppName} from './AliasManaging';
11
11
 
12
12
  export function generateValidateConstants(
@@ -10,7 +10,7 @@ import type {
10
10
  NativeModuleFunctionTypeAnnotation,
11
11
  NativeModulePropertyShape,
12
12
  NativeModuleSchema,
13
- } from 'react-native-tscodegen';
13
+ } from '@react-native/codegen/lib/CodegenSchema';
14
14
  import {AliasMap} from './AliasManaging';
15
15
  import {translateArgs, translateSpecArgs} from './ParamTypes';
16
16
  import {translateImplReturnType, translateSpecReturnType} from './ReturnTypes';
@@ -22,10 +22,6 @@ function isMethodSync(funcType: NativeModuleFunctionTypeAnnotation) {
22
22
  );
23
23
  }
24
24
 
25
- function isMethodReturnPromise(funcType: NativeModuleFunctionTypeAnnotation) {
26
- return funcType.returnTypeAnnotation.type === 'PromiseTypeAnnotation';
27
- }
28
-
29
25
  function getPossibleMethodSignatures(
30
26
  prop: NativeModulePropertyShape,
31
27
  funcType: NativeModuleFunctionTypeAnnotation,
@@ -33,9 +29,18 @@ function getPossibleMethodSignatures(
33
29
  baseAliasName: string,
34
30
  ): string[] {
35
31
  const args = translateArgs(funcType.params, aliases, baseAliasName);
36
- if (isMethodReturnPromise(funcType)) {
37
- // TODO: type of the promise could be provided in the future
38
- args.push('::React::ReactPromise<::React::JSValue> &&result');
32
+ if (funcType.returnTypeAnnotation.type === 'PromiseTypeAnnotation') {
33
+ if (funcType.returnTypeAnnotation.elementType) {
34
+ args.push(
35
+ `::React::ReactPromise<${translateImplReturnType(
36
+ funcType.returnTypeAnnotation.elementType,
37
+ aliases,
38
+ baseAliasName,
39
+ )}> &&result`,
40
+ );
41
+ } else {
42
+ args.push('::React::ReactPromise<::React::JSValue> &&result');
43
+ }
39
44
  }
40
45
 
41
46
  // TODO: be much more exhastive on the possible method signatures that can be used..
@@ -98,9 +103,18 @@ function renderProperties(
98
103
  propAliasName,
99
104
  );
100
105
 
101
- if (isMethodReturnPromise(funcType)) {
102
- // TODO: type of the promise could be provided in the future
103
- traversedArgs.push('Promise<::React::JSValue>');
106
+ if (funcType.returnTypeAnnotation.type === 'PromiseTypeAnnotation') {
107
+ if (funcType.returnTypeAnnotation.elementType) {
108
+ traversedArgs.push(
109
+ `Promise<${translateSpecReturnType(
110
+ funcType.returnTypeAnnotation.elementType,
111
+ aliases,
112
+ propAliasName,
113
+ )}>`,
114
+ );
115
+ } else {
116
+ traversedArgs.push('Promise<::React::JSValue>');
117
+ }
104
118
  }
105
119
 
106
120
  if (tuple) {
package/src/index.ts CHANGED
@@ -13,22 +13,31 @@ import {
13
13
  generateTypeScript,
14
14
  setOptionalTurboModule,
15
15
  } from './generators/GenerateTypeScript';
16
- import type {SchemaType} from 'react-native-tscodegen';
16
+ import type {SchemaType} from '@react-native/codegen/lib/CodegenSchema';
17
+ import type {Parser} from '@react-native/codegen/lib/parsers/parser';
17
18
 
18
- // Load react-native-codegen from react-native
19
+ // Load @react-native/codegen from react-native
19
20
  const rnPath = path.dirname(require.resolve('react-native/package.json'));
20
21
  const rncodegenPath = path.dirname(
21
- require.resolve('react-native-codegen/package.json', {paths: [rnPath]}),
22
+ require.resolve('@react-native/codegen/package.json', {paths: [rnPath]}),
22
23
  );
23
- const FlowParser = require(path.resolve(rncodegenPath, 'lib/parsers/flow'));
24
- const TypeScriptParser = require(path.resolve(
25
- rncodegenPath,
26
- 'lib/parsers/typescript',
27
- ));
24
+
25
+ function getParser(isTypeScript: boolean): Parser {
26
+ if (isTypeScript) {
27
+ const fp = require(path.resolve(
28
+ rncodegenPath,
29
+ 'lib/parsers/typescript/parser',
30
+ ));
31
+ return new fp.TypeScriptParser();
32
+ } else {
33
+ const fp = require(path.resolve(rncodegenPath, 'lib/parsers/flow/parser'));
34
+ return new fp.FlowParser();
35
+ }
36
+ }
28
37
 
29
38
  const schemaValidator = require(path.resolve(
30
39
  rncodegenPath,
31
- 'lib/SchemaValidator',
40
+ 'lib/schemaValidator',
32
41
  ));
33
42
 
34
43
  interface Options {
@@ -65,15 +74,20 @@ function checkFilesForChanges(
65
74
  ): boolean {
66
75
  let hasChanges = false;
67
76
 
77
+ outputDir = path.resolve(outputDir);
78
+ const globbyDir = outputDir.replace(/\\/g, '/');
68
79
  const allExistingFiles = globby
69
- .sync(`${outputDir}/**`)
70
- .map(_ => path.normalize(_))
71
- .sort();
80
+ .sync([`${globbyDir}/**`, `${globbyDir}/**/.*`], {absolute: true})
81
+ .map(_ => path.normalize(_));
72
82
  const allGeneratedFiles = [...map.keys()].map(_ => path.normalize(_)).sort();
73
83
 
74
84
  if (
75
85
  allExistingFiles.length !== allGeneratedFiles.length ||
76
- !allExistingFiles.every((val, index) => val === allGeneratedFiles[index])
86
+ !allGeneratedFiles.every(filepath =>
87
+ allExistingFiles.includes(
88
+ path.normalize(path.resolve(process.cwd(), filepath)),
89
+ ),
90
+ )
77
91
  )
78
92
  return true;
79
93
 
@@ -97,10 +111,19 @@ function checkFilesForChanges(
97
111
  function writeMapToFiles(map: Map<string, string>, outputDir: string) {
98
112
  let success = true;
99
113
 
114
+ outputDir = path.resolve(outputDir);
115
+ const globbyDir = outputDir.replace(/\\/g, '/');
116
+
100
117
  // This ensures that we delete any generated files from modules that have been deleted
101
- const allExistingFiles = globby.sync(`${outputDir}/**`);
118
+ const allExistingFiles = globby.sync(
119
+ [`${globbyDir}/**`, `${globbyDir}/**/.*`],
120
+ {absolute: true},
121
+ );
122
+
123
+ const allGeneratedFiles = [...map.keys()].map(_ => path.normalize(_)).sort();
102
124
  allExistingFiles.forEach(existingFile => {
103
- if (!map.has(path.normalize(existingFile))) {
125
+ if (!allGeneratedFiles.includes(path.normalize(existingFile))) {
126
+ console.log('Deleting ', existingFile);
104
127
  fs.unlinkSync(existingFile);
105
128
  }
106
129
  });
@@ -117,6 +140,7 @@ function writeMapToFiles(map: Map<string, string>, outputDir: string) {
117
140
  }
118
141
  }
119
142
 
143
+ console.log('Writing ', fileName);
120
144
  fs.writeFileSync(fileName, contents);
121
145
  } catch (error) {
122
146
  success = false;
@@ -132,15 +156,12 @@ export function parseFile(filename: string): SchemaType {
132
156
  const isTypeScript =
133
157
  path.extname(filename) === '.ts' || path.extname(filename) === '.tsx';
134
158
  const contents = fs.readFileSync(filename, 'utf8');
135
- const schema = isTypeScript
136
- ? TypeScriptParser.parseString(contents, filename)
137
- : FlowParser.parseString(contents, filename);
159
+ const schema = getParser(isTypeScript).parseString(contents, filename);
138
160
  // there will be at most one turbo module per file
139
161
  const moduleName = Object.keys(schema.modules)[0];
140
162
  if (moduleName) {
141
163
  const spec = schema.modules[moduleName];
142
164
  if (spec.type === 'NativeModule') {
143
- const contents = fs.readFileSync(filename, 'utf8');
144
165
  if (contents) {
145
166
  // This is a temporary implementation until such information is added to the schema in facebook/react-native
146
167
  if (contents.includes('TurboModuleRegistry.get<')) {