@react-native-windows/codegen 0.0.0-canary.13 → 0.0.0-canary.131
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 +1135 -16
- package/README.md +1 -1
- package/bin.js +0 -0
- package/lib-commonjs/Cli.d.ts +7 -0
- package/lib-commonjs/Cli.js +103 -0
- package/lib-commonjs/Cli.js.map +1 -0
- package/lib-commonjs/generators/AliasGen.d.ts +12 -0
- package/lib-commonjs/generators/AliasGen.js +115 -0
- package/lib-commonjs/generators/AliasGen.js.map +1 -0
- package/lib-commonjs/generators/AliasManaging.d.ts +15 -0
- package/lib-commonjs/generators/AliasManaging.js +49 -0
- package/lib-commonjs/generators/AliasManaging.js.map +1 -0
- package/lib-commonjs/generators/GenerateComponentWindows.d.ts +13 -0
- package/lib-commonjs/generators/GenerateComponentWindows.js +468 -0
- package/lib-commonjs/generators/GenerateComponentWindows.js.map +1 -0
- package/lib-commonjs/generators/GenerateNM2.d.ts +15 -0
- package/lib-commonjs/generators/GenerateNM2.js +145 -0
- package/lib-commonjs/generators/GenerateNM2.js.map +1 -0
- package/lib-commonjs/generators/GenerateTypeScript.d.ts +11 -0
- package/lib-commonjs/generators/GenerateTypeScript.js +165 -0
- package/lib-commonjs/generators/GenerateTypeScript.js.map +1 -0
- package/lib-commonjs/generators/ObjectTypes.d.ts +13 -0
- package/lib-commonjs/generators/ObjectTypes.js +81 -0
- package/lib-commonjs/generators/ObjectTypes.js.map +1 -0
- package/lib-commonjs/generators/ParamTypes.d.ts +13 -0
- package/lib-commonjs/generators/ParamTypes.js +183 -0
- package/lib-commonjs/generators/ParamTypes.js.map +1 -0
- package/lib-commonjs/generators/PropObjectTypes.d.ts +18 -0
- package/lib-commonjs/generators/PropObjectTypes.js +208 -0
- package/lib-commonjs/generators/PropObjectTypes.js.map +1 -0
- package/lib-commonjs/generators/ReturnTypes.d.ts +10 -0
- package/lib-commonjs/generators/ReturnTypes.js +29 -0
- package/lib-commonjs/generators/ReturnTypes.js.map +1 -0
- package/lib-commonjs/generators/ValidateConstants.d.ts +8 -0
- package/lib-commonjs/generators/ValidateConstants.js +38 -0
- package/lib-commonjs/generators/ValidateConstants.js.map +1 -0
- package/lib-commonjs/generators/ValidateMethods.d.ts +14 -0
- package/lib-commonjs/generators/ValidateMethods.js +112 -0
- package/lib-commonjs/generators/ValidateMethods.js.map +1 -0
- package/lib-commonjs/index.d.ts +39 -0
- package/lib-commonjs/index.js +227 -0
- package/lib-commonjs/index.js.map +1 -0
- package/package.json +39 -21
- package/src/Cli.ts +69 -232
- package/src/generators/AliasGen.ts +195 -0
- package/src/generators/AliasManaging.ts +75 -0
- package/src/generators/GenerateComponentWindows.ts +616 -0
- package/src/generators/GenerateNM2.ts +128 -131
- package/src/generators/GenerateTypeScript.ts +250 -0
- package/src/generators/ObjectTypes.ts +95 -37
- package/src/generators/ParamTypes.ts +309 -53
- package/src/generators/PropObjectTypes.ts +223 -0
- package/src/generators/ReturnTypes.ts +38 -40
- package/src/generators/ValidateConstants.ts +50 -0
- package/src/generators/ValidateMethods.ts +270 -0
- package/src/index.ts +412 -0
- package/.eslintrc.js +0 -4
- package/.vscode/launch.json +0 -23
- package/CHANGELOG.json +0 -726
- package/jest.config.js +0 -1
- package/tsconfig.json +0 -5
|
@@ -6,23 +6,18 @@
|
|
|
6
6
|
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
} from '
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
translateObjectBody,
|
|
18
|
-
} from './ObjectTypes';
|
|
19
|
-
import {translateArgs, translateSpecArgs} from './ParamTypes';
|
|
20
|
-
import {translateImplReturnType, translateSpecReturnType} from './ReturnTypes';
|
|
9
|
+
import type {SchemaType} from '@react-native/codegen/lib/CodegenSchema';
|
|
10
|
+
import {AliasMap, setPreferredModuleName} from './AliasManaging';
|
|
11
|
+
import {createAliasMap, generateAliases} from './AliasGen';
|
|
12
|
+
import {generateValidateConstants} from './ValidateConstants';
|
|
13
|
+
import {generateValidateMethods} from './ValidateMethods';
|
|
14
|
+
import type {CppStringTypes} from './ObjectTypes';
|
|
15
|
+
|
|
16
|
+
export type {CppStringTypes} from './ObjectTypes';
|
|
21
17
|
|
|
22
18
|
type FilesOutput = Map<string, string>;
|
|
23
19
|
|
|
24
|
-
const
|
|
25
|
-
/*
|
|
20
|
+
const headerTemplate = `/*
|
|
26
21
|
* This file is auto-generated from a NativeModule spec file in js.
|
|
27
22
|
*
|
|
28
23
|
* This is a C++ Spec class that should be used with MakeTurboModuleProvider to register native modules
|
|
@@ -30,117 +25,71 @@ const moduleTemplate = `
|
|
|
30
25
|
* by the TurboModule JS spec.
|
|
31
26
|
*/
|
|
32
27
|
#pragma once
|
|
28
|
+
// clang-format off`;
|
|
33
29
|
|
|
34
|
-
|
|
35
|
-
#include <tuple>
|
|
36
|
-
|
|
37
|
-
namespace ::_NAMESPACE_:: {
|
|
38
|
-
::_MODULE_ALIASED_STRUCTS_::
|
|
30
|
+
const specTemplate = `::_MODULE_CUSTOM_TYPES_REFLECTION_::
|
|
39
31
|
struct ::_MODULE_NAME_::Spec : winrt::Microsoft::ReactNative::TurboModuleSpec {
|
|
40
|
-
|
|
41
|
-
::_MODULE_PROPERTIES_TUPLE_::
|
|
42
|
-
};
|
|
32
|
+
::_MODULE_MEMBERS_TUPLES_::
|
|
43
33
|
|
|
44
34
|
template <class TModule>
|
|
45
35
|
static constexpr void ValidateModule() noexcept {
|
|
46
|
-
|
|
36
|
+
::_MODULE_MEMBERS_CHECKS_::
|
|
47
37
|
|
|
48
|
-
::
|
|
49
|
-
}
|
|
50
|
-
|
|
38
|
+
::_MODULE_MEMBERS_ERRORS_::
|
|
39
|
+
}`;
|
|
40
|
+
|
|
41
|
+
const typeOnlyTemplate = `
|
|
42
|
+
${headerTemplate}
|
|
51
43
|
|
|
44
|
+
#include <string>
|
|
45
|
+
#include <optional>
|
|
46
|
+
#include <functional>
|
|
47
|
+
#include <vector>
|
|
48
|
+
|
|
49
|
+
namespace ::_NAMESPACE_:: {
|
|
50
|
+
::_MODULE_CUSTOM_TYPES_::
|
|
52
51
|
} // namespace ::_NAMESPACE_::
|
|
53
52
|
`;
|
|
54
53
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
funcType.returnTypeAnnotation.type !== 'VoidTypeAnnotation' &&
|
|
58
|
-
funcType.returnTypeAnnotation.type !== 'PromiseTypeAnnotation'
|
|
59
|
-
);
|
|
60
|
-
}
|
|
54
|
+
const moduleOnlyTemplate = `
|
|
55
|
+
${headerTemplate}
|
|
61
56
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
57
|
+
::_TYPE_DEFINITION_INCLUDE_::
|
|
58
|
+
#include <NativeModules.h>
|
|
59
|
+
#include <tuple>
|
|
65
60
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
): string[] {
|
|
70
|
-
const args = translateArgs(funcType.params);
|
|
71
|
-
if (isMethodReturnPromise(funcType)) {
|
|
72
|
-
// TODO: type of the promise could be provided in the future
|
|
73
|
-
args.push('React::ReactPromise<React::JSValue> &&result');
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// TODO: be much more exhastive on the possible method signatures that can be used..
|
|
77
|
-
const sig = `REACT_${isMethodSync(funcType) ? 'SYNC_' : ''}METHOD(${
|
|
78
|
-
prop.name
|
|
79
|
-
}) ${translateImplReturnType(funcType.returnTypeAnnotation)} ${
|
|
80
|
-
prop.name
|
|
81
|
-
}(${args.join(', ')}) noexcept { /* implementation */ }}`;
|
|
82
|
-
|
|
83
|
-
const staticsig = `REACT_${isMethodSync(funcType) ? 'SYNC_' : ''}METHOD(${
|
|
84
|
-
prop.name
|
|
85
|
-
}) static ${translateImplReturnType(funcType.returnTypeAnnotation)} ${
|
|
86
|
-
prop.name
|
|
87
|
-
}(${args.join(', ')}) noexcept { /* implementation */ }}`;
|
|
88
|
-
|
|
89
|
-
return [sig, staticsig];
|
|
90
|
-
}
|
|
61
|
+
namespace ::_NAMESPACE_:: {
|
|
62
|
+
${specTemplate}
|
|
63
|
+
};
|
|
91
64
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
funcType: NativeModuleFunctionTypeAnnotation,
|
|
95
|
-
): string {
|
|
96
|
-
return getPossibleMethodSignatures(prop, funcType)
|
|
97
|
-
.map(sig => `" ${sig}\\n"`)
|
|
98
|
-
.join('\n ');
|
|
99
|
-
}
|
|
65
|
+
} // namespace ::_NAMESPACE_::
|
|
66
|
+
`;
|
|
100
67
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
tuple: boolean,
|
|
104
|
-
): string {
|
|
105
|
-
// TODO: generate code for constants
|
|
106
|
-
return properties
|
|
107
|
-
.filter(prop => prop.name !== 'getConstants')
|
|
108
|
-
.map((prop, index) => {
|
|
109
|
-
// TODO: prop.optional === true
|
|
110
|
-
// TODO: prop.typeAnnotation.type === 'NullableTypeAnnotation'
|
|
111
|
-
const funcType =
|
|
112
|
-
prop.typeAnnotation.type === 'NullableTypeAnnotation'
|
|
113
|
-
? prop.typeAnnotation.typeAnnotation
|
|
114
|
-
: prop.typeAnnotation;
|
|
115
|
-
|
|
116
|
-
const traversedArgs = translateSpecArgs(funcType.params);
|
|
117
|
-
|
|
118
|
-
const translatedReturnParam = translateSpecReturnType(
|
|
119
|
-
funcType.returnTypeAnnotation,
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
if (isMethodReturnPromise(funcType)) {
|
|
123
|
-
// TODO: type of the promise could be provided in the future
|
|
124
|
-
traversedArgs.push('Promise<React::JSValue>');
|
|
125
|
-
}
|
|
68
|
+
const allInOneTemplate = `
|
|
69
|
+
${headerTemplate}
|
|
126
70
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
isMethodSync(funcType) ? 'Sync' : ''
|
|
130
|
-
}Method<${translatedReturnParam}(${traversedArgs.join(
|
|
131
|
-
', ',
|
|
132
|
-
)}) noexcept>{${index}, L"${prop.name}"},`;
|
|
133
|
-
} else {
|
|
134
|
-
return ` REACT_SHOW_METHOD_SPEC_ERRORS(
|
|
135
|
-
${index},
|
|
136
|
-
"${prop.name}",
|
|
137
|
-
${translatePossibleMethodSignatures(prop, funcType)});`;
|
|
138
|
-
}
|
|
139
|
-
})
|
|
140
|
-
.join('\n');
|
|
141
|
-
}
|
|
71
|
+
#include <NativeModules.h>
|
|
72
|
+
#include <tuple>
|
|
142
73
|
|
|
143
|
-
|
|
74
|
+
namespace ::_NAMESPACE_:: {
|
|
75
|
+
::_MODULE_CUSTOM_TYPES_::
|
|
76
|
+
${specTemplate}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
} // namespace ::_NAMESPACE_::
|
|
80
|
+
`;
|
|
81
|
+
|
|
82
|
+
export function createNM2Generator({
|
|
83
|
+
methodOnly,
|
|
84
|
+
namespace,
|
|
85
|
+
cppStringType,
|
|
86
|
+
separateDataTypes,
|
|
87
|
+
}: {
|
|
88
|
+
methodOnly: boolean;
|
|
89
|
+
namespace: string;
|
|
90
|
+
cppStringType: CppStringTypes;
|
|
91
|
+
separateDataTypes: boolean;
|
|
92
|
+
}) {
|
|
144
93
|
return (
|
|
145
94
|
_libraryName: string,
|
|
146
95
|
schema: SchemaType,
|
|
@@ -161,33 +110,81 @@ export function createNM2Generator({namespace}: {namespace: string}) {
|
|
|
161
110
|
if (nativeModule.type === 'NativeModule') {
|
|
162
111
|
console.log(`Generating Native${preferredModuleName}Spec.g.h`);
|
|
163
112
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
113
|
+
// copy all explicit to a map
|
|
114
|
+
const aliases: AliasMap = createAliasMap(nativeModule.aliasMap);
|
|
115
|
+
|
|
116
|
+
// prepare methods
|
|
117
|
+
const methods = generateValidateMethods(nativeModule, aliases, {
|
|
118
|
+
cppStringType,
|
|
119
|
+
});
|
|
120
|
+
let tuples = `
|
|
121
|
+
static constexpr auto methods = std::tuple{
|
|
122
|
+
${methods.traversedPropertyTuples}${
|
|
123
|
+
methods.traversedEventEmitterTuples ? '\n' : ''
|
|
124
|
+
}${methods.traversedEventEmitterTuples}
|
|
125
|
+
};`;
|
|
126
|
+
let checks = `
|
|
127
|
+
constexpr auto methodCheckResults = CheckMethods<TModule, ::_MODULE_NAME_::Spec>();`;
|
|
128
|
+
let errors =
|
|
129
|
+
methods.traversedProperties +
|
|
130
|
+
(methods.traversedEventEmitters ? '\n' : '') +
|
|
131
|
+
methods.traversedEventEmitters;
|
|
132
|
+
|
|
133
|
+
// prepare constants
|
|
134
|
+
const constants = generateValidateConstants(nativeModule, aliases);
|
|
135
|
+
if (constants !== undefined && !methodOnly) {
|
|
136
|
+
tuples = `
|
|
137
|
+
static constexpr auto constants = std::tuple{
|
|
138
|
+
${constants[0]}
|
|
139
|
+
};${tuples}`;
|
|
140
|
+
checks = `
|
|
141
|
+
constexpr auto constantCheckResults = CheckConstants<TModule, ::_MODULE_NAME_::Spec>();${checks}`;
|
|
142
|
+
errors = `${constants[1]}
|
|
143
|
+
|
|
144
|
+
${errors}`;
|
|
173
145
|
}
|
|
174
146
|
|
|
175
|
-
|
|
176
|
-
const
|
|
177
|
-
|
|
147
|
+
// generate code for structs
|
|
148
|
+
const [customTypes, customReflection] = generateAliases(aliases, {
|
|
149
|
+
cppStringType,
|
|
150
|
+
});
|
|
178
151
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
.replace(/::
|
|
152
|
+
const customTypesExist = customTypes !== '';
|
|
153
|
+
|
|
154
|
+
const replaceContent = function (template: string): string {
|
|
155
|
+
return template
|
|
156
|
+
.replace(/::_MODULE_CUSTOM_TYPES_::/g, customTypes)
|
|
157
|
+
.replace(/::_MODULE_CUSTOM_TYPES_REFLECTION_::/g, customReflection)
|
|
158
|
+
.replace(/::_MODULE_MEMBERS_TUPLES_::/g, tuples.substring(1))
|
|
159
|
+
.replace(/::_MODULE_MEMBERS_CHECKS_::/g, checks.substring(1))
|
|
160
|
+
.replace(/::_MODULE_MEMBERS_ERRORS_::/g, errors)
|
|
161
|
+
.replace(/::_MODULE_NAME_::/g, preferredModuleName)
|
|
184
162
|
.replace(
|
|
185
|
-
/::
|
|
186
|
-
|
|
163
|
+
/::_TYPE_DEFINITION_INCLUDE_::/g,
|
|
164
|
+
customTypesExist
|
|
165
|
+
? `// #include "Native${preferredModuleName}DataTypes.g.h" before this file to use the generated type definition`
|
|
166
|
+
: '',
|
|
187
167
|
)
|
|
188
|
-
.replace(/::
|
|
189
|
-
|
|
190
|
-
|
|
168
|
+
.replace(/::_NAMESPACE_::/g, namespace);
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
if (separateDataTypes) {
|
|
172
|
+
if (customTypesExist) {
|
|
173
|
+
files.set(
|
|
174
|
+
`Native${preferredModuleName}DataTypes.g.h`,
|
|
175
|
+
replaceContent(typeOnlyTemplate),
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
files.set(
|
|
179
|
+
`Native${preferredModuleName}Spec.g.h`,
|
|
180
|
+
replaceContent(moduleOnlyTemplate),
|
|
181
|
+
);
|
|
182
|
+
} else {
|
|
183
|
+
files.set(
|
|
184
|
+
`Native${preferredModuleName}Spec.g.h`,
|
|
185
|
+
replaceContent(allInOneTemplate),
|
|
186
|
+
);
|
|
187
|
+
}
|
|
191
188
|
}
|
|
192
189
|
}
|
|
193
190
|
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Microsoft Corporation.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
* @format
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
import type {
|
|
10
|
+
NamedShape,
|
|
11
|
+
NativeModuleBaseTypeAnnotation,
|
|
12
|
+
NativeModuleFunctionTypeAnnotation,
|
|
13
|
+
NativeModuleObjectTypeAnnotation,
|
|
14
|
+
NativeModuleParamTypeAnnotation,
|
|
15
|
+
NativeModuleReturnTypeAnnotation,
|
|
16
|
+
NativeModuleSchema,
|
|
17
|
+
UnsafeAnyTypeAnnotation,
|
|
18
|
+
Nullable,
|
|
19
|
+
SchemaType,
|
|
20
|
+
} from '@react-native/codegen/lib/CodegenSchema';
|
|
21
|
+
|
|
22
|
+
interface CodegenNativeModuleSchema extends NativeModuleSchema {
|
|
23
|
+
optionalTurboModule?: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function setOptionalTurboModule(
|
|
27
|
+
schema: NativeModuleSchema,
|
|
28
|
+
optional: boolean,
|
|
29
|
+
): void {
|
|
30
|
+
const cs = <CodegenNativeModuleSchema>schema;
|
|
31
|
+
cs.optionalTurboModule = optional;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function getOptionalTurboModule(schema: NativeModuleSchema): boolean {
|
|
35
|
+
return (<CodegenNativeModuleSchema>schema).optionalTurboModule ?? false;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
type ObjectProp = NamedShape<Nullable<NativeModuleBaseTypeAnnotation>>;
|
|
39
|
+
type FunctionParam = NamedShape<Nullable<NativeModuleParamTypeAnnotation>>;
|
|
40
|
+
type FunctionDecl = NamedShape<Nullable<NativeModuleFunctionTypeAnnotation>>;
|
|
41
|
+
type FilesOutput = Map<string, string>;
|
|
42
|
+
|
|
43
|
+
const moduleTemplate = `
|
|
44
|
+
/*
|
|
45
|
+
* This file is auto-generated from a NativeModule spec file in js.
|
|
46
|
+
*
|
|
47
|
+
* This is a TypeScript turbo module definition file.
|
|
48
|
+
*/
|
|
49
|
+
|
|
50
|
+
import {TurboModule, TurboModuleRegistry} from 'react-native';
|
|
51
|
+
'use strict';
|
|
52
|
+
::_MODULE_ALIASED_STRUCTS_::
|
|
53
|
+
export interface Spec extends TurboModule {
|
|
54
|
+
::_MODULE_MEMBERS_::
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export default TurboModuleRegistry.::_MODULE_GETTER_::<Spec>('::_MODULE_NAME_::');
|
|
58
|
+
`;
|
|
59
|
+
|
|
60
|
+
function optionalSign<T>(obj: NamedShape<T>): string {
|
|
61
|
+
return obj.optional ? '?' : '';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function translateType(
|
|
65
|
+
type:
|
|
66
|
+
| Nullable<
|
|
67
|
+
| NativeModuleBaseTypeAnnotation
|
|
68
|
+
| NativeModuleParamTypeAnnotation
|
|
69
|
+
| NativeModuleReturnTypeAnnotation
|
|
70
|
+
>
|
|
71
|
+
| UnsafeAnyTypeAnnotation,
|
|
72
|
+
): string {
|
|
73
|
+
// avoid: Property 'type' does not exist on type 'never'
|
|
74
|
+
const returnType = type.type;
|
|
75
|
+
switch (type.type) {
|
|
76
|
+
case 'StringTypeAnnotation':
|
|
77
|
+
return 'string';
|
|
78
|
+
case 'NumberTypeAnnotation':
|
|
79
|
+
case 'FloatTypeAnnotation':
|
|
80
|
+
case 'DoubleTypeAnnotation':
|
|
81
|
+
case 'Int32TypeAnnotation':
|
|
82
|
+
return 'number';
|
|
83
|
+
case 'BooleanTypeAnnotation':
|
|
84
|
+
return 'boolean';
|
|
85
|
+
case 'ArrayTypeAnnotation':
|
|
86
|
+
if (type.elementType.type !== 'AnyTypeAnnotation') {
|
|
87
|
+
return `${translateType(type.elementType)}[]`;
|
|
88
|
+
} else {
|
|
89
|
+
return `Array`;
|
|
90
|
+
}
|
|
91
|
+
case 'GenericObjectTypeAnnotation':
|
|
92
|
+
return 'object';
|
|
93
|
+
case 'ObjectTypeAnnotation':
|
|
94
|
+
return `{${type.properties
|
|
95
|
+
.map((prop: ObjectProp) => {
|
|
96
|
+
return `${prop.name}${optionalSign(prop)}: ${translateType(
|
|
97
|
+
prop.typeAnnotation,
|
|
98
|
+
)}`;
|
|
99
|
+
})
|
|
100
|
+
.join(', ')}}`;
|
|
101
|
+
case 'ReservedTypeAnnotation': {
|
|
102
|
+
// avoid: Property 'name' does not exist on type 'never'
|
|
103
|
+
const name = type.name;
|
|
104
|
+
// (#6597)
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
106
|
+
if (name !== 'RootTag')
|
|
107
|
+
throw new Error(
|
|
108
|
+
`Unknown reserved function: ${name} in translateReturnType`,
|
|
109
|
+
);
|
|
110
|
+
return 'number';
|
|
111
|
+
}
|
|
112
|
+
case 'TypeAliasTypeAnnotation':
|
|
113
|
+
return type.name;
|
|
114
|
+
case 'NullableTypeAnnotation':
|
|
115
|
+
return `(${translateType(type.typeAnnotation)} | null | undefined)`;
|
|
116
|
+
case 'VoidTypeAnnotation':
|
|
117
|
+
return `void`;
|
|
118
|
+
case 'PromiseTypeAnnotation':
|
|
119
|
+
return `Promise`;
|
|
120
|
+
case `FunctionTypeAnnotation`:
|
|
121
|
+
return `((${type.params
|
|
122
|
+
.map((param: FunctionParam) => {
|
|
123
|
+
return `${param.name}${optionalSign(param)}: ${translateType(
|
|
124
|
+
param.typeAnnotation,
|
|
125
|
+
)}`;
|
|
126
|
+
})
|
|
127
|
+
.join(', ')}) => ${translateType(type.returnTypeAnnotation)})`;
|
|
128
|
+
default:
|
|
129
|
+
throw new Error(`Unhandled type in translateReturnType: ${returnType}`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function translateAlias(
|
|
134
|
+
name: string,
|
|
135
|
+
type: NativeModuleObjectTypeAnnotation,
|
|
136
|
+
): string {
|
|
137
|
+
return `
|
|
138
|
+
export interface ${name} {
|
|
139
|
+
${type.properties
|
|
140
|
+
.map((prop: ObjectProp) => {
|
|
141
|
+
return ` ${prop.name}${optionalSign(prop)}: ${translateType(
|
|
142
|
+
prop.typeAnnotation,
|
|
143
|
+
)};`;
|
|
144
|
+
})
|
|
145
|
+
.join('\n')}
|
|
146
|
+
}
|
|
147
|
+
`;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function tryGetConstantType(
|
|
151
|
+
nativeModule: NativeModuleSchema,
|
|
152
|
+
): NativeModuleObjectTypeAnnotation | undefined {
|
|
153
|
+
const candidates = nativeModule.spec.methods.filter(
|
|
154
|
+
prop => prop.name === 'getConstants',
|
|
155
|
+
);
|
|
156
|
+
if (candidates.length === 0) {
|
|
157
|
+
return undefined;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const getConstant = candidates[0];
|
|
161
|
+
const funcType =
|
|
162
|
+
getConstant.typeAnnotation.type === 'NullableTypeAnnotation'
|
|
163
|
+
? getConstant.typeAnnotation.typeAnnotation
|
|
164
|
+
: getConstant.typeAnnotation;
|
|
165
|
+
if (
|
|
166
|
+
funcType.params.length > 0 ||
|
|
167
|
+
funcType.returnTypeAnnotation.type !== 'ObjectTypeAnnotation'
|
|
168
|
+
) {
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const constantType = funcType.returnTypeAnnotation;
|
|
173
|
+
if (constantType.properties.length === 0) {
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return constantType;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function translateMethod(func: FunctionDecl): string {
|
|
181
|
+
const funcType =
|
|
182
|
+
func.typeAnnotation.type === 'NullableTypeAnnotation'
|
|
183
|
+
? func.typeAnnotation.typeAnnotation
|
|
184
|
+
: func.typeAnnotation;
|
|
185
|
+
|
|
186
|
+
return `
|
|
187
|
+
${func.name}(${funcType.params
|
|
188
|
+
.map((param: FunctionParam) => {
|
|
189
|
+
return `${param.name}${optionalSign(param)}: ${translateType(
|
|
190
|
+
param.typeAnnotation,
|
|
191
|
+
)}`;
|
|
192
|
+
})
|
|
193
|
+
.join(', ')})${optionalSign(func)}: ${translateType(
|
|
194
|
+
funcType.returnTypeAnnotation,
|
|
195
|
+
)}${
|
|
196
|
+
funcType.returnTypeAnnotation.type === 'ObjectTypeAnnotation' ? '' : ';'
|
|
197
|
+
}`;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export function generateTypeScript(
|
|
201
|
+
_libraryName: string,
|
|
202
|
+
schema: SchemaType,
|
|
203
|
+
_moduleSpecName: string,
|
|
204
|
+
): FilesOutput {
|
|
205
|
+
const files = new Map<string, string>();
|
|
206
|
+
|
|
207
|
+
for (const moduleName of Object.keys(schema.modules)) {
|
|
208
|
+
const nativeModule = schema.modules[moduleName];
|
|
209
|
+
// from 0.65 facebook's react-native-codegen
|
|
210
|
+
// the module name has the Native prefix comparing to 0.63
|
|
211
|
+
// when reading files we provided
|
|
212
|
+
const nativePrefix = 'Native';
|
|
213
|
+
const preferredModuleName = moduleName.startsWith(nativePrefix)
|
|
214
|
+
? moduleName.substr(nativePrefix.length)
|
|
215
|
+
: moduleName;
|
|
216
|
+
|
|
217
|
+
if (nativeModule.type === 'NativeModule') {
|
|
218
|
+
console.log(`Generating ${preferredModuleName}Spec.g.ts`);
|
|
219
|
+
|
|
220
|
+
const aliasCode = Object.keys(nativeModule.aliasMap)
|
|
221
|
+
.map(name => translateAlias(name, nativeModule.aliasMap[name]))
|
|
222
|
+
.join('');
|
|
223
|
+
|
|
224
|
+
const constantType = tryGetConstantType(nativeModule);
|
|
225
|
+
const constantCode =
|
|
226
|
+
constantType === undefined
|
|
227
|
+
? ''
|
|
228
|
+
: ` getConstants(): ${translateType(constantType)}`;
|
|
229
|
+
|
|
230
|
+
const methods = nativeModule.spec.methods.filter(
|
|
231
|
+
prop => prop.name !== 'getConstants',
|
|
232
|
+
);
|
|
233
|
+
const membersCode = methods.map(translateMethod).join('');
|
|
234
|
+
|
|
235
|
+
files.set(
|
|
236
|
+
`${preferredModuleName}Spec.g.ts`,
|
|
237
|
+
moduleTemplate
|
|
238
|
+
.replace(/::_MODULE_ALIASED_STRUCTS_::/g, aliasCode)
|
|
239
|
+
.replace(/::_MODULE_MEMBERS_::/g, constantCode + membersCode)
|
|
240
|
+
.replace(/::_MODULE_NAME_::/g, preferredModuleName)
|
|
241
|
+
.replace(
|
|
242
|
+
/::_MODULE_GETTER_::/g,
|
|
243
|
+
getOptionalTurboModule(nativeModule) ? 'get' : 'getEnforcing',
|
|
244
|
+
),
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return files;
|
|
250
|
+
}
|