@react-native-windows/codegen 0.70.0 → 0.71.0-preview.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 (38) hide show
  1. package/CHANGELOG.md +97 -10
  2. package/lib-commonjs/Cli.js +18 -187
  3. package/lib-commonjs/Cli.js.map +1 -1
  4. package/lib-commonjs/generators/AliasGen.d.ts +1 -1
  5. package/lib-commonjs/generators/AliasGen.js.map +1 -1
  6. package/lib-commonjs/generators/AliasManaging.d.ts +1 -1
  7. package/lib-commonjs/generators/AliasManaging.js.map +1 -1
  8. package/lib-commonjs/generators/GenerateNM2.d.ts +3 -3
  9. package/lib-commonjs/generators/GenerateNM2.js +2 -2
  10. package/lib-commonjs/generators/GenerateNM2.js.map +1 -1
  11. package/lib-commonjs/generators/GenerateTypeScript.d.ts +1 -1
  12. package/lib-commonjs/generators/GenerateTypeScript.js.map +1 -1
  13. package/lib-commonjs/generators/ObjectTypes.d.ts +1 -1
  14. package/lib-commonjs/generators/ObjectTypes.js.map +1 -1
  15. package/lib-commonjs/generators/ParamTypes.d.ts +1 -1
  16. package/lib-commonjs/generators/ParamTypes.js.map +1 -1
  17. package/lib-commonjs/generators/ReturnTypes.d.ts +1 -1
  18. package/lib-commonjs/generators/ReturnTypes.js.map +1 -1
  19. package/lib-commonjs/generators/ValidateConstants.d.ts +1 -1
  20. package/lib-commonjs/generators/ValidateConstants.js.map +1 -1
  21. package/lib-commonjs/generators/ValidateMethods.d.ts +1 -1
  22. package/lib-commonjs/generators/ValidateMethods.js +2 -2
  23. package/lib-commonjs/generators/ValidateMethods.js.map +1 -1
  24. package/lib-commonjs/index.d.ts +39 -0
  25. package/lib-commonjs/index.js +209 -0
  26. package/lib-commonjs/index.js.map +1 -0
  27. package/package.json +18 -15
  28. package/src/Cli.ts +18 -279
  29. package/src/generators/AliasGen.ts +1 -1
  30. package/src/generators/AliasManaging.ts +1 -1
  31. package/src/generators/GenerateNM2.ts +4 -4
  32. package/src/generators/GenerateTypeScript.ts +1 -1
  33. package/src/generators/ObjectTypes.ts +4 -1
  34. package/src/generators/ParamTypes.ts +1 -1
  35. package/src/generators/ReturnTypes.ts +1 -1
  36. package/src/generators/ValidateConstants.ts +1 -1
  37. package/src/generators/ValidateMethods.ts +3 -3
  38. package/src/index.ts +363 -0
package/src/Cli.ts CHANGED
@@ -6,18 +6,7 @@
6
6
  */
7
7
 
8
8
  import yargs from 'yargs';
9
- import path from 'path';
10
- import fs from '@react-native-windows/fs';
11
- import globby from 'globby';
12
- import {createNM2Generator} from './generators/GenerateNM2';
13
- import {
14
- generateTypeScript,
15
- setOptionalTurboModule,
16
- } from './generators/GenerateTypeScript';
17
- // @ts-ignore
18
- import {parseFile} from 'react-native-tscodegen/lib/rncodegen/src/parsers/flow';
19
- // @ts-ignore
20
- import schemaValidator from 'react-native-tscodegen/lib/rncodegen/src/schemaValidator';
9
+ import {runCodeGen} from './index';
21
10
 
22
11
  const argv = yargs.options({
23
12
  file: {
@@ -25,20 +14,31 @@ const argv = yargs.options({
25
14
  describe: 'file which contains spec',
26
15
  },
27
16
  files: {
28
- type: 'array',
17
+ type: 'string',
18
+ array: true,
29
19
  describe: 'glob patterns for files which contains specs',
30
20
  },
31
- ts: {
21
+ modulesTypeScriptTypes: {
32
22
  type: 'boolean',
33
23
  describe: 'generate turbo module definition files in TypeScript',
34
24
  default: false,
35
25
  },
36
- methodonly: {
26
+ modulesCxx: {
27
+ type: 'boolean',
28
+ describe: 'generate C++ JSI turbo module spec files',
29
+ default: false,
30
+ },
31
+ modulesWindows: {
32
+ type: 'boolean',
33
+ describe: 'generate turbo module spec files for REACT_MODULE',
34
+ default: false,
35
+ },
36
+ methodOnly: {
37
37
  type: 'boolean',
38
38
  describe: 'generate only method metadata in C++ turbo module spec',
39
39
  default: false,
40
40
  },
41
- outdir: {
41
+ outputDirectory: {
42
42
  type: 'string',
43
43
  describe: 'output directory',
44
44
  default: 'codegen',
@@ -46,6 +46,7 @@ const argv = yargs.options({
46
46
  test: {
47
47
  type: 'boolean',
48
48
  describe: 'Verify that the generated output is unchanged',
49
+ default: false,
49
50
  },
50
51
  namespace: {
51
52
  type: 'string',
@@ -59,271 +60,9 @@ const argv = yargs.options({
59
60
  },
60
61
  }).argv;
61
62
 
62
- import {SchemaType} from 'react-native-tscodegen';
63
-
64
- interface Options {
65
- libraryName: string;
66
- schema: SchemaType;
67
- outputDirectory: string;
68
- moduleSpecName: string;
69
- }
70
-
71
- interface Config {
72
- generators: any[] /*Generators[]*/;
73
- test?: boolean;
74
- }
75
-
76
- /*
77
- const GENERATORS = {
78
- descriptors: [generateComponentDescriptorH.generate],
79
- events: [
80
- generateEventEmitterCpp.generate,
81
- generateEventEmitterH.generate,
82
- generateModuleHObjCpp.generate,
83
- generateModuleMm.generate,
84
- ],
85
- props: [
86
- generateComponentHObjCpp.generate,
87
- generatePropsCpp.generate,
88
- generatePropsH.generate,
89
- generatePropsJavaInterface.generate,
90
- generatePropsJavaDelegate.generate,
91
- ],
92
- modules: [generateModuleCpp.generate, generateModuleH.generate],
93
- tests: [generateTests.generate],
94
- 'shadow-nodes': [
95
- generateShadowNodeCpp.generate,
96
- generateShadowNodeH.generate,
97
- ],
98
- };
99
- */
100
-
101
- function normalizeFileMap(
102
- map: Map<string, string>,
103
- outputDir: string,
104
- outMap: Map<string, string>,
105
- ): void {
106
- for (const [fileName, contents] of map) {
107
- const location = path.join(outputDir, fileName);
108
- outMap.set(path.normalize(location), contents);
109
- }
110
- }
111
-
112
- function checkFilesForChanges(
113
- map: Map<string, string>,
114
- outputDir: string,
115
- ): boolean {
116
- let hasChanges = false;
117
-
118
- const allExistingFiles = globby
119
- .sync(`${outputDir}/**`)
120
- .map(_ => path.normalize(_))
121
- .sort();
122
- const allGeneratedFiles = [...map.keys()].map(_ => path.normalize(_)).sort();
123
-
124
- if (
125
- allExistingFiles.length !== allGeneratedFiles.length ||
126
- !allExistingFiles.every((val, index) => val === allGeneratedFiles[index])
127
- )
128
- return true;
129
-
130
- for (const [fileName, contents] of map) {
131
- if (!fs.existsSync(fileName)) {
132
- hasChanges = true;
133
- continue;
134
- }
135
-
136
- const currentContents = fs.readFileSync(fileName, 'utf8');
137
- if (currentContents !== contents) {
138
- console.error(`- ${fileName} has changed`);
139
- hasChanges = true;
140
- continue;
141
- }
142
- }
143
-
144
- return hasChanges;
145
- }
146
-
147
- function writeMapToFiles(map: Map<string, string>, outputDir: string) {
148
- let success = true;
149
-
150
- // This ensures that we delete any generated files from modules that have been deleted
151
- const allExistingFiles = globby.sync(`${outputDir}/**`);
152
- allExistingFiles.forEach(existingFile => {
153
- if (!map.has(path.normalize(existingFile))) {
154
- fs.unlinkSync(existingFile);
155
- }
156
- });
157
-
158
- for (const [fileName, contents] of map) {
159
- try {
160
- fs.mkdirSync(path.dirname(fileName), {recursive: true});
161
-
162
- if (fs.existsSync(fileName)) {
163
- const currentContents = fs.readFileSync(fileName, 'utf8');
164
- // Don't update the files if there are no changes as this breaks incremental builds
165
- if (currentContents === contents) {
166
- continue;
167
- }
168
- }
169
-
170
- fs.writeFileSync(fileName, contents);
171
- } catch (error) {
172
- success = false;
173
- console.error(`Failed to write ${fileName} to ${fileName}`, error);
174
- }
175
- }
176
-
177
- return success;
178
- }
179
-
180
- function parseFlowFile(filename: string): SchemaType {
181
- try {
182
- const schema = parseFile(filename);
183
- // there will be at most one turbo module per file
184
- const moduleName = Object.keys(schema.modules)[0];
185
- if (moduleName) {
186
- const spec = schema.modules[moduleName];
187
- if (spec.type === 'NativeModule') {
188
- const contents = fs.readFileSync(filename, 'utf8');
189
- if (contents) {
190
- // This is a temporary implementation until such information is added to the schema in facebook/react-native
191
- if (contents.includes('TurboModuleRegistry.get<')) {
192
- setOptionalTurboModule(spec, true);
193
- } else if (contents.includes('TurboModuleRegistry.getEnforcing<')) {
194
- setOptionalTurboModule(spec, false);
195
- }
196
- }
197
- }
198
- }
199
- return schema;
200
- } catch (e) {
201
- if (e instanceof Error) {
202
- e.message = `(${filename}): ${e.message}`;
203
- }
204
- throw e;
205
- }
206
- }
207
-
208
- function combineSchemas(files: string[]): SchemaType {
209
- return files.reduce(
210
- (merged, filename) => {
211
- const contents = fs.readFileSync(filename, 'utf8');
212
- if (
213
- contents &&
214
- (/export\s+default\s+\(?codegenNativeComponent</.test(contents) ||
215
- contents.includes('extends TurboModule'))
216
- ) {
217
- const schema = parseFlowFile(filename);
218
- merged.modules = {...merged.modules, ...schema.modules};
219
- }
220
- return merged;
221
- },
222
- {modules: {}},
223
- );
224
- }
225
-
226
- function generate(
227
- {libraryName, schema, outputDirectory, moduleSpecName}: Options,
228
- {/*generators,*/ test}: Config,
229
- ): boolean {
230
- schemaValidator.validate(schema);
231
-
232
- const componentOutputdir = path.join(
233
- outputDirectory,
234
- 'react/components',
235
- libraryName,
236
- );
237
-
238
- const generatedFiles = new Map<string, string>();
239
-
240
- generatedFiles.set(
241
- path.join(outputDirectory, '.clang-format'),
242
- 'DisableFormat: true\nSortIncludes: false',
243
- );
244
-
245
- const generateNM2 = createNM2Generator({
246
- namespace: argv.namespace,
247
- methodonly: argv.methodonly,
248
- });
249
-
250
- const generatorPropsH =
251
- require('react-native-tscodegen/lib/rncodegen/src/generators/components/GeneratePropsH').generate;
252
- const generatorPropsCPP =
253
- require('react-native-tscodegen/lib/rncodegen/src/generators/components/GeneratePropsCPP').generate;
254
- const generatorShadowNodeH =
255
- require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateShadowNodeH').generate;
256
- const generatorShadowNodeCPP =
257
- require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateShadowNodeCPP').generate;
258
- const generatorComponentDescriptorH =
259
- require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateComponentDescriptorH').generate;
260
- const generatorEventEmitterH =
261
- require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateEventEmitterH').generate;
262
- const generatorEventEmitterCPP =
263
- require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateEventEmitterCpp').generate;
264
-
265
- normalizeFileMap(
266
- generateNM2(libraryName, schema, moduleSpecName),
267
- outputDirectory,
268
- generatedFiles,
269
- );
270
-
271
- if (argv.ts) {
272
- normalizeFileMap(
273
- generateTypeScript(libraryName, schema, moduleSpecName),
274
- outputDirectory,
275
- generatedFiles,
276
- );
277
- }
278
-
279
- if (
280
- Object.keys(schema.modules).some(
281
- moduleName => schema.modules[moduleName].type === 'Component',
282
- )
283
- ) {
284
- const componentGenerators = [
285
- generatorPropsH,
286
- generatorPropsCPP,
287
- generatorShadowNodeH,
288
- generatorShadowNodeCPP,
289
- generatorComponentDescriptorH,
290
- generatorEventEmitterH,
291
- generatorEventEmitterCPP,
292
- ];
293
-
294
- componentGenerators.forEach(generator => {
295
- const generated: Map<string, string> = generator(
296
- libraryName,
297
- schema,
298
- moduleSpecName,
299
- );
300
- normalizeFileMap(generated, componentOutputdir, generatedFiles);
301
- });
302
- }
303
-
304
- if (test === true) {
305
- return checkFilesForChanges(generatedFiles, outputDirectory);
306
- }
307
-
308
- return writeMapToFiles(generatedFiles, outputDirectory);
309
- }
310
-
311
63
  if ((argv.file && argv.files) || (!argv.file && !argv.files)) {
312
64
  console.error('You must specify either --file or --files.');
313
65
  process.exit(1);
314
66
  }
315
67
 
316
- let schema: SchemaType;
317
- if (argv.file) {
318
- schema = parseFlowFile(argv.file);
319
- } else {
320
- schema = combineSchemas(globby.sync(argv.files as string[]));
321
- }
322
-
323
- const libraryName = argv.libraryName;
324
- const moduleSpecName = 'moduleSpecName';
325
- const outputDirectory = argv.outdir;
326
- generate(
327
- {libraryName, schema, outputDirectory, moduleSpecName},
328
- {generators: [], test: false},
329
- );
68
+ runCodeGen(argv);
@@ -6,7 +6,7 @@
6
6
 
7
7
  'use strict';
8
8
 
9
- import {
9
+ import type {
10
10
  NativeModuleBaseTypeAnnotation,
11
11
  NativeModuleObjectTypeAnnotation,
12
12
  NamedShape,
@@ -6,7 +6,7 @@
6
6
 
7
7
  'use strict';
8
8
 
9
- import {NativeModuleObjectTypeAnnotation} from 'react-native-tscodegen';
9
+ import type {NativeModuleObjectTypeAnnotation} from 'react-native-tscodegen';
10
10
 
11
11
  let preferredModuleName: string = '';
12
12
 
@@ -6,7 +6,7 @@
6
6
 
7
7
  'use strict';
8
8
 
9
- import {SchemaType} from 'react-native-tscodegen';
9
+ import type {SchemaType} from 'react-native-tscodegen';
10
10
  import {AliasMap, setPreferredModuleName} from './AliasManaging';
11
11
  import {createAliasMap, generateAliases} from './AliasGen';
12
12
  import {generateValidateConstants} from './ValidateConstants';
@@ -44,11 +44,11 @@ struct ::_MODULE_NAME_::Spec : winrt::Microsoft::ReactNative::TurboModuleSpec {
44
44
  `;
45
45
 
46
46
  export function createNM2Generator({
47
+ methodOnly,
47
48
  namespace,
48
- methodonly,
49
49
  }: {
50
+ methodOnly: boolean;
50
51
  namespace: string;
51
- methodonly: boolean;
52
52
  }) {
53
53
  return (
54
54
  _libraryName: string,
@@ -85,7 +85,7 @@ ${methods[0]}
85
85
 
86
86
  // prepare constants
87
87
  const constants = generateValidateConstants(nativeModule, aliases);
88
- if (constants !== undefined && !methodonly) {
88
+ if (constants !== undefined && !methodOnly) {
89
89
  tuples = `
90
90
  static constexpr auto constants = std::tuple{
91
91
  ${constants[0]}
@@ -6,7 +6,7 @@
6
6
 
7
7
  'use strict';
8
8
 
9
- import {
9
+ import type {
10
10
  NamedShape,
11
11
  NativeModuleBaseTypeAnnotation,
12
12
  NativeModuleFunctionTypeAnnotation,
@@ -6,7 +6,10 @@
6
6
 
7
7
  'use strict';
8
8
 
9
- import {NativeModuleBaseTypeAnnotation, Nullable} from 'react-native-tscodegen';
9
+ import type {
10
+ NativeModuleBaseTypeAnnotation,
11
+ Nullable,
12
+ } from 'react-native-tscodegen';
10
13
  import {
11
14
  AliasMap,
12
15
  getAliasCppName,
@@ -6,7 +6,7 @@
6
6
 
7
7
  'use strict';
8
8
 
9
- import {
9
+ import type {
10
10
  NamedShape,
11
11
  NativeModuleParamTypeAnnotation,
12
12
  Nullable,
@@ -6,7 +6,7 @@
6
6
 
7
7
  'use strict';
8
8
 
9
- import {
9
+ import type {
10
10
  NativeModuleReturnTypeAnnotation,
11
11
  Nullable,
12
12
  } from 'react-native-tscodegen';
@@ -6,7 +6,7 @@
6
6
 
7
7
  'use strict';
8
8
 
9
- import {NativeModuleSchema} from 'react-native-tscodegen';
9
+ import type {NativeModuleSchema} from 'react-native-tscodegen';
10
10
  import {AliasMap, getAnonymousAliasCppName} from './AliasManaging';
11
11
 
12
12
  export function generateValidateConstants(
@@ -6,7 +6,7 @@
6
6
 
7
7
  'use strict';
8
8
 
9
- import {
9
+ import type {
10
10
  NativeModuleFunctionTypeAnnotation,
11
11
  NativeModulePropertyShape,
12
12
  NativeModuleSchema,
@@ -45,7 +45,7 @@ function getPossibleMethodSignatures(
45
45
  funcType.returnTypeAnnotation,
46
46
  aliases,
47
47
  baseAliasName,
48
- )} ${prop.name}(${args.join(', ')}) noexcept { /* implementation */ }}`;
48
+ )} ${prop.name}(${args.join(', ')}) noexcept { /* implementation */ }`;
49
49
 
50
50
  const staticsig = `REACT_${isMethodSync(funcType) ? 'SYNC_' : ''}METHOD(${
51
51
  prop.name
@@ -53,7 +53,7 @@ function getPossibleMethodSignatures(
53
53
  funcType.returnTypeAnnotation,
54
54
  aliases,
55
55
  baseAliasName,
56
- )} ${prop.name}(${args.join(', ')}) noexcept { /* implementation */ }}`;
56
+ )} ${prop.name}(${args.join(', ')}) noexcept { /* implementation */ }`;
57
57
 
58
58
  return [sig, staticsig];
59
59
  }