@react-native-windows/codegen 0.0.0-canary.35 → 0.0.0-canary.36
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/CHANGELOG.md +14 -6
- package/lib-commonjs/Cli.js +5 -184
- package/lib-commonjs/Cli.js.map +1 -1
- package/lib-commonjs/index.d.ts +35 -0
- package/lib-commonjs/index.js +185 -0
- package/lib-commonjs/index.js.map +1 -0
- package/package.json +2 -2
- package/src/Cli.ts +5 -276
- package/src/index.ts +290 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,19 +1,27 @@
|
|
|
1
1
|
# Change Log - @react-native-windows/codegen
|
|
2
2
|
|
|
3
|
-
This log was last generated on
|
|
3
|
+
This log was last generated on Tue, 27 Sep 2022 05:10:57 GMT and should not be manually modified.
|
|
4
4
|
|
|
5
5
|
<!-- Start content -->
|
|
6
6
|
|
|
7
|
-
## 0.0.0-canary.
|
|
7
|
+
## 0.0.0-canary.36
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Tue, 27 Sep 2022 05:10:57 GMT
|
|
10
10
|
|
|
11
11
|
### Changes
|
|
12
12
|
|
|
13
|
-
-
|
|
14
|
-
- Bump @rnw-scripts/jest-unittest-config to v1.2.8
|
|
15
|
-
- Bump @rnw-scripts/just-task to v2.2.5
|
|
13
|
+
- Export functionality to allow cli to use it (30809111+acoates-ms@users.noreply.github.com)
|
|
16
14
|
|
|
15
|
+
## 0.0.0-canary.35
|
|
16
|
+
|
|
17
|
+
Sat, 04 Jun 2022 05:10:05 GMT
|
|
18
|
+
|
|
19
|
+
### Changes
|
|
20
|
+
|
|
21
|
+
- Bump @react-native-windows/fs to v0.0.0-canary.5
|
|
22
|
+
- Bump @rnw-scripts/jest-unittest-config to v1.2.8
|
|
23
|
+
- Bump @rnw-scripts/just-task to v2.2.5
|
|
24
|
+
|
|
17
25
|
## 0.0.0-canary.34
|
|
18
26
|
|
|
19
27
|
Thu, 12 May 2022 05:09:43 GMT
|
package/lib-commonjs/Cli.js
CHANGED
|
@@ -10,22 +10,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
const yargs_1 = __importDefault(require("yargs"));
|
|
13
|
-
const
|
|
14
|
-
const fs_1 = __importDefault(require("@react-native-windows/fs"));
|
|
15
|
-
const globby_1 = __importDefault(require("globby"));
|
|
16
|
-
const GenerateNM2_1 = require("./generators/GenerateNM2");
|
|
17
|
-
const GenerateTypeScript_1 = require("./generators/GenerateTypeScript");
|
|
18
|
-
// @ts-ignore
|
|
19
|
-
const flow_1 = require("react-native-tscodegen/lib/rncodegen/src/parsers/flow");
|
|
20
|
-
// @ts-ignore
|
|
21
|
-
const schemaValidator_1 = __importDefault(require("react-native-tscodegen/lib/rncodegen/src/schemaValidator"));
|
|
13
|
+
const index_1 = require("./index");
|
|
22
14
|
const argv = yargs_1.default.options({
|
|
23
15
|
file: {
|
|
24
16
|
type: 'string',
|
|
25
17
|
describe: 'file which contains spec',
|
|
26
18
|
},
|
|
27
19
|
files: {
|
|
28
|
-
type: '
|
|
20
|
+
type: 'string',
|
|
21
|
+
array: true,
|
|
29
22
|
describe: 'glob patterns for files which contains specs',
|
|
30
23
|
},
|
|
31
24
|
ts: {
|
|
@@ -46,6 +39,7 @@ const argv = yargs_1.default.options({
|
|
|
46
39
|
test: {
|
|
47
40
|
type: 'boolean',
|
|
48
41
|
describe: 'Verify that the generated output is unchanged',
|
|
42
|
+
default: false,
|
|
49
43
|
},
|
|
50
44
|
namespace: {
|
|
51
45
|
type: 'string',
|
|
@@ -58,182 +52,9 @@ const argv = yargs_1.default.options({
|
|
|
58
52
|
describe: 'Used for part of the path generated within the codegen dir',
|
|
59
53
|
},
|
|
60
54
|
}).argv;
|
|
61
|
-
/*
|
|
62
|
-
const GENERATORS = {
|
|
63
|
-
descriptors: [generateComponentDescriptorH.generate],
|
|
64
|
-
events: [
|
|
65
|
-
generateEventEmitterCpp.generate,
|
|
66
|
-
generateEventEmitterH.generate,
|
|
67
|
-
generateModuleHObjCpp.generate,
|
|
68
|
-
generateModuleMm.generate,
|
|
69
|
-
],
|
|
70
|
-
props: [
|
|
71
|
-
generateComponentHObjCpp.generate,
|
|
72
|
-
generatePropsCpp.generate,
|
|
73
|
-
generatePropsH.generate,
|
|
74
|
-
generatePropsJavaInterface.generate,
|
|
75
|
-
generatePropsJavaDelegate.generate,
|
|
76
|
-
],
|
|
77
|
-
modules: [generateModuleCpp.generate, generateModuleH.generate],
|
|
78
|
-
tests: [generateTests.generate],
|
|
79
|
-
'shadow-nodes': [
|
|
80
|
-
generateShadowNodeCpp.generate,
|
|
81
|
-
generateShadowNodeH.generate,
|
|
82
|
-
],
|
|
83
|
-
};
|
|
84
|
-
*/
|
|
85
|
-
function normalizeFileMap(map, outputDir, outMap) {
|
|
86
|
-
for (const [fileName, contents] of map) {
|
|
87
|
-
const location = path_1.default.join(outputDir, fileName);
|
|
88
|
-
outMap.set(path_1.default.normalize(location), contents);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
function checkFilesForChanges(map, outputDir) {
|
|
92
|
-
let hasChanges = false;
|
|
93
|
-
const allExistingFiles = globby_1.default
|
|
94
|
-
.sync(`${outputDir}/**`)
|
|
95
|
-
.map(_ => path_1.default.normalize(_))
|
|
96
|
-
.sort();
|
|
97
|
-
const allGeneratedFiles = [...map.keys()].map(_ => path_1.default.normalize(_)).sort();
|
|
98
|
-
if (allExistingFiles.length !== allGeneratedFiles.length ||
|
|
99
|
-
!allExistingFiles.every((val, index) => val === allGeneratedFiles[index]))
|
|
100
|
-
return true;
|
|
101
|
-
for (const [fileName, contents] of map) {
|
|
102
|
-
if (!fs_1.default.existsSync(fileName)) {
|
|
103
|
-
hasChanges = true;
|
|
104
|
-
continue;
|
|
105
|
-
}
|
|
106
|
-
const currentContents = fs_1.default.readFileSync(fileName, 'utf8');
|
|
107
|
-
if (currentContents !== contents) {
|
|
108
|
-
console.error(`- ${fileName} has changed`);
|
|
109
|
-
hasChanges = true;
|
|
110
|
-
continue;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
return hasChanges;
|
|
114
|
-
}
|
|
115
|
-
function writeMapToFiles(map, outputDir) {
|
|
116
|
-
let success = true;
|
|
117
|
-
// This ensures that we delete any generated files from modules that have been deleted
|
|
118
|
-
const allExistingFiles = globby_1.default.sync(`${outputDir}/**`);
|
|
119
|
-
allExistingFiles.forEach(existingFile => {
|
|
120
|
-
if (!map.has(path_1.default.normalize(existingFile))) {
|
|
121
|
-
fs_1.default.unlinkSync(existingFile);
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
for (const [fileName, contents] of map) {
|
|
125
|
-
try {
|
|
126
|
-
fs_1.default.mkdirSync(path_1.default.dirname(fileName), { recursive: true });
|
|
127
|
-
if (fs_1.default.existsSync(fileName)) {
|
|
128
|
-
const currentContents = fs_1.default.readFileSync(fileName, 'utf8');
|
|
129
|
-
// Don't update the files if there are no changes as this breaks incremental builds
|
|
130
|
-
if (currentContents === contents) {
|
|
131
|
-
continue;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
fs_1.default.writeFileSync(fileName, contents);
|
|
135
|
-
}
|
|
136
|
-
catch (error) {
|
|
137
|
-
success = false;
|
|
138
|
-
console.error(`Failed to write ${fileName} to ${fileName}`, error);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
return success;
|
|
142
|
-
}
|
|
143
|
-
function parseFlowFile(filename) {
|
|
144
|
-
try {
|
|
145
|
-
const schema = (0, flow_1.parseFile)(filename);
|
|
146
|
-
// there will be at most one turbo module per file
|
|
147
|
-
const moduleName = Object.keys(schema.modules)[0];
|
|
148
|
-
if (moduleName) {
|
|
149
|
-
const spec = schema.modules[moduleName];
|
|
150
|
-
if (spec.type === 'NativeModule') {
|
|
151
|
-
const contents = fs_1.default.readFileSync(filename, 'utf8');
|
|
152
|
-
if (contents) {
|
|
153
|
-
// This is a temporary implementation until such information is added to the schema in facebook/react-native
|
|
154
|
-
if (contents.includes('TurboModuleRegistry.get<')) {
|
|
155
|
-
(0, GenerateTypeScript_1.setOptionalTurboModule)(spec, true);
|
|
156
|
-
}
|
|
157
|
-
else if (contents.includes('TurboModuleRegistry.getEnforcing<')) {
|
|
158
|
-
(0, GenerateTypeScript_1.setOptionalTurboModule)(spec, false);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
return schema;
|
|
164
|
-
}
|
|
165
|
-
catch (e) {
|
|
166
|
-
if (e instanceof Error) {
|
|
167
|
-
e.message = `(${filename}): ${e.message}`;
|
|
168
|
-
}
|
|
169
|
-
throw e;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
function combineSchemas(files) {
|
|
173
|
-
return files.reduce((merged, filename) => {
|
|
174
|
-
const contents = fs_1.default.readFileSync(filename, 'utf8');
|
|
175
|
-
if (contents &&
|
|
176
|
-
(/export\s+default\s+\(?codegenNativeComponent</.test(contents) ||
|
|
177
|
-
contents.includes('extends TurboModule'))) {
|
|
178
|
-
const schema = parseFlowFile(filename);
|
|
179
|
-
merged.modules = { ...merged.modules, ...schema.modules };
|
|
180
|
-
}
|
|
181
|
-
return merged;
|
|
182
|
-
}, { modules: {} });
|
|
183
|
-
}
|
|
184
|
-
function generate({ libraryName, schema, outputDirectory, moduleSpecName }, { /*generators,*/ test }) {
|
|
185
|
-
schemaValidator_1.default.validate(schema);
|
|
186
|
-
const componentOutputdir = path_1.default.join(outputDirectory, 'react/components', libraryName);
|
|
187
|
-
const generatedFiles = new Map();
|
|
188
|
-
generatedFiles.set(path_1.default.join(outputDirectory, '.clang-format'), 'DisableFormat: true\nSortIncludes: false');
|
|
189
|
-
const generateNM2 = (0, GenerateNM2_1.createNM2Generator)({
|
|
190
|
-
namespace: argv.namespace,
|
|
191
|
-
methodonly: argv.methodonly,
|
|
192
|
-
});
|
|
193
|
-
const generatorPropsH = require('react-native-tscodegen/lib/rncodegen/src/generators/components/GeneratePropsH').generate;
|
|
194
|
-
const generatorPropsCPP = require('react-native-tscodegen/lib/rncodegen/src/generators/components/GeneratePropsCPP').generate;
|
|
195
|
-
const generatorShadowNodeH = require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateShadowNodeH').generate;
|
|
196
|
-
const generatorShadowNodeCPP = require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateShadowNodeCPP').generate;
|
|
197
|
-
const generatorComponentDescriptorH = require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateComponentDescriptorH').generate;
|
|
198
|
-
const generatorEventEmitterH = require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateEventEmitterH').generate;
|
|
199
|
-
const generatorEventEmitterCPP = require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateEventEmitterCpp').generate;
|
|
200
|
-
normalizeFileMap(generateNM2(libraryName, schema, moduleSpecName), outputDirectory, generatedFiles);
|
|
201
|
-
if (argv.ts) {
|
|
202
|
-
normalizeFileMap((0, GenerateTypeScript_1.generateTypeScript)(libraryName, schema, moduleSpecName), outputDirectory, generatedFiles);
|
|
203
|
-
}
|
|
204
|
-
if (Object.keys(schema.modules).some(moduleName => schema.modules[moduleName].type === 'Component')) {
|
|
205
|
-
const componentGenerators = [
|
|
206
|
-
generatorPropsH,
|
|
207
|
-
generatorPropsCPP,
|
|
208
|
-
generatorShadowNodeH,
|
|
209
|
-
generatorShadowNodeCPP,
|
|
210
|
-
generatorComponentDescriptorH,
|
|
211
|
-
generatorEventEmitterH,
|
|
212
|
-
generatorEventEmitterCPP,
|
|
213
|
-
];
|
|
214
|
-
componentGenerators.forEach(generator => {
|
|
215
|
-
const generated = generator(libraryName, schema, moduleSpecName);
|
|
216
|
-
normalizeFileMap(generated, componentOutputdir, generatedFiles);
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
if (test === true) {
|
|
220
|
-
return checkFilesForChanges(generatedFiles, outputDirectory);
|
|
221
|
-
}
|
|
222
|
-
return writeMapToFiles(generatedFiles, outputDirectory);
|
|
223
|
-
}
|
|
224
55
|
if ((argv.file && argv.files) || (!argv.file && !argv.files)) {
|
|
225
56
|
console.error('You must specify either --file or --files.');
|
|
226
57
|
process.exit(1);
|
|
227
58
|
}
|
|
228
|
-
|
|
229
|
-
if (argv.file) {
|
|
230
|
-
schema = parseFlowFile(argv.file);
|
|
231
|
-
}
|
|
232
|
-
else {
|
|
233
|
-
schema = combineSchemas(globby_1.default.sync(argv.files));
|
|
234
|
-
}
|
|
235
|
-
const libraryName = argv.libraryName;
|
|
236
|
-
const moduleSpecName = 'moduleSpecName';
|
|
237
|
-
const outputDirectory = argv.outdir;
|
|
238
|
-
generate({ libraryName, schema, outputDirectory, moduleSpecName }, { generators: [], test: false });
|
|
59
|
+
(0, index_1.runCodeGen)(argv);
|
|
239
60
|
//# sourceMappingURL=Cli.js.map
|
package/lib-commonjs/Cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Cli.js","sourceRoot":"","sources":["../src/Cli.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Copyright (c) Microsoft Corporation.\n * Licensed under the MIT License.\n *\n * @format\n */\n\nimport yargs from 'yargs';\nimport path from 'path';\nimport fs from '@react-native-windows/fs';\nimport globby from 'globby';\nimport {createNM2Generator} from './generators/GenerateNM2';\nimport {\n generateTypeScript,\n setOptionalTurboModule,\n} from './generators/GenerateTypeScript';\n// @ts-ignore\nimport {parseFile} from 'react-native-tscodegen/lib/rncodegen/src/parsers/flow';\n// @ts-ignore\nimport schemaValidator from 'react-native-tscodegen/lib/rncodegen/src/schemaValidator';\n\nconst argv = yargs.options({\n file: {\n type: 'string',\n describe: 'file which contains spec',\n },\n files: {\n type: 'array',\n describe: 'glob patterns for files which contains specs',\n },\n ts: {\n type: 'boolean',\n describe: 'generate turbo module definition files in TypeScript',\n default: false,\n },\n methodonly: {\n type: 'boolean',\n describe: 'generate only method metadata in C++ turbo module spec',\n default: false,\n },\n outdir: {\n type: 'string',\n describe: 'output directory',\n default: 'codegen',\n },\n test: {\n type: 'boolean',\n describe: 'Verify that the generated output is unchanged',\n },\n namespace: {\n type: 'string',\n describe: 'C++/C# Namespace to put generated native modules in',\n default: 'MyNamespace',\n },\n libraryName: {\n type: 'string',\n required: true,\n describe: 'Used for part of the path generated within the codegen dir',\n },\n}).argv;\n\nimport {SchemaType} from 'react-native-tscodegen';\n\ninterface Options {\n libraryName: string;\n schema: SchemaType;\n outputDirectory: string;\n moduleSpecName: string;\n}\n\ninterface Config {\n generators: any[] /*Generators[]*/;\n test?: boolean;\n}\n\n/*\nconst GENERATORS = {\n descriptors: [generateComponentDescriptorH.generate],\n events: [\n generateEventEmitterCpp.generate,\n generateEventEmitterH.generate,\n generateModuleHObjCpp.generate,\n generateModuleMm.generate,\n ],\n props: [\n generateComponentHObjCpp.generate,\n generatePropsCpp.generate,\n generatePropsH.generate,\n generatePropsJavaInterface.generate,\n generatePropsJavaDelegate.generate,\n ],\n modules: [generateModuleCpp.generate, generateModuleH.generate],\n tests: [generateTests.generate],\n 'shadow-nodes': [\n generateShadowNodeCpp.generate,\n generateShadowNodeH.generate,\n ],\n};\n*/\n\nfunction normalizeFileMap(\n map: Map<string, string>,\n outputDir: string,\n outMap: Map<string, string>,\n): void {\n for (const [fileName, contents] of map) {\n const location = path.join(outputDir, fileName);\n outMap.set(path.normalize(location), contents);\n }\n}\n\nfunction checkFilesForChanges(\n map: Map<string, string>,\n outputDir: string,\n): boolean {\n let hasChanges = false;\n\n const allExistingFiles = globby\n .sync(`${outputDir}/**`)\n .map(_ => path.normalize(_))\n .sort();\n const allGeneratedFiles = [...map.keys()].map(_ => path.normalize(_)).sort();\n\n if (\n allExistingFiles.length !== allGeneratedFiles.length ||\n !allExistingFiles.every((val, index) => val === allGeneratedFiles[index])\n )\n return true;\n\n for (const [fileName, contents] of map) {\n if (!fs.existsSync(fileName)) {\n hasChanges = true;\n continue;\n }\n\n const currentContents = fs.readFileSync(fileName, 'utf8');\n if (currentContents !== contents) {\n console.error(`- ${fileName} has changed`);\n hasChanges = true;\n continue;\n }\n }\n\n return hasChanges;\n}\n\nfunction writeMapToFiles(map: Map<string, string>, outputDir: string) {\n let success = true;\n\n // This ensures that we delete any generated files from modules that have been deleted\n const allExistingFiles = globby.sync(`${outputDir}/**`);\n allExistingFiles.forEach(existingFile => {\n if (!map.has(path.normalize(existingFile))) {\n fs.unlinkSync(existingFile);\n }\n });\n\n for (const [fileName, contents] of map) {\n try {\n fs.mkdirSync(path.dirname(fileName), {recursive: true});\n\n if (fs.existsSync(fileName)) {\n const currentContents = fs.readFileSync(fileName, 'utf8');\n // Don't update the files if there are no changes as this breaks incremental builds\n if (currentContents === contents) {\n continue;\n }\n }\n\n fs.writeFileSync(fileName, contents);\n } catch (error) {\n success = false;\n console.error(`Failed to write ${fileName} to ${fileName}`, error);\n }\n }\n\n return success;\n}\n\nfunction parseFlowFile(filename: string): SchemaType {\n try {\n const schema = parseFile(filename);\n // there will be at most one turbo module per file\n const moduleName = Object.keys(schema.modules)[0];\n if (moduleName) {\n const spec = schema.modules[moduleName];\n if (spec.type === 'NativeModule') {\n const contents = fs.readFileSync(filename, 'utf8');\n if (contents) {\n // This is a temporary implementation until such information is added to the schema in facebook/react-native\n if (contents.includes('TurboModuleRegistry.get<')) {\n setOptionalTurboModule(spec, true);\n } else if (contents.includes('TurboModuleRegistry.getEnforcing<')) {\n setOptionalTurboModule(spec, false);\n }\n }\n }\n }\n return schema;\n } catch (e) {\n if (e instanceof Error) {\n e.message = `(${filename}): ${e.message}`;\n }\n throw e;\n }\n}\n\nfunction combineSchemas(files: string[]): SchemaType {\n return files.reduce(\n (merged, filename) => {\n const contents = fs.readFileSync(filename, 'utf8');\n if (\n contents &&\n (/export\\s+default\\s+\\(?codegenNativeComponent</.test(contents) ||\n contents.includes('extends TurboModule'))\n ) {\n const schema = parseFlowFile(filename);\n merged.modules = {...merged.modules, ...schema.modules};\n }\n return merged;\n },\n {modules: {}},\n );\n}\n\nfunction generate(\n {libraryName, schema, outputDirectory, moduleSpecName}: Options,\n {/*generators,*/ test}: Config,\n): boolean {\n schemaValidator.validate(schema);\n\n const componentOutputdir = path.join(\n outputDirectory,\n 'react/components',\n libraryName,\n );\n\n const generatedFiles = new Map<string, string>();\n\n generatedFiles.set(\n path.join(outputDirectory, '.clang-format'),\n 'DisableFormat: true\\nSortIncludes: false',\n );\n\n const generateNM2 = createNM2Generator({\n namespace: argv.namespace,\n methodonly: argv.methodonly,\n });\n\n const generatorPropsH =\n require('react-native-tscodegen/lib/rncodegen/src/generators/components/GeneratePropsH').generate;\n const generatorPropsCPP =\n require('react-native-tscodegen/lib/rncodegen/src/generators/components/GeneratePropsCPP').generate;\n const generatorShadowNodeH =\n require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateShadowNodeH').generate;\n const generatorShadowNodeCPP =\n require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateShadowNodeCPP').generate;\n const generatorComponentDescriptorH =\n require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateComponentDescriptorH').generate;\n const generatorEventEmitterH =\n require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateEventEmitterH').generate;\n const generatorEventEmitterCPP =\n require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateEventEmitterCpp').generate;\n\n normalizeFileMap(\n generateNM2(libraryName, schema, moduleSpecName),\n outputDirectory,\n generatedFiles,\n );\n\n if (argv.ts) {\n normalizeFileMap(\n generateTypeScript(libraryName, schema, moduleSpecName),\n outputDirectory,\n generatedFiles,\n );\n }\n\n if (\n Object.keys(schema.modules).some(\n moduleName => schema.modules[moduleName].type === 'Component',\n )\n ) {\n const componentGenerators = [\n generatorPropsH,\n generatorPropsCPP,\n generatorShadowNodeH,\n generatorShadowNodeCPP,\n generatorComponentDescriptorH,\n generatorEventEmitterH,\n generatorEventEmitterCPP,\n ];\n\n componentGenerators.forEach(generator => {\n const generated: Map<string, string> = generator(\n libraryName,\n schema,\n moduleSpecName,\n );\n normalizeFileMap(generated, componentOutputdir, generatedFiles);\n });\n }\n\n if (test === true) {\n return checkFilesForChanges(generatedFiles, outputDirectory);\n }\n\n return writeMapToFiles(generatedFiles, outputDirectory);\n}\n\nif ((argv.file && argv.files) || (!argv.file && !argv.files)) {\n console.error('You must specify either --file or --files.');\n process.exit(1);\n}\n\nlet schema: SchemaType;\nif (argv.file) {\n schema = parseFlowFile(argv.file);\n} else {\n schema = combineSchemas(globby.sync(argv.files as string[]));\n}\n\nconst libraryName = argv.libraryName;\nconst moduleSpecName = 'moduleSpecName';\nconst outputDirectory = argv.outdir;\ngenerate(\n {libraryName, schema, outputDirectory, moduleSpecName},\n {generators: [], test: false},\n);\n"]}
|
|
1
|
+
{"version":3,"file":"Cli.js","sourceRoot":"","sources":["../src/Cli.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;AAEH,kDAA0B;AAC1B,mCAAmC;AAEnC,MAAM,IAAI,GAAG,eAAK,CAAC,OAAO,CAAC;IACzB,IAAI,EAAE;QACJ,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,0BAA0B;KACrC;IACD,KAAK,EAAE;QACL,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,IAAI;QACX,QAAQ,EAAE,8CAA8C;KACzD;IACD,EAAE,EAAE;QACF,IAAI,EAAE,SAAS;QACf,QAAQ,EAAE,sDAAsD;QAChE,OAAO,EAAE,KAAK;KACf;IACD,UAAU,EAAE;QACV,IAAI,EAAE,SAAS;QACf,QAAQ,EAAE,wDAAwD;QAClE,OAAO,EAAE,KAAK;KACf;IACD,MAAM,EAAE;QACN,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,kBAAkB;QAC5B,OAAO,EAAE,SAAS;KACnB;IACD,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,QAAQ,EAAE,+CAA+C;QACzD,OAAO,EAAE,KAAK;KACf;IACD,SAAS,EAAE;QACT,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,qDAAqD;QAC/D,OAAO,EAAE,aAAa;KACvB;IACD,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,IAAI;QACd,QAAQ,EAAE,4DAA4D;KACvE;CACF,CAAC,CAAC,IAAI,CAAC;AAER,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;IAC5D,OAAO,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAC5D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;CACjB;AAED,IAAA,kBAAU,EAAC,IAAI,CAAC,CAAC","sourcesContent":["/**\n * Copyright (c) Microsoft Corporation.\n * Licensed under the MIT License.\n *\n * @format\n */\n\nimport yargs from 'yargs';\nimport {runCodeGen} from './index';\n\nconst argv = yargs.options({\n file: {\n type: 'string',\n describe: 'file which contains spec',\n },\n files: {\n type: 'string',\n array: true,\n describe: 'glob patterns for files which contains specs',\n },\n ts: {\n type: 'boolean',\n describe: 'generate turbo module definition files in TypeScript',\n default: false,\n },\n methodonly: {\n type: 'boolean',\n describe: 'generate only method metadata in C++ turbo module spec',\n default: false,\n },\n outdir: {\n type: 'string',\n describe: 'output directory',\n default: 'codegen',\n },\n test: {\n type: 'boolean',\n describe: 'Verify that the generated output is unchanged',\n default: false,\n },\n namespace: {\n type: 'string',\n describe: 'C++/C# Namespace to put generated native modules in',\n default: 'MyNamespace',\n },\n libraryName: {\n type: 'string',\n required: true,\n describe: 'Used for part of the path generated within the codegen dir',\n },\n}).argv;\n\nif ((argv.file && argv.files) || (!argv.file && !argv.files)) {\n console.error('You must specify either --file or --files.');\n process.exit(1);\n}\n\nrunCodeGen(argv);\n"]}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Microsoft Corporation.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*
|
|
5
|
+
* @format
|
|
6
|
+
*/
|
|
7
|
+
import { SchemaType } from 'react-native-tscodegen';
|
|
8
|
+
interface Options {
|
|
9
|
+
libraryName: string;
|
|
10
|
+
schema: SchemaType;
|
|
11
|
+
outputDirectory: string;
|
|
12
|
+
moduleSpecName: string;
|
|
13
|
+
namespace: string;
|
|
14
|
+
methodonly: boolean;
|
|
15
|
+
ts: boolean;
|
|
16
|
+
}
|
|
17
|
+
interface Config {
|
|
18
|
+
generators: any[];
|
|
19
|
+
test?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export declare function parseFlowFile(filename: string): SchemaType;
|
|
22
|
+
export declare function combineSchemas(files: string[]): SchemaType;
|
|
23
|
+
export declare function generate({ libraryName, schema, outputDirectory, moduleSpecName, namespace, methodonly, ts, }: Options, { /*generators,*/ test }: Config): boolean;
|
|
24
|
+
export declare type CodeGenOptions = {
|
|
25
|
+
file?: string;
|
|
26
|
+
files?: string[];
|
|
27
|
+
libraryName: string;
|
|
28
|
+
outdir: string;
|
|
29
|
+
namespace: string;
|
|
30
|
+
methodonly: boolean;
|
|
31
|
+
ts: boolean;
|
|
32
|
+
test: boolean;
|
|
33
|
+
};
|
|
34
|
+
export declare function runCodeGen(options: CodeGenOptions): boolean;
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Microsoft Corporation.
|
|
4
|
+
* Licensed under the MIT License.
|
|
5
|
+
*
|
|
6
|
+
* @format
|
|
7
|
+
*/
|
|
8
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.runCodeGen = exports.generate = exports.combineSchemas = exports.parseFlowFile = void 0;
|
|
13
|
+
const path_1 = __importDefault(require("path"));
|
|
14
|
+
const fs_1 = __importDefault(require("@react-native-windows/fs"));
|
|
15
|
+
const globby_1 = __importDefault(require("globby"));
|
|
16
|
+
const GenerateNM2_1 = require("./generators/GenerateNM2");
|
|
17
|
+
const GenerateTypeScript_1 = require("./generators/GenerateTypeScript");
|
|
18
|
+
// @ts-ignore
|
|
19
|
+
const flow_1 = require("react-native-tscodegen/lib/rncodegen/src/parsers/flow");
|
|
20
|
+
// @ts-ignore
|
|
21
|
+
const schemaValidator_1 = __importDefault(require("react-native-tscodegen/lib/rncodegen/src/schemaValidator"));
|
|
22
|
+
function normalizeFileMap(map, outputDir, outMap) {
|
|
23
|
+
for (const [fileName, contents] of map) {
|
|
24
|
+
const location = path_1.default.join(outputDir, fileName);
|
|
25
|
+
outMap.set(path_1.default.normalize(location), contents);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function checkFilesForChanges(map, outputDir) {
|
|
29
|
+
let hasChanges = false;
|
|
30
|
+
const allExistingFiles = globby_1.default
|
|
31
|
+
.sync(`${outputDir}/**`)
|
|
32
|
+
.map(_ => path_1.default.normalize(_))
|
|
33
|
+
.sort();
|
|
34
|
+
const allGeneratedFiles = [...map.keys()].map(_ => path_1.default.normalize(_)).sort();
|
|
35
|
+
if (allExistingFiles.length !== allGeneratedFiles.length ||
|
|
36
|
+
!allExistingFiles.every((val, index) => val === allGeneratedFiles[index]))
|
|
37
|
+
return true;
|
|
38
|
+
for (const [fileName, contents] of map) {
|
|
39
|
+
if (!fs_1.default.existsSync(fileName)) {
|
|
40
|
+
hasChanges = true;
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
const currentContents = fs_1.default.readFileSync(fileName, 'utf8');
|
|
44
|
+
if (currentContents !== contents) {
|
|
45
|
+
console.log(`- ${fileName} has changed`);
|
|
46
|
+
hasChanges = true;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return hasChanges;
|
|
51
|
+
}
|
|
52
|
+
function writeMapToFiles(map, outputDir) {
|
|
53
|
+
let success = true;
|
|
54
|
+
// This ensures that we delete any generated files from modules that have been deleted
|
|
55
|
+
const allExistingFiles = globby_1.default.sync(`${outputDir}/**`);
|
|
56
|
+
allExistingFiles.forEach(existingFile => {
|
|
57
|
+
if (!map.has(path_1.default.normalize(existingFile))) {
|
|
58
|
+
fs_1.default.unlinkSync(existingFile);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
for (const [fileName, contents] of map) {
|
|
62
|
+
try {
|
|
63
|
+
fs_1.default.mkdirSync(path_1.default.dirname(fileName), { recursive: true });
|
|
64
|
+
if (fs_1.default.existsSync(fileName)) {
|
|
65
|
+
const currentContents = fs_1.default.readFileSync(fileName, 'utf8');
|
|
66
|
+
// Don't update the files if there are no changes as this breaks incremental builds
|
|
67
|
+
if (currentContents === contents) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
fs_1.default.writeFileSync(fileName, contents);
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
success = false;
|
|
75
|
+
console.error(`Failed to write ${fileName} to ${fileName}`, error);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return success;
|
|
79
|
+
}
|
|
80
|
+
function parseFlowFile(filename) {
|
|
81
|
+
try {
|
|
82
|
+
const schema = (0, flow_1.parseFile)(filename);
|
|
83
|
+
// there will be at most one turbo module per file
|
|
84
|
+
const moduleName = Object.keys(schema.modules)[0];
|
|
85
|
+
if (moduleName) {
|
|
86
|
+
const spec = schema.modules[moduleName];
|
|
87
|
+
if (spec.type === 'NativeModule') {
|
|
88
|
+
const contents = fs_1.default.readFileSync(filename, 'utf8');
|
|
89
|
+
if (contents) {
|
|
90
|
+
// This is a temporary implementation until such information is added to the schema in facebook/react-native
|
|
91
|
+
if (contents.includes('TurboModuleRegistry.get<')) {
|
|
92
|
+
(0, GenerateTypeScript_1.setOptionalTurboModule)(spec, true);
|
|
93
|
+
}
|
|
94
|
+
else if (contents.includes('TurboModuleRegistry.getEnforcing<')) {
|
|
95
|
+
(0, GenerateTypeScript_1.setOptionalTurboModule)(spec, false);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return schema;
|
|
101
|
+
}
|
|
102
|
+
catch (e) {
|
|
103
|
+
if (e instanceof Error) {
|
|
104
|
+
e.message = `(${filename}): ${e.message}`;
|
|
105
|
+
}
|
|
106
|
+
throw e;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
exports.parseFlowFile = parseFlowFile;
|
|
110
|
+
function combineSchemas(files) {
|
|
111
|
+
return files.reduce((merged, filename) => {
|
|
112
|
+
const contents = fs_1.default.readFileSync(filename, 'utf8');
|
|
113
|
+
if (contents &&
|
|
114
|
+
(/export\s+default\s+\(?codegenNativeComponent</.test(contents) ||
|
|
115
|
+
contents.includes('extends TurboModule'))) {
|
|
116
|
+
const schema = parseFlowFile(filename);
|
|
117
|
+
merged.modules = { ...merged.modules, ...schema.modules };
|
|
118
|
+
}
|
|
119
|
+
return merged;
|
|
120
|
+
}, { modules: {} });
|
|
121
|
+
}
|
|
122
|
+
exports.combineSchemas = combineSchemas;
|
|
123
|
+
function generate({ libraryName, schema, outputDirectory, moduleSpecName, namespace, methodonly, ts, }, { /*generators,*/ test }) {
|
|
124
|
+
schemaValidator_1.default.validate(schema);
|
|
125
|
+
const componentOutputdir = path_1.default.join(outputDirectory, 'react/components', libraryName);
|
|
126
|
+
const generatedFiles = new Map();
|
|
127
|
+
generatedFiles.set(path_1.default.join(outputDirectory, '.clang-format'), 'DisableFormat: true\nSortIncludes: false');
|
|
128
|
+
const generateNM2 = (0, GenerateNM2_1.createNM2Generator)({
|
|
129
|
+
namespace,
|
|
130
|
+
methodonly,
|
|
131
|
+
});
|
|
132
|
+
const generatorPropsH = require('react-native-tscodegen/lib/rncodegen/src/generators/components/GeneratePropsH').generate;
|
|
133
|
+
const generatorPropsCPP = require('react-native-tscodegen/lib/rncodegen/src/generators/components/GeneratePropsCPP').generate;
|
|
134
|
+
const generatorShadowNodeH = require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateShadowNodeH').generate;
|
|
135
|
+
const generatorShadowNodeCPP = require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateShadowNodeCPP').generate;
|
|
136
|
+
const generatorComponentDescriptorH = require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateComponentDescriptorH').generate;
|
|
137
|
+
const generatorEventEmitterH = require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateEventEmitterH').generate;
|
|
138
|
+
const generatorEventEmitterCPP = require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateEventEmitterCpp').generate;
|
|
139
|
+
normalizeFileMap(generateNM2(libraryName, schema, moduleSpecName), outputDirectory, generatedFiles);
|
|
140
|
+
if (ts) {
|
|
141
|
+
normalizeFileMap((0, GenerateTypeScript_1.generateTypeScript)(libraryName, schema, moduleSpecName), outputDirectory, generatedFiles);
|
|
142
|
+
}
|
|
143
|
+
if (Object.keys(schema.modules).some(moduleName => schema.modules[moduleName].type === 'Component')) {
|
|
144
|
+
const componentGenerators = [
|
|
145
|
+
generatorPropsH,
|
|
146
|
+
generatorPropsCPP,
|
|
147
|
+
generatorShadowNodeH,
|
|
148
|
+
generatorShadowNodeCPP,
|
|
149
|
+
generatorComponentDescriptorH,
|
|
150
|
+
generatorEventEmitterH,
|
|
151
|
+
generatorEventEmitterCPP,
|
|
152
|
+
];
|
|
153
|
+
componentGenerators.forEach(generator => {
|
|
154
|
+
const generated = generator(libraryName, schema, moduleSpecName);
|
|
155
|
+
normalizeFileMap(generated, componentOutputdir, generatedFiles);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
if (test === true) {
|
|
159
|
+
return checkFilesForChanges(generatedFiles, outputDirectory);
|
|
160
|
+
}
|
|
161
|
+
return writeMapToFiles(generatedFiles, outputDirectory);
|
|
162
|
+
}
|
|
163
|
+
exports.generate = generate;
|
|
164
|
+
function runCodeGen(options) {
|
|
165
|
+
if (!options.file && !options.files)
|
|
166
|
+
throw new Error('Must specify file or files option');
|
|
167
|
+
const schema = options.file
|
|
168
|
+
? parseFlowFile(options.file)
|
|
169
|
+
: combineSchemas(globby_1.default.sync(options.files));
|
|
170
|
+
const libraryName = options.libraryName;
|
|
171
|
+
const moduleSpecName = 'moduleSpecName';
|
|
172
|
+
const outputDirectory = options.outdir;
|
|
173
|
+
const { namespace, methodonly, ts } = options;
|
|
174
|
+
return generate({
|
|
175
|
+
libraryName,
|
|
176
|
+
schema,
|
|
177
|
+
outputDirectory,
|
|
178
|
+
moduleSpecName,
|
|
179
|
+
namespace,
|
|
180
|
+
methodonly,
|
|
181
|
+
ts,
|
|
182
|
+
}, { generators: [], test: options.test });
|
|
183
|
+
}
|
|
184
|
+
exports.runCodeGen = runCodeGen;
|
|
185
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Copyright (c) Microsoft Corporation.\n * Licensed under the MIT License.\n *\n * @format\n */\n\nimport path from 'path';\nimport fs from '@react-native-windows/fs';\nimport globby from 'globby';\nimport {createNM2Generator} from './generators/GenerateNM2';\nimport {\n generateTypeScript,\n setOptionalTurboModule,\n} from './generators/GenerateTypeScript';\nimport {SchemaType} from 'react-native-tscodegen';\n// @ts-ignore\nimport {parseFile} from 'react-native-tscodegen/lib/rncodegen/src/parsers/flow';\n// @ts-ignore\nimport schemaValidator from 'react-native-tscodegen/lib/rncodegen/src/schemaValidator';\n\ninterface Options {\n libraryName: string;\n schema: SchemaType;\n outputDirectory: string;\n moduleSpecName: string;\n namespace: string;\n methodonly: boolean;\n ts: boolean;\n}\n\ninterface Config {\n generators: any[] /*Generators[]*/;\n test?: boolean;\n}\n\nfunction normalizeFileMap(\n map: Map<string, string>,\n outputDir: string,\n outMap: Map<string, string>,\n): void {\n for (const [fileName, contents] of map) {\n const location = path.join(outputDir, fileName);\n outMap.set(path.normalize(location), contents);\n }\n}\n\nfunction checkFilesForChanges(\n map: Map<string, string>,\n outputDir: string,\n): boolean {\n let hasChanges = false;\n\n const allExistingFiles = globby\n .sync(`${outputDir}/**`)\n .map(_ => path.normalize(_))\n .sort();\n const allGeneratedFiles = [...map.keys()].map(_ => path.normalize(_)).sort();\n\n if (\n allExistingFiles.length !== allGeneratedFiles.length ||\n !allExistingFiles.every((val, index) => val === allGeneratedFiles[index])\n )\n return true;\n\n for (const [fileName, contents] of map) {\n if (!fs.existsSync(fileName)) {\n hasChanges = true;\n continue;\n }\n\n const currentContents = fs.readFileSync(fileName, 'utf8');\n if (currentContents !== contents) {\n console.log(`- ${fileName} has changed`);\n hasChanges = true;\n continue;\n }\n }\n\n return hasChanges;\n}\n\nfunction writeMapToFiles(map: Map<string, string>, outputDir: string) {\n let success = true;\n\n // This ensures that we delete any generated files from modules that have been deleted\n const allExistingFiles = globby.sync(`${outputDir}/**`);\n allExistingFiles.forEach(existingFile => {\n if (!map.has(path.normalize(existingFile))) {\n fs.unlinkSync(existingFile);\n }\n });\n\n for (const [fileName, contents] of map) {\n try {\n fs.mkdirSync(path.dirname(fileName), {recursive: true});\n\n if (fs.existsSync(fileName)) {\n const currentContents = fs.readFileSync(fileName, 'utf8');\n // Don't update the files if there are no changes as this breaks incremental builds\n if (currentContents === contents) {\n continue;\n }\n }\n\n fs.writeFileSync(fileName, contents);\n } catch (error) {\n success = false;\n console.error(`Failed to write ${fileName} to ${fileName}`, error);\n }\n }\n\n return success;\n}\n\nexport function parseFlowFile(filename: string): SchemaType {\n try {\n const schema = parseFile(filename);\n // there will be at most one turbo module per file\n const moduleName = Object.keys(schema.modules)[0];\n if (moduleName) {\n const spec = schema.modules[moduleName];\n if (spec.type === 'NativeModule') {\n const contents = fs.readFileSync(filename, 'utf8');\n if (contents) {\n // This is a temporary implementation until such information is added to the schema in facebook/react-native\n if (contents.includes('TurboModuleRegistry.get<')) {\n setOptionalTurboModule(spec, true);\n } else if (contents.includes('TurboModuleRegistry.getEnforcing<')) {\n setOptionalTurboModule(spec, false);\n }\n }\n }\n }\n return schema;\n } catch (e) {\n if (e instanceof Error) {\n e.message = `(${filename}): ${e.message}`;\n }\n throw e;\n }\n}\n\nexport function combineSchemas(files: string[]): SchemaType {\n return files.reduce(\n (merged, filename) => {\n const contents = fs.readFileSync(filename, 'utf8');\n if (\n contents &&\n (/export\\s+default\\s+\\(?codegenNativeComponent</.test(contents) ||\n contents.includes('extends TurboModule'))\n ) {\n const schema = parseFlowFile(filename);\n merged.modules = {...merged.modules, ...schema.modules};\n }\n return merged;\n },\n {modules: {}},\n );\n}\n\nexport function generate(\n {\n libraryName,\n schema,\n outputDirectory,\n moduleSpecName,\n namespace,\n methodonly,\n ts,\n }: Options,\n {/*generators,*/ test}: Config,\n): boolean {\n schemaValidator.validate(schema);\n\n const componentOutputdir = path.join(\n outputDirectory,\n 'react/components',\n libraryName,\n );\n\n const generatedFiles = new Map<string, string>();\n\n generatedFiles.set(\n path.join(outputDirectory, '.clang-format'),\n 'DisableFormat: true\\nSortIncludes: false',\n );\n\n const generateNM2 = createNM2Generator({\n namespace,\n methodonly,\n });\n\n const generatorPropsH =\n require('react-native-tscodegen/lib/rncodegen/src/generators/components/GeneratePropsH').generate;\n const generatorPropsCPP =\n require('react-native-tscodegen/lib/rncodegen/src/generators/components/GeneratePropsCPP').generate;\n const generatorShadowNodeH =\n require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateShadowNodeH').generate;\n const generatorShadowNodeCPP =\n require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateShadowNodeCPP').generate;\n const generatorComponentDescriptorH =\n require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateComponentDescriptorH').generate;\n const generatorEventEmitterH =\n require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateEventEmitterH').generate;\n const generatorEventEmitterCPP =\n require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateEventEmitterCpp').generate;\n\n normalizeFileMap(\n generateNM2(libraryName, schema, moduleSpecName),\n outputDirectory,\n generatedFiles,\n );\n\n if (ts) {\n normalizeFileMap(\n generateTypeScript(libraryName, schema, moduleSpecName),\n outputDirectory,\n generatedFiles,\n );\n }\n\n if (\n Object.keys(schema.modules).some(\n moduleName => schema.modules[moduleName].type === 'Component',\n )\n ) {\n const componentGenerators = [\n generatorPropsH,\n generatorPropsCPP,\n generatorShadowNodeH,\n generatorShadowNodeCPP,\n generatorComponentDescriptorH,\n generatorEventEmitterH,\n generatorEventEmitterCPP,\n ];\n\n componentGenerators.forEach(generator => {\n const generated: Map<string, string> = generator(\n libraryName,\n schema,\n moduleSpecName,\n );\n normalizeFileMap(generated, componentOutputdir, generatedFiles);\n });\n }\n\n if (test === true) {\n return checkFilesForChanges(generatedFiles, outputDirectory);\n }\n\n return writeMapToFiles(generatedFiles, outputDirectory);\n}\n\nexport type CodeGenOptions = {\n file?: string;\n files?: string[];\n libraryName: string;\n outdir: string;\n namespace: string;\n methodonly: boolean;\n ts: boolean;\n test: boolean;\n};\n\nexport function runCodeGen(options: CodeGenOptions): boolean {\n if (!options.file && !options.files)\n throw new Error('Must specify file or files option');\n\n const schema = options.file\n ? parseFlowFile(options.file)\n : combineSchemas(globby.sync(options.files!));\n\n const libraryName = options.libraryName;\n const moduleSpecName = 'moduleSpecName';\n const outputDirectory = options.outdir;\n const {namespace, methodonly, ts} = options;\n return generate(\n {\n libraryName,\n schema,\n outputDirectory,\n moduleSpecName,\n namespace,\n methodonly,\n ts,\n },\n {generators: [], test: options.test},\n );\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-native-windows/codegen",
|
|
3
|
-
"version": "0.0.0-canary.
|
|
3
|
+
"version": "0.0.0-canary.36",
|
|
4
4
|
"description": "Generators for react-native-codegen targeting react-native-windows",
|
|
5
|
-
"main": "index.js",
|
|
5
|
+
"main": "lib-commonjs/index.js",
|
|
6
6
|
"repository": "https://github.com/microsoft/react-native-windows",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"private": false,
|
package/src/Cli.ts
CHANGED
|
@@ -6,18 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import yargs from 'yargs';
|
|
9
|
-
import
|
|
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,7 +14,8 @@ const argv = yargs.options({
|
|
|
25
14
|
describe: 'file which contains spec',
|
|
26
15
|
},
|
|
27
16
|
files: {
|
|
28
|
-
type: '
|
|
17
|
+
type: 'string',
|
|
18
|
+
array: true,
|
|
29
19
|
describe: 'glob patterns for files which contains specs',
|
|
30
20
|
},
|
|
31
21
|
ts: {
|
|
@@ -46,6 +36,7 @@ const argv = yargs.options({
|
|
|
46
36
|
test: {
|
|
47
37
|
type: 'boolean',
|
|
48
38
|
describe: 'Verify that the generated output is unchanged',
|
|
39
|
+
default: false,
|
|
49
40
|
},
|
|
50
41
|
namespace: {
|
|
51
42
|
type: 'string',
|
|
@@ -59,271 +50,9 @@ const argv = yargs.options({
|
|
|
59
50
|
},
|
|
60
51
|
}).argv;
|
|
61
52
|
|
|
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
53
|
if ((argv.file && argv.files) || (!argv.file && !argv.files)) {
|
|
312
54
|
console.error('You must specify either --file or --files.');
|
|
313
55
|
process.exit(1);
|
|
314
56
|
}
|
|
315
57
|
|
|
316
|
-
|
|
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
|
-
);
|
|
58
|
+
runCodeGen(argv);
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Microsoft Corporation.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*
|
|
5
|
+
* @format
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import fs from '@react-native-windows/fs';
|
|
10
|
+
import globby from 'globby';
|
|
11
|
+
import {createNM2Generator} from './generators/GenerateNM2';
|
|
12
|
+
import {
|
|
13
|
+
generateTypeScript,
|
|
14
|
+
setOptionalTurboModule,
|
|
15
|
+
} from './generators/GenerateTypeScript';
|
|
16
|
+
import {SchemaType} from 'react-native-tscodegen';
|
|
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';
|
|
21
|
+
|
|
22
|
+
interface Options {
|
|
23
|
+
libraryName: string;
|
|
24
|
+
schema: SchemaType;
|
|
25
|
+
outputDirectory: string;
|
|
26
|
+
moduleSpecName: string;
|
|
27
|
+
namespace: string;
|
|
28
|
+
methodonly: boolean;
|
|
29
|
+
ts: boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface Config {
|
|
33
|
+
generators: any[] /*Generators[]*/;
|
|
34
|
+
test?: boolean;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function normalizeFileMap(
|
|
38
|
+
map: Map<string, string>,
|
|
39
|
+
outputDir: string,
|
|
40
|
+
outMap: Map<string, string>,
|
|
41
|
+
): void {
|
|
42
|
+
for (const [fileName, contents] of map) {
|
|
43
|
+
const location = path.join(outputDir, fileName);
|
|
44
|
+
outMap.set(path.normalize(location), contents);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function checkFilesForChanges(
|
|
49
|
+
map: Map<string, string>,
|
|
50
|
+
outputDir: string,
|
|
51
|
+
): boolean {
|
|
52
|
+
let hasChanges = false;
|
|
53
|
+
|
|
54
|
+
const allExistingFiles = globby
|
|
55
|
+
.sync(`${outputDir}/**`)
|
|
56
|
+
.map(_ => path.normalize(_))
|
|
57
|
+
.sort();
|
|
58
|
+
const allGeneratedFiles = [...map.keys()].map(_ => path.normalize(_)).sort();
|
|
59
|
+
|
|
60
|
+
if (
|
|
61
|
+
allExistingFiles.length !== allGeneratedFiles.length ||
|
|
62
|
+
!allExistingFiles.every((val, index) => val === allGeneratedFiles[index])
|
|
63
|
+
)
|
|
64
|
+
return true;
|
|
65
|
+
|
|
66
|
+
for (const [fileName, contents] of map) {
|
|
67
|
+
if (!fs.existsSync(fileName)) {
|
|
68
|
+
hasChanges = true;
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const currentContents = fs.readFileSync(fileName, 'utf8');
|
|
73
|
+
if (currentContents !== contents) {
|
|
74
|
+
console.log(`- ${fileName} has changed`);
|
|
75
|
+
hasChanges = true;
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return hasChanges;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function writeMapToFiles(map: Map<string, string>, outputDir: string) {
|
|
84
|
+
let success = true;
|
|
85
|
+
|
|
86
|
+
// This ensures that we delete any generated files from modules that have been deleted
|
|
87
|
+
const allExistingFiles = globby.sync(`${outputDir}/**`);
|
|
88
|
+
allExistingFiles.forEach(existingFile => {
|
|
89
|
+
if (!map.has(path.normalize(existingFile))) {
|
|
90
|
+
fs.unlinkSync(existingFile);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
for (const [fileName, contents] of map) {
|
|
95
|
+
try {
|
|
96
|
+
fs.mkdirSync(path.dirname(fileName), {recursive: true});
|
|
97
|
+
|
|
98
|
+
if (fs.existsSync(fileName)) {
|
|
99
|
+
const currentContents = fs.readFileSync(fileName, 'utf8');
|
|
100
|
+
// Don't update the files if there are no changes as this breaks incremental builds
|
|
101
|
+
if (currentContents === contents) {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
fs.writeFileSync(fileName, contents);
|
|
107
|
+
} catch (error) {
|
|
108
|
+
success = false;
|
|
109
|
+
console.error(`Failed to write ${fileName} to ${fileName}`, error);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return success;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function parseFlowFile(filename: string): SchemaType {
|
|
117
|
+
try {
|
|
118
|
+
const schema = parseFile(filename);
|
|
119
|
+
// there will be at most one turbo module per file
|
|
120
|
+
const moduleName = Object.keys(schema.modules)[0];
|
|
121
|
+
if (moduleName) {
|
|
122
|
+
const spec = schema.modules[moduleName];
|
|
123
|
+
if (spec.type === 'NativeModule') {
|
|
124
|
+
const contents = fs.readFileSync(filename, 'utf8');
|
|
125
|
+
if (contents) {
|
|
126
|
+
// This is a temporary implementation until such information is added to the schema in facebook/react-native
|
|
127
|
+
if (contents.includes('TurboModuleRegistry.get<')) {
|
|
128
|
+
setOptionalTurboModule(spec, true);
|
|
129
|
+
} else if (contents.includes('TurboModuleRegistry.getEnforcing<')) {
|
|
130
|
+
setOptionalTurboModule(spec, false);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return schema;
|
|
136
|
+
} catch (e) {
|
|
137
|
+
if (e instanceof Error) {
|
|
138
|
+
e.message = `(${filename}): ${e.message}`;
|
|
139
|
+
}
|
|
140
|
+
throw e;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function combineSchemas(files: string[]): SchemaType {
|
|
145
|
+
return files.reduce(
|
|
146
|
+
(merged, filename) => {
|
|
147
|
+
const contents = fs.readFileSync(filename, 'utf8');
|
|
148
|
+
if (
|
|
149
|
+
contents &&
|
|
150
|
+
(/export\s+default\s+\(?codegenNativeComponent</.test(contents) ||
|
|
151
|
+
contents.includes('extends TurboModule'))
|
|
152
|
+
) {
|
|
153
|
+
const schema = parseFlowFile(filename);
|
|
154
|
+
merged.modules = {...merged.modules, ...schema.modules};
|
|
155
|
+
}
|
|
156
|
+
return merged;
|
|
157
|
+
},
|
|
158
|
+
{modules: {}},
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export function generate(
|
|
163
|
+
{
|
|
164
|
+
libraryName,
|
|
165
|
+
schema,
|
|
166
|
+
outputDirectory,
|
|
167
|
+
moduleSpecName,
|
|
168
|
+
namespace,
|
|
169
|
+
methodonly,
|
|
170
|
+
ts,
|
|
171
|
+
}: Options,
|
|
172
|
+
{/*generators,*/ test}: Config,
|
|
173
|
+
): boolean {
|
|
174
|
+
schemaValidator.validate(schema);
|
|
175
|
+
|
|
176
|
+
const componentOutputdir = path.join(
|
|
177
|
+
outputDirectory,
|
|
178
|
+
'react/components',
|
|
179
|
+
libraryName,
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
const generatedFiles = new Map<string, string>();
|
|
183
|
+
|
|
184
|
+
generatedFiles.set(
|
|
185
|
+
path.join(outputDirectory, '.clang-format'),
|
|
186
|
+
'DisableFormat: true\nSortIncludes: false',
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
const generateNM2 = createNM2Generator({
|
|
190
|
+
namespace,
|
|
191
|
+
methodonly,
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
const generatorPropsH =
|
|
195
|
+
require('react-native-tscodegen/lib/rncodegen/src/generators/components/GeneratePropsH').generate;
|
|
196
|
+
const generatorPropsCPP =
|
|
197
|
+
require('react-native-tscodegen/lib/rncodegen/src/generators/components/GeneratePropsCPP').generate;
|
|
198
|
+
const generatorShadowNodeH =
|
|
199
|
+
require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateShadowNodeH').generate;
|
|
200
|
+
const generatorShadowNodeCPP =
|
|
201
|
+
require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateShadowNodeCPP').generate;
|
|
202
|
+
const generatorComponentDescriptorH =
|
|
203
|
+
require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateComponentDescriptorH').generate;
|
|
204
|
+
const generatorEventEmitterH =
|
|
205
|
+
require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateEventEmitterH').generate;
|
|
206
|
+
const generatorEventEmitterCPP =
|
|
207
|
+
require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateEventEmitterCpp').generate;
|
|
208
|
+
|
|
209
|
+
normalizeFileMap(
|
|
210
|
+
generateNM2(libraryName, schema, moduleSpecName),
|
|
211
|
+
outputDirectory,
|
|
212
|
+
generatedFiles,
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
if (ts) {
|
|
216
|
+
normalizeFileMap(
|
|
217
|
+
generateTypeScript(libraryName, schema, moduleSpecName),
|
|
218
|
+
outputDirectory,
|
|
219
|
+
generatedFiles,
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (
|
|
224
|
+
Object.keys(schema.modules).some(
|
|
225
|
+
moduleName => schema.modules[moduleName].type === 'Component',
|
|
226
|
+
)
|
|
227
|
+
) {
|
|
228
|
+
const componentGenerators = [
|
|
229
|
+
generatorPropsH,
|
|
230
|
+
generatorPropsCPP,
|
|
231
|
+
generatorShadowNodeH,
|
|
232
|
+
generatorShadowNodeCPP,
|
|
233
|
+
generatorComponentDescriptorH,
|
|
234
|
+
generatorEventEmitterH,
|
|
235
|
+
generatorEventEmitterCPP,
|
|
236
|
+
];
|
|
237
|
+
|
|
238
|
+
componentGenerators.forEach(generator => {
|
|
239
|
+
const generated: Map<string, string> = generator(
|
|
240
|
+
libraryName,
|
|
241
|
+
schema,
|
|
242
|
+
moduleSpecName,
|
|
243
|
+
);
|
|
244
|
+
normalizeFileMap(generated, componentOutputdir, generatedFiles);
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (test === true) {
|
|
249
|
+
return checkFilesForChanges(generatedFiles, outputDirectory);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return writeMapToFiles(generatedFiles, outputDirectory);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
export type CodeGenOptions = {
|
|
256
|
+
file?: string;
|
|
257
|
+
files?: string[];
|
|
258
|
+
libraryName: string;
|
|
259
|
+
outdir: string;
|
|
260
|
+
namespace: string;
|
|
261
|
+
methodonly: boolean;
|
|
262
|
+
ts: boolean;
|
|
263
|
+
test: boolean;
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
export function runCodeGen(options: CodeGenOptions): boolean {
|
|
267
|
+
if (!options.file && !options.files)
|
|
268
|
+
throw new Error('Must specify file or files option');
|
|
269
|
+
|
|
270
|
+
const schema = options.file
|
|
271
|
+
? parseFlowFile(options.file)
|
|
272
|
+
: combineSchemas(globby.sync(options.files!));
|
|
273
|
+
|
|
274
|
+
const libraryName = options.libraryName;
|
|
275
|
+
const moduleSpecName = 'moduleSpecName';
|
|
276
|
+
const outputDirectory = options.outdir;
|
|
277
|
+
const {namespace, methodonly, ts} = options;
|
|
278
|
+
return generate(
|
|
279
|
+
{
|
|
280
|
+
libraryName,
|
|
281
|
+
schema,
|
|
282
|
+
outputDirectory,
|
|
283
|
+
moduleSpecName,
|
|
284
|
+
namespace,
|
|
285
|
+
methodonly,
|
|
286
|
+
ts,
|
|
287
|
+
},
|
|
288
|
+
{generators: [], test: options.test},
|
|
289
|
+
);
|
|
290
|
+
}
|