expo-type-information 0.0.0 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +31 -0
- package/bin/cli.js +2 -0
- package/build/cli.d.ts +1 -0
- package/build/cli.js +35 -0
- package/build/cli.js.map +1 -0
- package/build/commands/commandUtils.d.ts +46 -0
- package/build/commands/commandUtils.js +274 -0
- package/build/commands/commandUtils.js.map +1 -0
- package/build/commands/generateJSXIntrinsicsCommand.d.ts +2 -0
- package/build/commands/generateJSXIntrinsicsCommand.js +28 -0
- package/build/commands/generateJSXIntrinsicsCommand.js.map +1 -0
- package/build/commands/generateMocksForFileCommand.d.ts +2 -0
- package/build/commands/generateMocksForFileCommand.js +22 -0
- package/build/commands/generateMocksForFileCommand.js.map +1 -0
- package/build/commands/generateModuleTypesCommand.d.ts +2 -0
- package/build/commands/generateModuleTypesCommand.js +32 -0
- package/build/commands/generateModuleTypesCommand.js.map +1 -0
- package/build/commands/generateViewTypesCommand.d.ts +2 -0
- package/build/commands/generateViewTypesCommand.js +28 -0
- package/build/commands/generateViewTypesCommand.js.map +1 -0
- package/build/commands/inlineModulesInterfaceCommand.d.ts +2 -0
- package/build/commands/inlineModulesInterfaceCommand.js +129 -0
- package/build/commands/inlineModulesInterfaceCommand.js.map +1 -0
- package/build/commands/moduleInterfaceCommand.d.ts +2 -0
- package/build/commands/moduleInterfaceCommand.js +46 -0
- package/build/commands/moduleInterfaceCommand.js.map +1 -0
- package/build/commands/shortModuleInterfaceCommand.d.ts +2 -0
- package/build/commands/shortModuleInterfaceCommand.js +17 -0
- package/build/commands/shortModuleInterfaceCommand.js.map +1 -0
- package/build/commands/typeInformationCommand.d.ts +2 -0
- package/build/commands/typeInformationCommand.js +24 -0
- package/build/commands/typeInformationCommand.js.map +1 -0
- package/build/index.d.ts +3 -0
- package/build/index.js +28 -0
- package/build/index.js.map +1 -0
- package/build/mockgen.d.ts +4 -0
- package/build/mockgen.js +204 -0
- package/build/mockgen.js.map +1 -0
- package/build/swift/sourcekittenTypeInformation.d.ts +6 -0
- package/build/swift/sourcekittenTypeInformation.js +875 -0
- package/build/swift/sourcekittenTypeInformation.js.map +1 -0
- package/build/typeInformation.d.ts +209 -0
- package/build/typeInformation.js +157 -0
- package/build/typeInformation.js.map +1 -0
- package/build/types.d.ts +59 -0
- package/build/types.js +3 -0
- package/build/types.js.map +1 -0
- package/build/typescriptGeneration.d.ts +61 -0
- package/build/typescriptGeneration.js +696 -0
- package/build/typescriptGeneration.js.map +1 -0
- package/build/utils.d.ts +6 -0
- package/build/utils.js +44 -0
- package/build/utils.js.map +1 -0
- package/jest.config.js +6 -0
- package/package.json +46 -5
- package/src/cli.ts +38 -0
- package/src/commands/commandUtils.ts +352 -0
- package/src/commands/generateJSXIntrinsicsCommand.ts +38 -0
- package/src/commands/generateMocksForFileCommand.ts +30 -0
- package/src/commands/generateModuleTypesCommand.ts +39 -0
- package/src/commands/generateViewTypesCommand.ts +39 -0
- package/src/commands/inlineModulesInterfaceCommand.ts +175 -0
- package/src/commands/moduleInterfaceCommand.ts +56 -0
- package/src/commands/shortModuleInterfaceCommand.ts +26 -0
- package/src/commands/typeInformationCommand.ts +35 -0
- package/src/index.ts +9 -0
- package/src/mockgen.ts +338 -0
- package/src/swift/sourcekittenTypeInformation.ts +1173 -0
- package/src/typeInformation.ts +326 -0
- package/src/types.ts +68 -0
- package/src/typescriptGeneration.ts +1179 -0
- package/src/utils.ts +44 -0
- package/tests/TestModule.swift +175 -0
- package/tests/__snapshots__/typeInformation.test.ts.snap +1578 -0
- package/tests/typeInformation.test.ts +134 -0
- package/tsconfig.json +11 -0
|
@@ -0,0 +1,696 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createDefaultGenerationContext = createDefaultGenerationContext;
|
|
7
|
+
exports.getBasicTypesIdentifiers = getBasicTypesIdentifiers;
|
|
8
|
+
exports.joinTSNodesWithNewlines = joinTSNodesWithNewlines;
|
|
9
|
+
exports.mapTypeToTsTypeNode = mapTypeToTsTypeNode;
|
|
10
|
+
exports.buildViewPropsInterface = buildViewPropsInterface;
|
|
11
|
+
exports.buildFunction = buildFunction;
|
|
12
|
+
exports.buildConstructor = buildConstructor;
|
|
13
|
+
exports.buildClass = buildClass;
|
|
14
|
+
exports.buildUnknownTypeAlias = buildUnknownTypeAlias;
|
|
15
|
+
exports.buildRecordTypeAlias = buildRecordTypeAlias;
|
|
16
|
+
exports.buildEnumTypeDeclaration = buildEnumTypeDeclaration;
|
|
17
|
+
exports.buildExposedTypesDeclarations = buildExposedTypesDeclarations;
|
|
18
|
+
exports.getViewPropsTypeName = getViewPropsTypeName;
|
|
19
|
+
exports.prettifyCode = prettifyCode;
|
|
20
|
+
exports.generateViewTypesFileContent = generateViewTypesFileContent;
|
|
21
|
+
exports.generateJSXIntrinsicsFileContent = generateJSXIntrinsicsFileContent;
|
|
22
|
+
exports.generateModuleTypesFileContent = generateModuleTypesFileContent;
|
|
23
|
+
exports.generateConciseTsInterface = generateConciseTsInterface;
|
|
24
|
+
exports.generateFullTsInterface = generateFullTsInterface;
|
|
25
|
+
const prettier_1 = __importDefault(require("prettier"));
|
|
26
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
27
|
+
const typeInformation_1 = require("./typeInformation");
|
|
28
|
+
const prefix = `Automatically generated by expo-type-information.`;
|
|
29
|
+
const exportModifier = () => typescript_1.default.factory.createModifier(typescript_1.default.SyntaxKind.ExportKeyword);
|
|
30
|
+
const declareModifier = () => typescript_1.default.factory.createModifier(typescript_1.default.SyntaxKind.DeclareKeyword);
|
|
31
|
+
const asyncModifier = () => typescript_1.default.factory.createModifier(typescript_1.default.SyntaxKind.AsyncKeyword);
|
|
32
|
+
const readonlyModifier = () => typescript_1.default.factory.createModifier(typescript_1.default.SyntaxKind.ReadonlyKeyword);
|
|
33
|
+
const constModifier = () => typescript_1.default.factory.createModifier(typescript_1.default.SyntaxKind.ConstKeyword);
|
|
34
|
+
const defaultModifier = () => typescript_1.default.factory.createModifier(typescript_1.default.SyntaxKind.DefaultKeyword);
|
|
35
|
+
const unknownKeywordType = () => typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.UnknownKeyword);
|
|
36
|
+
const anyKeywordType = () => typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.AnyKeyword);
|
|
37
|
+
const voidKeywordType = () => typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.VoidKeyword);
|
|
38
|
+
const newlineIdentifier = () => typescript_1.default.factory.createIdentifier('\n\n');
|
|
39
|
+
let freeId = 0;
|
|
40
|
+
function getNextFreeId() {
|
|
41
|
+
freeId += 1;
|
|
42
|
+
return freeId;
|
|
43
|
+
}
|
|
44
|
+
function createDefaultGenerationContext(fileInfo) {
|
|
45
|
+
const module = fileInfo.moduleClasses[0];
|
|
46
|
+
if (!module) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
const view = module.views[0] ?? null;
|
|
50
|
+
return {
|
|
51
|
+
fileInfo,
|
|
52
|
+
module,
|
|
53
|
+
view,
|
|
54
|
+
missingTypes: getMissingTypeIdentifiers(fileInfo),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function getBasicTypesIdentifiers() {
|
|
58
|
+
return new Set(['any', 'number', 'string', 'undefined', 'null', 'Map', 'Set', 'Promise']);
|
|
59
|
+
}
|
|
60
|
+
function getAllNonBasicTypes(fileInfo) {
|
|
61
|
+
return fileInfo.declaredTypeIdentifiers
|
|
62
|
+
.union(fileInfo.usedTypeIdentifiers)
|
|
63
|
+
.difference(getBasicTypesIdentifiers());
|
|
64
|
+
}
|
|
65
|
+
function createGeneratedPrefix() {
|
|
66
|
+
return [
|
|
67
|
+
typescript_1.default.addSyntheticLeadingComment(typescript_1.default.factory.createIdentifier(''), typescript_1.default.SyntaxKind.MultiLineCommentTrivia, prefix),
|
|
68
|
+
];
|
|
69
|
+
}
|
|
70
|
+
function constructModifiersArray(modifiers) {
|
|
71
|
+
const modifiersArray = [];
|
|
72
|
+
if (modifiers.exported)
|
|
73
|
+
modifiersArray.push(exportModifier());
|
|
74
|
+
if (modifiers.declare)
|
|
75
|
+
modifiersArray.push(declareModifier());
|
|
76
|
+
if (modifiers.async)
|
|
77
|
+
modifiersArray.push(asyncModifier());
|
|
78
|
+
if (modifiers.readonly)
|
|
79
|
+
modifiersArray.push(readonlyModifier());
|
|
80
|
+
return modifiersArray;
|
|
81
|
+
}
|
|
82
|
+
function joinTSNodesWithNewlines(nodes) {
|
|
83
|
+
const new_nodes = [];
|
|
84
|
+
for (const node of nodes) {
|
|
85
|
+
if (node.length > 0) {
|
|
86
|
+
new_nodes.push(...node);
|
|
87
|
+
new_nodes.push(newlineIdentifier());
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return new_nodes;
|
|
91
|
+
}
|
|
92
|
+
function mapBasicTypeToTypeNode(basicType) {
|
|
93
|
+
if (basicType === typeInformation_1.BasicType.UNRESOLVED) {
|
|
94
|
+
return typescript_1.default.addSyntheticTrailingComment(unknownKeywordType(), typescript_1.default.SyntaxKind.MultiLineCommentTrivia, "The type couldn't be resolved automatically.");
|
|
95
|
+
}
|
|
96
|
+
const BASIC_TYPE_MAP = {
|
|
97
|
+
[typeInformation_1.BasicType.ANY]: typescript_1.default.SyntaxKind.AnyKeyword,
|
|
98
|
+
[typeInformation_1.BasicType.BOOLEAN]: typescript_1.default.SyntaxKind.BooleanKeyword,
|
|
99
|
+
[typeInformation_1.BasicType.NUMBER]: typescript_1.default.SyntaxKind.NumberKeyword,
|
|
100
|
+
[typeInformation_1.BasicType.STRING]: typescript_1.default.SyntaxKind.StringKeyword,
|
|
101
|
+
[typeInformation_1.BasicType.VOID]: typescript_1.default.SyntaxKind.VoidKeyword,
|
|
102
|
+
[typeInformation_1.BasicType.UNDEFINED]: typescript_1.default.SyntaxKind.UndefinedKeyword,
|
|
103
|
+
[typeInformation_1.BasicType.UNRESOLVED]: typescript_1.default.SyntaxKind.UndefinedKeyword, // This is handled earlier
|
|
104
|
+
};
|
|
105
|
+
return typescript_1.default.factory.createKeywordTypeNode(BASIC_TYPE_MAP[basicType]);
|
|
106
|
+
}
|
|
107
|
+
function mapTypeToTsTypeNode(type) {
|
|
108
|
+
switch (type.kind) {
|
|
109
|
+
case typeInformation_1.TypeKind.BASIC:
|
|
110
|
+
return mapBasicTypeToTypeNode(type.type);
|
|
111
|
+
case typeInformation_1.TypeKind.IDENTIFIER:
|
|
112
|
+
return typescript_1.default.factory.createTypeReferenceNode(type.type);
|
|
113
|
+
case typeInformation_1.TypeKind.SUM:
|
|
114
|
+
return typescript_1.default.factory.createUnionTypeNode(type.type.types.map(mapTypeToTsTypeNode));
|
|
115
|
+
case typeInformation_1.TypeKind.ARRAY:
|
|
116
|
+
return typescript_1.default.factory.createArrayTypeNode(mapTypeToTsTypeNode(type.type));
|
|
117
|
+
case typeInformation_1.TypeKind.DICTIONARY: {
|
|
118
|
+
const dictionaryType = type.type;
|
|
119
|
+
const name = 'key';
|
|
120
|
+
const typeNode = mapTypeToTsTypeNode(dictionaryType.key);
|
|
121
|
+
const valueType = mapTypeToTsTypeNode(dictionaryType.value);
|
|
122
|
+
return typescript_1.default.factory.createTypeLiteralNode([
|
|
123
|
+
typescript_1.default.factory.createIndexSignature(undefined, [createParameter({ name, type: typeNode })], valueType),
|
|
124
|
+
]);
|
|
125
|
+
}
|
|
126
|
+
// Technically this one should only be the top one and it should be handled somewhere else
|
|
127
|
+
// for example when creating arguemnt adding the '?' token.
|
|
128
|
+
//
|
|
129
|
+
// However we can just make it (type | undefined) in here.
|
|
130
|
+
// TODO(@HubertBer): Maybe also need null?
|
|
131
|
+
case typeInformation_1.TypeKind.OPTIONAL:
|
|
132
|
+
return typescript_1.default.factory.createUnionTypeNode([
|
|
133
|
+
mapTypeToTsTypeNode(type.type),
|
|
134
|
+
mapBasicTypeToTypeNode(typeInformation_1.BasicType.UNDEFINED),
|
|
135
|
+
]);
|
|
136
|
+
case typeInformation_1.TypeKind.PARAMETRIZED:
|
|
137
|
+
return typescript_1.default.factory.createTypeReferenceNode(type.type.name, type.type.types.map(mapTypeToTsTypeNode));
|
|
138
|
+
}
|
|
139
|
+
return mapBasicTypeToTypeNode(typeInformation_1.BasicType.UNRESOLVED);
|
|
140
|
+
}
|
|
141
|
+
//
|
|
142
|
+
// ts.factory wrapper functions
|
|
143
|
+
//
|
|
144
|
+
function createImportDeclaration({ defaultImportName, namedImportsNames, importFromName, }) {
|
|
145
|
+
const hasDefault = !!defaultImportName;
|
|
146
|
+
const hasNamed = namedImportsNames && namedImportsNames.length > 0;
|
|
147
|
+
if (!hasDefault && !hasNamed) {
|
|
148
|
+
return [];
|
|
149
|
+
}
|
|
150
|
+
const defaultImport = hasDefault ? typescript_1.default.factory.createIdentifier(defaultImportName) : undefined;
|
|
151
|
+
const namedImports = hasNamed
|
|
152
|
+
? typescript_1.default.factory.createNamedImports(namedImportsNames.map((name) => typescript_1.default.factory.createImportSpecifier(false, undefined, typescript_1.default.factory.createIdentifier(name))))
|
|
153
|
+
: undefined;
|
|
154
|
+
return [
|
|
155
|
+
typescript_1.default.factory.createImportDeclaration(undefined, typescript_1.default.factory.createImportClause(undefined, defaultImport, namedImports), typescript_1.default.factory.createStringLiteral(importFromName)),
|
|
156
|
+
];
|
|
157
|
+
}
|
|
158
|
+
function createParameter({ modifiers, name, type, questionToken, dotDotDotToken, initializer, }) {
|
|
159
|
+
return typescript_1.default.factory.createParameterDeclaration(modifiers, dotDotDotToken, name, questionToken, type, initializer);
|
|
160
|
+
}
|
|
161
|
+
function createProperty({ modifiers, name, typeNode, initializer, optional, }) {
|
|
162
|
+
return typescript_1.default.factory.createPropertyDeclaration(modifiers, name, optional ? typescript_1.default.factory.createToken(typescript_1.default.SyntaxKind.QuestionToken) : undefined, typeNode, initializer);
|
|
163
|
+
}
|
|
164
|
+
function createPropertySignature({ name, typeNode, optional, modifiers, }) {
|
|
165
|
+
return typescript_1.default.factory.createPropertySignature(modifiers, name, optional ? typescript_1.default.factory.createToken(typescript_1.default.SyntaxKind.QuestionToken) : undefined, typeNode);
|
|
166
|
+
}
|
|
167
|
+
function createCall({ expression, args, typeArgs, }) {
|
|
168
|
+
return typescript_1.default.factory.createCallExpression(typeof expression === 'string' ? typescript_1.default.factory.createIdentifier(expression) : expression, typeArgs, args);
|
|
169
|
+
}
|
|
170
|
+
function createRequireNativeModuleExpression({ moduleType, moduleName, }) {
|
|
171
|
+
return typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createIdentifier('requireNativeModule'), moduleType ? [typescript_1.default.factory.createTypeReferenceNode(moduleType)] : undefined, [typescript_1.default.factory.createStringLiteral(moduleName)]);
|
|
172
|
+
}
|
|
173
|
+
function createExportDefaultAsDeclaration({ exportAsName, importFromName, }) {
|
|
174
|
+
return [
|
|
175
|
+
typescript_1.default.factory.createExportDeclaration(undefined, false, typescript_1.default.factory.createNamedExports([
|
|
176
|
+
typescript_1.default.factory.createExportSpecifier(false, typescript_1.default.factory.createIdentifier('default'), typescript_1.default.factory.createIdentifier(exportAsName)),
|
|
177
|
+
]), typescript_1.default.factory.createStringLiteral(importFromName)),
|
|
178
|
+
];
|
|
179
|
+
}
|
|
180
|
+
function createTypeAlias({ exported, alias, typeParams, type, }) {
|
|
181
|
+
return typescript_1.default.factory.createTypeAliasDeclaration(constructModifiersArray({ exported }), alias, typeParams, type);
|
|
182
|
+
}
|
|
183
|
+
function createRequireNativeViewDeclaration(module, view) {
|
|
184
|
+
return [
|
|
185
|
+
createParameter({
|
|
186
|
+
modifiers: [constModifier()],
|
|
187
|
+
name: view.name,
|
|
188
|
+
initializer: createCall({
|
|
189
|
+
expression: 'requireNativeView',
|
|
190
|
+
typeArgs: [typescript_1.default.factory.createTypeReferenceNode(getViewPropsTypeName(view))],
|
|
191
|
+
args: [
|
|
192
|
+
typescript_1.default.factory.createStringLiteral(module.name),
|
|
193
|
+
typescript_1.default.factory.createStringLiteral(view.name),
|
|
194
|
+
],
|
|
195
|
+
}),
|
|
196
|
+
}),
|
|
197
|
+
];
|
|
198
|
+
}
|
|
199
|
+
function createExportAllDeclaration({ importFromName, justTypes, }) {
|
|
200
|
+
return [
|
|
201
|
+
typescript_1.default.factory.createExportDeclaration(undefined, justTypes ?? false, undefined, typescript_1.default.factory.createStringLiteral(importFromName)),
|
|
202
|
+
];
|
|
203
|
+
}
|
|
204
|
+
function createExportDefault(name = '_default') {
|
|
205
|
+
return [typescript_1.default.factory.createExportDefault(typescript_1.default.factory.createIdentifier(name))];
|
|
206
|
+
}
|
|
207
|
+
function createComponentType(propsTypeName) {
|
|
208
|
+
return typescript_1.default.factory.createTypeReferenceNode('React.JSXElementConstructor', [
|
|
209
|
+
typescript_1.default.factory.createTypeReferenceNode(propsTypeName),
|
|
210
|
+
]);
|
|
211
|
+
}
|
|
212
|
+
function getMissingTypeIdentifiers(fileTypeInformation) {
|
|
213
|
+
return fileTypeInformation.usedTypeIdentifiers
|
|
214
|
+
.difference(fileTypeInformation.declaredTypeIdentifiers)
|
|
215
|
+
.difference(getBasicTypesIdentifiers());
|
|
216
|
+
}
|
|
217
|
+
function buildPropsMembers({ props, events }) {
|
|
218
|
+
const buildEventPropertySignature = (eventDeclaration) => {
|
|
219
|
+
const name = eventDeclaration;
|
|
220
|
+
const typeNode = typescript_1.default.factory.createFunctionTypeNode(undefined, [createParameter({ name: 'event', type: anyKeywordType() })], voidKeywordType());
|
|
221
|
+
// TODO(@HubertBer) check whether we have ways of making events not optional
|
|
222
|
+
return createPropertySignature({ name, typeNode, optional: true });
|
|
223
|
+
};
|
|
224
|
+
const buildPropPropertySignature = (propDeclaration) => {
|
|
225
|
+
const propTypeArgument = propDeclaration.arguments[1]?.type;
|
|
226
|
+
if (!propDeclaration || !propDeclaration.arguments || !propTypeArgument) {
|
|
227
|
+
return undefined;
|
|
228
|
+
}
|
|
229
|
+
const name = propDeclaration.name;
|
|
230
|
+
const typeNode = mapTypeToTsTypeNode(propTypeArgument);
|
|
231
|
+
return createPropertySignature({ name, typeNode });
|
|
232
|
+
};
|
|
233
|
+
return [
|
|
234
|
+
...props.map(buildPropPropertySignature).filter((p) => p),
|
|
235
|
+
...events.map(buildEventPropertySignature),
|
|
236
|
+
];
|
|
237
|
+
}
|
|
238
|
+
function buildViewPropsInterface(view, options) {
|
|
239
|
+
if (!view) {
|
|
240
|
+
return [];
|
|
241
|
+
}
|
|
242
|
+
return [
|
|
243
|
+
typescript_1.default.factory.createInterfaceDeclaration(constructModifiersArray(options), getViewPropsTypeName(view), undefined, [
|
|
244
|
+
typescript_1.default.factory.createHeritageClause(typescript_1.default.SyntaxKind.ExtendsKeyword, [
|
|
245
|
+
typescript_1.default.factory.createExpressionWithTypeArguments(typescript_1.default.factory.createIdentifier('ViewProps'), undefined),
|
|
246
|
+
]),
|
|
247
|
+
], buildPropsMembers(view)),
|
|
248
|
+
];
|
|
249
|
+
}
|
|
250
|
+
function buildClassProperty(declaration) {
|
|
251
|
+
return createProperty({
|
|
252
|
+
modifiers: [readonlyModifier()],
|
|
253
|
+
name: declaration.name,
|
|
254
|
+
typeNode: mapTypeToTsTypeNode(declaration.type),
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
function buildNativeModuleClassDeclaration({ moduleClassDeclaration, exportedModuleName, }) {
|
|
258
|
+
const buildClassTypeProperty = (classDeclaration) => createProperty({
|
|
259
|
+
// TODO(@HubertBer): that's a hack, but I couldn't find a proper way to do this
|
|
260
|
+
// The problem is that declare class semantics seem somewhat different than class semantics.
|
|
261
|
+
name: classDeclaration.name,
|
|
262
|
+
typeNode: typescript_1.default.factory.createTypeQueryNode(typescript_1.default.factory.createIdentifier(classDeclaration.name)),
|
|
263
|
+
});
|
|
264
|
+
const buildSyncMethod = (functionDeclaration) => buildFunction({
|
|
265
|
+
functionDeclaration,
|
|
266
|
+
method: true,
|
|
267
|
+
declaration: true,
|
|
268
|
+
});
|
|
269
|
+
const buildAsyncMethod = (functionDeclaration) => buildFunction({
|
|
270
|
+
functionDeclaration,
|
|
271
|
+
async: true,
|
|
272
|
+
method: true,
|
|
273
|
+
declaration: true,
|
|
274
|
+
});
|
|
275
|
+
return [
|
|
276
|
+
typescript_1.default.factory.createClassDeclaration([exportModifier(), declareModifier()], exportedModuleName ?? `${moduleClassDeclaration.name}NativeModuleType`, undefined, [
|
|
277
|
+
typescript_1.default.factory.createHeritageClause(typescript_1.default.SyntaxKind.ExtendsKeyword, [
|
|
278
|
+
typescript_1.default.factory.createExpressionWithTypeArguments(typescript_1.default.factory.createIdentifier('NativeModule'), undefined),
|
|
279
|
+
]),
|
|
280
|
+
], [
|
|
281
|
+
...moduleClassDeclaration.constants.map(buildClassProperty),
|
|
282
|
+
...moduleClassDeclaration.properties.map(buildClassProperty),
|
|
283
|
+
...moduleClassDeclaration.functions.map(buildSyncMethod),
|
|
284
|
+
...moduleClassDeclaration.asyncFunctions.map(buildAsyncMethod),
|
|
285
|
+
...moduleClassDeclaration.classes.map(buildClassTypeProperty),
|
|
286
|
+
]),
|
|
287
|
+
];
|
|
288
|
+
}
|
|
289
|
+
function buildArgumentDeclarationAndName(arg) {
|
|
290
|
+
const argName = arg.name ?? '_' + getNextFreeId();
|
|
291
|
+
const argDeclaration = createParameter({
|
|
292
|
+
name: argName,
|
|
293
|
+
type: mapTypeToTsTypeNode(arg.type),
|
|
294
|
+
});
|
|
295
|
+
return { argDeclaration, argName };
|
|
296
|
+
}
|
|
297
|
+
function buildArgumentDeclaration(arg) {
|
|
298
|
+
return buildArgumentDeclarationAndName(arg).argDeclaration;
|
|
299
|
+
}
|
|
300
|
+
function buildFunction({ functionDeclaration, async, method, exported, declaration, returnStatement, overrideArgumentDeclarations, omitReturnType, }) {
|
|
301
|
+
const functionModifiers = constructModifiersArray({ exported, async: async && !declaration });
|
|
302
|
+
const customReturn = !!returnStatement;
|
|
303
|
+
const bareReturnTypeNode = mapTypeToTsTypeNode(functionDeclaration.returnType);
|
|
304
|
+
const wrapWithPromiseType = (typeNode) => typescript_1.default.factory.createTypeReferenceNode('Promise', [typeNode]);
|
|
305
|
+
let returnTypeNode = async
|
|
306
|
+
? wrapWithPromiseType(bareReturnTypeNode)
|
|
307
|
+
: bareReturnTypeNode;
|
|
308
|
+
if (omitReturnType) {
|
|
309
|
+
returnTypeNode = undefined;
|
|
310
|
+
}
|
|
311
|
+
const argumentDeclarations = overrideArgumentDeclarations ?? functionDeclaration.arguments.map(buildArgumentDeclaration);
|
|
312
|
+
if (method) {
|
|
313
|
+
return typescript_1.default.factory.createMethodDeclaration(functionModifiers, undefined, functionDeclaration.name, undefined, undefined, argumentDeclarations, returnTypeNode, declaration ? undefined : typescript_1.default.factory.createBlock(customReturn ? returnStatement : []));
|
|
314
|
+
}
|
|
315
|
+
return typescript_1.default.factory.createFunctionDeclaration(functionModifiers, undefined, functionDeclaration.name, undefined, argumentDeclarations, returnTypeNode, declaration ? undefined : typescript_1.default.factory.createBlock(customReturn ? returnStatement : []));
|
|
316
|
+
}
|
|
317
|
+
function buildConstructor(constructor, declaration) {
|
|
318
|
+
return typescript_1.default.factory.createConstructorDeclaration(undefined, constructor.arguments.map(buildArgumentDeclaration), declaration ? undefined : typescript_1.default.factory.createBlock([]));
|
|
319
|
+
}
|
|
320
|
+
// TODO(@HubertBer): figure out what about inheritance, should or should not inherit SharedObject
|
|
321
|
+
function buildClass({ classDeclaration, exported, declaration, getFunctionReturnBlock, }) {
|
|
322
|
+
const getReturnStatement = (method) => !declaration && getFunctionReturnBlock ? getFunctionReturnBlock(method) : null;
|
|
323
|
+
const buildMethod = (method, async) => buildFunction({
|
|
324
|
+
functionDeclaration: method,
|
|
325
|
+
method: true,
|
|
326
|
+
async,
|
|
327
|
+
declaration,
|
|
328
|
+
returnStatement: getReturnStatement(method),
|
|
329
|
+
});
|
|
330
|
+
const classMembers = [
|
|
331
|
+
...classDeclaration.methods.map((m) => buildMethod(m)),
|
|
332
|
+
...classDeclaration.asyncMethods.map((m) => buildMethod(m, true)),
|
|
333
|
+
...(declaration ? classDeclaration.properties.map(buildClassProperty) : []),
|
|
334
|
+
classDeclaration.constructor
|
|
335
|
+
? buildConstructor(classDeclaration.constructor, declaration ?? false)
|
|
336
|
+
: undefined,
|
|
337
|
+
].filter((x) => x !== undefined);
|
|
338
|
+
return typescript_1.default.factory.createClassDeclaration(constructModifiersArray({ exported, declare: declaration }), typescript_1.default.factory.createIdentifier(classDeclaration.name), undefined, [], classMembers);
|
|
339
|
+
}
|
|
340
|
+
function buildModuleDefaultExport({ moduleName, moduleType, declaration, }) {
|
|
341
|
+
const name = '_default';
|
|
342
|
+
const type = moduleType ? typescript_1.default.factory.createTypeReferenceNode(moduleType) : undefined;
|
|
343
|
+
return [
|
|
344
|
+
createParameter({
|
|
345
|
+
modifiers: [constModifier()],
|
|
346
|
+
name,
|
|
347
|
+
type,
|
|
348
|
+
initializer: declaration
|
|
349
|
+
? undefined
|
|
350
|
+
: createRequireNativeModuleExpression({ moduleName, moduleType }),
|
|
351
|
+
}),
|
|
352
|
+
typescript_1.default.factory.createExportDefault(typescript_1.default.factory.createIdentifier('_default')),
|
|
353
|
+
];
|
|
354
|
+
}
|
|
355
|
+
function buildUnknownTypeAlias(identifier, exported, inferredTypeParametersCount) {
|
|
356
|
+
const paramCount = inferredTypeParametersCount.get(identifier);
|
|
357
|
+
const typeParamsList = [];
|
|
358
|
+
for (let i = 0; i < (paramCount ?? 0); i += 1) {
|
|
359
|
+
typeParamsList.push(typescript_1.default.factory.createTypeParameterDeclaration(undefined, 'T' + i));
|
|
360
|
+
}
|
|
361
|
+
const typeParams = (paramCount ?? 0) === 0 ? undefined : typeParamsList;
|
|
362
|
+
return createTypeAlias({ exported, alias: identifier, type: unknownKeywordType(), typeParams });
|
|
363
|
+
}
|
|
364
|
+
function buildRecordTypeAlias(recordType, exported) {
|
|
365
|
+
return createTypeAlias({
|
|
366
|
+
exported,
|
|
367
|
+
alias: recordType.name,
|
|
368
|
+
type: typescript_1.default.factory.createTypeLiteralNode(recordType.fields.map((field) => {
|
|
369
|
+
const optional = field.type.kind === typeInformation_1.TypeKind.OPTIONAL;
|
|
370
|
+
const typeNode = mapTypeToTsTypeNode(optional ? field.type.type : field.type);
|
|
371
|
+
const name = field.name ?? '_' + getNextFreeId();
|
|
372
|
+
return createPropertySignature({ name, optional, typeNode });
|
|
373
|
+
})),
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
function buildEnumTypeDeclaration(enumType, exported, declared) {
|
|
377
|
+
return typescript_1.default.factory.createEnumDeclaration(constructModifiersArray({ exported, declare: declared }), enumType.name, enumType.cases.map((enumcase) => typescript_1.default.factory.createEnumMember(enumcase)));
|
|
378
|
+
}
|
|
379
|
+
function buildMissingTypesDeclarations(ctx) {
|
|
380
|
+
if (ctx.missingTypes.size === 0) {
|
|
381
|
+
return [];
|
|
382
|
+
}
|
|
383
|
+
const header = typescript_1.default.addSyntheticLeadingComment(typescript_1.default.factory.createIdentifier(''), typescript_1.default.SyntaxKind.SingleLineCommentTrivia, ` These types haven't been defined in provided file(s).`, true);
|
|
384
|
+
const aliases = [...ctx.missingTypes].map((identifier) => buildUnknownTypeAlias(identifier, true, ctx.fileInfo.inferredTypeParametersCount));
|
|
385
|
+
return [header, ...aliases];
|
|
386
|
+
}
|
|
387
|
+
function buildDefaultViewComponent({ componentName, propsTypeAlias, }) {
|
|
388
|
+
const jsxElement = typescript_1.default.factory.createJsxSelfClosingElement(typescript_1.default.factory.createIdentifier(componentName), undefined, typescript_1.default.factory.createJsxAttributes([
|
|
389
|
+
typescript_1.default.factory.createJsxSpreadAttribute(typescript_1.default.factory.createIdentifier('props')),
|
|
390
|
+
]));
|
|
391
|
+
const functionBody = typescript_1.default.factory.createBlock([typescript_1.default.factory.createReturnStatement(jsxElement)]);
|
|
392
|
+
return [
|
|
393
|
+
typescript_1.default.factory.createFunctionExpression([exportModifier(), defaultModifier()], undefined, componentName + 'Component', undefined, [
|
|
394
|
+
createParameter({
|
|
395
|
+
name: 'props',
|
|
396
|
+
type: typescript_1.default.factory.createTypeReferenceNode(propsTypeAlias),
|
|
397
|
+
}),
|
|
398
|
+
], undefined, functionBody),
|
|
399
|
+
];
|
|
400
|
+
}
|
|
401
|
+
function buildExposedTypesDeclarations(ctx, options) {
|
|
402
|
+
const recordDeclarationMap = (recordType) => buildRecordTypeAlias(recordType, options.exported ?? false);
|
|
403
|
+
const enumDeclarationMap = (enumType) => buildEnumTypeDeclaration(enumType, options.exported ?? false, options.declare ?? false);
|
|
404
|
+
const classDeclarationMap = (classDeclaration) => buildClass({ classDeclaration, exported: true, declaration: true });
|
|
405
|
+
return joinTSNodesWithNewlines([
|
|
406
|
+
createImportDeclaration({ namedImportsNames: ['NativeModule'], importFromName: 'expo' }),
|
|
407
|
+
buildMissingTypesDeclarations(ctx),
|
|
408
|
+
ctx.fileInfo.records.flatMap(recordDeclarationMap),
|
|
409
|
+
ctx.fileInfo.enums.flatMap(enumDeclarationMap),
|
|
410
|
+
ctx.module.classes.map(classDeclarationMap),
|
|
411
|
+
]);
|
|
412
|
+
}
|
|
413
|
+
function buildModuleDeclarationNodes(ctx) {
|
|
414
|
+
return joinTSNodesWithNewlines([
|
|
415
|
+
createGeneratedPrefix(),
|
|
416
|
+
buildExposedTypesDeclarations(ctx, { exported: true }),
|
|
417
|
+
buildNativeModuleClassDeclaration({ moduleClassDeclaration: ctx.module }),
|
|
418
|
+
buildModuleDefaultExport({
|
|
419
|
+
moduleName: ctx.module.name,
|
|
420
|
+
moduleType: ctx.module.name,
|
|
421
|
+
declaration: true,
|
|
422
|
+
}),
|
|
423
|
+
]);
|
|
424
|
+
}
|
|
425
|
+
function getViewPropsTypeName(view) {
|
|
426
|
+
return view.name + (view.name.endsWith('View') ? 'Props' : 'ViewProps');
|
|
427
|
+
}
|
|
428
|
+
function buildViewDeclarationNodes(ctx) {
|
|
429
|
+
if (!ctx.view) {
|
|
430
|
+
return [];
|
|
431
|
+
}
|
|
432
|
+
const viewComponentType = createComponentType(getViewPropsTypeName(ctx.view));
|
|
433
|
+
const modifiers = [declareModifier(), constModifier()];
|
|
434
|
+
return joinTSNodesWithNewlines([
|
|
435
|
+
createGeneratedPrefix(),
|
|
436
|
+
createImportDeclaration({ namedImportsNames: ['ViewProps'], importFromName: 'react-native' }),
|
|
437
|
+
buildMissingTypesDeclarations(ctx),
|
|
438
|
+
buildViewPropsInterface(ctx.view, {}),
|
|
439
|
+
[createParameter({ modifiers, name: '_default', type: viewComponentType })],
|
|
440
|
+
createExportDefault(),
|
|
441
|
+
]);
|
|
442
|
+
}
|
|
443
|
+
function buildJSXIntrinsicsViewNodes(ctx) {
|
|
444
|
+
const name = ctx.module.name;
|
|
445
|
+
const propsTypeNode = ctx.view
|
|
446
|
+
? typescript_1.default.factory.createTypeLiteralNode(buildPropsMembers(ctx.view))
|
|
447
|
+
: undefined;
|
|
448
|
+
const jsxIntrinsicElementsNodes = [];
|
|
449
|
+
if (ctx.view) {
|
|
450
|
+
const globalIdentifier = typescript_1.default.factory.createIdentifier('global');
|
|
451
|
+
const jsxIdentifier = typescript_1.default.factory.createIdentifier('JSX');
|
|
452
|
+
const intrinsicElementsIdentifier = typescript_1.default.factory.createIdentifier('IntrinsicElements');
|
|
453
|
+
jsxIntrinsicElementsNodes.push(typescript_1.default.factory.createModuleDeclaration([declareModifier()], globalIdentifier, typescript_1.default.factory.createModuleBlock([
|
|
454
|
+
typescript_1.default.factory.createModuleDeclaration(undefined, jsxIdentifier, typescript_1.default.factory.createModuleBlock([
|
|
455
|
+
typescript_1.default.factory.createInterfaceDeclaration(undefined, intrinsicElementsIdentifier, undefined, undefined, [createPropertySignature({ name, typeNode: propsTypeNode })]),
|
|
456
|
+
]), typescript_1.default.NodeFlags.Namespace),
|
|
457
|
+
]), typescript_1.default.NodeFlags.GlobalAugmentation));
|
|
458
|
+
}
|
|
459
|
+
return joinTSNodesWithNewlines([
|
|
460
|
+
buildExposedTypesDeclarations(ctx, { declare: true }),
|
|
461
|
+
jsxIntrinsicElementsNodes,
|
|
462
|
+
]);
|
|
463
|
+
}
|
|
464
|
+
function buildNativeModuleGeneratedNodes(ctx) {
|
|
465
|
+
return joinTSNodesWithNewlines([
|
|
466
|
+
createGeneratedPrefix(),
|
|
467
|
+
createImportDeclaration({ namedImportsNames: ['ViewProps'], importFromName: 'react-native' }),
|
|
468
|
+
buildExposedTypesDeclarations(ctx, { exported: true }),
|
|
469
|
+
buildViewPropsInterface(ctx.view, { exported: true }),
|
|
470
|
+
buildNativeModuleClassDeclaration({ moduleClassDeclaration: ctx.module }),
|
|
471
|
+
]);
|
|
472
|
+
}
|
|
473
|
+
function buildStableNativeModuleInterface(ctx) {
|
|
474
|
+
const generatedModuleAlias = ctx.module.name;
|
|
475
|
+
const generatedModuleTypeAlias = `${ctx.module.name}NativeModuleType`;
|
|
476
|
+
const generatedFilePath = `./${ctx.module.name}.generated`;
|
|
477
|
+
const exportedFunctionReturnStatement = (functionDeclaration, overrideArguments) => {
|
|
478
|
+
const expression = `${generatedModuleAlias}.${functionDeclaration.name}`;
|
|
479
|
+
const args = overrideArguments ??
|
|
480
|
+
functionDeclaration.arguments.map((arg) => typescript_1.default.factory.createIdentifier(arg.name ?? 'unnamedArgument'));
|
|
481
|
+
return typescript_1.default.factory.createReturnStatement(createCall({
|
|
482
|
+
expression,
|
|
483
|
+
args,
|
|
484
|
+
}));
|
|
485
|
+
};
|
|
486
|
+
const mapFunctionDeclarationTemplate = (isAsync) => (functionDeclaration) => {
|
|
487
|
+
const argumentDeclarations = [];
|
|
488
|
+
const argumentNames = [];
|
|
489
|
+
for (const arg of functionDeclaration.arguments) {
|
|
490
|
+
const { argDeclaration, argName } = buildArgumentDeclarationAndName(arg);
|
|
491
|
+
argumentDeclarations.push(argDeclaration);
|
|
492
|
+
argumentNames.push(argName);
|
|
493
|
+
}
|
|
494
|
+
return [
|
|
495
|
+
buildFunction({
|
|
496
|
+
functionDeclaration,
|
|
497
|
+
async: isAsync,
|
|
498
|
+
exported: true,
|
|
499
|
+
returnStatement: [
|
|
500
|
+
exportedFunctionReturnStatement(functionDeclaration, argumentNames.map(typescript_1.default.factory.createIdentifier)),
|
|
501
|
+
],
|
|
502
|
+
overrideArgumentDeclarations: argumentDeclarations,
|
|
503
|
+
omitReturnType: true,
|
|
504
|
+
}),
|
|
505
|
+
];
|
|
506
|
+
};
|
|
507
|
+
const mapSyncFunctionDeclaration = mapFunctionDeclarationTemplate(false);
|
|
508
|
+
const mapAsyncFunctionDeclaration = mapFunctionDeclarationTemplate(true);
|
|
509
|
+
const buildConstantExportProperty = (constant) => {
|
|
510
|
+
const typeNode = mapTypeToTsTypeNode(constant.type);
|
|
511
|
+
const modifiers = [exportModifier(), constModifier()];
|
|
512
|
+
const initializer = typescript_1.default.factory.createIdentifier(`${generatedModuleAlias}.${constant.name}`);
|
|
513
|
+
return createProperty({ modifiers, name: constant.name, typeNode, initializer });
|
|
514
|
+
};
|
|
515
|
+
return joinTSNodesWithNewlines([
|
|
516
|
+
ctx.view
|
|
517
|
+
? createImportDeclaration({ importFromName: 'react', defaultImportName: 'React' })
|
|
518
|
+
: [],
|
|
519
|
+
createImportDeclaration({
|
|
520
|
+
namedImportsNames: [
|
|
521
|
+
...ctx.fileInfo.usedTypeIdentifiers.difference(getBasicTypesIdentifiers()),
|
|
522
|
+
...[generatedModuleTypeAlias, ctx.view ? getViewPropsTypeName(ctx.view) : null].filter((v) => v !== null),
|
|
523
|
+
],
|
|
524
|
+
importFromName: generatedFilePath,
|
|
525
|
+
}),
|
|
526
|
+
createImportDeclaration({
|
|
527
|
+
namedImportsNames: ['requireNativeModule', 'requireNativeView'],
|
|
528
|
+
importFromName: 'expo',
|
|
529
|
+
}),
|
|
530
|
+
[
|
|
531
|
+
createParameter({
|
|
532
|
+
modifiers: [constModifier()],
|
|
533
|
+
name: ctx.module.name,
|
|
534
|
+
type: typescript_1.default.factory.createTypeReferenceNode(generatedModuleTypeAlias),
|
|
535
|
+
initializer: createRequireNativeModuleExpression({
|
|
536
|
+
moduleName: ctx.module.name,
|
|
537
|
+
moduleType: generatedModuleTypeAlias,
|
|
538
|
+
}),
|
|
539
|
+
}),
|
|
540
|
+
],
|
|
541
|
+
ctx.view ? createRequireNativeViewDeclaration(ctx.module, ctx.view) : [],
|
|
542
|
+
ctx.module.constants.map(buildConstantExportProperty),
|
|
543
|
+
ctx.module.functions.flatMap(mapSyncFunctionDeclaration),
|
|
544
|
+
ctx.module.asyncFunctions.flatMap(mapAsyncFunctionDeclaration),
|
|
545
|
+
ctx.view
|
|
546
|
+
? buildDefaultViewComponent({
|
|
547
|
+
componentName: ctx.view.name,
|
|
548
|
+
propsTypeAlias: getViewPropsTypeName(ctx.view),
|
|
549
|
+
})
|
|
550
|
+
: [],
|
|
551
|
+
]);
|
|
552
|
+
}
|
|
553
|
+
async function tsNodesToString(elements) {
|
|
554
|
+
const printer = typescript_1.default.createPrinter({ newLine: typescript_1.default.NewLineKind.LineFeed });
|
|
555
|
+
const resultFile = typescript_1.default.createSourceFile('', '', typescript_1.default.ScriptTarget.Latest, false, typescript_1.default.ScriptKind.TSX);
|
|
556
|
+
const viewTypes = typescript_1.default.factory.createNodeArray(elements);
|
|
557
|
+
const printedTs = printer.printList(typescript_1.default.ListFormat.MultiLine | typescript_1.default.ListFormat.PreserveLines, viewTypes, resultFile);
|
|
558
|
+
return await prettifyCode(printedTs, 'typescript');
|
|
559
|
+
}
|
|
560
|
+
async function prettifyCode(text, parser = 'babel') {
|
|
561
|
+
return await prettier_1.default.format(text, {
|
|
562
|
+
parser,
|
|
563
|
+
tabWidth: 2,
|
|
564
|
+
printWidth: 100,
|
|
565
|
+
trailingComma: 'none',
|
|
566
|
+
singleQuote: true,
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
async function generateViewTypesFileContent(fileTypeInformation) {
|
|
570
|
+
const ctx = createDefaultGenerationContext(fileTypeInformation);
|
|
571
|
+
if (!ctx) {
|
|
572
|
+
return null;
|
|
573
|
+
}
|
|
574
|
+
return tsNodesToString(buildViewDeclarationNodes(ctx));
|
|
575
|
+
}
|
|
576
|
+
async function generateJSXIntrinsicsFileContent(fileTypeInformation) {
|
|
577
|
+
const ctx = createDefaultGenerationContext(fileTypeInformation);
|
|
578
|
+
if (!ctx) {
|
|
579
|
+
return null;
|
|
580
|
+
}
|
|
581
|
+
return tsNodesToString(buildJSXIntrinsicsViewNodes(ctx));
|
|
582
|
+
}
|
|
583
|
+
async function generateModuleTypesFileContent(fileTypeInformation) {
|
|
584
|
+
const ctx = createDefaultGenerationContext(fileTypeInformation);
|
|
585
|
+
if (!ctx) {
|
|
586
|
+
return null;
|
|
587
|
+
}
|
|
588
|
+
return tsNodesToString(buildModuleDeclarationNodes(ctx));
|
|
589
|
+
}
|
|
590
|
+
async function generateConciseTsInterface(fileTypeInformation) {
|
|
591
|
+
const ctx = createDefaultGenerationContext(fileTypeInformation);
|
|
592
|
+
if (!ctx) {
|
|
593
|
+
return { volatileGeneratedFileContent: '', moduleTypescriptInterfaceFileContent: '' };
|
|
594
|
+
}
|
|
595
|
+
const volatileGeneratedFileContent = await tsNodesToString(buildNativeModuleGeneratedNodes(ctx));
|
|
596
|
+
const moduleTypescriptInterfaceFileContent = await tsNodesToString(buildStableNativeModuleInterface(ctx));
|
|
597
|
+
return {
|
|
598
|
+
volatileGeneratedFileContent,
|
|
599
|
+
moduleTypescriptInterfaceFileContent,
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
async function generateFullTsInterface(fileTypeInformation) {
|
|
603
|
+
const ctx = createDefaultGenerationContext(fileTypeInformation);
|
|
604
|
+
if (!ctx) {
|
|
605
|
+
return null;
|
|
606
|
+
}
|
|
607
|
+
const moduleNativeFileImportName = `${ctx?.module.name}Module`;
|
|
608
|
+
const moduleTypesFileImportName = `${ctx?.module.name}.types`;
|
|
609
|
+
const moduleViewsFilesImportNames = [];
|
|
610
|
+
const moduleTypesFileNodes = joinTSNodesWithNewlines([
|
|
611
|
+
createGeneratedPrefix(),
|
|
612
|
+
createImportDeclaration({ namedImportsNames: ['ViewProps'], importFromName: 'react-native' }),
|
|
613
|
+
buildExposedTypesDeclarations(ctx, { exported: true }),
|
|
614
|
+
...ctx.module.views.map((view) => buildViewPropsInterface(view, { exported: true })),
|
|
615
|
+
]);
|
|
616
|
+
const moduleViewFilesNodes = [];
|
|
617
|
+
for (const view of ctx.module.views) {
|
|
618
|
+
const moduleViewFileNodes = joinTSNodesWithNewlines([
|
|
619
|
+
createGeneratedPrefix(),
|
|
620
|
+
createImportDeclaration({
|
|
621
|
+
namedImportsNames: ['requireNativeView'],
|
|
622
|
+
importFromName: 'expo',
|
|
623
|
+
}),
|
|
624
|
+
createImportDeclaration({
|
|
625
|
+
namedImportsNames: [getViewPropsTypeName(view)],
|
|
626
|
+
importFromName: `./${moduleTypesFileImportName}`,
|
|
627
|
+
}),
|
|
628
|
+
createRequireNativeViewDeclaration(ctx.module, view),
|
|
629
|
+
buildDefaultViewComponent({
|
|
630
|
+
componentName: view.name,
|
|
631
|
+
propsTypeAlias: getViewPropsTypeName(view),
|
|
632
|
+
}),
|
|
633
|
+
]);
|
|
634
|
+
moduleViewFilesNodes.push(moduleViewFileNodes);
|
|
635
|
+
moduleViewsFilesImportNames.push(`${view.name}View`);
|
|
636
|
+
}
|
|
637
|
+
const moduleNativeModuleNodes = joinTSNodesWithNewlines([
|
|
638
|
+
createGeneratedPrefix(),
|
|
639
|
+
createImportDeclaration({
|
|
640
|
+
namedImportsNames: ['requireNativeModule', 'NativeModule'],
|
|
641
|
+
importFromName: 'expo',
|
|
642
|
+
}),
|
|
643
|
+
createImportDeclaration({
|
|
644
|
+
namedImportsNames: [...getAllNonBasicTypes(ctx.fileInfo)],
|
|
645
|
+
importFromName: `./${moduleTypesFileImportName}`,
|
|
646
|
+
}),
|
|
647
|
+
buildNativeModuleClassDeclaration({
|
|
648
|
+
moduleClassDeclaration: ctx.module,
|
|
649
|
+
exportedModuleName: ctx.module.name,
|
|
650
|
+
}),
|
|
651
|
+
buildModuleDefaultExport({ moduleName: ctx.module.name, moduleType: ctx.module.name }),
|
|
652
|
+
]);
|
|
653
|
+
const indexFileNodes = joinTSNodesWithNewlines([
|
|
654
|
+
createGeneratedPrefix(),
|
|
655
|
+
createExportAllDeclaration({
|
|
656
|
+
importFromName: `./${moduleTypesFileImportName}`,
|
|
657
|
+
justTypes: true,
|
|
658
|
+
}),
|
|
659
|
+
createExportDefaultAsDeclaration({
|
|
660
|
+
exportAsName: ctx.module.name,
|
|
661
|
+
importFromName: `./${moduleNativeFileImportName}`,
|
|
662
|
+
}),
|
|
663
|
+
...ctx.module.views.map((view, idx) => createExportDefaultAsDeclaration({
|
|
664
|
+
exportAsName: view.name,
|
|
665
|
+
importFromName: `./${moduleViewsFilesImportNames[idx]}`,
|
|
666
|
+
})),
|
|
667
|
+
]);
|
|
668
|
+
const [moduleTypesFileContent, moduleViewFilesContents, moduleNativeFileContent, indexFileContent,] = await Promise.all([
|
|
669
|
+
tsNodesToString(moduleTypesFileNodes),
|
|
670
|
+
Promise.all(moduleViewFilesNodes.map(tsNodesToString)),
|
|
671
|
+
tsNodesToString(moduleNativeModuleNodes),
|
|
672
|
+
tsNodesToString(indexFileNodes),
|
|
673
|
+
]);
|
|
674
|
+
const moduleTypesFile = {
|
|
675
|
+
content: moduleTypesFileContent,
|
|
676
|
+
name: `${moduleTypesFileImportName}.ts`,
|
|
677
|
+
};
|
|
678
|
+
const moduleViewsFiles = moduleViewFilesContents.map((moduleViewFileContent, idx) => {
|
|
679
|
+
return {
|
|
680
|
+
content: moduleViewFileContent,
|
|
681
|
+
name: `${moduleViewsFilesImportNames[idx]}.tsx`,
|
|
682
|
+
};
|
|
683
|
+
});
|
|
684
|
+
const moduleNativeFile = {
|
|
685
|
+
content: moduleNativeFileContent,
|
|
686
|
+
name: `${moduleNativeFileImportName}.ts`,
|
|
687
|
+
};
|
|
688
|
+
const indexFile = { content: indexFileContent, name: `index.ts` };
|
|
689
|
+
return {
|
|
690
|
+
moduleTypesFile,
|
|
691
|
+
moduleViewsFiles,
|
|
692
|
+
moduleNativeFile,
|
|
693
|
+
indexFile,
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
//# sourceMappingURL=typescriptGeneration.js.map
|